payment-kit 1.25.10 → 1.26.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.
Files changed (86) hide show
  1. package/api/src/libs/session.ts +43 -25
  2. package/api/src/queues/subscription.ts +3 -1
  3. package/api/src/routes/checkout-sessions.ts +50 -34
  4. package/api/src/routes/meters.ts +28 -0
  5. package/blocklet.yml +2 -1
  6. package/package.json +6 -6
  7. package/src/components/customer/actions.tsx +1 -1
  8. package/src/components/customer/credit-overview.tsx +3 -1
  9. package/src/components/customer/overdraft-protection.tsx +1 -1
  10. package/src/components/event/list.tsx +1 -1
  11. package/src/components/filter-toolbar.tsx +2 -2
  12. package/src/components/invoice/action.tsx +3 -3
  13. package/src/components/invoice/list.tsx +1 -1
  14. package/src/components/invoice/recharge.tsx +2 -2
  15. package/src/components/meter/add-usage-dialog.tsx +1 -1
  16. package/src/components/passport/actions.tsx +1 -1
  17. package/src/components/passport/assign.tsx +1 -1
  18. package/src/components/payment-currency/add.tsx +1 -1
  19. package/src/components/payment-currency/edit.tsx +1 -1
  20. package/src/components/payment-intent/actions.tsx +4 -4
  21. package/src/components/payment-intent/list.tsx +1 -1
  22. package/src/components/payment-link/actions.tsx +4 -4
  23. package/src/components/payment-link/item.tsx +1 -1
  24. package/src/components/payouts/list.tsx +1 -1
  25. package/src/components/payouts/portal/list.tsx +1 -1
  26. package/src/components/price/upsell-select.tsx +1 -1
  27. package/src/components/price/upsell.tsx +2 -2
  28. package/src/components/pricing-table/actions.tsx +3 -3
  29. package/src/components/pricing-table/product-item.tsx +1 -1
  30. package/src/components/product/actions.tsx +3 -3
  31. package/src/components/product/create.tsx +1 -1
  32. package/src/components/product/cross-sell.tsx +2 -2
  33. package/src/components/promotion/active-redemptions.tsx +1 -1
  34. package/src/components/refund/list.tsx +1 -1
  35. package/src/components/subscription/actions/index.tsx +1 -1
  36. package/src/components/subscription/items/usage-records.tsx +4 -2
  37. package/src/components/subscription/list.tsx +1 -1
  38. package/src/components/subscription/metrics.tsx +3 -3
  39. package/src/components/subscription/portal/actions.tsx +15 -12
  40. package/src/components/subscription/portal/list.tsx +1 -1
  41. package/src/components/webhook/attempts.tsx +4 -4
  42. package/src/hooks/subscription.ts +2 -2
  43. package/src/pages/admin/billing/meter-events/index.tsx +3 -3
  44. package/src/pages/admin/billing/meters/index.tsx +1 -1
  45. package/src/pages/admin/billing/overdue/index.tsx +2 -2
  46. package/src/pages/admin/billing/subscriptions/detail.tsx +2 -2
  47. package/src/pages/admin/customers/customers/credit-grant/detail.tsx +1 -1
  48. package/src/pages/admin/customers/customers/credit-transaction/detail.tsx +1 -1
  49. package/src/pages/admin/customers/customers/detail.tsx +4 -4
  50. package/src/pages/admin/developers/events/detail.tsx +1 -1
  51. package/src/pages/admin/developers/webhooks/detail.tsx +1 -1
  52. package/src/pages/admin/developers/webhooks/index.tsx +1 -1
  53. package/src/pages/admin/payments/intents/detail.tsx +2 -2
  54. package/src/pages/admin/payments/payouts/detail.tsx +2 -2
  55. package/src/pages/admin/payments/refunds/detail.tsx +2 -2
  56. package/src/pages/admin/products/coupons/detail.tsx +1 -1
  57. package/src/pages/admin/products/coupons/index.tsx +1 -1
  58. package/src/pages/admin/products/exchange-rate-providers/index.tsx +1 -1
  59. package/src/pages/admin/products/links/create.tsx +1 -1
  60. package/src/pages/admin/products/links/detail.tsx +2 -2
  61. package/src/pages/admin/products/links/index.tsx +1 -1
  62. package/src/pages/admin/products/passports/index.tsx +1 -1
  63. package/src/pages/admin/products/prices/actions.tsx +4 -4
  64. package/src/pages/admin/products/prices/detail.tsx +2 -2
  65. package/src/pages/admin/products/pricing-tables/create.tsx +1 -1
  66. package/src/pages/admin/products/pricing-tables/detail.tsx +2 -2
  67. package/src/pages/admin/products/pricing-tables/index.tsx +1 -1
  68. package/src/pages/admin/products/products/index.tsx +1 -1
  69. package/src/pages/admin/products/promotion-codes/actions.tsx +2 -2
  70. package/src/pages/admin/products/promotion-codes/detail.tsx +2 -2
  71. package/src/pages/admin/products/promotion-codes/list.tsx +1 -1
  72. package/src/pages/admin/settings/payment-methods/create.tsx +1 -1
  73. package/src/pages/admin/settings/payment-methods/edit.tsx +1 -1
  74. package/src/pages/admin/settings/payment-methods/index.tsx +2 -2
  75. package/src/pages/admin/tax/detail.tsx +2 -2
  76. package/src/pages/admin/tax/list.tsx +1 -1
  77. package/src/pages/checkout/pay.tsx +2 -2
  78. package/src/pages/customer/index.tsx +1 -1
  79. package/src/pages/customer/invoice/past-due.tsx +1 -1
  80. package/src/pages/customer/payout/detail.tsx +1 -1
  81. package/src/pages/customer/refund/list.tsx +1 -1
  82. package/src/pages/customer/subscription/change-payment.tsx +2 -2
  83. package/src/pages/customer/subscription/change-plan.tsx +3 -3
  84. package/src/pages/customer/subscription/detail.tsx +3 -3
  85. package/src/pages/integrations/donations/index.tsx +1 -1
  86. package/vite.config.ts +2 -1
@@ -120,9 +120,16 @@ export async function getCheckoutAmount(
120
120
  .reduce(
121
121
  async (accPromise, x) => {
122
122
  const acc = await accPromise;
123
+ const price = x.upsell_price || x.price;
124
+
125
+ const isRecurring = price?.type === 'recurring';
126
+ // trialing/metered recurring items: no upfront charge, skip adding to subtotal
127
+ const skipAccAdd = isRecurring && (trialing || price?.recurring?.usage_type === 'metered');
123
128
 
124
129
  // Priority 1: Use custom_amount if available
125
130
  if (x.custom_amount) {
131
+ if (isRecurring) renew = renew.add(new BN(x.custom_amount));
132
+ if (skipAccAdd) return acc;
126
133
  return acc.add(new BN(x.custom_amount));
127
134
  }
128
135
 
@@ -136,6 +143,8 @@ export async function getCheckoutAmount(
136
143
  quoteId: (x as any).quote_id,
137
144
  quotedAmount: quote.quoted_amount,
138
145
  });
146
+ if (isRecurring) renew = renew.add(new BN(quote.quoted_amount));
147
+ if (skipAccAdd) return acc;
139
148
  return acc.add(new BN(quote.quoted_amount));
140
149
  }
141
150
 
@@ -154,27 +163,23 @@ export async function getCheckoutAmount(
154
163
  }
155
164
 
156
165
  // Priority 3: Calculate from price (fixed pricing or quote query failed)
157
- const price = x.upsell_price || x.price;
158
166
  const unitPrice = getPriceUintAmountByCurrency(price, currencyId);
159
167
 
168
+ const itemPrice = new BN(unitPrice).mul(new BN(x.quantity));
160
169
  if (price.custom_unit_amount) {
161
170
  if (unitPrice) {
162
- return acc.add(new BN(unitPrice).mul(new BN(x.quantity)));
171
+ if (isRecurring) renew = renew.add(itemPrice);
172
+ if (skipAccAdd) return acc;
173
+ return acc.add(itemPrice);
163
174
  }
164
175
  }
165
176
 
166
- if (price?.type === 'recurring') {
167
- renew = renew.add(new BN(unitPrice).mul(new BN(x.quantity)));
168
-
169
- if (trialing) {
170
- return acc;
171
- }
172
- if (price?.recurring?.usage_type === 'metered') {
173
- return acc;
174
- }
177
+ if (isRecurring) {
178
+ renew = renew.add(itemPrice);
179
+ if (skipAccAdd) return acc;
175
180
  }
176
181
 
177
- return acc.add(new BN(unitPrice).mul(new BN(x.quantity)));
182
+ return acc.add(itemPrice);
178
183
  },
179
184
  Promise.resolve(new BN(0))
180
185
  )
@@ -1301,19 +1306,24 @@ export async function validatePaymentAmounts(
1301
1306
  return { valid: true };
1302
1307
  }
1303
1308
 
1304
- // Case 2: Mixed or subscription only - validate subscription pricing
1309
+ // Case 2: Subscriptions - validate non-metered recurring items only.
1310
+ // Metered items are usage-based, their invoice amount depends on actual usage,
1311
+ // so checking unit_price against the minimum is meaningless.
1305
1312
  if (recurringItems.length > 0) {
1306
1313
  if (enableGrouping) {
1307
- // When grouping is enabled, validate each subscription product's unit price
1314
+ // Each subscription group is billed independently
1308
1315
  const priceGroups = groupLineItemsByPrice(lineItems);
1309
1316
 
1310
1317
  for (const [priceId, items] of Object.entries(priceGroups)) {
1311
- // Calculate total unit price for this subscription product
1312
- let totalUnitPrice = new BN(0);
1318
+ // Skip metered groups invoice amount depends on usage, not fixed price
1319
+ const price = items[0]?.upsell_price || items[0]?.price;
1320
+ // eslint-disable-next-line no-continue
1321
+ if (price?.recurring?.usage_type === 'metered') continue;
1313
1322
 
1323
+ let totalUnitPrice = new BN(0);
1314
1324
  items.forEach((item) => {
1315
- const price = item.upsell_price || item.price;
1316
- const unitPrice = getPriceUintAmountByCurrency(price, currency.id);
1325
+ const p = item.upsell_price || item.price;
1326
+ const unitPrice = getPriceUintAmountByCurrency(p, currency.id);
1317
1327
  totalUnitPrice = totalUnitPrice.add(new BN(unitPrice).mul(new BN(item.quantity)));
1318
1328
  });
1319
1329
 
@@ -1326,13 +1336,21 @@ export async function validatePaymentAmounts(
1326
1336
  }
1327
1337
  }
1328
1338
  } else {
1329
- // When grouping is disabled, validate total subscription amount
1330
- const { renew } = await getCheckoutAmount(lineItems, currency.id);
1331
- if (new BN(renew).lt(new BN(minAmountInUnits))) {
1332
- return {
1333
- valid: false,
1334
- error: 'Total subscription amount must be greater or equal to 0.5 USD',
1335
- };
1339
+ // Non-grouping: all recurring items share one invoice
1340
+ const nonMeteredItems = recurringItems.filter((item) => {
1341
+ const price = item.upsell_price || item.price;
1342
+ return price?.recurring?.usage_type !== 'metered';
1343
+ });
1344
+
1345
+ // If all recurring items are metered, skip validation
1346
+ if (nonMeteredItems.length > 0) {
1347
+ const { renew } = await getCheckoutAmount(nonMeteredItems, currency.id);
1348
+ if (new BN(renew).lt(new BN(minAmountInUnits))) {
1349
+ return {
1350
+ valid: false,
1351
+ error: 'Total subscription amount must be greater or equal to 0.5 USD',
1352
+ };
1353
+ }
1336
1354
  }
1337
1355
  }
1338
1356
  }
@@ -399,7 +399,9 @@ const doHandleSubscriptionInvoice = async ({
399
399
  });
400
400
  }
401
401
 
402
- const shouldMarkOverdue = slippageCheck?.belowThreshold === true;
402
+ // Skip slippage check when final amount is 0 (e.g. 100% discount) — no crypto payment needed
403
+ const isFinalAmountZero = new BN(safeFinalTotal).isZero();
404
+ const shouldMarkOverdue = slippageCheck?.belowThreshold === true && !isFinalAmountZero;
403
405
  const invoiceStatus = shouldMarkOverdue && status === 'open' ? 'uncollectible' : status;
404
406
 
405
407
  const { invoice } = await ensureInvoiceAndItems({
@@ -550,13 +550,15 @@ async function createOrUpdatePaymentIntent(
550
550
  if (shouldLockQuotes) {
551
551
  const lockedAtMs = paymentIntent.quote_locked_at ? new Date(paymentIntent.quote_locked_at).getTime() : null;
552
552
  if (lockedAtMs && nowMs - lockedAtMs > QUOTE_LOCK_DURATION_MS) {
553
- await paymentIntent.update({ quote_locked_at: undefined });
554
- await checkoutSession.update({
555
- metadata: { ...checkoutSession.metadata, quote_locked_at: undefined },
553
+ // Lock expired reset instead of throwing
554
+ // Intent: "Quote never expires due to time — time limits are flow SLAs, not price validity"
555
+ logger.info('Quote lock expired, resetting for resubmit', {
556
+ sessionId: checkoutSession.id,
557
+ lockedAtMs,
558
+ expiredMs: nowMs - lockedAtMs,
556
559
  });
557
- throw new CustomError(409, 'QUOTE_LOCK_EXPIRED', 'Quote lock expired, please refresh and retry');
558
- }
559
- if (!lockedAtMs) {
560
+ updateData.quote_locked_at = new Date(nowMs);
561
+ } else if (!lockedAtMs) {
560
562
  updateData.quote_locked_at = new Date(nowMs);
561
563
  }
562
564
  }
@@ -1894,38 +1896,52 @@ async function createQuotesAtSubmit(options: {
1894
1896
 
1895
1897
  // Early check: if user has set min_acceptable_rate, verify current rate is above it
1896
1898
  // This prevents users from submitting when the rate has already dropped below their limit
1897
- if (minAcceptableRate) {
1898
- try {
1899
- const rateResult = await fetchCurrentExchangeRate(
1900
- paymentCurrency as PaymentCurrency,
1901
- paymentCurrency?.payment_method as PaymentMethod
1902
- );
1903
-
1904
- if (isRateBelowMinAcceptableRate(rateResult.rate, minAcceptableRate)) {
1905
- logger.info('Current rate below user slippage limit', {
1906
- sessionId: checkoutSession.id,
1907
- currentRate: rateResult.rate,
1908
- minAcceptableRate,
1909
- slippagePercent,
1910
- });
1899
+ // Skip for idempotent retries: if quotes already exist, reuse them (intent: "retry with same Quote")
1900
+ if (minAcceptableRate && dynamicItems.length > 0) {
1901
+ const firstItem = dynamicItems[0]!;
1902
+ const firstPriceId = firstItem.upsell_price_id || firstItem.price_id;
1903
+ const firstItemKey = `${idempotencyKey}:${firstPriceId}`;
1904
+ const existingQuote = await PriceQuote.findByIdempotencyKey(firstItemKey);
1905
+
1906
+ if (existingQuote) {
1907
+ logger.info('Skipping early rate check for idempotent retry (quotes already exist)', {
1908
+ sessionId: checkoutSession.id,
1909
+ idempotencyKey,
1910
+ existingQuoteId: existingQuote.id,
1911
+ });
1912
+ } else {
1913
+ try {
1914
+ const rateResult = await fetchCurrentExchangeRate(
1915
+ paymentCurrency as PaymentCurrency,
1916
+ paymentCurrency?.payment_method as PaymentMethod
1917
+ );
1911
1918
 
1912
- return {
1913
- lineItems,
1914
- consumedQuotes: [],
1915
- validationError: {
1916
- code: 'RATE_BELOW_SLIPPAGE_LIMIT',
1917
- message: `Current exchange rate (${rateResult.rate}) is below your minimum acceptable rate (${minAcceptableRate}). Please update your slippage settings.`,
1919
+ if (isRateBelowMinAcceptableRate(rateResult.rate, minAcceptableRate)) {
1920
+ logger.info('Current rate below user slippage limit', {
1921
+ sessionId: checkoutSession.id,
1918
1922
  currentRate: rateResult.rate,
1919
1923
  minAcceptableRate,
1920
- },
1921
- };
1924
+ slippagePercent,
1925
+ });
1926
+
1927
+ return {
1928
+ lineItems,
1929
+ consumedQuotes: [],
1930
+ validationError: {
1931
+ code: 'RATE_BELOW_SLIPPAGE_LIMIT',
1932
+ message: `Current exchange rate (${rateResult.rate}) is below your minimum acceptable rate (${minAcceptableRate}). Please update your slippage settings.`,
1933
+ currentRate: rateResult.rate,
1934
+ minAcceptableRate,
1935
+ },
1936
+ };
1937
+ }
1938
+ } catch (error: any) {
1939
+ logger.warn('Failed to fetch rate for slippage limit check', {
1940
+ sessionId: checkoutSession.id,
1941
+ error: error.message,
1942
+ });
1943
+ // Continue with normal flow if rate fetch fails - will be caught later
1922
1944
  }
1923
- } catch (error: any) {
1924
- logger.warn('Failed to fetch rate for slippage limit check', {
1925
- sessionId: checkoutSession.id,
1926
- error: error.message,
1927
- });
1928
- // Continue with normal flow if rate fetch fails - will be caught later
1929
1945
  }
1930
1946
  }
1931
1947
 
@@ -137,6 +137,34 @@ router.post('/', auth, async (req, res) => {
137
137
  }
138
138
  });
139
139
 
140
+ // Public endpoint: only returns safe fields, no auth required
141
+ const PUBLIC_METER_FIELDS = ['id', 'name', 'event_name', 'status', 'unit', 'description', 'currency_id'] as const;
142
+
143
+ router.get('/public/:id', async (req, res) => {
144
+ try {
145
+ const meter = await Meter.findOne({
146
+ where: {
147
+ [Op.or]: [{ id: req.params.id }, { event_name: req.params.id }],
148
+ },
149
+ include: [{ model: PaymentCurrency, as: 'paymentCurrency' }],
150
+ });
151
+
152
+ if (!meter) {
153
+ return res.status(404).json({ error: 'Meter not found' });
154
+ }
155
+
156
+ return res.json({
157
+ ...pick(meter.toJSON(), PUBLIC_METER_FIELDS),
158
+ paymentCurrency: (meter as any).paymentCurrency
159
+ ? pick((meter as any).paymentCurrency.toJSON(), ['id', 'name', 'symbol', 'decimal', 'logo', 'type'])
160
+ : null,
161
+ });
162
+ } catch (err) {
163
+ logger.error('get public meter failed', { error: err?.message, meterId: req.params.id });
164
+ return res.status(400).json({ error: err?.message });
165
+ }
166
+ });
167
+
140
168
  router.get('/:id', auth, async (req, res) => {
141
169
  try {
142
170
  const meter = await Meter.findOne({
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.25.10
17
+ version: 1.26.1
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
@@ -47,6 +47,7 @@ interfaces:
47
47
  - /api/products/**
48
48
  - /methods/**
49
49
  - /currencies/**
50
+ - /meters/public/**
50
51
  blockUnauthorized: false
51
52
  proxyBehavior: service
52
53
  community: ''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.25.10",
3
+ "version": "1.26.1",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "prelint": "npm run types",
@@ -59,9 +59,9 @@
59
59
  "@blocklet/error": "^0.3.5",
60
60
  "@blocklet/js-sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
61
61
  "@blocklet/logger": "^1.17.8-beta-20260104-120132-cb5b1914",
62
- "@blocklet/payment-broker-client": "1.25.10",
63
- "@blocklet/payment-react": "1.25.10",
64
- "@blocklet/payment-vendor": "1.25.10",
62
+ "@blocklet/payment-broker-client": "1.26.1",
63
+ "@blocklet/payment-react": "1.26.1",
64
+ "@blocklet/payment-vendor": "1.26.1",
65
65
  "@blocklet/sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
66
66
  "@blocklet/ui-react": "^3.5.1",
67
67
  "@blocklet/uploader": "^0.3.19",
@@ -132,7 +132,7 @@
132
132
  "devDependencies": {
133
133
  "@abtnode/types": "^1.17.8-beta-20260104-120132-cb5b1914",
134
134
  "@arcblock/eslint-config-ts": "^0.3.3",
135
- "@blocklet/payment-types": "1.25.10",
135
+ "@blocklet/payment-types": "1.26.1",
136
136
  "@types/cookie-parser": "^1.4.9",
137
137
  "@types/cors": "^2.8.19",
138
138
  "@types/debug": "^4.1.12",
@@ -179,5 +179,5 @@
179
179
  "parser": "typescript"
180
180
  }
181
181
  },
182
- "gitHead": "36417122ec9a0cfd1e289b4ca21d33f1b5d87a9a"
182
+ "gitHead": "1ba42f376f040b1214d992420cda37053fc14288"
183
183
  }
@@ -25,7 +25,7 @@ export default function CustomerActions({ data, onChange, variant = 'compact' }:
25
25
  const onUpdateInfo = async (updates: TCustomerExpanded) => {
26
26
  try {
27
27
  setState({ loading: true });
28
- await api.put(`/api/customers/${data.id}`, updates).then((res) => res.data);
28
+ await api.put(`/api/customers/${data.id}`, updates).then((res: any) => res.data);
29
29
  Toast.success(t('common.saved'));
30
30
  onChange('update');
31
31
  } catch (err) {
@@ -117,7 +117,9 @@ export default function CreditOverview({ customerId, settings, mode = 'portal' }
117
117
 
118
118
  const handleRecharge = async (currency: TPaymentCurrency) => {
119
119
  try {
120
- const response = await api.get(`/api/payment-currencies/${currency.id}/recharge-config`).then((res) => res.data);
120
+ const response = await api
121
+ .get(`/api/payment-currencies/${currency.id}/recharge-config`)
122
+ .then((res: any) => res.data);
121
123
  if (response.recharge_config && response.recharge_config.payment_url) {
122
124
  const url = new URL(response.recharge_config.payment_url);
123
125
  url.searchParams.set('redirect', window.location.href);
@@ -35,7 +35,7 @@ const fetchCycleAmount = (
35
35
  subscriptionId: string,
36
36
  params: { overdraftProtection: boolean }
37
37
  ): Promise<{ amount: string; gas: string; currency: TPaymentCurrency }> => {
38
- return api.get(`/api/subscriptions/${subscriptionId}/cycle-amount`, { params }).then((res) => res.data);
38
+ return api.get(`/api/subscriptions/${subscriptionId}/cycle-amount`, { params }).then((res: any) => res.data);
39
39
  };
40
40
 
41
41
  function safeAdd(currency: { decimal: number }, ...numbers: string[]) {
@@ -16,7 +16,7 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TEventExpa
16
16
  Object.keys(params).forEach((key) => {
17
17
  search.set(key, String(params[key]));
18
18
  });
19
- return api.get(`/api/events?${search.toString()}`).then((res) => res.data);
19
+ return api.get(`/api/events?${search.toString()}`).then((res: any) => res.data);
20
20
  };
21
21
 
22
22
  type SearchProps = {
@@ -30,7 +30,7 @@ const fetchUserData = (params: Record<string, any> = {}): Promise<{ list: TCusto
30
30
  }
31
31
  search.set(key, String(v));
32
32
  });
33
- return api.get(`api/customers?${search.toString()}`).then((res) => res.data);
33
+ return api.get(`api/customers?${search.toString()}`).then((res: any) => res.data);
34
34
  };
35
35
 
36
36
  const fetchSubscriptionItems = (params: Record<string, any> = {}): Promise<{ list: TCustomer[]; count: number }> => {
@@ -39,7 +39,7 @@ const fetchSubscriptionItems = (params: Record<string, any> = {}): Promise<{ lis
39
39
  const v = params[key];
40
40
  search.set(key, String(v));
41
41
  });
42
- return api.get(`api/subscription-items?${search.toString()}`).then((res) => res.data);
42
+ return api.get(`api/subscription-items?${search.toString()}`).then((res: any) => res.data);
43
43
  };
44
44
 
45
45
  type Props = {
@@ -55,7 +55,7 @@ export default function InvoiceActions({ data, variant = 'compact', onChange, mo
55
55
  try {
56
56
  setState({ loading: true });
57
57
  if (state.action === 'return-stake') {
58
- const result = await api.post(`/api/invoices/${data.id}/return-stake`).then((res) => res.data);
58
+ const result = await api.post(`/api/invoices/${data.id}/return-stake`).then((res: any) => res.data);
59
59
  if (result.success) {
60
60
  Toast.success(t('admin.invoice.returnStake.success'));
61
61
  } else {
@@ -69,11 +69,11 @@ export default function InvoiceActions({ data, variant = 'compact', onChange, mo
69
69
  invoiceId: data.id,
70
70
  },
71
71
  })
72
- .then((res) => res.data);
72
+ .then((res: any) => res.data);
73
73
  Toast.success(t('admin.invoice.retryUncollectible.success'));
74
74
  }
75
75
  if (state.action === 'void') {
76
- await api.post(`/api/invoices/${data.id}/void`).then((res) => res.data);
76
+ await api.post(`/api/invoices/${data.id}/void`).then((res: any) => res.data);
77
77
  Toast.success(t('admin.invoice.void.success'));
78
78
  }
79
79
  onChange(state.action);
@@ -52,7 +52,7 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TInvoiceEx
52
52
  search.set(key, String(v));
53
53
  });
54
54
 
55
- return api.get(`/api/invoices?${search.toString()}`).then((res) => res.data);
55
+ return api.get(`/api/invoices?${search.toString()}`).then((res: any) => res.data);
56
56
  };
57
57
 
58
58
  type SearchProps = {
@@ -35,12 +35,12 @@ const fetchData = (
35
35
  });
36
36
 
37
37
  if (subscriptionId) {
38
- return api.get(`/api/subscriptions/${subscriptionId}/recharge?${search.toString()}`).then((res) => res.data);
38
+ return api.get(`/api/subscriptions/${subscriptionId}/recharge?${search.toString()}`).then((res: any) => res.data);
39
39
  }
40
40
 
41
41
  if (currencyId) {
42
42
  search.set('currency_id', currencyId);
43
- return api.get(`/api/invoices/recharge?${search.toString()}`).then((res) => res.data);
43
+ return api.get(`/api/invoices/recharge?${search.toString()}`).then((res: any) => res.data);
44
44
  }
45
45
 
46
46
  return Promise.resolve({ list: [], count: 0 });
@@ -50,7 +50,7 @@ const addMeterEvent = (data: any): Promise<any> => {
50
50
  },
51
51
  ],
52
52
  })
53
- .then((res) => res.data);
53
+ .then((res: any) => res.data);
54
54
  };
55
55
 
56
56
  export default function AddUsageDialog({ open, onClose, meterId, customers, onSuccess }: AddUsageDialogProps) {
@@ -30,7 +30,7 @@ export default function PassportActions(rawProps: Props) {
30
30
  try {
31
31
  setState({ loading: true });
32
32
  // eslint-disable-next-line react/prop-types
33
- await api.delete(`/api/passports/assign/${props.data.name}`).then((res) => res.data);
33
+ await api.delete(`/api/passports/assign/${props.data.name}`).then((res: any) => res.data);
34
34
  Toast.success(t('common.saved'));
35
35
  } catch (err) {
36
36
  console.error(err);
@@ -6,7 +6,7 @@ import { useRequest } from 'ahooks';
6
6
  import { useEffect, useState } from 'react';
7
7
 
8
8
  const fetchData = (): Promise<any[]> => {
9
- return api.get('/api/passports').then((res) => res.data);
9
+ return api.get('/api/passports').then((res: any) => res.data);
10
10
  };
11
11
 
12
12
  export default function AssignPassportDialog(props: { id: string; onCancel: any }) {
@@ -116,7 +116,7 @@ export default function PaymentCurrencyAdd({
116
116
  dispatch('drawer.submitted');
117
117
  dispatch('paymentCurrency.added');
118
118
  })
119
- .catch((err) => {
119
+ .catch((err: any) => {
120
120
  setState({ loading: false });
121
121
  console.error(err);
122
122
  Toast.error(formatError(err));
@@ -132,7 +132,7 @@ export default function PaymentCurrencyEdit({
132
132
  dispatch('drawer.submitted');
133
133
  dispatch('paymentCurrency.updated');
134
134
  })
135
- .catch((err) => {
135
+ .catch((err: any) => {
136
136
  setState({ loading: false });
137
137
  console.error(err);
138
138
  Toast.error(formatError(err));
@@ -28,7 +28,7 @@ type Props = {
28
28
  };
29
29
 
30
30
  const fetchRefundData = (id: string) => {
31
- return api.get(`/api/payment-intents/${id}/refundable-amount`).then((res) => res.data);
31
+ return api.get(`/api/payment-intents/${id}/refundable-amount`).then((res: any) => res.data);
32
32
  };
33
33
 
34
34
  function RefundForm({ data, refundMaxAmount }: { data: TPaymentIntentExpanded; refundMaxAmount: string }) {
@@ -176,7 +176,7 @@ export function PaymentIntentActionsInner({ data, variant = 'compact', onChange
176
176
  });
177
177
  const [refundMaxAmount, setRefundMaxAmount] = useState('0');
178
178
  const isSlash = data.payment_details?.arcblock?.type === 'slash' && data.paymentMethod?.type === 'arcblock';
179
- const { runAsync: runRefundAmountAsync } = useRequest(
179
+ const { runAsync: runRefundAmountAsync } = useRequest<any, any[]>(
180
180
  () => {
181
181
  if (isSlash) {
182
182
  return Promise.resolve({ amount: '0' });
@@ -184,7 +184,7 @@ export function PaymentIntentActionsInner({ data, variant = 'compact', onChange
184
184
  return fetchRefundData(data.id);
185
185
  },
186
186
  {
187
- onSuccess: (res) => {
187
+ onSuccess: (res: any) => {
188
188
  const amount = formatBNStr(res?.amount, data.paymentCurrency.decimal);
189
189
  setRefundMaxAmount(amount);
190
190
  },
@@ -200,7 +200,7 @@ export function PaymentIntentActionsInner({ data, variant = 'compact', onChange
200
200
  }
201
201
  try {
202
202
  setState({ loading: true });
203
- await api.put(`/api/payment-intents/${data.id}/refund`, refund).then((res) => res.data);
203
+ await api.put(`/api/payment-intents/${data.id}/refund`, refund).then((res: any) => res.data);
204
204
  Toast.success(t('admin.paymentIntent.refundSuccess'));
205
205
  onChange('refund');
206
206
  runRefundAmountAsync();
@@ -31,7 +31,7 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TPaymentIn
31
31
  }
32
32
  search.set(key, String(v));
33
33
  });
34
- return api.get(`/api/payment-intents?${search.toString()}`).then((res) => res.data);
34
+ return api.get(`/api/payment-intents?${search.toString()}`).then((res: any) => res.data);
35
35
  };
36
36
 
37
37
  type SearchProps = {
@@ -28,7 +28,7 @@ export default function PaymentLinkActions({ data, variant = 'compact', onChange
28
28
  const onUpdate = async (updates: TPaymentLinkExpanded) => {
29
29
  try {
30
30
  setState({ loading: true });
31
- await api.put(`/api/payment-links/${data.id}`, updates).then((res) => res.data);
31
+ await api.put(`/api/payment-links/${data.id}`, updates).then((res: any) => res.data);
32
32
  Toast.success(t('common.saved'));
33
33
  onChange(state.action);
34
34
  } catch (err) {
@@ -41,7 +41,7 @@ export default function PaymentLinkActions({ data, variant = 'compact', onChange
41
41
  const onArchive = async () => {
42
42
  try {
43
43
  setState({ loading: true });
44
- await api.put(`/api/payment-links/${data.id}/archive`).then((res) => res.data);
44
+ await api.put(`/api/payment-links/${data.id}/archive`).then((res: any) => res.data);
45
45
  Toast.success(t('common.saved'));
46
46
  onChange(state.action);
47
47
  } catch (err) {
@@ -54,7 +54,7 @@ export default function PaymentLinkActions({ data, variant = 'compact', onChange
54
54
  const onRemove = async () => {
55
55
  try {
56
56
  setState({ loading: true });
57
- await api.delete(`/api/payment-links/${data.id}`).then((res) => res.data);
57
+ await api.delete(`/api/payment-links/${data.id}`).then((res: any) => res.data);
58
58
  Toast.success(t('common.removed'));
59
59
  onChange(state.action);
60
60
  } catch (err) {
@@ -72,7 +72,7 @@ export default function PaymentLinkActions({ data, variant = 'compact', onChange
72
72
  .put(`/api/payment-links/${data.id}`, {
73
73
  allow_promotion_codes: !data.allow_promotion_codes,
74
74
  })
75
- .then((res) => res.data);
75
+ .then((res: any) => res.data);
76
76
  Toast.success(t('common.saved'));
77
77
  onChange(state.action);
78
78
  } catch (err) {
@@ -34,7 +34,7 @@ export default function LineItem({ prefix, product, valid, onUpdate, onRemove }:
34
34
  const onSave = async (updates: TProduct) => {
35
35
  try {
36
36
  setState({ loading: true });
37
- await api.put(`/api/products/${product.id}`, updates).then((res) => res.data);
37
+ await api.put(`/api/products/${product.id}`, updates).then((res: any) => res.data);
38
38
  Toast.success(t('common.saved'));
39
39
  onUpdate();
40
40
  } catch (err) {
@@ -34,7 +34,7 @@ const fetchData = (params: Record<string, any> = {}): Promise<{ list: TPayoutExp
34
34
  }
35
35
  search.set(key, String(v));
36
36
  });
37
- return api.get(`/api/payouts?${search.toString()}`).then((res) => res.data);
37
+ return api.get(`/api/payouts?${search.toString()}`).then((res: any) => res.data);
38
38
  };
39
39
 
40
40
  type SearchProps = {
@@ -31,7 +31,7 @@ const fetchData = (
31
31
  }
32
32
  search.set(key, String(v));
33
33
  });
34
- return api.get(`/api/payouts/mine?${search.toString()}`).then((res) => res.data);
34
+ return api.get(`/api/payouts/mine?${search.toString()}`).then((res: any) => res.data);
35
35
  };
36
36
 
37
37
  type SearchProps = {
@@ -16,7 +16,7 @@ type Props = {
16
16
  };
17
17
 
18
18
  const fetchData = (id: string): Promise<TPriceExpanded[]> => {
19
- return api.get(`/api/prices/${id}/upsell`).then((res) => res.data);
19
+ return api.get(`/api/prices/${id}/upsell`).then((res: any) => res.data);
20
20
  };
21
21
 
22
22
  export default function UpsellSelect({ price, onSelect, onAdd }: Props) {
@@ -17,7 +17,7 @@ export function UpsellForm({ data, onChange }: { data: TPriceExpanded; onChange:
17
17
  const onRemoveUpsell = async () => {
18
18
  try {
19
19
  setState({ loading: true });
20
- await api.put(`/api/prices/${data.id}`, { upsell: { upsells_to_id: '' } }).then((res) => res.data);
20
+ await api.put(`/api/prices/${data.id}`, { upsell: { upsells_to_id: '' } }).then((res: any) => res.data);
21
21
  setState({ loading: false });
22
22
  onChange();
23
23
  } catch (err) {
@@ -30,7 +30,7 @@ export function UpsellForm({ data, onChange }: { data: TPriceExpanded; onChange:
30
30
  const onSelectUpsell = async (id: string) => {
31
31
  try {
32
32
  setState({ loading: true });
33
- await api.put(`/api/prices/${data.id}`, { upsell: { upsells_to_id: id } }).then((res) => res.data);
33
+ await api.put(`/api/prices/${data.id}`, { upsell: { upsells_to_id: id } }).then((res: any) => res.data);
34
34
  setState({ loading: false });
35
35
  onChange();
36
36
  } catch (err) {