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.
@@ -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 };
package/dist/index.js ADDED
@@ -0,0 +1,254 @@
1
+ // src/constants.ts
2
+ var BASE_URL = "https://api.agentmall.sh";
3
+ var SERVICE_FEE_CENTS = 150;
4
+ var SUPPORTED_RETAILERS = [
5
+ "amazon.com",
6
+ "walmart.com",
7
+ "target.com",
8
+ "bestbuy.com",
9
+ "homedepot.com",
10
+ "ebay.com",
11
+ "lowes.com",
12
+ "wayfair.com",
13
+ "acehardware.com",
14
+ "1800flowers.com",
15
+ "pokemoncenter.com"
16
+ ];
17
+
18
+ // src/errors.ts
19
+ var AgentMallError = class extends Error {
20
+ status;
21
+ body;
22
+ constructor(status, body) {
23
+ const message = typeof body === "object" && body !== null && "error" in body ? body.error : `Request failed with status ${status}`;
24
+ super(message);
25
+ this.name = "AgentMallError";
26
+ this.status = status;
27
+ this.body = body;
28
+ }
29
+ };
30
+ var RateLimitError = class extends AgentMallError {
31
+ retryAfterMs;
32
+ constructor(body, retryAfterMs) {
33
+ super(429, body);
34
+ this.name = "RateLimitError";
35
+ this.retryAfterMs = retryAfterMs;
36
+ }
37
+ };
38
+ var PaymentRequiredError = class extends AgentMallError {
39
+ headers;
40
+ constructor(body, headers) {
41
+ super(402, body);
42
+ this.name = "PaymentRequiredError";
43
+ this.headers = headers;
44
+ }
45
+ };
46
+ var ValidationError = class extends AgentMallError {
47
+ constructor(body) {
48
+ super(400, body);
49
+ this.name = "ValidationError";
50
+ }
51
+ };
52
+ var ConflictError = class extends AgentMallError {
53
+ constructor(body) {
54
+ super(409, body);
55
+ this.name = "ConflictError";
56
+ }
57
+ };
58
+
59
+ // src/client.ts
60
+ function createIdempotencyKey() {
61
+ return globalThis.crypto?.randomUUID?.() ?? `agentmall_${Date.now()}_${Math.random().toString(16).slice(2)}`;
62
+ }
63
+ var AgentMall = class {
64
+ baseUrl;
65
+ apiSecret;
66
+ _fetch;
67
+ products;
68
+ purchases;
69
+ payments;
70
+ refunds;
71
+ constructor(config = {}) {
72
+ this.baseUrl = (config.baseUrl ?? BASE_URL).replace(/\/$/, "");
73
+ this.apiSecret = config.apiSecret;
74
+ this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);
75
+ this.products = new AgentMallProducts(this);
76
+ this.purchases = new AgentMallPurchases(this);
77
+ this.payments = new AgentMallPayments(this);
78
+ this.refunds = new AgentMallRefunds(this);
79
+ }
80
+ /** @internal */
81
+ async request(method, path, options) {
82
+ const url = new URL(`${this.baseUrl}${path}`);
83
+ if (options?.params) {
84
+ for (const [key, value] of Object.entries(options.params)) {
85
+ if (value !== void 0) url.searchParams.set(key, value);
86
+ }
87
+ }
88
+ const headers = { ...options?.headers ?? {} };
89
+ if (options?.auth) {
90
+ if (!this.apiSecret) {
91
+ throw new Error("apiSecret is required for this endpoint");
92
+ }
93
+ headers["Authorization"] = `Bearer ${this.apiSecret}`;
94
+ }
95
+ if (options?.body) {
96
+ headers["Content-Type"] = "application/json";
97
+ }
98
+ const response = await this._fetch(url.toString(), {
99
+ method,
100
+ headers,
101
+ body: options?.body ? JSON.stringify(options.body) : void 0
102
+ });
103
+ if (!response.ok) {
104
+ let body;
105
+ try {
106
+ body = await response.json();
107
+ } catch {
108
+ body = await response.text().catch(() => null);
109
+ }
110
+ if (response.status === 429) {
111
+ const retryAfter = response.headers.get("Retry-After");
112
+ const retryMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : 6e4;
113
+ throw new RateLimitError(body, retryMs);
114
+ }
115
+ if (response.status === 402) {
116
+ throw new PaymentRequiredError(body, response.headers);
117
+ }
118
+ if (response.status === 400) {
119
+ throw new ValidationError(body);
120
+ }
121
+ if (response.status === 409) {
122
+ throw new ConflictError(body);
123
+ }
124
+ throw new AgentMallError(response.status, body);
125
+ }
126
+ return await response.json();
127
+ }
128
+ };
129
+ var AgentMallProducts = class {
130
+ constructor(client) {
131
+ this.client = client;
132
+ }
133
+ /** Look up product info by URL. Returns price, availability, variants, and suggested max_budget. */
134
+ async lookup(url) {
135
+ return this.client.request("GET", "/api/products", {
136
+ params: { url }
137
+ });
138
+ }
139
+ };
140
+ var AgentMallPurchases = class {
141
+ constructor(client) {
142
+ this.client = client;
143
+ }
144
+ /**
145
+ * Create a purchase. The first call returns a 402 MPP payment challenge.
146
+ * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
147
+ */
148
+ async create(body) {
149
+ const idempotencyKey = body.idempotency_key ?? createIdempotencyKey();
150
+ return this.client.request("POST", "/api/purchases", {
151
+ body: {
152
+ ...body,
153
+ idempotency_key: idempotencyKey
154
+ },
155
+ headers: {
156
+ "X-Idempotency-Key": idempotencyKey
157
+ }
158
+ });
159
+ }
160
+ /** Get a single purchase by ID. Requires apiSecret. */
161
+ async get(id) {
162
+ return this.client.request("GET", "/api/purchases", {
163
+ auth: true,
164
+ params: { id }
165
+ });
166
+ }
167
+ /** List purchases. Requires apiSecret. */
168
+ async list(filters) {
169
+ const result = await this.client.request(
170
+ "GET",
171
+ "/api/purchases",
172
+ { auth: true, params: filters }
173
+ );
174
+ return result.purchases;
175
+ }
176
+ };
177
+ var AgentMallPayments = class {
178
+ constructor(client) {
179
+ this.client = client;
180
+ }
181
+ /** Get a single payment by ID. Requires apiSecret. */
182
+ async get(id) {
183
+ return this.client.request("GET", "/api/payments", {
184
+ auth: true,
185
+ params: { id }
186
+ });
187
+ }
188
+ /** List payments. Requires apiSecret. */
189
+ async list(filters) {
190
+ const result = await this.client.request(
191
+ "GET",
192
+ "/api/payments",
193
+ { auth: true, params: filters }
194
+ );
195
+ return result.payments;
196
+ }
197
+ };
198
+ var AgentMallRefunds = class {
199
+ constructor(client) {
200
+ this.client = client;
201
+ }
202
+ /** Get a single refund by public ID. Requires apiSecret. */
203
+ async get(id) {
204
+ return this.client.request("GET", "/api/refunds", {
205
+ auth: true,
206
+ params: { id }
207
+ });
208
+ }
209
+ /** List refunds. Requires apiSecret. */
210
+ async list(filters) {
211
+ const result = await this.client.request(
212
+ "GET",
213
+ "/api/refunds",
214
+ { auth: true, params: filters }
215
+ );
216
+ return result.refunds;
217
+ }
218
+ };
219
+
220
+ // src/purchase.ts
221
+ async function purchase(config) {
222
+ const { account, baseUrl, ...body } = config;
223
+ let mppxClient;
224
+ try {
225
+ mppxClient = await import("mppx/client");
226
+ } catch {
227
+ throw new Error("mppx is required for purchases. Install it: npm install mppx");
228
+ }
229
+ const Mppx = mppxClient.Mppx;
230
+ const tempo = mppxClient.tempo;
231
+ if (!Mppx || !tempo) {
232
+ throw new Error("mppx is required for purchases. Install it: npm install mppx");
233
+ }
234
+ const mppx = Mppx.create({
235
+ methods: [tempo({ account })]
236
+ });
237
+ const client = new AgentMall({
238
+ baseUrl: baseUrl ?? BASE_URL,
239
+ fetch: mppx.fetch.bind(mppx)
240
+ });
241
+ return client.purchases.create(body);
242
+ }
243
+ export {
244
+ AgentMall,
245
+ AgentMallError,
246
+ BASE_URL,
247
+ ConflictError,
248
+ PaymentRequiredError,
249
+ RateLimitError,
250
+ SERVICE_FEE_CENTS,
251
+ SUPPORTED_RETAILERS,
252
+ ValidationError,
253
+ purchase
254
+ };
package/package.json CHANGED
@@ -1,17 +1,45 @@
1
1
  {
2
2
  "name": "agentmall",
3
- "version": "0.0.1",
4
- "description": "Universal checkout for AI agents. Buy any item with a URL, pay with stablecoins via MPP or x402.",
5
- "keywords": ["ai", "agents", "checkout", "mpp", "x402", "stablecoins", "ecommerce"],
6
- "author": "signetsai",
7
- "license": "MIT",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/signetsai/agentmall"
3
+ "version": "0.1.1",
4
+ "description": "SDK and CLI for the AgentMall API let AI agents buy physical products from US retailers",
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
+ "require": "./dist/index.cjs"
13
+ }
11
14
  },
12
- "homepage": "https://agentmall.com",
13
15
  "bin": {
14
- "agentmall": "./bin/cli.js"
16
+ "agentmall": "dist/cli.js"
15
17
  },
16
- "main": "index.js"
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch"
26
+ },
27
+ "dependencies": {
28
+ "mppx": "^0.4.7",
29
+ "viem": "^2.47.5",
30
+ "@inquirer/prompts": "^7.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "tsup": "^8.0.0",
34
+ "typescript": "^5"
35
+ },
36
+ "keywords": [
37
+ "agentmall",
38
+ "ai",
39
+ "agent",
40
+ "ecommerce",
41
+ "mpp",
42
+ "checkout"
43
+ ],
44
+ "license": "MIT"
17
45
  }
package/bin/cli.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- console.log("agentmall v0.0.1 — coming soon")
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = {}