agentmall 0.1.20 → 0.1.22

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/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { spawn } from "child_process";
5
+ import { privateKeyToAccount } from "viem/accounts";
5
6
 
6
7
  // src/constants.ts
7
8
  var BASE_URL = "https://api.agentmall.sh";
@@ -73,6 +74,7 @@ var AgentMall = class {
73
74
  purchases;
74
75
  payments;
75
76
  refunds;
77
+ storeAccounts;
76
78
  managedAccounts;
77
79
  constructor(config = {}) {
78
80
  this.baseUrl = (config.baseUrl ?? BASE_URL).replace(/\/$/, "");
@@ -82,7 +84,8 @@ var AgentMall = class {
82
84
  this.purchases = new AgentMallPurchases(this);
83
85
  this.payments = new AgentMallPayments(this);
84
86
  this.refunds = new AgentMallRefunds(this);
85
- this.managedAccounts = new AgentMallManagedAccounts(this);
87
+ this.storeAccounts = new AgentMallStoreAccounts(this);
88
+ this.managedAccounts = this.storeAccounts;
86
89
  }
87
90
  /** @internal */
88
91
  hasApiSecret() {
@@ -140,6 +143,25 @@ var AgentMall = class {
140
143
  return await response.json();
141
144
  }
142
145
  };
146
+ async function createStoreAccountHeaders(client, account) {
147
+ const challenge = await client.request(
148
+ "POST",
149
+ "/api/managed-accounts/challenge",
150
+ {
151
+ body: {
152
+ address: account.address
153
+ }
154
+ }
155
+ );
156
+ const signature = await account.signMessage({
157
+ message: challenge.message
158
+ });
159
+ return {
160
+ "X-AgentMall-Wallet-Address": account.address,
161
+ "X-AgentMall-Auth-Challenge": challenge.challenge,
162
+ "X-AgentMall-Auth-Signature": signature
163
+ };
164
+ }
143
165
  var AgentMallProducts = class {
144
166
  constructor(client) {
145
167
  this.client = client;
@@ -159,35 +181,41 @@ var AgentMallPurchases = class {
159
181
  * Create a purchase. The first call returns a 402 MPP payment challenge.
160
182
  * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
161
183
  */
162
- async create(body) {
184
+ async create(body, options) {
163
185
  const idempotencyKey = body.idempotency_key ?? createIdempotencyKey();
186
+ const storeAccountId = body.store_account_id ?? body.retailer_credentials_id;
187
+ const headers = {
188
+ ...storeAccountId && options?.account ? await createStoreAccountHeaders(this.client, options.account) : {},
189
+ "X-Idempotency-Key": idempotencyKey
190
+ };
164
191
  return this.client.request("POST", "/api/purchases", {
165
192
  body: {
166
193
  ...body,
194
+ ...storeAccountId ? { retailer_credentials_id: storeAccountId } : {},
167
195
  idempotency_key: idempotencyKey
168
196
  },
169
- headers: {
170
- "X-Idempotency-Key": idempotencyKey
171
- }
197
+ headers
172
198
  });
173
199
  }
174
200
  /** Get a single purchase by ID using either operator auth or a buyer token. */
175
201
  async get(id, options) {
176
202
  if (options?.buyerToken) {
177
- return this.client.request("POST", "/api/purchases/status", {
203
+ const purchase2 = await this.client.request("POST", "/api/purchases/status", {
178
204
  body: {
179
205
  id,
180
206
  buyer_token: options.buyerToken
181
207
  }
182
208
  });
209
+ return normalizePurchase(purchase2);
183
210
  }
184
211
  if (!this.client.hasApiSecret()) {
185
212
  throw new Error("buyerToken or apiSecret is required for this endpoint");
186
213
  }
187
- return this.client.request("GET", "/api/purchases", {
214
+ const purchase = await this.client.request("GET", "/api/purchases", {
188
215
  auth: true,
189
216
  params: { id }
190
217
  });
218
+ return normalizePurchase(purchase);
191
219
  }
192
220
  /** List purchases. Requires apiSecret. */
193
221
  async list(filters) {
@@ -196,7 +224,7 @@ var AgentMallPurchases = class {
196
224
  "/api/purchases",
197
225
  { auth: true, params: filters }
198
226
  );
199
- return result.purchases;
227
+ return result.purchases.map(normalizePurchase);
200
228
  }
201
229
  };
202
230
  var AgentMallPayments = class {
@@ -268,51 +296,41 @@ var AgentMallRefunds = class {
268
296
  return result.refunds;
269
297
  }
270
298
  };
271
- var AgentMallManagedAccounts = class {
299
+ function normalizePurchase(purchase) {
300
+ return {
301
+ ...purchase,
302
+ ...purchase.storeAccountId ? {} : purchase.retailerCredentialsId ? { storeAccountId: purchase.retailerCredentialsId } : {}
303
+ };
304
+ }
305
+ var AgentMallStoreAccounts = class {
272
306
  constructor(client) {
273
307
  this.client = client;
274
308
  }
275
309
  async walletHeaders(account) {
276
- const challenge = await this.client.request(
277
- "POST",
278
- "/api/managed-accounts/challenge",
279
- {
280
- body: {
281
- address: account.address
282
- }
283
- }
284
- );
285
- const signature = await account.signMessage({
286
- message: challenge.message
287
- });
288
- return {
289
- "X-AgentMall-Wallet-Address": account.address,
290
- "X-AgentMall-Auth-Challenge": challenge.challenge,
291
- "X-AgentMall-Auth-Signature": signature
292
- };
310
+ return createStoreAccountHeaders(this.client, account);
293
311
  }
294
- /** List managed retailer accounts. Requires either apiSecret or a wallet signer. */
312
+ /** List your store accounts. Requires either apiSecret or a wallet signer. */
295
313
  async list(options) {
296
314
  const result = await this.client.request("GET", "/api/managed-accounts", {
297
315
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true }
298
316
  });
299
317
  return result.credentials;
300
318
  }
301
- /** Create a managed retailer account. Requires either apiSecret or a wallet signer. */
319
+ /** Create a store account. Requires either apiSecret or a wallet signer. */
302
320
  async create(body, options) {
303
321
  return this.client.request("POST", "/api/managed-accounts", {
304
322
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
305
323
  body
306
324
  });
307
325
  }
308
- /** Update a managed retailer account. Requires either apiSecret or a wallet signer. */
326
+ /** Update a store account. Requires either apiSecret or a wallet signer. */
309
327
  async update(body, options) {
310
328
  return this.client.request("PUT", "/api/managed-accounts", {
311
329
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
312
330
  body
313
331
  });
314
332
  }
315
- /** Delete a managed retailer account. Requires either apiSecret or a wallet signer. */
333
+ /** Delete a store account. Requires either apiSecret or a wallet signer. */
316
334
  async delete(shortId, options) {
317
335
  await this.client.request("DELETE", "/api/managed-accounts", {
318
336
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
@@ -690,6 +708,13 @@ function displayOrderSummary(body) {
690
708
  line(
691
709
  `${addr.city}, ${addr.state ?? ""} ${addr.postal_code} ${addr.country}`
692
710
  );
711
+ if (body.store_account_id || body.retailer_credentials_id) {
712
+ gap();
713
+ kv(
714
+ "Store account",
715
+ `${c.bold}${body.store_account_id ?? body.retailer_credentials_id}${c.reset}`
716
+ );
717
+ }
693
718
  }
694
719
  function displayOrderResult(order) {
695
720
  gap();
@@ -772,6 +797,35 @@ function displayRefund(refund2) {
772
797
  }
773
798
  gap();
774
799
  }
800
+ function formatTimestamp(value) {
801
+ return new Date(value).toLocaleString();
802
+ }
803
+ function displayStoreAccount(account, opts) {
804
+ section(opts?.title ?? `Store Account ${account.short_id}`);
805
+ kv("Short ID", account.short_id);
806
+ kv("Retailer", account.retailer ?? "default");
807
+ kv("Email", account.email);
808
+ kv("2FA", account.has_totp ? "configured" : "not set", {
809
+ color: account.has_totp ? c.green : c.yellow
810
+ });
811
+ kv("Forwarding", account.has_forwarding ? "ready" : "pending", {
812
+ color: account.has_forwarding ? c.green : c.yellow
813
+ });
814
+ kv("Forward Email", account.forwarding_email, { dim: true });
815
+ kv("Created", formatTimestamp(account.created_at), { dim: true });
816
+ kv("Updated", formatTimestamp(account.updated_at), { dim: true });
817
+ }
818
+ function displayStoreAccounts(accounts) {
819
+ section("Store Accounts");
820
+ if (accounts.length === 0) {
821
+ line("No store accounts found.");
822
+ return;
823
+ }
824
+ kv("Total", String(accounts.length));
825
+ for (const account of accounts) {
826
+ displayStoreAccount(account);
827
+ }
828
+ }
775
829
 
776
830
  // src/cli/prompts.ts
777
831
  import { input, confirm, select } from "@inquirer/prompts";
@@ -965,6 +1019,17 @@ function parseTempoBalance(balance) {
965
1019
  function formatUsdcNumber(amount) {
966
1020
  return amount.toFixed(6).replace(/\.?0+$/, "");
967
1021
  }
1022
+ function createIdempotencyKey2() {
1023
+ return globalThis.crypto?.randomUUID?.() ?? `agentmall_${Date.now()}_${Math.random().toString(16).slice(2)}`;
1024
+ }
1025
+ function normalizeAddress(value) {
1026
+ const trimmed = value?.trim();
1027
+ return trimmed ? trimmed.toLowerCase() : void 0;
1028
+ }
1029
+ function formatAddress(address) {
1030
+ if (!address) return null;
1031
+ return `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
1032
+ }
968
1033
  async function runCommandCapture(command2, args2, envOverrides) {
969
1034
  return await new Promise((resolve, reject) => {
970
1035
  const child = spawn(command2, args2, {
@@ -1017,6 +1082,15 @@ async function readTempoWhoami() {
1017
1082
  return null;
1018
1083
  }
1019
1084
  }
1085
+ async function readTempoKeys() {
1086
+ try {
1087
+ const result = await runCommandCapture("tempo", ["wallet", "keys", "-j"]);
1088
+ if (result.code !== 0) return null;
1089
+ return JSON.parse(result.stdout);
1090
+ } catch {
1091
+ return null;
1092
+ }
1093
+ }
1020
1094
  async function ensureTempoInstalled() {
1021
1095
  try {
1022
1096
  const result = await runCommandCapture("tempo", ["--version"]);
@@ -1049,6 +1123,94 @@ function formatUsdAmount(cents) {
1049
1123
  function sleep(ms) {
1050
1124
  return new Promise((resolve) => setTimeout(resolve, ms));
1051
1125
  }
1126
+ async function getTempoSignerContext(wallet) {
1127
+ const readyWallet = wallet ?? await ensureTempoReady();
1128
+ const fallbackKey = (await readTempoKeys())?.keys?.[0];
1129
+ const tempoKey = readyWallet.key ?? fallbackKey;
1130
+ const privateKey = tempoKey?.key?.trim();
1131
+ const signerAddress = normalizeAddress(tempoKey?.address);
1132
+ if (!privateKey || !signerAddress) {
1133
+ throw new Error(
1134
+ "Tempo wallet does not expose a signing key. Run `tempo wallet login` again."
1135
+ );
1136
+ }
1137
+ const account = privateKeyToAccount(privateKey);
1138
+ if (normalizeAddress(account.address) !== signerAddress) {
1139
+ throw new Error("Tempo signing key does not match the signer address.");
1140
+ }
1141
+ return {
1142
+ account,
1143
+ signerAddress,
1144
+ walletAddress: normalizeAddress(readyWallet.wallet) ?? normalizeAddress(tempoKey?.wallet_address)
1145
+ };
1146
+ }
1147
+ async function createStoreAccountAuthHeaders(account) {
1148
+ const response = await fetch(`${BASE_URL}/api/managed-accounts/challenge`, {
1149
+ method: "POST",
1150
+ headers: {
1151
+ "Content-Type": "application/json"
1152
+ },
1153
+ body: JSON.stringify({
1154
+ address: account.address
1155
+ })
1156
+ });
1157
+ const text = await response.text();
1158
+ let payload = null;
1159
+ try {
1160
+ payload = text ? JSON.parse(text) : null;
1161
+ } catch {
1162
+ payload = text || null;
1163
+ }
1164
+ if (!response.ok) {
1165
+ const message = typeof payload === "string" ? payload : payload?.error ?? "Unable to authorize store account";
1166
+ throw new Error(message);
1167
+ }
1168
+ const challenge = payload;
1169
+ if (!challenge?.challenge || !challenge.message) {
1170
+ throw new Error("Store account authorization challenge was invalid.");
1171
+ }
1172
+ const signature = await account.signMessage({
1173
+ message: challenge.message
1174
+ });
1175
+ return {
1176
+ "X-AgentMall-Wallet-Address": account.address,
1177
+ "X-AgentMall-Auth-Challenge": challenge.challenge,
1178
+ "X-AgentMall-Auth-Signature": signature
1179
+ };
1180
+ }
1181
+ function normalizeOptional(value) {
1182
+ const trimmed = value?.trim();
1183
+ return trimmed ? trimmed : void 0;
1184
+ }
1185
+ async function promptStoreAccountFields(mode) {
1186
+ const { input: input2 } = await import("@inquirer/prompts");
1187
+ const email = mode === "create" ? await input2({
1188
+ message: "Store account email",
1189
+ validate: (value) => EMAIL_PATTERN.test(value.trim()) ? true : "A valid email is required"
1190
+ }) : await input2({
1191
+ message: "Email (leave blank to keep current)",
1192
+ default: "",
1193
+ validate: (value) => !value.trim() || EMAIL_PATTERN.test(value.trim()) ? true : "Enter a valid email or leave blank"
1194
+ });
1195
+ const retailer = await input2({
1196
+ message: mode === "create" ? "Retailer" : "Retailer (leave blank to keep current)",
1197
+ default: mode === "create" ? "amazon" : ""
1198
+ });
1199
+ const password = await input2({
1200
+ message: mode === "create" ? "Password (optional)" : "Password (leave blank to keep current)",
1201
+ default: ""
1202
+ });
1203
+ const totpSecret = await input2({
1204
+ message: mode === "create" ? "TOTP secret (optional)" : "TOTP secret (leave blank to keep current)",
1205
+ default: ""
1206
+ });
1207
+ return {
1208
+ ...normalizeOptional(email) ? { email: normalizeOptional(email) } : {},
1209
+ ...normalizeOptional(retailer) ? { retailer: normalizeOptional(retailer) } : {},
1210
+ ...normalizeOptional(password) ? { password: normalizeOptional(password) } : {},
1211
+ ...normalizeOptional(totpSecret) ? { totpSecret: normalizeOptional(totpSecret) } : {}
1212
+ };
1213
+ }
1052
1214
  function getSelectedVariantUnitPriceCents(selectedVariants) {
1053
1215
  const highestVariantPrice = selectedVariants?.reduce((highest, variant) => {
1054
1216
  const variantPriceCents = typeof variant.price === "number" ? Math.round(variant.price * 100) : 0;
@@ -1098,23 +1260,25 @@ async function ensureSufficientBalance(requiredCents, wallet) {
1098
1260
  `Still not enough USDC after funding: have ${formatUsdcNumber(available)}, need ${formatUsdAmount(requiredCents)}.`
1099
1261
  );
1100
1262
  }
1101
- async function createPurchaseWithTempo(body) {
1102
- const totalChargeCents = body.max_budget + SERVICE_FEE_CENTS;
1103
- const result = await runCommandCapture(
1104
- "tempo",
1105
- [
1106
- "request",
1107
- "-s",
1108
- "-X",
1109
- "POST",
1110
- "--json",
1111
- JSON.stringify(body),
1112
- `${BASE_URL}/api/purchases`
1113
- ],
1114
- {
1115
- TEMPO_MAX_SPEND: formatUsdAmount(totalChargeCents)
1116
- }
1117
- );
1263
+ async function createPurchaseWithTempo(body, options) {
1264
+ const idempotencyKey = body.idempotency_key?.trim() || createIdempotencyKey2();
1265
+ const requestBody = {
1266
+ ...body,
1267
+ idempotency_key: idempotencyKey
1268
+ };
1269
+ const totalChargeCents = requestBody.max_budget + SERVICE_FEE_CENTS;
1270
+ const headers = {
1271
+ "X-Idempotency-Key": idempotencyKey,
1272
+ ...options?.headers ?? {}
1273
+ };
1274
+ const args2 = ["request", "-s", "-X", "POST"];
1275
+ for (const [key, value] of Object.entries(headers)) {
1276
+ args2.push("-H", `${key}: ${value}`);
1277
+ }
1278
+ args2.push("--json", JSON.stringify(requestBody), `${BASE_URL}/api/purchases`);
1279
+ const result = await runCommandCapture("tempo", args2, {
1280
+ TEMPO_MAX_SPEND: formatUsdAmount(totalChargeCents)
1281
+ });
1118
1282
  if (result.code !== 0) {
1119
1283
  const raw = result.stderr.trim() || result.stdout.trim();
1120
1284
  const payload = raw ? (() => {
@@ -1135,7 +1299,7 @@ async function createPurchaseWithTempo(body) {
1135
1299
  );
1136
1300
  }
1137
1301
  }
1138
- async function buy(urlArg) {
1302
+ async function buy(urlArg, options) {
1139
1303
  try {
1140
1304
  banner();
1141
1305
  gap();
@@ -1181,6 +1345,7 @@ async function buy(urlArg) {
1181
1345
  message: "Email for order updates",
1182
1346
  validate: (value) => EMAIL_PATTERN.test(value.trim()) ? true : "A valid email is required"
1183
1347
  });
1348
+ const storeAccountId = normalizeOptional(options?.storeAccountId);
1184
1349
  const body = {
1185
1350
  items: [
1186
1351
  {
@@ -1191,7 +1356,9 @@ async function buy(urlArg) {
1191
1356
  ],
1192
1357
  delivery_address: address,
1193
1358
  max_budget: maxBudget,
1194
- buyer_email: buyerEmail
1359
+ buyer_email: buyerEmail,
1360
+ ...storeAccountId ? { store_account_id: storeAccountId } : {},
1361
+ idempotency_key: createIdempotencyKey2()
1195
1362
  };
1196
1363
  displayOrderSummary(body);
1197
1364
  gap();
@@ -1215,17 +1382,32 @@ async function buy(urlArg) {
1215
1382
  return;
1216
1383
  }
1217
1384
  const totalChargeCents = maxBudget + SERVICE_FEE_CENTS;
1218
- const wallet = await spin("Connecting wallet", () => ensureTempoReady());
1219
- await ensureSufficientBalance(totalChargeCents, wallet);
1385
+ const initialWallet = await spin("Connecting wallet", () => ensureTempoReady());
1386
+ const wallet = await ensureSufficientBalance(totalChargeCents, initialWallet);
1220
1387
  if (wallet.wallet) {
1221
1388
  const addr = wallet.wallet;
1222
1389
  const short = `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
1223
1390
  const bal = wallet.balance?.available ? ` \xB7 ${wallet.balance.available} ${wallet.balance?.symbol ?? "USDC"}` : "";
1224
1391
  muted(`Wallet ${short}${bal}`);
1225
1392
  }
1393
+ let purchaseHeaders;
1394
+ if (storeAccountId) {
1395
+ const signer = await spin("Authorizing store account", async () => {
1396
+ const context = await getTempoSignerContext(wallet);
1397
+ const headers = await createStoreAccountAuthHeaders(context.account);
1398
+ return { headers, context };
1399
+ });
1400
+ purchaseHeaders = signer.headers;
1401
+ const signerLine = formatAddress(signer.context.signerAddress);
1402
+ muted(
1403
+ signerLine ? `Store account ${storeAccountId} authorized by signer ${signerLine}` : `Store account ${storeAccountId} authorized`
1404
+ );
1405
+ }
1226
1406
  const order = await spin(
1227
1407
  "Placing order",
1228
- () => createPurchaseWithTempo(body)
1408
+ () => createPurchaseWithTempo(body, {
1409
+ ...purchaseHeaders ? { headers: purchaseHeaders } : {}
1410
+ })
1229
1411
  );
1230
1412
  if (order.buyerToken) {
1231
1413
  await saveBuyerToken(order.id, order.buyerToken);
@@ -1335,6 +1517,120 @@ async function onboard() {
1335
1517
  );
1336
1518
  gap();
1337
1519
  }
1520
+ async function storeAccountsList() {
1521
+ banner();
1522
+ gap();
1523
+ const wallet = await spin("Connecting wallet", () => ensureTempoReady());
1524
+ const signer = await getTempoSignerContext(wallet);
1525
+ const client = new AgentMall();
1526
+ const walletLabel = formatAddress(signer.walletAddress);
1527
+ const signerLabel = formatAddress(signer.signerAddress);
1528
+ if (walletLabel || signerLabel) {
1529
+ muted(
1530
+ `Using ${walletLabel ? `wallet ${walletLabel}` : "Tempo wallet"}${walletLabel && signerLabel ? " \xB7 " : ""}${signerLabel ? `signer ${signerLabel}` : ""}`
1531
+ );
1532
+ gap();
1533
+ }
1534
+ const accounts = await spin(
1535
+ "Loading store accounts",
1536
+ () => client.storeAccounts.list({ account: signer.account })
1537
+ );
1538
+ displayStoreAccounts(accounts);
1539
+ gap();
1540
+ }
1541
+ async function storeAccountsCreate(options) {
1542
+ banner();
1543
+ gap();
1544
+ const fields = {
1545
+ ...normalizeOptional(options?.email) ? { email: normalizeOptional(options?.email) } : {},
1546
+ ...normalizeOptional(options?.retailer) ? { retailer: normalizeOptional(options?.retailer) } : {},
1547
+ ...normalizeOptional(options?.password) ? { password: normalizeOptional(options?.password) } : {},
1548
+ ...normalizeOptional(options?.totpSecret) ? { totpSecret: normalizeOptional(options?.totpSecret) } : {}
1549
+ };
1550
+ const prompted = fields.email && fields.retailer !== void 0 ? fields : {
1551
+ ...fields,
1552
+ ...await promptStoreAccountFields("create")
1553
+ };
1554
+ if (!prompted.email) {
1555
+ throw new Error("Email is required.");
1556
+ }
1557
+ const body = {
1558
+ email: prompted.email,
1559
+ ...prompted.retailer ? { retailer: prompted.retailer } : {},
1560
+ ...prompted.password ? { password: prompted.password } : {},
1561
+ ...prompted.totpSecret ? { totp_secret: prompted.totpSecret } : {}
1562
+ };
1563
+ const wallet = await spin("Connecting wallet", () => ensureTempoReady());
1564
+ const signer = await getTempoSignerContext(wallet);
1565
+ const client = new AgentMall();
1566
+ const account = await spin(
1567
+ "Creating store account",
1568
+ () => client.storeAccounts.create(body, { account: signer.account })
1569
+ );
1570
+ displayStoreAccount(account, { title: "Store Account Created" });
1571
+ gap();
1572
+ line(
1573
+ `Use ${c.bold}store_account_id: "${account.short_id}"${c.reset} on purchases.`
1574
+ );
1575
+ gap();
1576
+ }
1577
+ async function storeAccountsUpdate(shortId, options) {
1578
+ banner();
1579
+ gap();
1580
+ if (!shortId.trim()) {
1581
+ throw new Error("short_id is required.");
1582
+ }
1583
+ let fields = {
1584
+ ...normalizeOptional(options?.email) ? { email: normalizeOptional(options?.email) } : {},
1585
+ ...normalizeOptional(options?.retailer) ? { retailer: normalizeOptional(options?.retailer) } : {},
1586
+ ...normalizeOptional(options?.password) ? { password: normalizeOptional(options?.password) } : {},
1587
+ ...normalizeOptional(options?.totpSecret) ? { totpSecret: normalizeOptional(options?.totpSecret) } : {}
1588
+ };
1589
+ if (Object.keys(fields).length === 0) {
1590
+ fields = await promptStoreAccountFields("update");
1591
+ }
1592
+ if (Object.keys(fields).length === 0) {
1593
+ throw new Error("No updates provided.");
1594
+ }
1595
+ const body = {
1596
+ short_id: shortId.trim(),
1597
+ ...fields.email ? { email: fields.email } : {},
1598
+ ...fields.retailer ? { retailer: fields.retailer } : {},
1599
+ ...fields.password ? { password: fields.password } : {},
1600
+ ...fields.totpSecret ? { totp_secret: fields.totpSecret } : {}
1601
+ };
1602
+ const wallet = await spin("Connecting wallet", () => ensureTempoReady());
1603
+ const signer = await getTempoSignerContext(wallet);
1604
+ const client = new AgentMall();
1605
+ const account = await spin(
1606
+ "Updating store account",
1607
+ () => client.storeAccounts.update(body, { account: signer.account })
1608
+ );
1609
+ displayStoreAccount(account, { title: "Store Account Updated" });
1610
+ gap();
1611
+ }
1612
+ async function storeAccountsDelete(shortId, options) {
1613
+ banner();
1614
+ gap();
1615
+ if (!shortId.trim()) {
1616
+ throw new Error("short_id is required.");
1617
+ }
1618
+ const confirmed = options?.yes ?? await promptConfirm(`Delete store account ${shortId.trim()}?`);
1619
+ if (!confirmed) {
1620
+ muted("Cancelled.");
1621
+ return;
1622
+ }
1623
+ const wallet = await spin("Connecting wallet", () => ensureTempoReady());
1624
+ const signer = await getTempoSignerContext(wallet);
1625
+ const client = new AgentMall();
1626
+ await spin(
1627
+ "Deleting store account",
1628
+ () => client.storeAccounts.delete(shortId.trim(), { account: signer.account })
1629
+ );
1630
+ section("Store Account Deleted");
1631
+ line(`${c.bold}${shortId.trim()}${c.reset} was removed.`);
1632
+ gap();
1633
+ }
1338
1634
 
1339
1635
  // src/cli.ts
1340
1636
  var c2 = {
@@ -1346,22 +1642,78 @@ var c2 = {
1346
1642
  };
1347
1643
  var args = process.argv.slice(2);
1348
1644
  var command = args[0];
1349
- function readBuyerTokenFlag(values) {
1350
- const inline = values.find((value) => value.startsWith("--buyer-token="));
1645
+ function readFlagValue(values, flag) {
1646
+ const inline = values.find((value2) => value2.startsWith(`${flag}=`));
1351
1647
  if (inline) {
1352
- const token2 = inline.slice("--buyer-token=".length).trim();
1353
- return token2 || void 0;
1648
+ const value2 = inline.slice(`${flag}=`.length).trim();
1649
+ return value2 || void 0;
1354
1650
  }
1355
- const index = values.indexOf("--buyer-token");
1651
+ const index = values.indexOf(flag);
1356
1652
  if (index === -1) return void 0;
1357
- const token = values[index + 1]?.trim();
1358
- return token || void 0;
1653
+ const value = values[index + 1]?.trim();
1654
+ return value || void 0;
1655
+ }
1656
+ function hasFlag(values, flag) {
1657
+ return values.includes(flag);
1658
+ }
1659
+ function readBuyerTokenFlag(values) {
1660
+ return readFlagValue(values, "--buyer-token");
1661
+ }
1662
+ function readStoreAccountFlag(values) {
1663
+ return readFlagValue(values, "--store-account");
1664
+ }
1665
+ async function handleStoreAccounts(values) {
1666
+ const subcommand = values[0];
1667
+ const rest = values.slice(1);
1668
+ switch (subcommand) {
1669
+ case "list":
1670
+ await storeAccountsList();
1671
+ break;
1672
+ case "create":
1673
+ await storeAccountsCreate({
1674
+ email: readFlagValue(rest, "--email"),
1675
+ retailer: readFlagValue(rest, "--retailer"),
1676
+ password: readFlagValue(rest, "--password"),
1677
+ totpSecret: readFlagValue(rest, "--totp-secret")
1678
+ });
1679
+ break;
1680
+ case "update":
1681
+ if (!rest[0]) {
1682
+ console.error(
1683
+ "Usage: agentmall store-accounts update <short_id> [--email <email>] [--retailer <name>] [--password <password>] [--totp-secret <secret>]"
1684
+ );
1685
+ process.exit(1);
1686
+ }
1687
+ await storeAccountsUpdate(rest[0], {
1688
+ email: readFlagValue(rest.slice(1), "--email"),
1689
+ retailer: readFlagValue(rest.slice(1), "--retailer"),
1690
+ password: readFlagValue(rest.slice(1), "--password"),
1691
+ totpSecret: readFlagValue(rest.slice(1), "--totp-secret")
1692
+ });
1693
+ break;
1694
+ case "delete":
1695
+ if (!rest[0]) {
1696
+ console.error("Usage: agentmall store-accounts delete <short_id> [--yes]");
1697
+ process.exit(1);
1698
+ }
1699
+ await storeAccountsDelete(rest[0], {
1700
+ yes: hasFlag(rest.slice(1), "--yes")
1701
+ });
1702
+ break;
1703
+ default:
1704
+ console.error(
1705
+ "Usage: agentmall store-accounts <list|create|update|delete> ..."
1706
+ );
1707
+ process.exit(1);
1708
+ }
1359
1709
  }
1360
1710
  async function main() {
1361
1711
  try {
1362
1712
  switch (command) {
1363
1713
  case "buy":
1364
- await buy(args[1]);
1714
+ await buy(args[1], {
1715
+ storeAccountId: readStoreAccountFlag(args.slice(2))
1716
+ });
1365
1717
  break;
1366
1718
  case "status":
1367
1719
  if (!args[1]) {
@@ -1381,6 +1733,9 @@ async function main() {
1381
1733
  case "setup":
1382
1734
  await onboard();
1383
1735
  break;
1736
+ case "store-accounts":
1737
+ await handleStoreAccounts(args.slice(1));
1738
+ break;
1384
1739
  case "help":
1385
1740
  case "--help":
1386
1741
  case "-h":
@@ -1419,6 +1774,9 @@ function printHelp() {
1419
1774
  console.log(
1420
1775
  ` ${c2.cyan}agentmall buy${c2.reset} <url> ${c2.dim}Buy a product${c2.reset}`
1421
1776
  );
1777
+ console.log(
1778
+ ` ${c2.cyan}agentmall store-accounts${c2.reset} ${c2.dim}Manage your store accounts${c2.reset}`
1779
+ );
1422
1780
  console.log(
1423
1781
  ` ${c2.cyan}agentmall status${c2.reset} <id> ${c2.dim}Check order status${c2.reset}`
1424
1782
  );
@@ -1436,6 +1794,12 @@ function printHelp() {
1436
1794
  console.log(
1437
1795
  ` ${c2.dim}$${c2.reset} npx agentmall https://amazon.com/dp/B0DWTMJHCG`
1438
1796
  );
1797
+ console.log(
1798
+ ` ${c2.dim}$${c2.reset} npx agentmall buy <url> --store-account zn_acct_abc123`
1799
+ );
1800
+ console.log(
1801
+ ` ${c2.dim}$${c2.reset} npx agentmall store-accounts create`
1802
+ );
1439
1803
  console.log(` ${c2.dim}$${c2.reset} npx agentmall status pur_abc123`);
1440
1804
  console.log(
1441
1805
  ` ${c2.dim}$${c2.reset} npx agentmall status pur_abc123 --buyer-token amtk_...`
package/dist/index.cjs CHANGED
@@ -113,6 +113,7 @@ var AgentMall = class {
113
113
  purchases;
114
114
  payments;
115
115
  refunds;
116
+ storeAccounts;
116
117
  managedAccounts;
117
118
  constructor(config = {}) {
118
119
  this.baseUrl = (config.baseUrl ?? BASE_URL).replace(/\/$/, "");
@@ -122,7 +123,8 @@ var AgentMall = class {
122
123
  this.purchases = new AgentMallPurchases(this);
123
124
  this.payments = new AgentMallPayments(this);
124
125
  this.refunds = new AgentMallRefunds(this);
125
- this.managedAccounts = new AgentMallManagedAccounts(this);
126
+ this.storeAccounts = new AgentMallStoreAccounts(this);
127
+ this.managedAccounts = this.storeAccounts;
126
128
  }
127
129
  /** @internal */
128
130
  hasApiSecret() {
@@ -180,6 +182,25 @@ var AgentMall = class {
180
182
  return await response.json();
181
183
  }
182
184
  };
185
+ async function createStoreAccountHeaders(client, account) {
186
+ const challenge = await client.request(
187
+ "POST",
188
+ "/api/managed-accounts/challenge",
189
+ {
190
+ body: {
191
+ address: account.address
192
+ }
193
+ }
194
+ );
195
+ const signature = await account.signMessage({
196
+ message: challenge.message
197
+ });
198
+ return {
199
+ "X-AgentMall-Wallet-Address": account.address,
200
+ "X-AgentMall-Auth-Challenge": challenge.challenge,
201
+ "X-AgentMall-Auth-Signature": signature
202
+ };
203
+ }
183
204
  var AgentMallProducts = class {
184
205
  constructor(client) {
185
206
  this.client = client;
@@ -199,35 +220,41 @@ var AgentMallPurchases = class {
199
220
  * Create a purchase. The first call returns a 402 MPP payment challenge.
200
221
  * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
201
222
  */
202
- async create(body) {
223
+ async create(body, options) {
203
224
  const idempotencyKey = body.idempotency_key ?? createIdempotencyKey();
225
+ const storeAccountId = body.store_account_id ?? body.retailer_credentials_id;
226
+ const headers = {
227
+ ...storeAccountId && options?.account ? await createStoreAccountHeaders(this.client, options.account) : {},
228
+ "X-Idempotency-Key": idempotencyKey
229
+ };
204
230
  return this.client.request("POST", "/api/purchases", {
205
231
  body: {
206
232
  ...body,
233
+ ...storeAccountId ? { retailer_credentials_id: storeAccountId } : {},
207
234
  idempotency_key: idempotencyKey
208
235
  },
209
- headers: {
210
- "X-Idempotency-Key": idempotencyKey
211
- }
236
+ headers
212
237
  });
213
238
  }
214
239
  /** Get a single purchase by ID using either operator auth or a buyer token. */
215
240
  async get(id, options) {
216
241
  if (options?.buyerToken) {
217
- return this.client.request("POST", "/api/purchases/status", {
242
+ const purchase3 = await this.client.request("POST", "/api/purchases/status", {
218
243
  body: {
219
244
  id,
220
245
  buyer_token: options.buyerToken
221
246
  }
222
247
  });
248
+ return normalizePurchase(purchase3);
223
249
  }
224
250
  if (!this.client.hasApiSecret()) {
225
251
  throw new Error("buyerToken or apiSecret is required for this endpoint");
226
252
  }
227
- return this.client.request("GET", "/api/purchases", {
253
+ const purchase2 = await this.client.request("GET", "/api/purchases", {
228
254
  auth: true,
229
255
  params: { id }
230
256
  });
257
+ return normalizePurchase(purchase2);
231
258
  }
232
259
  /** List purchases. Requires apiSecret. */
233
260
  async list(filters) {
@@ -236,7 +263,7 @@ var AgentMallPurchases = class {
236
263
  "/api/purchases",
237
264
  { auth: true, params: filters }
238
265
  );
239
- return result.purchases;
266
+ return result.purchases.map(normalizePurchase);
240
267
  }
241
268
  };
242
269
  var AgentMallPayments = class {
@@ -308,51 +335,41 @@ var AgentMallRefunds = class {
308
335
  return result.refunds;
309
336
  }
310
337
  };
311
- var AgentMallManagedAccounts = class {
338
+ function normalizePurchase(purchase2) {
339
+ return {
340
+ ...purchase2,
341
+ ...purchase2.storeAccountId ? {} : purchase2.retailerCredentialsId ? { storeAccountId: purchase2.retailerCredentialsId } : {}
342
+ };
343
+ }
344
+ var AgentMallStoreAccounts = class {
312
345
  constructor(client) {
313
346
  this.client = client;
314
347
  }
315
348
  async walletHeaders(account) {
316
- const challenge = await this.client.request(
317
- "POST",
318
- "/api/managed-accounts/challenge",
319
- {
320
- body: {
321
- address: account.address
322
- }
323
- }
324
- );
325
- const signature = await account.signMessage({
326
- message: challenge.message
327
- });
328
- return {
329
- "X-AgentMall-Wallet-Address": account.address,
330
- "X-AgentMall-Auth-Challenge": challenge.challenge,
331
- "X-AgentMall-Auth-Signature": signature
332
- };
349
+ return createStoreAccountHeaders(this.client, account);
333
350
  }
334
- /** List managed retailer accounts. Requires either apiSecret or a wallet signer. */
351
+ /** List your store accounts. Requires either apiSecret or a wallet signer. */
335
352
  async list(options) {
336
353
  const result = await this.client.request("GET", "/api/managed-accounts", {
337
354
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true }
338
355
  });
339
356
  return result.credentials;
340
357
  }
341
- /** Create a managed retailer account. Requires either apiSecret or a wallet signer. */
358
+ /** Create a store account. Requires either apiSecret or a wallet signer. */
342
359
  async create(body, options) {
343
360
  return this.client.request("POST", "/api/managed-accounts", {
344
361
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
345
362
  body
346
363
  });
347
364
  }
348
- /** Update a managed retailer account. Requires either apiSecret or a wallet signer. */
365
+ /** Update a store account. Requires either apiSecret or a wallet signer. */
349
366
  async update(body, options) {
350
367
  return this.client.request("PUT", "/api/managed-accounts", {
351
368
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
352
369
  body
353
370
  });
354
371
  }
355
- /** Delete a managed retailer account. Requires either apiSecret or a wallet signer. */
372
+ /** Delete a store account. Requires either apiSecret or a wallet signer. */
356
373
  async delete(shortId, options) {
357
374
  await this.client.request("DELETE", "/api/managed-accounts", {
358
375
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
@@ -382,7 +399,7 @@ async function purchase(config) {
382
399
  baseUrl: baseUrl ?? BASE_URL,
383
400
  fetch: mppx.fetch.bind(mppx)
384
401
  });
385
- return client.purchases.create(body);
402
+ return client.purchases.create(body, { account });
386
403
  }
387
404
  // Annotate the CommonJS export names for ESM import in node:
388
405
  0 && (module.exports = {
package/dist/index.d.cts CHANGED
@@ -62,6 +62,7 @@ type CreatePurchaseRequest = {
62
62
  delivery_address: DeliveryAddress;
63
63
  max_budget: number;
64
64
  buyer_email: string;
65
+ store_account_id?: string;
65
66
  retailer_credentials_id?: string;
66
67
  idempotency_key?: string;
67
68
  metadata?: unknown;
@@ -92,6 +93,7 @@ type Purchase = {
92
93
  items: PurchaseItem[];
93
94
  deliveryMethod?: string;
94
95
  tracking?: unknown;
96
+ storeAccountId?: string;
95
97
  retailerCredentialsId?: string;
96
98
  maxBudget: number;
97
99
  finalTotal?: number;
@@ -143,7 +145,7 @@ type RefundFilters = {
143
145
  purchase_id?: string;
144
146
  status?: string;
145
147
  };
146
- type ManagedAccount = {
148
+ type StoreAccount = {
147
149
  id: string;
148
150
  short_id: string;
149
151
  email: string;
@@ -155,19 +157,25 @@ type ManagedAccount = {
155
157
  created_at: string;
156
158
  updated_at: string;
157
159
  };
158
- type ManagedAccountAuthChallenge = {
160
+ type RetailerAccount = StoreAccount;
161
+ type ManagedAccount = StoreAccount;
162
+ type StoreAccountAuthChallenge = {
159
163
  challenge: string;
160
164
  message: string;
161
165
  expiresAt: number;
162
166
  };
163
- type CreateManagedAccountRequest = {
167
+ type RetailerAccountAuthChallenge = StoreAccountAuthChallenge;
168
+ type ManagedAccountAuthChallenge = StoreAccountAuthChallenge;
169
+ type CreateStoreAccountRequest = {
164
170
  email: string;
165
171
  password?: string | null;
166
172
  retailer?: string | null;
167
173
  totp_secret?: string | null;
168
174
  retailer_config?: Record<string, unknown> | null;
169
175
  };
170
- type UpdateManagedAccountRequest = {
176
+ type CreateRetailerAccountRequest = CreateStoreAccountRequest;
177
+ type CreateManagedAccountRequest = CreateStoreAccountRequest;
178
+ type UpdateStoreAccountRequest = {
171
179
  short_id: string;
172
180
  email?: string | null;
173
181
  password?: string | null;
@@ -175,6 +183,8 @@ type UpdateManagedAccountRequest = {
175
183
  totp_secret?: string | null;
176
184
  retailer_config?: Record<string, unknown> | null;
177
185
  };
186
+ type UpdateRetailerAccountRequest = UpdateStoreAccountRequest;
187
+ type UpdateManagedAccountRequest = UpdateStoreAccountRequest;
178
188
 
179
189
  declare class AgentMall {
180
190
  private baseUrl;
@@ -184,6 +194,7 @@ declare class AgentMall {
184
194
  purchases: AgentMallPurchases;
185
195
  payments: AgentMallPayments;
186
196
  refunds: AgentMallRefunds;
197
+ storeAccounts: AgentMallStoreAccounts;
187
198
  managedAccounts: AgentMallManagedAccounts;
188
199
  constructor(config?: AgentMallConfig);
189
200
  /** @internal */
@@ -209,7 +220,9 @@ declare class AgentMallPurchases {
209
220
  * Create a purchase. The first call returns a 402 MPP payment challenge.
210
221
  * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
211
222
  */
212
- create(body: CreatePurchaseRequest): Promise<CreatePurchaseResponse>;
223
+ create(body: CreatePurchaseRequest, options?: {
224
+ account?: WalletAccount;
225
+ }): Promise<CreatePurchaseResponse>;
213
226
  /** Get a single purchase by ID using either operator auth or a buyer token. */
214
227
  get(id: string, options?: {
215
228
  buyerToken?: string;
@@ -237,31 +250,32 @@ declare class AgentMallRefunds {
237
250
  /** List refunds. Requires apiSecret. */
238
251
  list(filters?: RefundFilters): Promise<Refund[]>;
239
252
  }
240
- declare class AgentMallManagedAccounts {
253
+ declare class AgentMallStoreAccounts {
241
254
  private client;
242
255
  constructor(client: AgentMall);
243
256
  private walletHeaders;
244
- /** List managed retailer accounts. Requires either apiSecret or a wallet signer. */
257
+ /** List your store accounts. Requires either apiSecret or a wallet signer. */
245
258
  list(options?: {
246
259
  account?: WalletAccount;
247
- }): Promise<ManagedAccount[]>;
248
- /** Create a managed retailer account. Requires either apiSecret or a wallet signer. */
249
- create(body: CreateManagedAccountRequest, options?: {
260
+ }): Promise<StoreAccount[]>;
261
+ /** Create a store account. Requires either apiSecret or a wallet signer. */
262
+ create(body: CreateStoreAccountRequest, options?: {
250
263
  account?: WalletAccount;
251
- }): Promise<ManagedAccount>;
252
- /** Update a managed retailer account. Requires either apiSecret or a wallet signer. */
253
- update(body: UpdateManagedAccountRequest, options?: {
264
+ }): Promise<StoreAccount>;
265
+ /** Update a store account. Requires either apiSecret or a wallet signer. */
266
+ update(body: UpdateStoreAccountRequest, options?: {
254
267
  account?: WalletAccount;
255
- }): Promise<ManagedAccount>;
256
- /** Delete a managed retailer account. Requires either apiSecret or a wallet signer. */
268
+ }): Promise<StoreAccount>;
269
+ /** Delete a store account. Requires either apiSecret or a wallet signer. */
257
270
  delete(shortId: string, options?: {
258
271
  account?: WalletAccount;
259
272
  }): Promise<void>;
260
273
  }
274
+ type AgentMallManagedAccounts = AgentMallStoreAccounts;
261
275
 
262
276
  type PurchaseConfig = CreatePurchaseRequest & {
263
277
  /** viem Account for MPP payment (from privateKeyToAccount or mppx resolveAccount). */
264
- account: unknown;
278
+ account: WalletAccount;
265
279
  /** API base URL. Defaults to https://api.agentmall.sh */
266
280
  baseUrl?: string;
267
281
  };
@@ -308,4 +322,4 @@ declare const BASE_URL = "https://api.agentmall.sh";
308
322
  declare const SERVICE_FEE_CENTS = 150;
309
323
  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"];
310
324
 
311
- export { AgentMall, type AgentMallConfig, AgentMallError, BASE_URL, ConflictError, type CreateManagedAccountRequest, type CreatePurchaseRequest, type CreatePurchaseResponse, type DeliveryAddress, type ManagedAccount, type ManagedAccountAuthChallenge, type Payment, type PaymentFilters, PaymentRequiredError, type ProductLookup, type ProductVariant, type Purchase, type PurchaseFilters, type PurchaseItem, type PurchaseItemInput, type PurchaseLifecycleStatus, type PurchaseStatusChallenge, RateLimitError, type Refund, type RefundFilters, type RefundStatusChallenge, SERVICE_FEE_CENTS, SUPPORTED_RETAILERS, type UpdateManagedAccountRequest, ValidationError, type VariantSelection, type WalletAccount, purchase };
325
+ export { AgentMall, type AgentMallConfig, AgentMallError, BASE_URL, ConflictError, type CreateManagedAccountRequest, type CreatePurchaseRequest, type CreatePurchaseResponse, type CreateRetailerAccountRequest, type CreateStoreAccountRequest, type DeliveryAddress, type ManagedAccount, type ManagedAccountAuthChallenge, type Payment, type PaymentFilters, PaymentRequiredError, type ProductLookup, type ProductVariant, type Purchase, type PurchaseFilters, type PurchaseItem, type PurchaseItemInput, type PurchaseLifecycleStatus, type PurchaseStatusChallenge, RateLimitError, type Refund, type RefundFilters, type RefundStatusChallenge, type RetailerAccount, type RetailerAccountAuthChallenge, SERVICE_FEE_CENTS, SUPPORTED_RETAILERS, type StoreAccount, type StoreAccountAuthChallenge, type UpdateManagedAccountRequest, type UpdateRetailerAccountRequest, type UpdateStoreAccountRequest, ValidationError, type VariantSelection, type WalletAccount, purchase };
package/dist/index.d.ts CHANGED
@@ -62,6 +62,7 @@ type CreatePurchaseRequest = {
62
62
  delivery_address: DeliveryAddress;
63
63
  max_budget: number;
64
64
  buyer_email: string;
65
+ store_account_id?: string;
65
66
  retailer_credentials_id?: string;
66
67
  idempotency_key?: string;
67
68
  metadata?: unknown;
@@ -92,6 +93,7 @@ type Purchase = {
92
93
  items: PurchaseItem[];
93
94
  deliveryMethod?: string;
94
95
  tracking?: unknown;
96
+ storeAccountId?: string;
95
97
  retailerCredentialsId?: string;
96
98
  maxBudget: number;
97
99
  finalTotal?: number;
@@ -143,7 +145,7 @@ type RefundFilters = {
143
145
  purchase_id?: string;
144
146
  status?: string;
145
147
  };
146
- type ManagedAccount = {
148
+ type StoreAccount = {
147
149
  id: string;
148
150
  short_id: string;
149
151
  email: string;
@@ -155,19 +157,25 @@ type ManagedAccount = {
155
157
  created_at: string;
156
158
  updated_at: string;
157
159
  };
158
- type ManagedAccountAuthChallenge = {
160
+ type RetailerAccount = StoreAccount;
161
+ type ManagedAccount = StoreAccount;
162
+ type StoreAccountAuthChallenge = {
159
163
  challenge: string;
160
164
  message: string;
161
165
  expiresAt: number;
162
166
  };
163
- type CreateManagedAccountRequest = {
167
+ type RetailerAccountAuthChallenge = StoreAccountAuthChallenge;
168
+ type ManagedAccountAuthChallenge = StoreAccountAuthChallenge;
169
+ type CreateStoreAccountRequest = {
164
170
  email: string;
165
171
  password?: string | null;
166
172
  retailer?: string | null;
167
173
  totp_secret?: string | null;
168
174
  retailer_config?: Record<string, unknown> | null;
169
175
  };
170
- type UpdateManagedAccountRequest = {
176
+ type CreateRetailerAccountRequest = CreateStoreAccountRequest;
177
+ type CreateManagedAccountRequest = CreateStoreAccountRequest;
178
+ type UpdateStoreAccountRequest = {
171
179
  short_id: string;
172
180
  email?: string | null;
173
181
  password?: string | null;
@@ -175,6 +183,8 @@ type UpdateManagedAccountRequest = {
175
183
  totp_secret?: string | null;
176
184
  retailer_config?: Record<string, unknown> | null;
177
185
  };
186
+ type UpdateRetailerAccountRequest = UpdateStoreAccountRequest;
187
+ type UpdateManagedAccountRequest = UpdateStoreAccountRequest;
178
188
 
179
189
  declare class AgentMall {
180
190
  private baseUrl;
@@ -184,6 +194,7 @@ declare class AgentMall {
184
194
  purchases: AgentMallPurchases;
185
195
  payments: AgentMallPayments;
186
196
  refunds: AgentMallRefunds;
197
+ storeAccounts: AgentMallStoreAccounts;
187
198
  managedAccounts: AgentMallManagedAccounts;
188
199
  constructor(config?: AgentMallConfig);
189
200
  /** @internal */
@@ -209,7 +220,9 @@ declare class AgentMallPurchases {
209
220
  * Create a purchase. The first call returns a 402 MPP payment challenge.
210
221
  * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
211
222
  */
212
- create(body: CreatePurchaseRequest): Promise<CreatePurchaseResponse>;
223
+ create(body: CreatePurchaseRequest, options?: {
224
+ account?: WalletAccount;
225
+ }): Promise<CreatePurchaseResponse>;
213
226
  /** Get a single purchase by ID using either operator auth or a buyer token. */
214
227
  get(id: string, options?: {
215
228
  buyerToken?: string;
@@ -237,31 +250,32 @@ declare class AgentMallRefunds {
237
250
  /** List refunds. Requires apiSecret. */
238
251
  list(filters?: RefundFilters): Promise<Refund[]>;
239
252
  }
240
- declare class AgentMallManagedAccounts {
253
+ declare class AgentMallStoreAccounts {
241
254
  private client;
242
255
  constructor(client: AgentMall);
243
256
  private walletHeaders;
244
- /** List managed retailer accounts. Requires either apiSecret or a wallet signer. */
257
+ /** List your store accounts. Requires either apiSecret or a wallet signer. */
245
258
  list(options?: {
246
259
  account?: WalletAccount;
247
- }): Promise<ManagedAccount[]>;
248
- /** Create a managed retailer account. Requires either apiSecret or a wallet signer. */
249
- create(body: CreateManagedAccountRequest, options?: {
260
+ }): Promise<StoreAccount[]>;
261
+ /** Create a store account. Requires either apiSecret or a wallet signer. */
262
+ create(body: CreateStoreAccountRequest, options?: {
250
263
  account?: WalletAccount;
251
- }): Promise<ManagedAccount>;
252
- /** Update a managed retailer account. Requires either apiSecret or a wallet signer. */
253
- update(body: UpdateManagedAccountRequest, options?: {
264
+ }): Promise<StoreAccount>;
265
+ /** Update a store account. Requires either apiSecret or a wallet signer. */
266
+ update(body: UpdateStoreAccountRequest, options?: {
254
267
  account?: WalletAccount;
255
- }): Promise<ManagedAccount>;
256
- /** Delete a managed retailer account. Requires either apiSecret or a wallet signer. */
268
+ }): Promise<StoreAccount>;
269
+ /** Delete a store account. Requires either apiSecret or a wallet signer. */
257
270
  delete(shortId: string, options?: {
258
271
  account?: WalletAccount;
259
272
  }): Promise<void>;
260
273
  }
274
+ type AgentMallManagedAccounts = AgentMallStoreAccounts;
261
275
 
262
276
  type PurchaseConfig = CreatePurchaseRequest & {
263
277
  /** viem Account for MPP payment (from privateKeyToAccount or mppx resolveAccount). */
264
- account: unknown;
278
+ account: WalletAccount;
265
279
  /** API base URL. Defaults to https://api.agentmall.sh */
266
280
  baseUrl?: string;
267
281
  };
@@ -308,4 +322,4 @@ declare const BASE_URL = "https://api.agentmall.sh";
308
322
  declare const SERVICE_FEE_CENTS = 150;
309
323
  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"];
310
324
 
311
- export { AgentMall, type AgentMallConfig, AgentMallError, BASE_URL, ConflictError, type CreateManagedAccountRequest, type CreatePurchaseRequest, type CreatePurchaseResponse, type DeliveryAddress, type ManagedAccount, type ManagedAccountAuthChallenge, type Payment, type PaymentFilters, PaymentRequiredError, type ProductLookup, type ProductVariant, type Purchase, type PurchaseFilters, type PurchaseItem, type PurchaseItemInput, type PurchaseLifecycleStatus, type PurchaseStatusChallenge, RateLimitError, type Refund, type RefundFilters, type RefundStatusChallenge, SERVICE_FEE_CENTS, SUPPORTED_RETAILERS, type UpdateManagedAccountRequest, ValidationError, type VariantSelection, type WalletAccount, purchase };
325
+ export { AgentMall, type AgentMallConfig, AgentMallError, BASE_URL, ConflictError, type CreateManagedAccountRequest, type CreatePurchaseRequest, type CreatePurchaseResponse, type CreateRetailerAccountRequest, type CreateStoreAccountRequest, type DeliveryAddress, type ManagedAccount, type ManagedAccountAuthChallenge, type Payment, type PaymentFilters, PaymentRequiredError, type ProductLookup, type ProductVariant, type Purchase, type PurchaseFilters, type PurchaseItem, type PurchaseItemInput, type PurchaseLifecycleStatus, type PurchaseStatusChallenge, RateLimitError, type Refund, type RefundFilters, type RefundStatusChallenge, type RetailerAccount, type RetailerAccountAuthChallenge, SERVICE_FEE_CENTS, SUPPORTED_RETAILERS, type StoreAccount, type StoreAccountAuthChallenge, type UpdateManagedAccountRequest, type UpdateRetailerAccountRequest, type UpdateStoreAccountRequest, ValidationError, type VariantSelection, type WalletAccount, purchase };
package/dist/index.js CHANGED
@@ -68,6 +68,7 @@ var AgentMall = class {
68
68
  purchases;
69
69
  payments;
70
70
  refunds;
71
+ storeAccounts;
71
72
  managedAccounts;
72
73
  constructor(config = {}) {
73
74
  this.baseUrl = (config.baseUrl ?? BASE_URL).replace(/\/$/, "");
@@ -77,7 +78,8 @@ var AgentMall = class {
77
78
  this.purchases = new AgentMallPurchases(this);
78
79
  this.payments = new AgentMallPayments(this);
79
80
  this.refunds = new AgentMallRefunds(this);
80
- this.managedAccounts = new AgentMallManagedAccounts(this);
81
+ this.storeAccounts = new AgentMallStoreAccounts(this);
82
+ this.managedAccounts = this.storeAccounts;
81
83
  }
82
84
  /** @internal */
83
85
  hasApiSecret() {
@@ -135,6 +137,25 @@ var AgentMall = class {
135
137
  return await response.json();
136
138
  }
137
139
  };
140
+ async function createStoreAccountHeaders(client, account) {
141
+ const challenge = await client.request(
142
+ "POST",
143
+ "/api/managed-accounts/challenge",
144
+ {
145
+ body: {
146
+ address: account.address
147
+ }
148
+ }
149
+ );
150
+ const signature = await account.signMessage({
151
+ message: challenge.message
152
+ });
153
+ return {
154
+ "X-AgentMall-Wallet-Address": account.address,
155
+ "X-AgentMall-Auth-Challenge": challenge.challenge,
156
+ "X-AgentMall-Auth-Signature": signature
157
+ };
158
+ }
138
159
  var AgentMallProducts = class {
139
160
  constructor(client) {
140
161
  this.client = client;
@@ -154,35 +175,41 @@ var AgentMallPurchases = class {
154
175
  * Create a purchase. The first call returns a 402 MPP payment challenge.
155
176
  * Use mppx-wrapped fetch to handle payment automatically, or catch PaymentRequiredError.
156
177
  */
157
- async create(body) {
178
+ async create(body, options) {
158
179
  const idempotencyKey = body.idempotency_key ?? createIdempotencyKey();
180
+ const storeAccountId = body.store_account_id ?? body.retailer_credentials_id;
181
+ const headers = {
182
+ ...storeAccountId && options?.account ? await createStoreAccountHeaders(this.client, options.account) : {},
183
+ "X-Idempotency-Key": idempotencyKey
184
+ };
159
185
  return this.client.request("POST", "/api/purchases", {
160
186
  body: {
161
187
  ...body,
188
+ ...storeAccountId ? { retailer_credentials_id: storeAccountId } : {},
162
189
  idempotency_key: idempotencyKey
163
190
  },
164
- headers: {
165
- "X-Idempotency-Key": idempotencyKey
166
- }
191
+ headers
167
192
  });
168
193
  }
169
194
  /** Get a single purchase by ID using either operator auth or a buyer token. */
170
195
  async get(id, options) {
171
196
  if (options?.buyerToken) {
172
- return this.client.request("POST", "/api/purchases/status", {
197
+ const purchase3 = await this.client.request("POST", "/api/purchases/status", {
173
198
  body: {
174
199
  id,
175
200
  buyer_token: options.buyerToken
176
201
  }
177
202
  });
203
+ return normalizePurchase(purchase3);
178
204
  }
179
205
  if (!this.client.hasApiSecret()) {
180
206
  throw new Error("buyerToken or apiSecret is required for this endpoint");
181
207
  }
182
- return this.client.request("GET", "/api/purchases", {
208
+ const purchase2 = await this.client.request("GET", "/api/purchases", {
183
209
  auth: true,
184
210
  params: { id }
185
211
  });
212
+ return normalizePurchase(purchase2);
186
213
  }
187
214
  /** List purchases. Requires apiSecret. */
188
215
  async list(filters) {
@@ -191,7 +218,7 @@ var AgentMallPurchases = class {
191
218
  "/api/purchases",
192
219
  { auth: true, params: filters }
193
220
  );
194
- return result.purchases;
221
+ return result.purchases.map(normalizePurchase);
195
222
  }
196
223
  };
197
224
  var AgentMallPayments = class {
@@ -263,51 +290,41 @@ var AgentMallRefunds = class {
263
290
  return result.refunds;
264
291
  }
265
292
  };
266
- var AgentMallManagedAccounts = class {
293
+ function normalizePurchase(purchase2) {
294
+ return {
295
+ ...purchase2,
296
+ ...purchase2.storeAccountId ? {} : purchase2.retailerCredentialsId ? { storeAccountId: purchase2.retailerCredentialsId } : {}
297
+ };
298
+ }
299
+ var AgentMallStoreAccounts = class {
267
300
  constructor(client) {
268
301
  this.client = client;
269
302
  }
270
303
  async walletHeaders(account) {
271
- const challenge = await this.client.request(
272
- "POST",
273
- "/api/managed-accounts/challenge",
274
- {
275
- body: {
276
- address: account.address
277
- }
278
- }
279
- );
280
- const signature = await account.signMessage({
281
- message: challenge.message
282
- });
283
- return {
284
- "X-AgentMall-Wallet-Address": account.address,
285
- "X-AgentMall-Auth-Challenge": challenge.challenge,
286
- "X-AgentMall-Auth-Signature": signature
287
- };
304
+ return createStoreAccountHeaders(this.client, account);
288
305
  }
289
- /** List managed retailer accounts. Requires either apiSecret or a wallet signer. */
306
+ /** List your store accounts. Requires either apiSecret or a wallet signer. */
290
307
  async list(options) {
291
308
  const result = await this.client.request("GET", "/api/managed-accounts", {
292
309
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true }
293
310
  });
294
311
  return result.credentials;
295
312
  }
296
- /** Create a managed retailer account. Requires either apiSecret or a wallet signer. */
313
+ /** Create a store account. Requires either apiSecret or a wallet signer. */
297
314
  async create(body, options) {
298
315
  return this.client.request("POST", "/api/managed-accounts", {
299
316
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
300
317
  body
301
318
  });
302
319
  }
303
- /** Update a managed retailer account. Requires either apiSecret or a wallet signer. */
320
+ /** Update a store account. Requires either apiSecret or a wallet signer. */
304
321
  async update(body, options) {
305
322
  return this.client.request("PUT", "/api/managed-accounts", {
306
323
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
307
324
  body
308
325
  });
309
326
  }
310
- /** Delete a managed retailer account. Requires either apiSecret or a wallet signer. */
327
+ /** Delete a store account. Requires either apiSecret or a wallet signer. */
311
328
  async delete(shortId, options) {
312
329
  await this.client.request("DELETE", "/api/managed-accounts", {
313
330
  ...options?.account ? { headers: await this.walletHeaders(options.account) } : { auth: true },
@@ -337,7 +354,7 @@ async function purchase(config) {
337
354
  baseUrl: baseUrl ?? BASE_URL,
338
355
  fetch: mppx.fetch.bind(mppx)
339
356
  });
340
- return client.purchases.create(body);
357
+ return client.purchases.create(body, { account });
341
358
  }
342
359
  export {
343
360
  AgentMall,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentmall",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "SDK and CLI for the AgentMall API — let AI agents buy physical products from US retailers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",