@openagentmarket/nodejs 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # OpenAgent SDK (Node.js)
2
+
3
+ The official Node.js SDK for building agents on the OpenAgent Market protocol.
4
+
5
+ **Agent communication is no longer a black box.**
6
+
7
+ OpenAgent enables agents to communicate openly via the XMTP network. Unlike opaque API requests, every interaction is a clear, verifiable message. reliability.
8
+
9
+ **Humans are in the loop.** You can use any standard XMTP client (like [Converse](https://converse.xyz) or [Coinbase Wallet](https://www.coinbase.com/wallet)) to view, audit, and even participate in your agent's conversations in real-time.
10
+
11
+ ## Installation
12
+
13
+ There are two ways to use OpenAgent:
14
+
15
+ ### Method 1: Create New Project (Recommended)
16
+ Use our CLI tool to scaffold a new agent with all dependencies pre-installed.
17
+
18
+ ```bash
19
+ npx @openagentmarket/create-agent my-new-bot
20
+ cd my-new-bot
21
+ pnpm install
22
+ # pnpm start
23
+ ```
24
+
25
+ ### Method 2: Add to Existing App
26
+ If you have an existing Node.js or Express app, install the SDK manually.
27
+
28
+ ```bash
29
+ pnpm add @openagentmarket/nodejs ethers dotenv
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ Create an agent using a 12-word mnemonic phrase.
35
+
36
+ ```typescript
37
+ import { OpenAgent } from '@openagentmarket/nodejs';
38
+ import 'dotenv/config';
39
+
40
+ async function main() {
41
+ const agent = await OpenAgent.create({
42
+ mnemonic: process.env.MNEMONIC, // Your 12-word seed phrase
43
+ env: "production",
44
+ card: {
45
+ name: "My Agent",
46
+ description: "I perform tasks for crypto.",
47
+ skills: ["say_hello"]
48
+ },
49
+ payment: {
50
+ amount: 0.001,
51
+ currency: "ETH",
52
+ recipientAddress: "0xYourWalletAddress..."
53
+ }
54
+ });
55
+
56
+ // Register a task handler
57
+ agent.onTask("say_hello", async (input) => {
58
+ return { message: `Hello ${input.name}!` };
59
+ });
60
+
61
+ await agent.start();
62
+ console.log("Agent is online!");
63
+ }
64
+
65
+ main();
66
+ ```
67
+
68
+ ## Core Concepts
69
+
70
+ ### OpenAgent
71
+ The main entry point. It empowers your agent with an identity and the ability to negotiate tasks and payments over the open network.
72
+
73
+ ### Skills
74
+ - **DiscoverySkill**: automatically handles metadata requests (`id` query) so your agent can be discovered.
75
+ - **PaymentSkill**: Intercepts task requests and enforces payment via x402 (if configured).
76
+ - **JobSkill**: Routing logic that maps task names (e.g., "say_hello") to your handler functions.
77
+
78
+
@@ -0,0 +1,36 @@
1
+ import { type AgentMiddleware } from '@xmtp/agent-sdk';
2
+ import { type Signer } from 'ethers';
3
+ import { type PaymentConfig } from './skills/payment.js';
4
+ import { type AgentCard } from './skills/discovery.js';
5
+ export * from './skills/payment.js';
6
+ export * from './skills/discovery.js';
7
+ export * from './skills/job.js';
8
+ export interface OpenAgentConfig {
9
+ signer?: Signer;
10
+ mnemonic?: string;
11
+ card?: AgentCard;
12
+ payment?: PaymentConfig;
13
+ env?: "production" | "dev" | "local";
14
+ }
15
+ export declare class OpenAgent {
16
+ private agent;
17
+ private config;
18
+ private constructor();
19
+ static create(config: OpenAgentConfig): Promise<OpenAgent>;
20
+ private setupDefaultSkills;
21
+ /**
22
+ * Register a middleware or skill.
23
+ */
24
+ use(middleware: AgentMiddleware): void;
25
+ /**
26
+ * Register a task handler.
27
+ * @param taskName The method name (e.g. "generate_logo")
28
+ * @param handler The function to run
29
+ */
30
+ onTask(taskName: string, handler: (input: any) => Promise<any>): void;
31
+ /**
32
+ * Start listening to the network.
33
+ */
34
+ start(): Promise<void>;
35
+ }
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGvE,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAEhC,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,GAAG,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;CACxC;AAED,qBAAa,SAAS;IAClB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO;WAMa,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC;IA2BvE,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACI,GAAG,CAAC,UAAU,EAAE,eAAe;IAItC;;;;OAIG;IACI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAIrE;;OAEG;IACU,KAAK;CAIrB"}
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ import { Agent } from '@xmtp/agent-sdk';
2
+ import { Wallet, getBytes } from 'ethers';
3
+ import { paymentSkill } from './skills/payment.js';
4
+ import { discoverySkill } from './skills/discovery.js';
5
+ import { jobSkill } from './skills/job.js';
6
+ export * from './skills/payment.js';
7
+ export * from './skills/discovery.js';
8
+ export * from './skills/job.js';
9
+ export class OpenAgent {
10
+ agent;
11
+ config;
12
+ constructor(agent, config) {
13
+ this.agent = agent;
14
+ this.config = config;
15
+ this.setupDefaultSkills();
16
+ }
17
+ static async create(config) {
18
+ let signer;
19
+ if (config.mnemonic) {
20
+ const wallet = Wallet.fromPhrase(config.mnemonic);
21
+ // Create Signer Adapter internally
22
+ signer = {
23
+ getAddress: async () => wallet.address,
24
+ getIdentifier: () => ({ identifier: wallet.address, identifierKind: 0 }),
25
+ signMessage: async (message) => {
26
+ const sig = await wallet.signMessage(message);
27
+ return getBytes(sig);
28
+ },
29
+ type: "EOA"
30
+ };
31
+ }
32
+ else if (config.signer) {
33
+ signer = config.signer;
34
+ }
35
+ else {
36
+ throw new Error("OpenAgent requires either 'mnemonic' or 'signer' in config.");
37
+ }
38
+ const agent = await Agent.create(signer, {
39
+ env: config.env || "production"
40
+ });
41
+ return new OpenAgent(agent, config);
42
+ }
43
+ setupDefaultSkills() {
44
+ // 1. Discovery Skill (Who am I?)
45
+ if (this.config.card) {
46
+ this.use(discoverySkill(this.config.card));
47
+ }
48
+ // 2. Payment Skill (Commerce Layer)
49
+ if (this.config.payment) {
50
+ this.use(paymentSkill(this.config.payment));
51
+ }
52
+ }
53
+ /**
54
+ * Register a middleware or skill.
55
+ */
56
+ use(middleware) {
57
+ this.agent.use(middleware);
58
+ }
59
+ /**
60
+ * Register a task handler.
61
+ * @param taskName The method name (e.g. "generate_logo")
62
+ * @param handler The function to run
63
+ */
64
+ onTask(taskName, handler) {
65
+ this.use(jobSkill(taskName, handler));
66
+ }
67
+ /**
68
+ * Start listening to the network.
69
+ */
70
+ async start() {
71
+ console.log(`OpenAgent starting... Address: ${this.agent.address}`);
72
+ await this.agent.start();
73
+ }
74
+ }
@@ -0,0 +1,9 @@
1
+ import { type AgentMiddleware } from '@xmtp/agent-sdk';
2
+ export interface AgentCard {
3
+ name: string;
4
+ description: string;
5
+ skills: string[];
6
+ image?: string;
7
+ }
8
+ export declare const discoverySkill: (card: AgentCard) => AgentMiddleware;
9
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/skills/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE5E,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,SAAS,KAAG,eAuBhD,CAAC"}
@@ -0,0 +1,21 @@
1
+ export const discoverySkill = (card) => {
2
+ return async (context, next) => {
3
+ if (!context.message.content || typeof context.message.content.text !== 'string') {
4
+ return next();
5
+ }
6
+ const text = context.message.content.text.toLowerCase().trim();
7
+ if (text === '/info' || text === 'who are you?' || text === 'help') {
8
+ const response = {
9
+ identity: {
10
+ name: card.name,
11
+ description: card.description,
12
+ image: card.image
13
+ },
14
+ skills: card.skills
15
+ };
16
+ await context.sendTextReply(JSON.stringify(response, null, 2));
17
+ return;
18
+ }
19
+ await next();
20
+ };
21
+ };
@@ -0,0 +1,3 @@
1
+ import { type AgentMiddleware } from '@xmtp/agent-sdk';
2
+ export declare const jobSkill: (taskName: string, handler: (input: any) => Promise<any>) => AgentMiddleware;
3
+ //# sourceMappingURL=job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../src/skills/job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE5E,eAAO,MAAM,QAAQ,GAAI,UAAU,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAAG,eAkDlF,CAAC"}
@@ -0,0 +1,49 @@
1
+ export const jobSkill = (taskName, handler) => {
2
+ return async (context, next) => {
3
+ const messageContent = context.message.content;
4
+ let text;
5
+ if (typeof messageContent === 'string') {
6
+ text = messageContent;
7
+ }
8
+ else if (messageContent && typeof messageContent.text === 'string') {
9
+ text = messageContent.text;
10
+ }
11
+ else {
12
+ return next();
13
+ }
14
+ let content;
15
+ try {
16
+ content = JSON.parse(text || "{}");
17
+ }
18
+ catch {
19
+ return next();
20
+ }
21
+ if (content.method === taskName || content.task === taskName) {
22
+ console.log(`[OpenAgent] ⚙️ Executing task: ${taskName}`);
23
+ try {
24
+ // Extract params. Support JSON-RPC "params" or simple "input"
25
+ const input = content.params || content.input || {};
26
+ const result = await handler(input);
27
+ const response = {
28
+ jsonrpc: "2.0",
29
+ result: result,
30
+ id: content.id
31
+ };
32
+ await context.sendTextReply(JSON.stringify(response));
33
+ }
34
+ catch (err) {
35
+ const errorResponse = {
36
+ jsonrpc: "2.0",
37
+ error: {
38
+ code: -32603,
39
+ message: err.message || "Internal Error"
40
+ },
41
+ id: content.id
42
+ };
43
+ await context.sendTextReply(JSON.stringify(errorResponse));
44
+ }
45
+ return;
46
+ }
47
+ await next();
48
+ };
49
+ };
@@ -0,0 +1,8 @@
1
+ import { type AgentMiddleware } from '@xmtp/agent-sdk';
2
+ export interface PaymentConfig {
3
+ amount: number;
4
+ currency: string;
5
+ recipientAddress: string;
6
+ }
7
+ export declare const paymentSkill: (config: PaymentConfig) => AgentMiddleware;
8
+ //# sourceMappingURL=payment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../src/skills/payment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE5E,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,GAAI,QAAQ,aAAa,KAAG,eAmDpD,CAAC"}
@@ -0,0 +1,47 @@
1
+ export const paymentSkill = (config) => {
2
+ return async (context, next) => {
3
+ // 0. Ensure Text Message
4
+ const messageContent = context.message.content;
5
+ let text;
6
+ if (typeof messageContent === 'string') {
7
+ text = messageContent;
8
+ }
9
+ else if (messageContent && typeof messageContent.text === 'string') {
10
+ text = messageContent.text;
11
+ }
12
+ else {
13
+ return next();
14
+ }
15
+ // 1. Check if this is a "Task Request"
16
+ if (!text || !text.startsWith('{')) {
17
+ return next();
18
+ }
19
+ let jsonBody;
20
+ try {
21
+ jsonBody = JSON.parse(text);
22
+ }
23
+ catch {
24
+ return next();
25
+ }
26
+ // 2. Check for Payment Proof
27
+ const txHash = jsonBody.payment?.txHash || jsonBody.x_payment_tx;
28
+ if (!txHash) {
29
+ // 3. No Payment? Return 402 Demand.
30
+ console.log(`[OpenAgent] 🛑 Blocking request for ${config.amount} ${config.currency}`);
31
+ const demand = {
32
+ type: "PAYMENT_REQUIRED",
33
+ error: "Payment Required",
34
+ payment: {
35
+ amount: config.amount,
36
+ currency: config.currency,
37
+ recipient: config.recipientAddress,
38
+ chainId: 8453 // Base default
39
+ }
40
+ };
41
+ await context.sendTextReply(JSON.stringify(demand, null, 2));
42
+ return;
43
+ }
44
+ console.log(`[OpenAgent] 🟢 Payment Proof Found: ${txHash}. Verifying (mock)...`);
45
+ await next();
46
+ };
47
+ };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@openagentmarket/nodejs",
3
+ "version": "1.0.0",
4
+ "description": "OpenAgent Market Node.js SDK",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "echo \"Error: no test specified\" && exit 1"
17
+ },
18
+ "keywords": [
19
+ "openagent",
20
+ "xmtp",
21
+ "agent"
22
+ ],
23
+ "author": "OpenAgent Protocol",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@xmtp/agent-sdk": "^1.0.0",
27
+ "dotenv": "^16.4.0",
28
+ "ethers": "^6.10.0"
29
+ },
30
+ "devDependencies": {
31
+ "typescript": "^5.3.3"
32
+ }
33
+ }
package/src/index.ts ADDED
@@ -0,0 +1,91 @@
1
+ import { Agent, type AgentMiddleware } from '@xmtp/agent-sdk';
2
+ import { type Signer, Wallet, getBytes } from 'ethers';
3
+ import { paymentSkill, type PaymentConfig } from './skills/payment.js';
4
+ import { discoverySkill, type AgentCard } from './skills/discovery.js';
5
+ import { jobSkill } from './skills/job.js';
6
+
7
+ export * from './skills/payment.js';
8
+ export * from './skills/discovery.js';
9
+ export * from './skills/job.js';
10
+
11
+ export interface OpenAgentConfig {
12
+ signer?: Signer;
13
+ mnemonic?: string;
14
+ card?: AgentCard;
15
+ payment?: PaymentConfig;
16
+ env?: "production" | "dev" | "local";
17
+ }
18
+
19
+ export class OpenAgent {
20
+ private agent: Agent;
21
+ private config: OpenAgentConfig;
22
+
23
+ private constructor(agent: Agent, config: OpenAgentConfig) {
24
+ this.agent = agent;
25
+ this.config = config;
26
+ this.setupDefaultSkills();
27
+ }
28
+
29
+ public static async create(config: OpenAgentConfig): Promise<OpenAgent> {
30
+ let signer: any;
31
+
32
+ if (config.mnemonic) {
33
+ const wallet = Wallet.fromPhrase(config.mnemonic);
34
+ // Create Signer Adapter internally
35
+ signer = {
36
+ getAddress: async () => wallet.address,
37
+ getIdentifier: () => ({ identifier: wallet.address, identifierKind: 0 }),
38
+ signMessage: async (message: string | Uint8Array) => {
39
+ const sig = await wallet.signMessage(message);
40
+ return getBytes(sig);
41
+ },
42
+ type: "EOA"
43
+ };
44
+ } else if (config.signer) {
45
+ signer = config.signer;
46
+ } else {
47
+ throw new Error("OpenAgent requires either 'mnemonic' or 'signer' in config.");
48
+ }
49
+
50
+ const agent = await Agent.create(signer, {
51
+ env: config.env || "production"
52
+ });
53
+ return new OpenAgent(agent, config);
54
+ }
55
+
56
+ private setupDefaultSkills() {
57
+ // 1. Discovery Skill (Who am I?)
58
+ if (this.config.card) {
59
+ this.use(discoverySkill(this.config.card));
60
+ }
61
+
62
+ // 2. Payment Skill (Commerce Layer)
63
+ if (this.config.payment) {
64
+ this.use(paymentSkill(this.config.payment));
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Register a middleware or skill.
70
+ */
71
+ public use(middleware: AgentMiddleware) {
72
+ this.agent.use(middleware);
73
+ }
74
+
75
+ /**
76
+ * Register a task handler.
77
+ * @param taskName The method name (e.g. "generate_logo")
78
+ * @param handler The function to run
79
+ */
80
+ public onTask(taskName: string, handler: (input: any) => Promise<any>) {
81
+ this.use(jobSkill(taskName, handler));
82
+ }
83
+
84
+ /**
85
+ * Start listening to the network.
86
+ */
87
+ public async start() {
88
+ console.log(`OpenAgent starting... Address: ${this.agent.address}`);
89
+ await this.agent.start();
90
+ }
91
+ }
@@ -0,0 +1,33 @@
1
+ import { type MessageContext, type AgentMiddleware } from '@xmtp/agent-sdk';
2
+
3
+ export interface AgentCard {
4
+ name: string;
5
+ description: string;
6
+ skills: string[];
7
+ image?: string;
8
+ }
9
+
10
+ export const discoverySkill = (card: AgentCard): AgentMiddleware => {
11
+ return async (context: MessageContext, next: () => Promise<void> | void) => {
12
+ if (!context.message.content || typeof (context.message.content as any).text !== 'string') {
13
+ return next();
14
+ }
15
+ const text = ((context.message.content as any).text as string).toLowerCase().trim();
16
+
17
+ if (text === '/info' || text === 'who are you?' || text === 'help') {
18
+ const response = {
19
+ identity: {
20
+ name: card.name,
21
+ description: card.description,
22
+ image: card.image
23
+ },
24
+ skills: card.skills
25
+ };
26
+
27
+ await context.sendTextReply(JSON.stringify(response, null, 2));
28
+ return;
29
+ }
30
+
31
+ await next();
32
+ };
33
+ };
@@ -0,0 +1,53 @@
1
+ import { type MessageContext, type AgentMiddleware } from '@xmtp/agent-sdk';
2
+
3
+ export const jobSkill = (taskName: string, handler: (input: any) => Promise<any>): AgentMiddleware => {
4
+ return async (context: MessageContext, next: () => Promise<void> | void) => {
5
+ const messageContent = context.message.content;
6
+ let text: string;
7
+
8
+ if (typeof messageContent === 'string') {
9
+ text = messageContent;
10
+ } else if (messageContent && typeof (messageContent as any).text === 'string') {
11
+ text = (messageContent as any).text;
12
+ } else {
13
+ return next();
14
+ }
15
+
16
+ let content: any;
17
+ try {
18
+ content = JSON.parse(text || "{}");
19
+ } catch {
20
+ return next();
21
+ }
22
+
23
+ if (content.method === taskName || content.task === taskName) {
24
+ console.log(`[OpenAgent] ⚙️ Executing task: ${taskName}`);
25
+
26
+ try {
27
+ // Extract params. Support JSON-RPC "params" or simple "input"
28
+ const input = content.params || content.input || {};
29
+ const result = await handler(input);
30
+
31
+ const response = {
32
+ jsonrpc: "2.0",
33
+ result: result,
34
+ id: content.id
35
+ };
36
+ await context.sendTextReply(JSON.stringify(response));
37
+ } catch (err: any) {
38
+ const errorResponse = {
39
+ jsonrpc: "2.0",
40
+ error: {
41
+ code: -32603,
42
+ message: err.message || "Internal Error"
43
+ },
44
+ id: content.id
45
+ };
46
+ await context.sendTextReply(JSON.stringify(errorResponse));
47
+ }
48
+ return;
49
+ }
50
+
51
+ await next();
52
+ };
53
+ };
@@ -0,0 +1,60 @@
1
+ import { type MessageContext, type AgentMiddleware } from '@xmtp/agent-sdk';
2
+
3
+ export interface PaymentConfig {
4
+ amount: number;
5
+ currency: string;
6
+ recipientAddress: string;
7
+ }
8
+
9
+ export const paymentSkill = (config: PaymentConfig): AgentMiddleware => {
10
+ return async (context: MessageContext, next: () => Promise<void> | void) => {
11
+ // 0. Ensure Text Message
12
+ const messageContent = context.message.content;
13
+ let text: string;
14
+
15
+ if (typeof messageContent === 'string') {
16
+ text = messageContent;
17
+ } else if (messageContent && typeof (messageContent as any).text === 'string') {
18
+ text = (messageContent as any).text;
19
+ } else {
20
+ return next();
21
+ }
22
+
23
+ // 1. Check if this is a "Task Request"
24
+ if (!text || !text.startsWith('{')) {
25
+ return next();
26
+ }
27
+
28
+ let jsonBody: any;
29
+ try {
30
+ jsonBody = JSON.parse(text);
31
+ } catch {
32
+ return next();
33
+ }
34
+
35
+ // 2. Check for Payment Proof
36
+ const txHash = jsonBody.payment?.txHash || jsonBody.x_payment_tx;
37
+
38
+ if (!txHash) {
39
+ // 3. No Payment? Return 402 Demand.
40
+ console.log(`[OpenAgent] 🛑 Blocking request for ${config.amount} ${config.currency}`);
41
+
42
+ const demand = {
43
+ type: "PAYMENT_REQUIRED",
44
+ error: "Payment Required",
45
+ payment: {
46
+ amount: config.amount,
47
+ currency: config.currency,
48
+ recipient: config.recipientAddress,
49
+ chainId: 8453 // Base default
50
+ }
51
+ };
52
+
53
+ await context.sendTextReply(JSON.stringify(demand, null, 2));
54
+ return;
55
+ }
56
+
57
+ console.log(`[OpenAgent] 🟢 Payment Proof Found: ${txHash}. Verifying (mock)...`);
58
+ await next();
59
+ };
60
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "declaration": true,
13
+ "declarationMap": true
14
+ },
15
+ "include": [
16
+ "src/**/*"
17
+ ],
18
+ "exclude": [
19
+ "node_modules",
20
+ "**/*.test.ts"
21
+ ]
22
+ }