@reap-protocol/sdk 0.1.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.
@@ -0,0 +1,23 @@
1
+ import { ethers } from "ethers";
2
+ import { AxiosRequestConfig } from "axios";
3
+ export declare class ReapClient {
4
+ private wallet;
5
+ private builderUrl;
6
+ private provider;
7
+ constructor(privateKey: string, chainRpc?: string, builderUrl?: string);
8
+ /**
9
+ * Core Logic: Signs and Broadcasts transactions sequentially.
10
+ * Uses manual nonce management to prevent RPC lag errors.
11
+ */
12
+ private executeTransactions;
13
+ private callBuilder;
14
+ getProduct(productId: string): Promise<any>;
15
+ registerIdentity(profileUri?: string): Promise<ethers.TransactionReceipt | null | undefined>;
16
+ stockShelf(productQuery: string): Promise<{
17
+ receipt: ethers.TransactionReceipt | null | undefined;
18
+ items: any;
19
+ }>;
20
+ buyProduct(productId: string): Promise<ethers.TransactionReceipt | null | undefined>;
21
+ buyCart(productIds: string[]): Promise<ethers.TransactionReceipt | null | undefined>;
22
+ fetch(url: string, config?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<any, any, {}>>;
23
+ }
package/dist/index.js ADDED
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ReapClient = void 0;
7
+ const ethers_1 = require("ethers");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ class ReapClient {
10
+ constructor(privateKey, chainRpc = "https://sepolia.base.org", builderUrl = "https://api.reap.deals") {
11
+ this.provider = new ethers_1.ethers.JsonRpcProvider(chainRpc);
12
+ this.wallet = new ethers_1.ethers.Wallet(privateKey, this.provider);
13
+ this.builderUrl = builderUrl.replace(/\/$/, ""); // Remove trailing slash
14
+ console.log(`๐Ÿค– Reap Agent Online: ${this.wallet.address}`);
15
+ }
16
+ /**
17
+ * Core Logic: Signs and Broadcasts transactions sequentially.
18
+ * Uses manual nonce management to prevent RPC lag errors.
19
+ */
20
+ async executeTransactions(txList) {
21
+ let lastReceipt;
22
+ // 1. Fetch Nonce ONCE
23
+ let currentNonce = await this.provider.getTransactionCount(this.wallet.address, "pending");
24
+ for (const txData of txList) {
25
+ const label = txData.label || "Transaction";
26
+ console.log(` ๐Ÿ“ Signing: ${label}...`);
27
+ const tx = {
28
+ to: txData.to,
29
+ data: txData.data,
30
+ value: BigInt(txData.value),
31
+ gasLimit: 500000, // Safety limit
32
+ nonce: currentNonce,
33
+ chainId: (await this.provider.getNetwork()).chainId
34
+ };
35
+ try {
36
+ // 2. Sign & Send
37
+ const response = await this.wallet.sendTransaction(tx);
38
+ console.log(` ๐Ÿš€ Broadcasting: ${response.hash}`);
39
+ // 3. Wait
40
+ const receipt = await response.wait();
41
+ // 4. Check Status (1 = Success, 0 = Revert)
42
+ if (receipt && receipt.status === 0) {
43
+ throw new Error(`Transaction Reverted! Hash: ${receipt.hash}`);
44
+ }
45
+ console.log(` โœ… Settled on-chain.`);
46
+ lastReceipt = receipt;
47
+ // 5. Increment Nonce
48
+ currentNonce++;
49
+ }
50
+ catch (e) {
51
+ console.error(` โŒ Tx Failed: ${e.message}`);
52
+ if (label.includes("Approve") || label.includes("Payment"))
53
+ throw e;
54
+ }
55
+ }
56
+ return lastReceipt;
57
+ }
58
+ async callBuilder(endpoint, payload) {
59
+ try {
60
+ const { data } = await axios_1.default.post(`${this.builderUrl}${endpoint}`, payload);
61
+ return data;
62
+ }
63
+ catch (error) {
64
+ const msg = error.response?.data?.detail || error.message;
65
+ throw new Error(`Reap Protocol Error: ${msg}`);
66
+ }
67
+ }
68
+ // --- PUBLIC API ---
69
+ async getProduct(productId) {
70
+ const safeId = encodeURIComponent(productId);
71
+ const { data } = await axios_1.default.get(`${this.builderUrl}/read/product/${safeId}`);
72
+ return data;
73
+ }
74
+ // ... inside ReapClient class ...
75
+ async registerIdentity(profileUri = "ipfs://default") {
76
+ console.log("๐Ÿ†” Registering Protocol Identity...");
77
+ const res = await this.callBuilder("/build/identity/register", {
78
+ user_address: this.wallet.address,
79
+ profile_uri: profileUri
80
+ });
81
+ if (res.status === "already_registered") {
82
+ console.log(` โœ… Already Registered (Agent #${res.agent_id}). Skipping transaction.`);
83
+ return null;
84
+ }
85
+ return this.executeTransactions(res.transactions);
86
+ }
87
+ async stockShelf(productQuery) {
88
+ console.log(`๐Ÿ“ฆ Stocking Shelf: '${productQuery}'`);
89
+ const res = await this.callBuilder("/build/inventory/stock", {
90
+ product_query: productQuery,
91
+ provider_address: this.wallet.address
92
+ });
93
+ if (res.status === "payment_required") {
94
+ console.log("๐Ÿ›‘ 402 Payment Required via JSON Spec.");
95
+ console.log(` ๐Ÿงพ Invoice: ${res.meta.description}`);
96
+ }
97
+ else {
98
+ console.log(` ๐Ÿ” Found ${res.meta.count || 0} items.`);
99
+ }
100
+ const receipt = await this.executeTransactions(res.transactions);
101
+ // --- THE FIX: Return both Receipt AND Items ---
102
+ return {
103
+ receipt,
104
+ items: res.meta?.items || []
105
+ };
106
+ // ----------------------------------------------
107
+ }
108
+ async buyProduct(productId) {
109
+ console.log(`๐Ÿ’ธ Initiating Agentic Cart (Single Item): ${productId}`);
110
+ // Route to batch endpoint
111
+ const res = await this.callBuilder("/build/commerce/batch", {
112
+ product_ids: [productId]
113
+ });
114
+ return this.executeTransactions(res.transactions);
115
+ }
116
+ async buyCart(productIds) {
117
+ console.log(`๐Ÿ›’ Initiating Agentic Cart (Batch): ${productIds.length} items`);
118
+ const res = await this.callBuilder("/build/commerce/batch", {
119
+ product_ids: productIds
120
+ });
121
+ return this.executeTransactions(res.transactions);
122
+ }
123
+ async fetch(url, config = {}) {
124
+ console.log(`๐ŸŒ Accessing ${url}...`);
125
+ try {
126
+ return await axios_1.default.get(url, config);
127
+ }
128
+ catch (error) {
129
+ if (error.response && error.response.status === 402) {
130
+ console.log("๐Ÿ›‘ x402 Payment Required. Engaging Protocol...");
131
+ const header = error.response.headers["www-authenticate"];
132
+ if (header && header.includes("X402")) {
133
+ const match = header.match(/resource_id="([^"]+)"/);
134
+ if (match && match[1]) {
135
+ const rid = match[1];
136
+ // Pay Protocol
137
+ const receipt = await this.buyProduct(rid);
138
+ if (!receipt)
139
+ throw new Error("Payment Transaction failed");
140
+ const proof = receipt.hash;
141
+ console.log(` ๐Ÿ”„ Submitting Proof for Reactive Release: ${proof}`);
142
+ // Release Data
143
+ const newConfig = { ...config, headers: { ...config.headers, "Authorization": `X402-Proof ${proof}` } };
144
+ return await axios_1.default.get(url, newConfig);
145
+ }
146
+ }
147
+ }
148
+ throw error;
149
+ }
150
+ }
151
+ }
152
+ exports.ReapClient = ReapClient;
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@reap-protocol/sdk",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "scripts": {
7
+ "build": "tsc"
8
+ },
9
+ "dependencies": {
10
+ "axios": "^1.6.0",
11
+ "ethers": "^6.0.0"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "^5.0.0"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ }
19
+ }
package/src/README.md ADDED
@@ -0,0 +1,86 @@
1
+ Reap Protocol
2
+
3
+ The official TypeScript/Node.js SDK for the **Reap Protocol**: The Agentic Commerce Layer.
4
+ Enable Autonomous Agents to buy and sell on-chain with zero smart contract knowledge.
5
+
6
+
7
+
8
+ ๐Ÿ“ฆ Installation
9
+
10
+ npm install @reap-protocol/sdk ethers axios
11
+
12
+
13
+
14
+ ๐Ÿš€ Quick Start
15
+
16
+ 1. Setup
17
+ If using TypeScript, ensure your tsconfig.json targets ES2020 or higher.
18
+
19
+ 2. The Agent Code
20
+
21
+ TypeScript
22
+ import { ReapClient } from "@reap-protocol/sdk";
23
+
24
+ // Use a Base Sepolia Wallet
25
+ const PRIVATE_KEY = process.env.MY_WALLET_KEY || "";
26
+
27
+ async function main() {
28
+ // 1. Initialize
29
+ const client = new ReapClient(PRIVATE_KEY);
30
+ console.log("๐Ÿค– Agent Online");
31
+
32
+ try {
33
+ // 2. Identity
34
+ // Ensures this wallet is registered to trade
35
+ await client.registerIdentity();
36
+
37
+ // 3. Discovery (Stocking)
38
+ // Fetches data, registers it on Base Sepolia, and returns the list
39
+ console.log("๐Ÿ“ฆ Stocking Shelf...");
40
+ const result = await client.stockShelf("Tonnino Tuna");
41
+
42
+ const inventory = result.items;
43
+ console.log(` ๐Ÿ” Found ${inventory.length} items.`);
44
+
45
+ if (inventory.length > 0) {
46
+ // 4. Decision Engine
47
+ const target = inventory[0];
48
+ console.log(` ๐ŸŽฏ Target: ${target.name} ($${target.price})`);
49
+
50
+ // 5. Settlement (Agentic Cart)
51
+ // Automatically approves USDC and executes the purchase
52
+ console.log("๐Ÿ’ธ Purchasing...");
53
+ const receipt = await client.buyProduct(target.id);
54
+
55
+ console.log(`๐ŸŽ‰ SUCCESS! Tx: ${receipt.hash}`);
56
+ }
57
+
58
+ } catch (e: any) {
59
+ console.error("โŒ Error:", e.message);
60
+ }
61
+ }
62
+
63
+ main();
64
+
65
+
66
+
67
+ โœจ Features
68
+ Typed Interfaces: Full TypeScript support for Product Data and Transactions.
69
+ Agentic Cart: Automatically routes purchases through the Protocol's batch processor.
70
+ Protocol Negotiation: Built-in support for HTTP 402 Payment Negotiation loops.
71
+ Gas Optimized: Checks on-chain state before sending registration transactions.
72
+
73
+
74
+ ๐Ÿ”ง Configuration
75
+ code
76
+ TypeScript
77
+ const client = new ReapClient(
78
+ "YOUR_PRIVATE_KEY",
79
+ "https://sepolia.base.org", // Custom RPC
80
+ "https://api.reap.deals" // Middleware URL
81
+ );
82
+
83
+
84
+
85
+ License
86
+ MIT
package/src/index.ts ADDED
@@ -0,0 +1,178 @@
1
+ import { ethers } from "ethers";
2
+ import axios, { AxiosRequestConfig } from "axios";
3
+
4
+ export class ReapClient {
5
+ private wallet: ethers.Wallet;
6
+ private builderUrl: string;
7
+ private provider: ethers.JsonRpcProvider;
8
+
9
+ constructor(
10
+ privateKey: string,
11
+ chainRpc: string = "https://sepolia.base.org",
12
+ builderUrl: string = "https://api.reap.deals"
13
+ ) {
14
+ this.provider = new ethers.JsonRpcProvider(chainRpc);
15
+ this.wallet = new ethers.Wallet(privateKey, this.provider);
16
+ this.builderUrl = builderUrl.replace(/\/$/, ""); // Remove trailing slash
17
+ console.log(`๐Ÿค– Reap Agent Online: ${this.wallet.address}`);
18
+ }
19
+
20
+ /**
21
+ * Core Logic: Signs and Broadcasts transactions sequentially.
22
+ * Uses manual nonce management to prevent RPC lag errors.
23
+ */
24
+ private async executeTransactions(txList: any[]) {
25
+ let lastReceipt;
26
+
27
+ // 1. Fetch Nonce ONCE
28
+ let currentNonce = await this.provider.getTransactionCount(this.wallet.address, "pending");
29
+
30
+ for (const txData of txList) {
31
+ const label = txData.label || "Transaction";
32
+ console.log(` ๐Ÿ“ Signing: ${label}...`);
33
+
34
+ const tx = {
35
+ to: txData.to,
36
+ data: txData.data,
37
+ value: BigInt(txData.value),
38
+ gasLimit: 500000, // Safety limit
39
+ nonce: currentNonce,
40
+ chainId: (await this.provider.getNetwork()).chainId
41
+ };
42
+
43
+ try {
44
+ // 2. Sign & Send
45
+ const response = await this.wallet.sendTransaction(tx);
46
+ console.log(` ๐Ÿš€ Broadcasting: ${response.hash}`);
47
+
48
+ // 3. Wait
49
+ const receipt = await response.wait();
50
+
51
+ // 4. Check Status (1 = Success, 0 = Revert)
52
+ if (receipt && receipt.status === 0) {
53
+ throw new Error(`Transaction Reverted! Hash: ${receipt.hash}`);
54
+ }
55
+
56
+ console.log(` โœ… Settled on-chain.`);
57
+ lastReceipt = receipt;
58
+
59
+ // 5. Increment Nonce
60
+ currentNonce++;
61
+
62
+ } catch (e: any) {
63
+ console.error(` โŒ Tx Failed: ${e.message}`);
64
+
65
+ if (label.includes("Approve") || label.includes("Payment")) throw e;
66
+ }
67
+ }
68
+ return lastReceipt;
69
+ }
70
+
71
+ private async callBuilder(endpoint: string, payload: any) {
72
+ try {
73
+ const { data } = await axios.post(`${this.builderUrl}${endpoint}`, payload);
74
+ return data;
75
+ } catch (error: any) {
76
+ const msg = error.response?.data?.detail || error.message;
77
+ throw new Error(`Reap Protocol Error: ${msg}`);
78
+ }
79
+ }
80
+
81
+ // --- PUBLIC API ---
82
+
83
+ async getProduct(productId: string) {
84
+ const safeId = encodeURIComponent(productId);
85
+ const { data } = await axios.get(`${this.builderUrl}/read/product/${safeId}`);
86
+ return data;
87
+ }
88
+
89
+ // ... inside ReapClient class ...
90
+
91
+ async registerIdentity(profileUri: string = "ipfs://default") {
92
+ console.log("๐Ÿ†” Registering Protocol Identity...");
93
+ const res = await this.callBuilder("/build/identity/register", {
94
+ user_address: this.wallet.address,
95
+ profile_uri: profileUri
96
+ });
97
+
98
+ if (res.status === "already_registered") {
99
+ console.log(` โœ… Already Registered (Agent #${res.agent_id}). Skipping transaction.`);
100
+ return null;
101
+ }
102
+
103
+ return this.executeTransactions(res.transactions);
104
+ }
105
+
106
+ async stockShelf(productQuery: string) {
107
+ console.log(`๐Ÿ“ฆ Stocking Shelf: '${productQuery}'`);
108
+ const res = await this.callBuilder("/build/inventory/stock", {
109
+ product_query: productQuery,
110
+ provider_address: this.wallet.address
111
+ });
112
+
113
+ if (res.status === "payment_required") {
114
+ console.log("๐Ÿ›‘ 402 Payment Required via JSON Spec.");
115
+ console.log(` ๐Ÿงพ Invoice: ${res.meta.description}`);
116
+ } else {
117
+ console.log(` ๐Ÿ” Found ${res.meta.count || 0} items.`);
118
+ }
119
+
120
+ const receipt = await this.executeTransactions(res.transactions);
121
+
122
+ // --- THE FIX: Return both Receipt AND Items ---
123
+ return {
124
+ receipt,
125
+ items: res.meta?.items || []
126
+ };
127
+ // ----------------------------------------------
128
+ }
129
+
130
+ async buyProduct(productId: string) {
131
+ console.log(`๐Ÿ’ธ Initiating Agentic Cart (Single Item): ${productId}`);
132
+ // Route to batch endpoint
133
+ const res = await this.callBuilder("/build/commerce/batch", {
134
+ product_ids: [productId]
135
+ });
136
+ return this.executeTransactions(res.transactions);
137
+ }
138
+
139
+ async buyCart(productIds: string[]) {
140
+ console.log(`๐Ÿ›’ Initiating Agentic Cart (Batch): ${productIds.length} items`);
141
+ const res = await this.callBuilder("/build/commerce/batch", {
142
+ product_ids: productIds
143
+ });
144
+ return this.executeTransactions(res.transactions);
145
+ }
146
+
147
+ async fetch(url: string, config: AxiosRequestConfig = {}) {
148
+ console.log(`๐ŸŒ Accessing ${url}...`);
149
+ try {
150
+ return await axios.get(url, config);
151
+ } catch (error: any) {
152
+ if (error.response && error.response.status === 402) {
153
+ console.log("๐Ÿ›‘ x402 Payment Required. Engaging Protocol...");
154
+ const header = error.response.headers["www-authenticate"];
155
+
156
+ if (header && header.includes("X402")) {
157
+ const match = header.match(/resource_id="([^"]+)"/);
158
+ if (match && match[1]) {
159
+ const rid = match[1];
160
+
161
+ // Pay Protocol
162
+ const receipt = await this.buyProduct(rid);
163
+
164
+ if (!receipt) throw new Error("Payment Transaction failed");
165
+ const proof = receipt.hash;
166
+
167
+ console.log(` ๐Ÿ”„ Submitting Proof for Reactive Release: ${proof}`);
168
+
169
+ // Release Data
170
+ const newConfig = { ...config, headers: { ...config.headers, "Authorization": `X402-Proof ${proof}` } };
171
+ return await axios.get(url, newConfig);
172
+ }
173
+ }
174
+ }
175
+ throw error;
176
+ }
177
+ }
178
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "declaration": true, // <--- IMPORTANT: Generates .d.ts files
6
+ "outDir": "./dist",
7
+ "strict": true,
8
+ "esModuleInterop": true
9
+ },
10
+ "include": ["src"]
11
+ }