payment-kit 1.13.224 → 1.13.225

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.
@@ -94,7 +94,7 @@ function init() {
94
94
  },
95
95
  ],
96
96
  onError: (error: Error, name: string) => {
97
- logger.error('run job failed', { name, error: error.message, stack: error.stack });
97
+ logger.error('run job failed', { name, error });
98
98
  },
99
99
  });
100
100
  }
package/api/src/index.ts CHANGED
@@ -92,7 +92,7 @@ if (isProduction) {
92
92
 
93
93
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
94
94
  app.use(<ErrorRequestHandler>((err, req, res, _next) => {
95
- logger.error(err.stack);
95
+ console.error(err);
96
96
  if (req.accepts('json')) {
97
97
  res.status(500).send({ error: err.message });
98
98
  } else {
@@ -1,6 +1,7 @@
1
1
  import { JsonRpcProvider, TransactionReceipt, ethers } from 'ethers';
2
2
 
3
3
  import { ethWallet } from '../../libs/auth';
4
+ import logger from '../../libs/logger';
4
5
  import type { PaymentMethod } from '../../store/models/payment-method';
5
6
  import { getApproveFunction } from './contract';
6
7
  import erc20Abi from './erc20-abi.json';
@@ -125,7 +126,7 @@ export async function sendErc20ToUser(
125
126
  return receipt;
126
127
  }
127
128
 
128
- export async function executeEvmTransactions(
129
+ export async function executeEvmTransaction(
129
130
  type: string,
130
131
  userDid: string,
131
132
  claims: any[],
@@ -133,6 +134,7 @@ export async function executeEvmTransactions(
133
134
  ) {
134
135
  const client = paymentMethod.getEvmClient();
135
136
  const claim = claims.find((x) => x.type === 'signature');
137
+ logger.info('executeEvmTransaction', { type, userDid, claim });
136
138
  const receipt = await waitForEvmTxReceipt(client, claim.hash);
137
139
  if (!receipt.status) {
138
140
  throw new Error(`EVM Transaction failed: ${claim.hash}`);
@@ -4,15 +4,15 @@ import waitFor from 'p-wait-for';
4
4
  import logger from '../../libs/logger';
5
5
 
6
6
  export async function waitForEvmTxReceipt(provider: JsonRpcProvider, txHash: string) {
7
- let minted: TransactionResponse;
7
+ let mined: TransactionResponse;
8
8
  let receipt: TransactionReceipt;
9
9
 
10
10
  await waitFor(
11
11
  async () => {
12
12
  // @ts-ignore
13
- minted = await provider.getTransaction(txHash);
14
- logger.info('waitForTxReceipt.mintCheck', minted);
15
- return !!minted?.blockNumber;
13
+ mined = await provider.getTransaction(txHash);
14
+ logger.info('waitForTxReceipt.mineCheck', { mined, txHash });
15
+ return Number(mined?.blockNumber) > 0;
16
16
  },
17
17
  { interval: 3000, timeout: 30 * 60 * 1000 }
18
18
  );
@@ -21,7 +21,7 @@ export async function waitForEvmTxReceipt(provider: JsonRpcProvider, txHash: str
21
21
  async () => {
22
22
  // @ts-ignore
23
23
  receipt = await provider.getTransactionReceipt(txHash);
24
- logger.info('waitForTxReceipt.receiptCheck', receipt);
24
+ logger.info('waitForTxReceipt.receiptCheck', { txHash, receipt });
25
25
  return !!receipt;
26
26
  },
27
27
  { interval: 1000, timeout: 60 * 1000 }
@@ -30,3 +30,14 @@ export async function waitForEvmTxReceipt(provider: JsonRpcProvider, txHash: str
30
30
  // @ts-ignore
31
31
  return receipt;
32
32
  }
33
+
34
+ export async function waitForEvmTxConfirm(provider: JsonRpcProvider, height: number, confirmation: number = 1) {
35
+ await waitFor(
36
+ async () => {
37
+ const number = Number(await provider.getBlockNumber());
38
+ logger.info('waitForTxReceipt.heightCheck', { number, height });
39
+ return number - height >= confirmation;
40
+ },
41
+ { interval: 3000, timeout: 30 * 60 * 1000 }
42
+ );
43
+ }
@@ -14,6 +14,7 @@ import { Invoice, PaymentCurrency, PaymentIntent, PaymentMethod, TCustomer, TLin
14
14
  import type { TPaymentCurrency } from '../store/models/payment-currency';
15
15
  import { blocklet, ethWallet, wallet } from './auth';
16
16
  import { OCAP_PAYMENT_TX_TYPE } from './util';
17
+ import logger from './logger';
17
18
 
18
19
  export interface SufficientForPaymentResult {
19
20
  sufficient: boolean;
@@ -118,6 +119,7 @@ export async function isDelegationSufficientForPayment(args: {
118
119
  }
119
120
 
120
121
  const allowance = await fetchErc20Allowance(provider, paymentCurrency.contract, userDid, ethWallet.address);
122
+ logger.info('isDelegationSufficientForPayment', { userDid, amount, allowance, contract: paymentCurrency.contract });
121
123
  if (new BN(allowance).lt(new BN(amount))) {
122
124
  return { sufficient: false, reason: 'NO_ENOUGH_ALLOWANCE' };
123
125
  }
@@ -1,4 +1,5 @@
1
- import { executeEvmTransactions } from '../../integrations/ethereum/token';
1
+ import { executeEvmTransaction } from '../../integrations/ethereum/token';
2
+ import { waitForEvmTxConfirm } from '../../integrations/ethereum/tx';
2
3
  import type { CallbackArgs } from '../../libs/auth';
3
4
  import { isDelegationSufficientForPayment } from '../../libs/payment';
4
5
  import { getFastCheckoutAmount } from '../../libs/session';
@@ -148,8 +149,12 @@ export default {
148
149
 
149
150
  if (paymentMethod.type === 'ethereum') {
150
151
  await prepareTxExecution();
151
- const paymentDetails = await executeEvmTransactions('approve', userDid, claims, paymentMethod);
152
- await afterTxExecution(paymentDetails);
152
+ const paymentDetails = await executeEvmTransaction('approve', userDid, claims, paymentMethod);
153
+ waitForEvmTxConfirm(paymentMethod.getEvmClient(), +paymentDetails.block_height, paymentMethod.confirmation.block)
154
+ .then(async () => {
155
+ await afterTxExecution(paymentDetails);
156
+ })
157
+ .catch(console.error);
153
158
  return { hash: paymentDetails.tx_hash };
154
159
  }
155
160
 
@@ -1,4 +1,5 @@
1
- import { executeEvmTransactions } from '../../integrations/ethereum/token';
1
+ import { executeEvmTransaction } from '../../integrations/ethereum/token';
2
+ import { waitForEvmTxConfirm } from '../../integrations/ethereum/tx';
2
3
  import type { CallbackArgs } from '../../libs/auth';
3
4
  import { isDelegationSufficientForPayment } from '../../libs/payment';
4
5
  import { getFastCheckoutAmount } from '../../libs/session';
@@ -148,8 +149,12 @@ export default {
148
149
  if (paymentMethod.type === 'ethereum') {
149
150
  await prepareTxExecution();
150
151
 
151
- const paymentDetails = await executeEvmTransactions('approve', userDid, claims, paymentMethod);
152
- await afterTxExecution(paymentDetails);
152
+ const paymentDetails = await executeEvmTransaction('approve', userDid, claims, paymentMethod);
153
+ waitForEvmTxConfirm(paymentMethod.getEvmClient(), +paymentDetails.block_height, paymentMethod.confirmation.block)
154
+ .then(async () => {
155
+ await afterTxExecution(paymentDetails);
156
+ })
157
+ .catch(console.error);
153
158
 
154
159
  return { hash: paymentDetails.tx_hash };
155
160
  }
@@ -3,7 +3,7 @@ import { toBase58 } from '@ocap/util';
3
3
  import { fromAddress } from '@ocap/wallet';
4
4
 
5
5
  import { encodeTransferItx } from '../../integrations/ethereum/token';
6
- import { waitForEvmTxReceipt } from '../../integrations/ethereum/tx';
6
+ import { waitForEvmTxConfirm, waitForEvmTxReceipt } from '../../integrations/ethereum/tx';
7
7
  import type { CallbackArgs } from '../../libs/auth';
8
8
  import { ethWallet, wallet } from '../../libs/auth';
9
9
  import logger from '../../libs/logger';
@@ -168,14 +168,18 @@ export default {
168
168
  throw new Error(`EVM Transaction failed: ${claim.hash}`);
169
169
  }
170
170
 
171
- await afterTxExecution({
172
- tx_hash: claim.hash,
173
- block_height: receipt.blockNumber.toString(),
174
- gas_used: receipt.gasUsed.toString(),
175
- gas_price: receipt.gasPrice.toString(),
176
- payer: userDid,
177
- type: 'transfer',
178
- });
171
+ waitForEvmTxConfirm(client, Number(receipt.blockNumber), paymentMethod.confirmation.block)
172
+ .then(async () => {
173
+ await afterTxExecution({
174
+ tx_hash: claim.hash,
175
+ block_height: receipt.blockNumber.toString(),
176
+ gas_used: receipt.gasUsed.toString(),
177
+ gas_price: receipt.gasPrice.toString(),
178
+ payer: userDid,
179
+ type: 'transfer',
180
+ });
181
+ })
182
+ .catch(console.error);
179
183
 
180
184
  return { hash: claim.hash };
181
185
  }
@@ -2,7 +2,8 @@ import type { Transaction, TransferV3Tx } from '@ocap/client';
2
2
  import { toBase58 } from '@ocap/util';
3
3
  import { fromAddress } from '@ocap/wallet';
4
4
 
5
- import { encodeTransferItx, executeEvmTransactions } from '../../integrations/ethereum/token';
5
+ import { encodeTransferItx, executeEvmTransaction } from '../../integrations/ethereum/token';
6
+ import { waitForEvmTxConfirm } from '../../integrations/ethereum/tx';
6
7
  import { CallbackArgs, ethWallet } from '../../libs/auth';
7
8
  import logger from '../../libs/logger';
8
9
  import { getGasPayerExtra } from '../../libs/payment';
@@ -132,7 +133,8 @@ export default {
132
133
 
133
134
  return { hash: txHash };
134
135
  } catch (err) {
135
- logger.error('Failed to finalize paymentIntent', { paymentIntent: paymentIntent.id, error: err });
136
+ console.error(err);
137
+ logger.error('Failed to finalize paymentIntent on arcblock', { paymentIntent: paymentIntent.id, error: err });
136
138
  await paymentIntent.update({ status: 'requires_capture' });
137
139
  return {};
138
140
  }
@@ -142,18 +144,27 @@ export default {
142
144
  try {
143
145
  await paymentIntent.update({ status: 'processing' });
144
146
 
145
- const paymentDetails = await executeEvmTransactions('transfer', userDid, claims, paymentMethod);
146
- await paymentIntent.update({
147
- status: 'succeeded',
148
- amount_received: paymentIntent.amount,
149
- last_payment_error: null,
150
- payment_details: { [paymentMethod.type]: paymentDetails },
151
- });
152
- await handlePaymentSucceed(paymentIntent);
147
+ const paymentDetails = await executeEvmTransaction('transfer', userDid, claims, paymentMethod);
148
+ waitForEvmTxConfirm(
149
+ paymentMethod.getEvmClient(),
150
+ Number(paymentDetails.block_height),
151
+ paymentMethod.confirmation.block
152
+ )
153
+ .then(async () => {
154
+ await paymentIntent.update({
155
+ status: 'succeeded',
156
+ amount_received: paymentIntent.amount,
157
+ last_payment_error: null,
158
+ payment_details: { [paymentMethod.type]: paymentDetails },
159
+ });
160
+ await handlePaymentSucceed(paymentIntent);
161
+ })
162
+ .catch(console.error);
153
163
 
154
164
  return { hash: paymentDetails.tx_hash };
155
165
  } catch (err) {
156
- logger.error('Failed to finalize paymentIntent', { paymentIntent: paymentIntent.id, error: err });
166
+ console.error(err);
167
+ logger.error('Failed to finalize paymentIntent on ethereum', { paymentIntent: paymentIntent.id, error: err });
157
168
  await paymentIntent.update({ status: 'requires_capture' });
158
169
  return {};
159
170
  }
@@ -1,4 +1,5 @@
1
- import { executeEvmTransactions } from '../../integrations/ethereum/token';
1
+ import { executeEvmTransaction } from '../../integrations/ethereum/token';
2
+ import { waitForEvmTxConfirm } from '../../integrations/ethereum/tx';
2
3
  import type { CallbackArgs } from '../../libs/auth';
3
4
  import dayjs from '../../libs/dayjs';
4
5
  import logger from '../../libs/logger';
@@ -181,8 +182,12 @@ export default {
181
182
 
182
183
  if (paymentMethod.type === 'ethereum') {
183
184
  await prepareTxExecution();
184
- const paymentDetails = await executeEvmTransactions('approve', userDid, claims, paymentMethod);
185
- await afterTxExecution(paymentDetails);
185
+ const paymentDetails = await executeEvmTransaction('approve', userDid, claims, paymentMethod);
186
+ waitForEvmTxConfirm(paymentMethod.getEvmClient(), +paymentDetails.block_height, paymentMethod.confirmation.block)
187
+ .then(async () => {
188
+ await afterTxExecution(paymentDetails);
189
+ })
190
+ .catch(console.error);
186
191
 
187
192
  return { hash: paymentDetails.tx_hash };
188
193
  }
@@ -1,4 +1,5 @@
1
- import { executeEvmTransactions } from '../../integrations/ethereum/token';
1
+ import { executeEvmTransaction } from '../../integrations/ethereum/token';
2
+ import { waitForEvmTxConfirm } from '../../integrations/ethereum/tx';
2
3
  import type { CallbackArgs } from '../../libs/auth';
3
4
  import dayjs from '../../libs/dayjs';
4
5
  import logger from '../../libs/logger';
@@ -165,8 +166,16 @@ export default {
165
166
  await prepareTxExecution();
166
167
  const { invoice } = await ensureInvoiceForCheckout({ checkoutSession, customer, subscription });
167
168
 
168
- const paymentDetails = await executeEvmTransactions('approve', userDid, claims, paymentMethod);
169
- await afterTxExecution(invoice!, paymentDetails);
169
+ const paymentDetails = await executeEvmTransaction('approve', userDid, claims, paymentMethod);
170
+ waitForEvmTxConfirm(
171
+ paymentMethod.getEvmClient(),
172
+ Number(paymentDetails.block_height),
173
+ paymentMethod.confirmation.block
174
+ )
175
+ .then(async () => {
176
+ await afterTxExecution(invoice!, paymentDetails);
177
+ })
178
+ .catch(console.error);
170
179
 
171
180
  return { hash: paymentDetails.tx_hash };
172
181
  }
@@ -8,6 +8,7 @@ import { syncStripePayment } from '../integrations/stripe/handlers/payment-inten
8
8
  import { createListParamSchema, getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
9
9
  import { authenticate } from '../libs/security';
10
10
  import { formatMetadata } from '../libs/util';
11
+ import { paymentQueue } from '../queues/payment';
11
12
  import { CheckoutSession } from '../store/models/checkout-session';
12
13
  import { Customer } from '../store/models/customer';
13
14
  import { Invoice } from '../store/models/invoice';
@@ -202,4 +203,30 @@ router.put('/:id', authAdmin, async (req, res) => {
202
203
  }
203
204
  });
204
205
 
206
+ // eslint-disable-next-line consistent-return
207
+ router.get('/:id/retry', authAdmin, async (req, res) => {
208
+ try {
209
+ const doc = await PaymentIntent.findByPk(req.params.id as string);
210
+ if (!doc) {
211
+ return res.status(404).json({ error: 'PaymentIntent not found' });
212
+ }
213
+ if (doc.status === 'succeeded') {
214
+ return res.status(403).json({ error: 'PaymentIntent already done' });
215
+ }
216
+ if (doc.status === 'processing') {
217
+ return res.status(403).json({ error: 'PaymentIntent already processing' });
218
+ }
219
+
220
+ await doc.update({ status: 'requires_capture', last_payment_error: null });
221
+ await paymentQueue.pushAndWait({
222
+ id: doc.id,
223
+ job: { paymentIntentId: doc.id, retryOnError: false },
224
+ });
225
+ res.json(doc);
226
+ } catch (err) {
227
+ console.error(err);
228
+ res.json(null);
229
+ }
230
+ });
231
+
205
232
  export default router;
@@ -220,9 +220,11 @@ export type SubscriptionSchedulePhase = {
220
220
  export type PaymentMethodOptions = {
221
221
  arcblock?: {
222
222
  payer: string;
223
+ hash?: string;
223
224
  };
224
225
  ethereum?: {
225
226
  payer: string;
227
+ hash?: string;
226
228
  };
227
229
  stripe?: {
228
230
  payer: string;
package/blocklet.md CHANGED
@@ -1,3 +1,24 @@
1
1
  # Payment Kit
2
2
 
3
- The decentralized stripe alike payment solution for blocklet platform.
3
+ Payment Kit is a payment solution built by ArcBlock that allows developers to easily integrate payment processing into their applications. Payment Kit is designed to be easy to use, secure, and flexible. It supports both crypto and fiat payments, and can be used for one-time payments, usage-based billing, recurring subscriptions, tips, and donations.
4
+
5
+ ## Why build Payment Kit?
6
+
7
+ Payment is already everywhere why do we still create a new Payment Kit? Because all previous payment solutions have “middleman” to take some cut. Payment Kit is full decentralized peer to peer payment (when use crypto) and no one takes any cut!
8
+
9
+ - `Crypto Native`: Payment Kit handles transactions using cryptocurrency, ensuring they are completed in seconds with the added benefits of no chargebacks and no hidden fees..
10
+ - `Decentralization`: Payment Kit offers peer-to-peer payment capability leveraging blockchain technology, eliminating any intermediaries and associated costs.
11
+ - `Multiple Blockchain Support`: Payment Kit supports multiple blockchain platforms including ArcBlock, EVM-compatible chains, and upcoming support for Bitcoin, broadening your potential user base.
12
+ - `Composable Integration`: Payment Kit is built for easy integration with any applications running on the ArcBlock platform, simplifying the deployment process and enhancing functionality.
13
+ - `Seamless Fiat Replacement`: For traditional fiat currency users, Payment Kit acts as a straightforward enhancement for existing solutions like Stripe, making transitions smooth and hassle-free.
14
+ - `Flexible Billing Solutions`: Adapt to any billing requirement with Payment Kit’s versatile setup, capable of handling everything from simple one-time payments to complex recurring billing and donations.
15
+
16
+ ## Payment Kit Use Cases?
17
+
18
+ Payment Kit is seamlessly integrated with ArcBlock's DID and Blocklet ecosystems and widely used and battle tested in various ArcBlock services.
19
+
20
+ - `One-Time Payments`: Perfect for e-commerce transactions, digital downloads, and service fees, Payment Kit simplifies the checkout process, offering a quick and secure way for users to make single purchases.
21
+ - `Usage-Based Billing`: Ideal for services with variable consumption rates such as cloud computing or utilities, Payment Kit allows for flexible billing based on actual usage, ensuring fairness and transparency.
22
+ - `Recurring Subscriptions`: Enhance your subscription model with Payment Kit’s automated billing features. From software licenses to membership fees, ensure smooth, continuous access to services with regular payment schedules.
23
+ - `Tips and Donations`: Enable supporters to contribute easily with tips or donations. Payment Kit facilitates spontaneous generosity, supporting fundraising efforts, content creators, and nonprofit organizations.
24
+ - `Bonus Pool Distribution`: Distribute earnings or rewards through a bonus pool with Payment Kit. This feature is great for managing profit-sharing, employee incentives, or community rewards programs efficiently and transparently.
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.13.224
17
+ version: 1.13.225
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
@@ -70,8 +70,10 @@ screenshots:
70
70
  - 1-subscription.png
71
71
  - 2-customer-1.png
72
72
  - 3-customer-2.png
73
- - 4-admin-3.png
74
- - 5-admin-4.png
73
+ - 4-admin-payments.png
74
+ - 4-admin-products.png
75
+ - 4-admin-settings.png
76
+ - 5-dashboard.png
75
77
  components:
76
78
  - name: image-bin
77
79
  source:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.13.224",
3
+ "version": "1.13.225",
4
4
  "scripts": {
5
5
  "dev": "cross-env COMPONENT_STORE_URL=https://test.store.blocklet.dev blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -51,7 +51,7 @@
51
51
  "@arcblock/ux": "^2.9.66",
52
52
  "@arcblock/validator": "^1.18.115",
53
53
  "@blocklet/logger": "1.16.25",
54
- "@blocklet/payment-react": "1.13.224",
54
+ "@blocklet/payment-react": "1.13.225",
55
55
  "@blocklet/sdk": "1.16.25",
56
56
  "@blocklet/ui-react": "^2.9.66",
57
57
  "@blocklet/uploader": "^0.0.76",
@@ -116,7 +116,7 @@
116
116
  "devDependencies": {
117
117
  "@abtnode/types": "1.16.25",
118
118
  "@arcblock/eslint-config-ts": "^0.3.0",
119
- "@blocklet/payment-types": "1.13.224",
119
+ "@blocklet/payment-types": "1.13.225",
120
120
  "@types/cookie-parser": "^1.4.6",
121
121
  "@types/cors": "^2.8.17",
122
122
  "@types/dotenv-flow": "^3.3.3",
@@ -155,5 +155,5 @@
155
155
  "parser": "typescript"
156
156
  }
157
157
  },
158
- "gitHead": "748bfdf66a77b47f5d879cc4838ba519b9a5f6d3"
158
+ "gitHead": "e5e5f94d4f17d582d7266b063dda56d09ffadf7c"
159
159
  }
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -159,7 +159,7 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
159
159
  InputProps={{
160
160
  endAdornment: (
161
161
  <InputAdornment position="end">
162
- {settings.baseCurrency.symbol} on {basePaymentMethod?.name}
162
+ {settings.baseCurrency.symbol} ({basePaymentMethod?.name})
163
163
  </InputAdornment>
164
164
  ),
165
165
  }}
@@ -216,7 +216,7 @@ export default function PriceForm({ prefix, simple }: PriceFormProps) {
216
216
  InputProps={{
217
217
  endAdornment: (
218
218
  <InputAdornment position="end">
219
- {currency?.symbol} on {currency?.paymentMethod?.name}
219
+ {currency?.symbol} ({currency?.paymentMethod?.name})
220
220
  </InputAdornment>
221
221
  ),
222
222
  }}
@@ -141,7 +141,12 @@ export default function InvoiceDetail(props: { id: string }) {
141
141
  />
142
142
  <InfoRow
143
143
  label={t('admin.paymentCurrency.name')}
144
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
144
+ value={
145
+ <Currency
146
+ logo={data.paymentCurrency.logo}
147
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
148
+ />
149
+ }
145
150
  />
146
151
  {data.paymentIntent && data.paymentIntent.payment_details && (
147
152
  <InfoRow
@@ -144,13 +144,14 @@ export default function SubscriptionDetail(props: { id: string }) {
144
144
  />
145
145
  <InfoRow label={t('admin.subscription.discount')} value={data.discount_id ? data.discount_id : ''} />
146
146
  <InfoRow label={t('admin.subscription.collectionMethod')} value={data.collection_method} />
147
- <InfoRow
148
- label={t('admin.paymentMethod._name')}
149
- value={<Currency logo={data.paymentMethod.logo} name={data.paymentMethod.name} />}
150
- />
151
147
  <InfoRow
152
148
  label={t('admin.paymentCurrency.name')}
153
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
149
+ value={
150
+ <Currency
151
+ logo={data.paymentCurrency.logo}
152
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
153
+ />
154
+ }
154
155
  />
155
156
  {(data.payment_details?.arcblock?.tx_hash || data.payment_details?.ethereum?.tx_hash) && (
156
157
  <InfoRow
@@ -145,13 +145,14 @@ export default function PaymentIntentDetail(props: { id: string }) {
145
145
  <Stack>
146
146
  <InfoRow label={t('common.id')} value={data.paymentMethod.id} />
147
147
  <InfoRow label={t('admin.paymentMethod.type')} value={data.paymentMethod.type} />
148
- <InfoRow
149
- label={t('admin.paymentMethod._name')}
150
- value={<Currency logo={data.paymentMethod.logo} name={data.paymentMethod.name} />}
151
- />
152
148
  <InfoRow
153
149
  label={t('admin.paymentCurrency.name')}
154
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
150
+ value={
151
+ <Currency
152
+ logo={data.paymentCurrency.logo}
153
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
154
+ />
155
+ }
155
156
  />
156
157
  <InfoRow
157
158
  label={t(`common.${data.payment_details?.arcblock?.type || 'transfer'}TxHash`)}
@@ -142,13 +142,14 @@ export default function PayoutDetail(props: { id: string }) {
142
142
  <Stack>
143
143
  <InfoRow label={t('common.id')} value={data.paymentMethod.id} />
144
144
  <InfoRow label={t('admin.paymentMethod.type')} value={data.paymentMethod.type} />
145
- <InfoRow
146
- label={t('admin.paymentMethod._name')}
147
- value={<Currency logo={data.paymentMethod.logo} name={data.paymentMethod.name} />}
148
- />
149
145
  <InfoRow
150
146
  label={t('admin.paymentCurrency.name')}
151
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
147
+ value={
148
+ <Currency
149
+ logo={data.paymentCurrency.logo}
150
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
151
+ />
152
+ }
152
153
  />
153
154
  <InfoRow
154
155
  label={t(`common.${data.payment_details?.arcblock?.type || 'transfer'}TxHash`)}
@@ -142,13 +142,14 @@ export default function RefundDetail(props: { id: string }) {
142
142
  <Stack>
143
143
  <InfoRow label={t('common.id')} value={data.paymentMethod.id} />
144
144
  <InfoRow label={t('admin.paymentMethod.type')} value={data.paymentMethod.type} />
145
- <InfoRow
146
- label={t('admin.paymentMethod._name')}
147
- value={<Currency logo={data.paymentMethod.logo} name={data.paymentMethod.name} />}
148
- />
149
145
  <InfoRow
150
146
  label={t('admin.paymentCurrency.name')}
151
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
147
+ value={
148
+ <Currency
149
+ logo={data.paymentCurrency.logo}
150
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
151
+ />
152
+ }
152
153
  />
153
154
  <InfoRow
154
155
  label={t('common.txHash')}
@@ -142,7 +142,12 @@ export default function CustomerInvoiceDetail() {
142
142
  )}
143
143
  <InfoRow
144
144
  label={t('admin.paymentCurrency.name')}
145
- value={<Currency logo={data.paymentCurrency.logo} name={data.paymentCurrency.symbol} />}
145
+ value={
146
+ <Currency
147
+ logo={data.paymentCurrency.logo}
148
+ name={`${data.paymentCurrency.symbol} (${data.paymentMethod.name})`}
149
+ />
150
+ }
146
151
  />
147
152
  {data.paymentIntent && data.paymentIntent.payment_details && (
148
153
  <InfoRow
Binary file
Binary file