agentmall 0.0.1 → 0.1.1

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/dist/index.cjs ADDED
@@ -0,0 +1,300 @@
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
+ AgentMall: () => AgentMall,
34
+ AgentMallError: () => AgentMallError,
35
+ BASE_URL: () => BASE_URL,
36
+ ConflictError: () => ConflictError,
37
+ PaymentRequiredError: () => PaymentRequiredError,
38
+ RateLimitError: () => RateLimitError,
39
+ SERVICE_FEE_CENTS: () => SERVICE_FEE_CENTS,
40
+ SUPPORTED_RETAILERS: () => SUPPORTED_RETAILERS,
41
+ ValidationError: () => ValidationError,
42
+ purchase: () => purchase
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+
46
+ // src/constants.ts
47
+ var BASE_URL = "https://api.agentmall.sh";
48
+ var SERVICE_FEE_CENTS = 150;
49
+ var SUPPORTED_RETAILERS = [
50
+ "amazon.com",
51
+ "walmart.com",
52
+ "target.com",
53
+ "bestbuy.com",
54
+ "homedepot.com",
55
+ "ebay.com",
56
+ "lowes.com",
57
+ "wayfair.com",
58
+ "acehardware.com",
59
+ "1800flowers.com",
60
+ "pokemoncenter.com"
61
+ ];
62
+
63
+ // src/errors.ts
64
+ var AgentMallError = class extends Error {
65
+ status;
66
+ body;
67
+ constructor(status, body) {
68
+ const message = typeof body === "object" && body !== null && "error" in body ? body.error : `Request failed with status ${status}`;
69
+ super(message);
70
+ this.name = "AgentMallError";
71
+ this.status = status;
72
+ this.body = body;
73
+ }
74
+ };
75
+ var RateLimitError = class extends AgentMallError {
76
+ retryAfterMs;
77
+ constructor(body, retryAfterMs) {
78
+ super(429, body);
79
+ this.name = "RateLimitError";
80
+ this.retryAfterMs = retryAfterMs;
81
+ }
82
+ };
83
+ var PaymentRequiredError = class extends AgentMallError {
84
+ headers;
85
+ constructor(body, headers) {
86
+ super(402, body);
87
+ this.name = "PaymentRequiredError";
88
+ this.headers = headers;
89
+ }
90
+ };
91
+ var ValidationError = class extends AgentMallError {
92
+ constructor(body) {
93
+ super(400, body);
94
+ this.name = "ValidationError";
95
+ }
96
+ };
97
+ var ConflictError = class extends AgentMallError {
98
+ constructor(body) {
99
+ super(409, body);
100
+ this.name = "ConflictError";
101
+ }
102
+ };
103
+
104
+ // src/client.ts
105
+ function createIdempotencyKey() {
106
+ return globalThis.crypto?.randomUUID?.() ?? `agentmall_${Date.now()}_${Math.random().toString(16).slice(2)}`;
107
+ }
108
+ var AgentMall = class {
109
+ baseUrl;
110
+ apiSecret;
111
+ _fetch;
112
+ products;
113
+ purchases;
114
+ payments;
115
+ refunds;
116
+ constructor(config = {}) {
117
+ this.baseUrl = (config.baseUrl ?? BASE_URL).replace(/\/$/, "");
118
+ this.apiSecret = config.apiSecret;
119
+ this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);
120
+ this.products = new AgentMallProducts(this);
121
+ this.purchases = new AgentMallPurchases(this);
122
+ this.payments = new AgentMallPayments(this);
123
+ this.refunds = new AgentMallRefunds(this);
124
+ }
125
+ /** @internal */
126
+ async request(method, path, options) {
127
+ const url = new URL(`${this.baseUrl}${path}`);
128
+ if (options?.params) {
129
+ for (const [key, value] of Object.entries(options.params)) {
130
+ if (value !== void 0) url.searchParams.set(key, value);
131
+ }
132
+ }
133
+ const headers = { ...options?.headers ?? {} };
134
+ if (options?.auth) {
135
+ if (!this.apiSecret) {
136
+ throw new Error("apiSecret is required for this endpoint");
137
+ }
138
+ headers["Authorization"] = `Bearer ${this.apiSecret}`;
139
+ }
140
+ if (options?.body) {
141
+ headers["Content-Type"] = "application/json";
142
+ }
143
+ const response = await this._fetch(url.toString(), {
144
+ method,
145
+ headers,
146
+ body: options?.body ? JSON.stringify(options.body) : void 0
147
+ });
148
+ if (!response.ok) {
149
+ let body;
150
+ try {
151
+ body = await response.json();
152
+ } catch {
153
+ body = await response.text().catch(() => null);
154
+ }
155
+ if (response.status === 429) {
156
+ const retryAfter = response.headers.get("Retry-After");
157
+ const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : 6e4;
158
+ throw new RateLimitError(body, retryMs);
159
+ }
160
+ if (response.status === 402) {
161
+ throw new PaymentRequiredError(body, response.headers);
162
+ }
163
+ if (response.status === 400) {
164
+ throw new ValidationError(body);
165
+ }
166
+ if (response.status === 409) {
167
+ throw new ConflictError(body);
168
+ }
169
+ throw new AgentMallError(response.status, body);
170
+ }
171
+ return await response.json();
172
+ }
173
+ };
174
+ var AgentMallProducts = class {
175
+ constructor(client) {
176
+ this.client = client;
177
+ }
178
+ /** Look up product info by URL. Returns price, availability, variants, and suggested max_budget. */
179
+ async lookup(url) {
180
+ return this.client.request("GET", "/api/products", {
181
+ params: { url }
182
+ });
183
+ }
184
+ };
185
+ var AgentMallPurchases = class {
186
+ constructor(client) {
187
+ this.client = client;
188
+ }
189
+ /**
190
+ * Create a purchase. The first call returns a 402 MPP payment challenge.
191
+ * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
192
+ */
193
+ async create(body) {
194
+ const idempotencyKey = body.idempotency_key ?? createIdempotencyKey();
195
+ return this.client.request("POST", "/api/purchases", {
196
+ body: {
197
+ ...body,
198
+ idempotency_key: idempotencyKey
199
+ },
200
+ headers: {
201
+ "X-Idempotency-Key": idempotencyKey
202
+ }
203
+ });
204
+ }
205
+ /** Get a single purchase by ID. Requires apiSecret. */
206
+ async get(id) {
207
+ return this.client.request("GET", "/api/purchases", {
208
+ auth: true,
209
+ params: { id }
210
+ });
211
+ }
212
+ /** List purchases. Requires apiSecret. */
213
+ async list(filters) {
214
+ const result = await this.client.request(
215
+ "GET",
216
+ "/api/purchases",
217
+ { auth: true, params: filters }
218
+ );
219
+ return result.purchases;
220
+ }
221
+ };
222
+ var AgentMallPayments = class {
223
+ constructor(client) {
224
+ this.client = client;
225
+ }
226
+ /** Get a single payment by ID. Requires apiSecret. */
227
+ async get(id) {
228
+ return this.client.request("GET", "/api/payments", {
229
+ auth: true,
230
+ params: { id }
231
+ });
232
+ }
233
+ /** List payments. Requires apiSecret. */
234
+ async list(filters) {
235
+ const result = await this.client.request(
236
+ "GET",
237
+ "/api/payments",
238
+ { auth: true, params: filters }
239
+ );
240
+ return result.payments;
241
+ }
242
+ };
243
+ var AgentMallRefunds = class {
244
+ constructor(client) {
245
+ this.client = client;
246
+ }
247
+ /** Get a single refund by public ID. Requires apiSecret. */
248
+ async get(id) {
249
+ return this.client.request("GET", "/api/refunds", {
250
+ auth: true,
251
+ params: { id }
252
+ });
253
+ }
254
+ /** List refunds. Requires apiSecret. */
255
+ async list(filters) {
256
+ const result = await this.client.request(
257
+ "GET",
258
+ "/api/refunds",
259
+ { auth: true, params: filters }
260
+ );
261
+ return result.refunds;
262
+ }
263
+ };
264
+
265
+ // src/purchase.ts
266
+ async function purchase(config) {
267
+ const { account, baseUrl, ...body } = config;
268
+ let mppxClient;
269
+ try {
270
+ mppxClient = await import("mppx/client");
271
+ } catch {
272
+ throw new Error("mppx is required for purchases. Install it: npm install mppx");
273
+ }
274
+ const Mppx = mppxClient.Mppx;
275
+ const tempo = mppxClient.tempo;
276
+ if (!Mppx || !tempo) {
277
+ throw new Error("mppx is required for purchases. Install it: npm install mppx");
278
+ }
279
+ const mppx = Mppx.create({
280
+ methods: [tempo({ account })]
281
+ });
282
+ const client = new AgentMall({
283
+ baseUrl: baseUrl ?? BASE_URL,
284
+ fetch: mppx.fetch.bind(mppx)
285
+ });
286
+ return client.purchases.create(body);
287
+ }
288
+ // Annotate the CommonJS export names for ESM import in node:
289
+ 0 && (module.exports = {
290
+ AgentMall,
291
+ AgentMallError,
292
+ BASE_URL,
293
+ ConflictError,
294
+ PaymentRequiredError,
295
+ RateLimitError,
296
+ SERVICE_FEE_CENTS,
297
+ SUPPORTED_RETAILERS,
298
+ ValidationError,
299
+ purchase
300
+ });
@@ -0,0 +1,233 @@
1
+ type AgentMallConfig = {
2
+ /** API base URL. Defaults to https://api.agentmall.sh */
3
+ baseUrl?: string;
4
+ /** Operator API secret for read endpoints (Bearer auth). */
5
+ apiSecret?: string;
6
+ /** Custom fetch implementation (e.g. mppx-wrapped fetch for automatic 402 handling). */
7
+ fetch?: typeof globalThis.fetch;
8
+ };
9
+ type ProductVariant = {
10
+ label?: string;
11
+ value: string;
12
+ /** Price in dollars. */
13
+ price: number;
14
+ url?: string;
15
+ };
16
+ type ProductLookup = {
17
+ title: string;
18
+ /** Current/sale price in cents. */
19
+ price: number;
20
+ /** Original list price in cents (before discount). */
21
+ listPrice?: number;
22
+ /** Discount percentage (e.g. 13 for -13% off). */
23
+ discountPercent?: number;
24
+ currency: string;
25
+ availability: string;
26
+ imageUrl?: string;
27
+ retailer: string;
28
+ /** Suggested max_budget in cents (list price + 15% buffer). */
29
+ suggestedMaxBudget: number;
30
+ variants?: ProductVariant[];
31
+ /** True if served from cache. Price may not reflect current listing. */
32
+ cached?: boolean;
33
+ };
34
+ type VariantSelection = {
35
+ label: string;
36
+ value: string;
37
+ };
38
+ type PurchaseItemInput = {
39
+ product_url: string;
40
+ quantity?: number;
41
+ variant?: VariantSelection[];
42
+ };
43
+ type DeliveryAddress = {
44
+ first_name: string;
45
+ last_name: string;
46
+ address_line1: string;
47
+ address_line2?: string;
48
+ city: string;
49
+ state?: string;
50
+ postal_code: string;
51
+ phone_number: string;
52
+ country: string;
53
+ };
54
+ type CreatePurchaseRequest = {
55
+ items: PurchaseItemInput[];
56
+ delivery_address: DeliveryAddress;
57
+ max_budget: number;
58
+ buyer_email: string;
59
+ idempotency_key?: string;
60
+ metadata?: unknown;
61
+ };
62
+ type PurchaseLifecycleStatus = "payment_received" | "submitted" | "pending" | "completed" | "failed";
63
+ type CreatePurchaseResponse = {
64
+ id: string;
65
+ status: PurchaseLifecycleStatus;
66
+ deduplicated?: boolean;
67
+ };
68
+ type PurchaseItem = {
69
+ productRef: string;
70
+ quantity: number;
71
+ title?: string;
72
+ price?: number;
73
+ variant?: VariantSelection[];
74
+ };
75
+ type Purchase = {
76
+ id: string;
77
+ status: PurchaseLifecycleStatus;
78
+ items: PurchaseItem[];
79
+ deliveryMethod?: string;
80
+ maxBudget: number;
81
+ finalTotal?: number;
82
+ merchantReferences?: string[];
83
+ failureReason?: string;
84
+ paymentMethod?: string;
85
+ metadata?: unknown;
86
+ createdAt: number;
87
+ updatedAt: number;
88
+ };
89
+ type PurchaseFilters = {
90
+ status?: string;
91
+ lifecycle_status?: PurchaseLifecycleStatus;
92
+ };
93
+ type Payment = {
94
+ id: string;
95
+ purchaseId?: string;
96
+ idempotencyKey?: string;
97
+ amountCents: number;
98
+ currency: string;
99
+ network: string;
100
+ chainId?: string;
101
+ status: string;
102
+ paymentMethod: string;
103
+ paymentRef?: string;
104
+ payerAddress?: string;
105
+ receiptMethod?: string;
106
+ receiptStatus?: string;
107
+ receiptTimestamp?: string;
108
+ createdAt: number;
109
+ updatedAt: number;
110
+ };
111
+ type PaymentFilters = {
112
+ purchase_id?: string;
113
+ status?: string;
114
+ };
115
+ type Refund = {
116
+ id: string;
117
+ purchaseId: string;
118
+ payerAddress: string;
119
+ amountCents: number;
120
+ reason: string;
121
+ status: string;
122
+ txHash?: string;
123
+ createdAt: number;
124
+ processedAt?: number;
125
+ };
126
+ type RefundFilters = {
127
+ purchase_id?: string;
128
+ status?: string;
129
+ };
130
+
131
+ declare class AgentMall {
132
+ private baseUrl;
133
+ private apiSecret?;
134
+ private _fetch;
135
+ products: AgentMallProducts;
136
+ purchases: AgentMallPurchases;
137
+ payments: AgentMallPayments;
138
+ refunds: AgentMallRefunds;
139
+ constructor(config?: AgentMallConfig);
140
+ /** @internal */
141
+ request<T>(method: string, path: string, options?: {
142
+ body?: unknown;
143
+ auth?: boolean;
144
+ params?: Record<string, string | undefined>;
145
+ headers?: Record<string, string>;
146
+ }): Promise<T>;
147
+ }
148
+ declare class AgentMallProducts {
149
+ private client;
150
+ constructor(client: AgentMall);
151
+ /** Look up product info by URL. Returns price, availability, variants, and suggested max_budget. */
152
+ lookup(url: string): Promise<ProductLookup>;
153
+ }
154
+ declare class AgentMallPurchases {
155
+ private client;
156
+ constructor(client: AgentMall);
157
+ /**
158
+ * Create a purchase. The first call returns a 402 MPP payment challenge.
159
+ * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
160
+ */
161
+ create(body: CreatePurchaseRequest): Promise<CreatePurchaseResponse>;
162
+ /** Get a single purchase by ID. Requires apiSecret. */
163
+ get(id: string): Promise<Purchase>;
164
+ /** List purchases. Requires apiSecret. */
165
+ list(filters?: PurchaseFilters): Promise<Purchase[]>;
166
+ }
167
+ declare class AgentMallPayments {
168
+ private client;
169
+ constructor(client: AgentMall);
170
+ /** Get a single payment by ID. Requires apiSecret. */
171
+ get(id: string): Promise<Payment>;
172
+ /** List payments. Requires apiSecret. */
173
+ list(filters?: PaymentFilters): Promise<Payment[]>;
174
+ }
175
+ declare class AgentMallRefunds {
176
+ private client;
177
+ constructor(client: AgentMall);
178
+ /** Get a single refund by public ID. Requires apiSecret. */
179
+ get(id: string): Promise<Refund>;
180
+ /** List refunds. Requires apiSecret. */
181
+ list(filters?: RefundFilters): Promise<Refund[]>;
182
+ }
183
+
184
+ type PurchaseConfig = CreatePurchaseRequest & {
185
+ /** viem Account for MPP payment (from privateKeyToAccount or mppx resolveAccount). */
186
+ account: unknown;
187
+ /** API base URL. Defaults to https://api.agentmall.sh */
188
+ baseUrl?: string;
189
+ };
190
+ /**
191
+ * High-level purchase helper that handles the full 402→pay→retry flow.
192
+ * Requires mppx to be installed.
193
+ *
194
+ * ```ts
195
+ * import { purchase } from 'agentmall'
196
+ * import { privateKeyToAccount } from 'viem/accounts'
197
+ *
198
+ * const account = privateKeyToAccount('0x...')
199
+ * const order = await purchase({
200
+ * account,
201
+ * items: [{ product_url: 'https://amazon.com/dp/...', quantity: 1 }],
202
+ * delivery_address: { ... },
203
+ * max_budget: 9085,
204
+ * })
205
+ * ```
206
+ */
207
+ declare function purchase(config: PurchaseConfig): Promise<CreatePurchaseResponse>;
208
+
209
+ declare class AgentMallError extends Error {
210
+ status: number;
211
+ body: unknown;
212
+ constructor(status: number, body: unknown);
213
+ }
214
+ declare class RateLimitError extends AgentMallError {
215
+ retryAfterMs: number;
216
+ constructor(body: unknown, retryAfterMs: number);
217
+ }
218
+ declare class PaymentRequiredError extends AgentMallError {
219
+ headers: Headers;
220
+ constructor(body: unknown, headers: Headers);
221
+ }
222
+ declare class ValidationError extends AgentMallError {
223
+ constructor(body: unknown);
224
+ }
225
+ declare class ConflictError extends AgentMallError {
226
+ constructor(body: unknown);
227
+ }
228
+
229
+ declare const BASE_URL = "https://api.agentmall.sh";
230
+ declare const SERVICE_FEE_CENTS = 150;
231
+ declare const SUPPORTED_RETAILERS: readonly ["amazon.com", "walmart.com", "target.com", "bestbuy.com", "homedepot.com", "ebay.com", "lowes.com", "wayfair.com", "acehardware.com", "1800flowers.com", "pokemoncenter.com"];
232
+
233
+ export { AgentMall, type AgentMallConfig, AgentMallError, BASE_URL, ConflictError, type CreatePurchaseRequest, type CreatePurchaseResponse, type DeliveryAddress, type Payment, type PaymentFilters, PaymentRequiredError, type ProductLookup, type ProductVariant, type Purchase, type PurchaseFilters, type PurchaseItem, type PurchaseItemInput, type PurchaseLifecycleStatus, RateLimitError, type Refund, type RefundFilters, SERVICE_FEE_CENTS, SUPPORTED_RETAILERS, ValidationError, type VariantSelection, purchase };