agstell-cli 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.
- package/README.md +234 -0
- package/bin/agentmarket.js +2 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +761 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.js +412 -0
- package/package.json +49 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentMarket CLI - Types
|
|
3
|
+
*/
|
|
4
|
+
interface Config {
|
|
5
|
+
stellarNetwork: 'testnet' | 'mainnet';
|
|
6
|
+
secretKey?: string;
|
|
7
|
+
publicKey?: string;
|
|
8
|
+
marketplaceUrl: string;
|
|
9
|
+
budgetLimit: number;
|
|
10
|
+
contractId?: string;
|
|
11
|
+
}
|
|
12
|
+
interface ApiInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
slug: string;
|
|
15
|
+
description: string;
|
|
16
|
+
category: string;
|
|
17
|
+
priceUsdc: number;
|
|
18
|
+
endpoint: string;
|
|
19
|
+
method: 'GET' | 'POST';
|
|
20
|
+
provider: string;
|
|
21
|
+
}
|
|
22
|
+
interface WalletInfo {
|
|
23
|
+
publicKey: string;
|
|
24
|
+
network: 'testnet' | 'mainnet';
|
|
25
|
+
xlmBalance: string;
|
|
26
|
+
usdcBalance: string;
|
|
27
|
+
}
|
|
28
|
+
interface CallResult {
|
|
29
|
+
success: boolean;
|
|
30
|
+
data?: unknown;
|
|
31
|
+
error?: string;
|
|
32
|
+
txHash?: string;
|
|
33
|
+
amountPaid?: number;
|
|
34
|
+
latencyMs?: number;
|
|
35
|
+
}
|
|
36
|
+
interface BudgetStatus {
|
|
37
|
+
totalBudget: number;
|
|
38
|
+
spent: number;
|
|
39
|
+
remaining: number;
|
|
40
|
+
callsToday: number;
|
|
41
|
+
lastCall?: string;
|
|
42
|
+
}
|
|
43
|
+
interface TransactionRecord {
|
|
44
|
+
txHash: string;
|
|
45
|
+
api: string;
|
|
46
|
+
amount: number;
|
|
47
|
+
timestamp: string;
|
|
48
|
+
success: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* AgentMarket CLI - Stellar Client
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
declare class StellarClient {
|
|
56
|
+
private network;
|
|
57
|
+
private server;
|
|
58
|
+
private keypair;
|
|
59
|
+
constructor(network?: 'testnet' | 'mainnet');
|
|
60
|
+
setSecretKey(secretKey: string): void;
|
|
61
|
+
getPublicKey(): string | null;
|
|
62
|
+
getWalletInfo(): Promise<WalletInfo | null>;
|
|
63
|
+
fundTestnetAccount(): Promise<string | null>;
|
|
64
|
+
sendPayment(destination: string, amount: string, memo?: string): Promise<{
|
|
65
|
+
txHash: string;
|
|
66
|
+
success: boolean;
|
|
67
|
+
} | null>;
|
|
68
|
+
verifyTransaction(txHash: string): Promise<boolean>;
|
|
69
|
+
generateKeypair(): {
|
|
70
|
+
publicKey: string;
|
|
71
|
+
secretKey: string;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* AgentMarket CLI - API Client
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
declare function listApis(category?: string): ApiInfo[];
|
|
80
|
+
declare function getApiInfo(slug: string): ApiInfo | undefined;
|
|
81
|
+
declare function callApi(slug: string, params: Record<string, unknown>, stellarClient: StellarClient): Promise<CallResult>;
|
|
82
|
+
|
|
83
|
+
declare function loadConfig(): Config;
|
|
84
|
+
declare function saveConfig(config: Partial<Config>): void;
|
|
85
|
+
declare function loadHistory(): {
|
|
86
|
+
calls: {
|
|
87
|
+
api: string;
|
|
88
|
+
timestamp: string;
|
|
89
|
+
amount: number;
|
|
90
|
+
txHash: string;
|
|
91
|
+
}[];
|
|
92
|
+
};
|
|
93
|
+
declare function appendHistory(call: {
|
|
94
|
+
api: string;
|
|
95
|
+
timestamp: string;
|
|
96
|
+
amount: number;
|
|
97
|
+
txHash: string;
|
|
98
|
+
}): void;
|
|
99
|
+
|
|
100
|
+
export { type ApiInfo, type BudgetStatus, type CallResult, type Config, StellarClient, type TransactionRecord, type WalletInfo, appendHistory, callApi, getApiInfo, listApis, loadConfig, loadHistory, saveConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
StellarClient: () => StellarClient,
|
|
34
|
+
appendHistory: () => appendHistory,
|
|
35
|
+
callApi: () => callApi,
|
|
36
|
+
getApiInfo: () => getApiInfo,
|
|
37
|
+
listApis: () => listApis,
|
|
38
|
+
loadConfig: () => loadConfig,
|
|
39
|
+
loadHistory: () => loadHistory,
|
|
40
|
+
saveConfig: () => saveConfig
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/stellar.ts
|
|
45
|
+
var StellarSdk = __toESM(require("@stellar/stellar-sdk"));
|
|
46
|
+
var NETWORKS = {
|
|
47
|
+
testnet: {
|
|
48
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
49
|
+
horizonUrl: "https://horizon-testnet.stellar.org",
|
|
50
|
+
sorobanUrl: "https://soroban-testnet.stellar.org"
|
|
51
|
+
},
|
|
52
|
+
mainnet: {
|
|
53
|
+
networkPassphrase: StellarSdk.Networks.PUBLIC,
|
|
54
|
+
horizonUrl: "https://horizon.stellar.org",
|
|
55
|
+
sorobanUrl: "https://mainnet.stellar.org"
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var USDC_TESTNET_ISSUER = "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5";
|
|
59
|
+
var USDC_MAINNET_ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
|
|
60
|
+
var StellarClient = class {
|
|
61
|
+
network;
|
|
62
|
+
server;
|
|
63
|
+
keypair = null;
|
|
64
|
+
constructor(network = "testnet") {
|
|
65
|
+
this.network = network;
|
|
66
|
+
const config = NETWORKS[network];
|
|
67
|
+
this.server = new StellarSdk.Horizon.Server(config.horizonUrl);
|
|
68
|
+
}
|
|
69
|
+
setSecretKey(secretKey) {
|
|
70
|
+
this.keypair = StellarSdk.Keypair.fromSecret(secretKey);
|
|
71
|
+
}
|
|
72
|
+
getPublicKey() {
|
|
73
|
+
return this.keypair?.publicKey() || null;
|
|
74
|
+
}
|
|
75
|
+
async getWalletInfo() {
|
|
76
|
+
if (!this.keypair) return null;
|
|
77
|
+
try {
|
|
78
|
+
const account = await this.server.loadAccount(this.keypair.publicKey());
|
|
79
|
+
let xlmBalance = "0";
|
|
80
|
+
let usdcBalance = "0";
|
|
81
|
+
const usdcIssuer = this.network === "testnet" ? USDC_TESTNET_ISSUER : USDC_MAINNET_ISSUER;
|
|
82
|
+
for (const balance of account.balances) {
|
|
83
|
+
if (balance.asset_type === "native") {
|
|
84
|
+
xlmBalance = balance.balance;
|
|
85
|
+
} else if (balance.asset_type !== "liquidity_pool_shares" && balance.asset_code === "USDC" && balance.asset_issuer === usdcIssuer) {
|
|
86
|
+
usdcBalance = balance.balance;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
publicKey: this.keypair.publicKey(),
|
|
91
|
+
network: this.network,
|
|
92
|
+
xlmBalance,
|
|
93
|
+
usdcBalance
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return {
|
|
97
|
+
publicKey: this.keypair.publicKey(),
|
|
98
|
+
network: this.network,
|
|
99
|
+
xlmBalance: "0",
|
|
100
|
+
usdcBalance: "0"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async fundTestnetAccount() {
|
|
105
|
+
if (!this.keypair || this.network !== "testnet") return null;
|
|
106
|
+
try {
|
|
107
|
+
const response = await fetch(
|
|
108
|
+
`https://friendbot.stellar.org?addr=${this.keypair.publicKey()}`
|
|
109
|
+
);
|
|
110
|
+
if (response.ok) {
|
|
111
|
+
return this.keypair.publicKey();
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
async sendPayment(destination, amount, memo) {
|
|
118
|
+
if (!this.keypair) return null;
|
|
119
|
+
try {
|
|
120
|
+
const account = await this.server.loadAccount(this.keypair.publicKey());
|
|
121
|
+
const usdcIssuer = this.network === "testnet" ? USDC_TESTNET_ISSUER : USDC_MAINNET_ISSUER;
|
|
122
|
+
const usdcAsset = new StellarSdk.Asset("USDC", usdcIssuer);
|
|
123
|
+
const transaction = new StellarSdk.TransactionBuilder(account, {
|
|
124
|
+
fee: StellarSdk.BASE_FEE,
|
|
125
|
+
networkPassphrase: NETWORKS[this.network].networkPassphrase
|
|
126
|
+
}).addOperation(
|
|
127
|
+
StellarSdk.Operation.payment({
|
|
128
|
+
destination,
|
|
129
|
+
asset: usdcAsset,
|
|
130
|
+
amount
|
|
131
|
+
})
|
|
132
|
+
).setTimeout(30);
|
|
133
|
+
if (memo) {
|
|
134
|
+
transaction.addMemo(StellarSdk.Memo.text(memo.substring(0, 28)));
|
|
135
|
+
}
|
|
136
|
+
const builtTx = transaction.build();
|
|
137
|
+
builtTx.sign(this.keypair);
|
|
138
|
+
const result = await this.server.submitTransaction(builtTx);
|
|
139
|
+
return {
|
|
140
|
+
txHash: result.hash,
|
|
141
|
+
success: true
|
|
142
|
+
};
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error("Payment failed:", error);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
async verifyTransaction(txHash) {
|
|
149
|
+
try {
|
|
150
|
+
const tx = await this.server.transactions().transaction(txHash).call();
|
|
151
|
+
return tx.successful;
|
|
152
|
+
} catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
generateKeypair() {
|
|
157
|
+
const keypair = StellarSdk.Keypair.random();
|
|
158
|
+
return {
|
|
159
|
+
publicKey: keypair.publicKey(),
|
|
160
|
+
secretKey: keypair.secret()
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/config.ts
|
|
166
|
+
var fs = __toESM(require("fs"));
|
|
167
|
+
var path = __toESM(require("path"));
|
|
168
|
+
var os = __toESM(require("os"));
|
|
169
|
+
var CONFIG_DIR = path.join(os.homedir(), ".agentmarket");
|
|
170
|
+
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
171
|
+
var HISTORY_FILE = path.join(CONFIG_DIR, "history.json");
|
|
172
|
+
var REGISTRY_CACHE_FILE = path.join(CONFIG_DIR, "registry.json");
|
|
173
|
+
var CONTRACTS = {
|
|
174
|
+
testnet: {
|
|
175
|
+
budgetEnforcer: "CBCAATFEUDNV43RPERRZ66B76C2HIOJ7LJBG77F4KHAVU527Y3PLHPJB"
|
|
176
|
+
},
|
|
177
|
+
mainnet: {
|
|
178
|
+
budgetEnforcer: ""
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
var DEFAULT_CONFIG = {
|
|
182
|
+
stellarNetwork: "testnet",
|
|
183
|
+
marketplaceUrl: "https://agentmarket.xyz",
|
|
184
|
+
budgetLimit: 10,
|
|
185
|
+
// 10 USDC default
|
|
186
|
+
contractId: CONTRACTS.testnet.budgetEnforcer
|
|
187
|
+
};
|
|
188
|
+
function ensureConfigDir() {
|
|
189
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
190
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function loadConfig() {
|
|
194
|
+
ensureConfigDir();
|
|
195
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
196
|
+
try {
|
|
197
|
+
const data = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
198
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(data) };
|
|
199
|
+
} catch {
|
|
200
|
+
return DEFAULT_CONFIG;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return DEFAULT_CONFIG;
|
|
204
|
+
}
|
|
205
|
+
function saveConfig(config) {
|
|
206
|
+
ensureConfigDir();
|
|
207
|
+
const existing = loadConfig();
|
|
208
|
+
const updated = { ...existing, ...config };
|
|
209
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(updated, null, 2));
|
|
210
|
+
}
|
|
211
|
+
function loadHistory() {
|
|
212
|
+
ensureConfigDir();
|
|
213
|
+
if (fs.existsSync(HISTORY_FILE)) {
|
|
214
|
+
try {
|
|
215
|
+
const data = fs.readFileSync(HISTORY_FILE, "utf-8");
|
|
216
|
+
return JSON.parse(data);
|
|
217
|
+
} catch {
|
|
218
|
+
return { calls: [] };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return { calls: [] };
|
|
222
|
+
}
|
|
223
|
+
function appendHistory(call) {
|
|
224
|
+
const history = loadHistory();
|
|
225
|
+
history.calls.push(call);
|
|
226
|
+
if (history.calls.length > 1e3) {
|
|
227
|
+
history.calls = history.calls.slice(-1e3);
|
|
228
|
+
}
|
|
229
|
+
fs.writeFileSync(HISTORY_FILE, JSON.stringify(history, null, 2));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/api.ts
|
|
233
|
+
var REGISTRY_TTL_MS = 60 * 60 * 1e3;
|
|
234
|
+
var FALLBACK_REGISTRY = [
|
|
235
|
+
{
|
|
236
|
+
name: "Weather",
|
|
237
|
+
slug: "weather",
|
|
238
|
+
description: "Get current weather data for any city worldwide",
|
|
239
|
+
category: "Data",
|
|
240
|
+
priceUsdc: 1e-3,
|
|
241
|
+
endpoint: "/api/proxy/weather",
|
|
242
|
+
method: "GET",
|
|
243
|
+
provider: "AgentMarket"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: "Air Quality",
|
|
247
|
+
slug: "air-quality",
|
|
248
|
+
description: "Get real-time air quality index and pollution data",
|
|
249
|
+
category: "Data",
|
|
250
|
+
priceUsdc: 1e-3,
|
|
251
|
+
endpoint: "/api/proxy/air-quality",
|
|
252
|
+
method: "GET",
|
|
253
|
+
provider: "AgentMarket"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "News",
|
|
257
|
+
slug: "news",
|
|
258
|
+
description: "Fetch latest news headlines by topic",
|
|
259
|
+
category: "Data",
|
|
260
|
+
priceUsdc: 2e-3,
|
|
261
|
+
endpoint: "/api/proxy/news",
|
|
262
|
+
method: "GET",
|
|
263
|
+
provider: "AgentMarket"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "Currency Exchange",
|
|
267
|
+
slug: "currency",
|
|
268
|
+
description: "Convert between currencies with live rates",
|
|
269
|
+
category: "Finance",
|
|
270
|
+
priceUsdc: 1e-3,
|
|
271
|
+
endpoint: "/api/proxy/currency",
|
|
272
|
+
method: "GET",
|
|
273
|
+
provider: "AgentMarket"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "Geolocation",
|
|
277
|
+
slug: "geolocation",
|
|
278
|
+
description: "Get location data from IP address",
|
|
279
|
+
category: "Geo",
|
|
280
|
+
priceUsdc: 1e-3,
|
|
281
|
+
endpoint: "/api/proxy/geolocation",
|
|
282
|
+
method: "GET",
|
|
283
|
+
provider: "AgentMarket"
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
name: "AI Inference",
|
|
287
|
+
slug: "ai",
|
|
288
|
+
description: "Run AI inference queries (GPT, Claude)",
|
|
289
|
+
category: "AI",
|
|
290
|
+
priceUsdc: 5e-3,
|
|
291
|
+
endpoint: "/api/proxy/ai",
|
|
292
|
+
method: "POST",
|
|
293
|
+
provider: "AgentMarket"
|
|
294
|
+
}
|
|
295
|
+
];
|
|
296
|
+
var _registry = [...FALLBACK_REGISTRY];
|
|
297
|
+
function listApis(category) {
|
|
298
|
+
if (category) {
|
|
299
|
+
return _registry.filter(
|
|
300
|
+
(api) => api.category.toLowerCase() === category.toLowerCase()
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
return _registry;
|
|
304
|
+
}
|
|
305
|
+
function getApiInfo(slug) {
|
|
306
|
+
return _registry.find((api) => api.slug === slug);
|
|
307
|
+
}
|
|
308
|
+
function buildRequest(api, baseUrl, params, headers = {}) {
|
|
309
|
+
const url = new URL(api.endpoint, baseUrl);
|
|
310
|
+
if (api.method === "GET") {
|
|
311
|
+
for (const [key, value] of Object.entries(params)) {
|
|
312
|
+
if (value !== void 0 && value !== null) {
|
|
313
|
+
url.searchParams.set(key, String(value));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return { url: url.toString(), init: { method: "GET", headers } };
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
url: url.toString(),
|
|
320
|
+
init: {
|
|
321
|
+
method: "POST",
|
|
322
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
323
|
+
body: JSON.stringify(params)
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
async function callApi(slug, params, stellarClient) {
|
|
328
|
+
const startTime = Date.now();
|
|
329
|
+
const api = getApiInfo(slug);
|
|
330
|
+
if (!api) {
|
|
331
|
+
return { success: false, error: `API not found: ${slug}` };
|
|
332
|
+
}
|
|
333
|
+
const config = loadConfig();
|
|
334
|
+
const wallet = await stellarClient.getWalletInfo();
|
|
335
|
+
if (!wallet) {
|
|
336
|
+
return { success: false, error: "Wallet not configured. Run: agentmarket init" };
|
|
337
|
+
}
|
|
338
|
+
const usdcBalance = parseFloat(wallet.usdcBalance);
|
|
339
|
+
if (usdcBalance < api.priceUsdc) {
|
|
340
|
+
return {
|
|
341
|
+
success: false,
|
|
342
|
+
error: `Insufficient USDC balance. Need ${api.priceUsdc}, have ${usdcBalance}`
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const baseUrl = config.marketplaceUrl;
|
|
346
|
+
const initialRequest = buildRequest(api, baseUrl, params);
|
|
347
|
+
try {
|
|
348
|
+
const initialResponse = await fetch(initialRequest.url, initialRequest.init);
|
|
349
|
+
if (initialResponse.status === 402) {
|
|
350
|
+
const paymentDetails = await initialResponse.json();
|
|
351
|
+
if (!paymentDetails.payment?.recipient || !paymentDetails.payment?.amount) {
|
|
352
|
+
return { success: false, error: "Invalid 402 response: missing payment recipient or amount" };
|
|
353
|
+
}
|
|
354
|
+
const recipient = paymentDetails.payment.recipient;
|
|
355
|
+
const amount = paymentDetails.payment.amount;
|
|
356
|
+
const memo = paymentDetails.payment?.memo || `am:${slug}:${Date.now()}`;
|
|
357
|
+
const paymentResult = await stellarClient.sendPayment(recipient, amount, memo);
|
|
358
|
+
if (!paymentResult?.success) {
|
|
359
|
+
return { success: false, error: "Payment failed" };
|
|
360
|
+
}
|
|
361
|
+
const paymentProof = JSON.stringify({
|
|
362
|
+
txHash: paymentResult.txHash,
|
|
363
|
+
network: config.stellarNetwork,
|
|
364
|
+
timestamp: Date.now()
|
|
365
|
+
});
|
|
366
|
+
const retryRequest = buildRequest(api, baseUrl, params, {
|
|
367
|
+
"X-Payment-Proof": paymentProof,
|
|
368
|
+
"X-Payment-TxHash": paymentResult.txHash,
|
|
369
|
+
"X-Payment-Network": config.stellarNetwork
|
|
370
|
+
});
|
|
371
|
+
const retryResponse = await fetch(retryRequest.url, retryRequest.init);
|
|
372
|
+
if (!retryResponse.ok) {
|
|
373
|
+
return {
|
|
374
|
+
success: false,
|
|
375
|
+
error: `API call failed: ${retryResponse.status}`,
|
|
376
|
+
txHash: paymentResult.txHash,
|
|
377
|
+
amountPaid: api.priceUsdc
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
const data = await retryResponse.json();
|
|
381
|
+
const latencyMs = Date.now() - startTime;
|
|
382
|
+
appendHistory({
|
|
383
|
+
api: slug,
|
|
384
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
385
|
+
amount: api.priceUsdc,
|
|
386
|
+
txHash: paymentResult.txHash
|
|
387
|
+
});
|
|
388
|
+
return { success: true, data, txHash: paymentResult.txHash, amountPaid: api.priceUsdc, latencyMs };
|
|
389
|
+
}
|
|
390
|
+
if (initialResponse.ok) {
|
|
391
|
+
const data = await initialResponse.json();
|
|
392
|
+
return { success: true, data, latencyMs: Date.now() - startTime };
|
|
393
|
+
}
|
|
394
|
+
return { success: false, error: `Unexpected response: ${initialResponse.status}` };
|
|
395
|
+
} catch (error) {
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
error: `Request failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
403
|
+
0 && (module.exports = {
|
|
404
|
+
StellarClient,
|
|
405
|
+
appendHistory,
|
|
406
|
+
callApi,
|
|
407
|
+
getApiInfo,
|
|
408
|
+
listApis,
|
|
409
|
+
loadConfig,
|
|
410
|
+
loadHistory,
|
|
411
|
+
saveConfig
|
|
412
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agstell-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for AgentMarket — discover and call APIs with x402 micropayments on Stellar",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist/",
|
|
8
|
+
"bin/"
|
|
9
|
+
],
|
|
10
|
+
"bin": {
|
|
11
|
+
"agentmarket": "bin/agentmarket.js",
|
|
12
|
+
"am": "bin/agentmarket.js"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup src/index.ts src/cli.ts --format cjs --dts --clean",
|
|
16
|
+
"dev": "tsup src/cli.ts --format cjs --watch",
|
|
17
|
+
"start": "node dist/cli.js",
|
|
18
|
+
"test": "vitest run"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"cli",
|
|
22
|
+
"agentmarket",
|
|
23
|
+
"stellar",
|
|
24
|
+
"x402",
|
|
25
|
+
"ai-agents",
|
|
26
|
+
"api"
|
|
27
|
+
],
|
|
28
|
+
"author": "AgentMarket",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@stellar/stellar-sdk": "^13.1.0",
|
|
32
|
+
"agstell-sdk": "^0.2.0",
|
|
33
|
+
"chalk": "^5.3.0",
|
|
34
|
+
"commander": "^12.0.0",
|
|
35
|
+
"dotenv": "^16.0.0",
|
|
36
|
+
"inquirer": "^9.2.0",
|
|
37
|
+
"ora": "^8.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/inquirer": "^9.0.0",
|
|
41
|
+
"@types/node": "^22.0.0",
|
|
42
|
+
"tsup": "^8.3.0",
|
|
43
|
+
"typescript": "^5.7.0",
|
|
44
|
+
"vitest": "^2.1.0"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|