@compass-labs/widgets 0.1.36 → 0.1.38

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.
@@ -93,17 +93,46 @@ function createCompassHandler(config) {
93
93
  return await handleCreditExecute(client, body, config);
94
94
  case "credit/transfer":
95
95
  return await handleCreditTransfer(client, body);
96
+ case "approval/execute":
97
+ return await handleApprovalExecute(body, config);
96
98
  default:
97
99
  return jsonResponse({ error: `Unknown POST route: ${route}` }, 404);
98
100
  }
99
101
  }
100
102
  return jsonResponse({ error: `Method ${method} not allowed` }, 405);
101
103
  } catch (error) {
102
- const message = error instanceof Error ? error.message : "Internal server error";
103
- return jsonResponse({ error: message }, 500);
104
+ const { message, status } = extractErrorMessage(error);
105
+ return jsonResponse({ error: message }, status);
104
106
  }
105
107
  };
106
108
  }
109
+ function extractErrorMessage(error) {
110
+ if (!(error instanceof Error)) {
111
+ return { message: "Something went wrong. Please try again.", status: 500 };
112
+ }
113
+ const raw = error.message || "";
114
+ const jsonMatch = raw.match(/Body:\s*(\{[\s\S]*\})/);
115
+ if (jsonMatch) {
116
+ try {
117
+ const body = JSON.parse(jsonMatch[1]);
118
+ if (Array.isArray(body.detail)) {
119
+ const msgs = body.detail.map((d) => d.msg || d.message).filter(Boolean);
120
+ if (msgs.length > 0) return { message: msgs.join(". "), status: 422 };
121
+ }
122
+ if (typeof body.detail === "string") return { message: body.detail, status: 422 };
123
+ if (typeof body.error === "string") return { message: body.error, status: 500 };
124
+ if (typeof body.description === "string") return { message: body.description, status: 500 };
125
+ } catch {
126
+ }
127
+ }
128
+ if (error.name === "SDKValidationError" || raw.startsWith("Input validation failed")) {
129
+ return { message: "Invalid request data. Please check your inputs and try again.", status: 400 };
130
+ }
131
+ if (raw.includes("Insufficient") || raw.includes("not deployed") || raw.includes("reverted") || raw.includes("not configured") || raw.includes("Unsupported chain")) {
132
+ return { message: raw, status: 500 };
133
+ }
134
+ return { message: "Something went wrong. Please try again.", status: 500 };
135
+ }
107
136
  function jsonResponse(data, status = 200) {
108
137
  return new Response(JSON.stringify(data), {
109
138
  status,
@@ -262,10 +291,6 @@ async function handleExecute(client, body, config) {
262
291
  chain: viemChain,
263
292
  transport: viem.http(rpcUrl)
264
293
  });
265
- const publicClient = viem.createPublicClient({
266
- chain: viemChain,
267
- transport: viem.http(rpcUrl)
268
- });
269
294
  const response = await client.gasSponsorship.gasSponsorshipPrepare({
270
295
  chain,
271
296
  owner,
@@ -286,12 +311,6 @@ async function handleExecute(client, body, config) {
286
311
  value: transaction.value ? BigInt(transaction.value) : 0n,
287
312
  gas: transaction.gas ? BigInt(transaction.gas) : void 0
288
313
  });
289
- const receipt = await publicClient.waitForTransactionReceipt({
290
- hash: txHash
291
- });
292
- if (receipt.status === "reverted") {
293
- return jsonResponse({ error: "Transaction reverted" }, 500);
294
- }
295
314
  return jsonResponse({ txHash, success: true });
296
315
  }
297
316
  async function handleTransferApprove(client, body) {
@@ -344,8 +363,53 @@ async function handleTransferApprove(client, body) {
344
363
  throw error;
345
364
  }
346
365
  }
366
+ async function handleApprovalExecute(body, config) {
367
+ const { owner, chain = "base", transaction } = body;
368
+ const { gasSponsorPrivateKey, rpcUrls } = config;
369
+ if (!owner || !transaction) {
370
+ return jsonResponse({ error: "Missing required parameters (owner, transaction)" }, 400);
371
+ }
372
+ if (!gasSponsorPrivateKey) {
373
+ return jsonResponse(
374
+ { error: "Gas sponsor not configured. Set gasSponsorPrivateKey in handler config." },
375
+ 500
376
+ );
377
+ }
378
+ const viemChain = CHAIN_MAP[chain.toLowerCase()];
379
+ if (!viemChain) {
380
+ return jsonResponse({ error: `Unsupported chain: ${chain}` }, 500);
381
+ }
382
+ const rpcUrl = rpcUrls?.[chain.toLowerCase()];
383
+ if (!rpcUrl) {
384
+ return jsonResponse({ error: `No RPC URL configured for chain: ${chain}` }, 500);
385
+ }
386
+ const sponsorAccount = accounts.privateKeyToAccount(gasSponsorPrivateKey);
387
+ const walletClient = viem.createWalletClient({
388
+ account: sponsorAccount,
389
+ chain: viemChain,
390
+ transport: viem.http(rpcUrl)
391
+ });
392
+ const publicClient = viem.createPublicClient({
393
+ chain: viemChain,
394
+ transport: viem.http(rpcUrl)
395
+ });
396
+ const txHash = await walletClient.sendTransaction({
397
+ to: transaction.to,
398
+ data: transaction.data,
399
+ value: transaction.value ? BigInt(transaction.value) : 0n,
400
+ gas: transaction.gas ? BigInt(transaction.gas) : void 0
401
+ });
402
+ const receipt = await publicClient.waitForTransactionReceipt({
403
+ hash: txHash,
404
+ timeout: 6e4
405
+ });
406
+ if (receipt.status === "reverted") {
407
+ return jsonResponse({ error: "Approval transaction reverted" }, 500);
408
+ }
409
+ return jsonResponse({ txHash, status: "success" });
410
+ }
347
411
  async function handleTransferPrepare(client, body, config) {
348
- const { owner, chain = "base", token, amount, action } = body;
412
+ const { owner, chain = "base", token, amount, action, product } = body;
349
413
  const { gasSponsorPrivateKey } = config;
350
414
  if (!owner || !token || !amount || !action) {
351
415
  return jsonResponse({ error: "Missing required parameters" }, 400);
@@ -355,15 +419,28 @@ async function handleTransferPrepare(client, body, config) {
355
419
  const sponsorAccount = accounts.privateKeyToAccount(gasSponsorPrivateKey);
356
420
  spender = sponsorAccount.address;
357
421
  }
358
- const response = await client.earn.earnTransfer({
359
- owner,
360
- chain,
361
- token,
362
- amount,
363
- action,
364
- gasSponsorship: true,
365
- ...spender && { spender }
366
- });
422
+ let response;
423
+ if (product === "credit") {
424
+ response = await client.credit.creditTransfer({
425
+ owner,
426
+ chain,
427
+ token,
428
+ amount,
429
+ action,
430
+ gasSponsorship: true,
431
+ ...spender && { spender }
432
+ });
433
+ } else {
434
+ response = await client.earn.earnTransfer({
435
+ owner,
436
+ chain,
437
+ token,
438
+ amount,
439
+ action,
440
+ gasSponsorship: true,
441
+ ...spender && { spender }
442
+ });
443
+ }
367
444
  const eip712 = response.eip712;
368
445
  if (!eip712) {
369
446
  return jsonResponse({ error: "No EIP-712 data returned from API" }, 500);
@@ -391,7 +468,7 @@ async function handleTransferPrepare(client, body, config) {
391
468
  });
392
469
  }
393
470
  async function handleTransferExecute(client, body, config) {
394
- const { owner, chain = "base", eip712, signature } = body;
471
+ const { owner, chain = "base", eip712, signature, product } = body;
395
472
  const { gasSponsorPrivateKey, rpcUrls } = config;
396
473
  if (!owner || !eip712 || !signature) {
397
474
  return jsonResponse({ error: "Missing required parameters" }, 400);
@@ -416,22 +493,14 @@ async function handleTransferExecute(client, body, config) {
416
493
  chain: viemChain,
417
494
  transport: viem.http(rpcUrl)
418
495
  });
419
- const publicClient = viem.createPublicClient({
420
- chain: viemChain,
421
- transport: viem.http(rpcUrl)
496
+ const response = await client.gasSponsorship.gasSponsorshipPrepare({
497
+ chain,
498
+ owner,
499
+ sender: sponsorAccount.address,
500
+ eip712,
501
+ signature,
502
+ ...product === "credit" && { product: "credit" }
422
503
  });
423
- let response;
424
- try {
425
- response = await client.gasSponsorship.gasSponsorshipPrepare({
426
- chain,
427
- owner,
428
- sender: sponsorAccount.address,
429
- eip712,
430
- signature
431
- });
432
- } catch (prepareError) {
433
- throw prepareError;
434
- }
435
504
  const transaction = response.transaction;
436
505
  if (!transaction) {
437
506
  return jsonResponse(
@@ -445,12 +514,6 @@ async function handleTransferExecute(client, body, config) {
445
514
  value: transaction.value ? BigInt(transaction.value) : 0n,
446
515
  gas: transaction.gas ? BigInt(transaction.gas) : void 0
447
516
  });
448
- const receipt = await publicClient.waitForTransactionReceipt({
449
- hash: txHash
450
- });
451
- if (receipt.status === "reverted") {
452
- return jsonResponse({ error: "Transaction reverted" }, 500);
453
- }
454
517
  return jsonResponse({ txHash, success: true });
455
518
  }
456
519
  async function handleEarnAccountBalances(client, params) {
@@ -1362,6 +1425,7 @@ async function handleCreditTransfer(client, body) {
1362
1425
  chain,
1363
1426
  token,
1364
1427
  amount,
1428
+ action: "DEPOSIT",
1365
1429
  gasSponsorship: true
1366
1430
  });
1367
1431
  const eip712 = response.eip712;