@volr/react-ui 0.1.98 → 0.1.100

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/index.js CHANGED
@@ -3451,7 +3451,9 @@ var initialState = {
3451
3451
  isBalanceLoading: true,
3452
3452
  isConfigLoading: true,
3453
3453
  isPaying: false,
3454
- currentPayment: null,
3454
+ payOptions: null,
3455
+ tokenInfo: null,
3456
+ createdPayment: null,
3455
3457
  txHash: void 0,
3456
3458
  error: void 0,
3457
3459
  logoUrl: void 0,
@@ -3462,13 +3464,15 @@ function paymentModalReducer(state, action) {
3462
3464
  switch (action.type) {
3463
3465
  case "RESET":
3464
3466
  return { ...initialState };
3465
- case "INIT_PAYMENT":
3467
+ case "INIT":
3466
3468
  return {
3467
3469
  ...initialState,
3468
- currentPayment: action.payment,
3470
+ payOptions: action.options,
3469
3471
  isBalanceLoading: true,
3470
3472
  isConfigLoading: true
3471
3473
  };
3474
+ case "SET_TOKEN_INFO":
3475
+ return { ...state, tokenInfo: action.tokenInfo };
3472
3476
  case "SET_BALANCE":
3473
3477
  return { ...state, balance: action.balance };
3474
3478
  case "SET_BALANCE_LOADING":
@@ -3487,6 +3491,8 @@ function paymentModalReducer(state, action) {
3487
3491
  processingStep: "signing",
3488
3492
  error: void 0
3489
3493
  };
3494
+ case "SET_CREATED_PAYMENT":
3495
+ return { ...state, createdPayment: action.payment };
3490
3496
  case "SET_PROCESSING_STEP":
3491
3497
  return { ...state, processingStep: action.step };
3492
3498
  case "SET_TX_HASH":
@@ -3496,7 +3502,7 @@ function paymentModalReducer(state, action) {
3496
3502
  ...state,
3497
3503
  isPaying: false,
3498
3504
  step: "result",
3499
- currentPayment: action.payment
3505
+ createdPayment: action.payment
3500
3506
  };
3501
3507
  case "PAYMENT_ERROR":
3502
3508
  return {
@@ -3525,33 +3531,32 @@ function usePaymentModalState(open, onOpenChange) {
3525
3531
  const { client } = useInternalAuth();
3526
3532
  const { evm } = useVolr();
3527
3533
  const { paymentOptions } = useVolrModal();
3528
- const { updatePaymentToProcessing, pollPaymentStatus } = useVolrPaymentApi();
3534
+ const { createPayment, updatePaymentToProcessing, pollPaymentStatus, failPendingPayment } = useVolrPaymentApi();
3529
3535
  const [state, dispatch] = useReducer(paymentModalReducer, initialState);
3530
3536
  const fetchBalance = useCallback(
3531
- async (payment) => {
3537
+ async (tokenInfo) => {
3532
3538
  if (!user?.evmAddress) {
3533
3539
  dispatch({ type: "SET_BALANCE_LOADING", loading: false });
3534
3540
  return;
3535
3541
  }
3536
3542
  dispatch({ type: "SET_BALANCE_LOADING", loading: true });
3537
3543
  try {
3538
- const evmClient = evm(payment.token.chainId);
3539
- const tokenAddress = payment.token.id.split("_")[1];
3544
+ const evmClient = evm(tokenInfo.chainId);
3540
3545
  let balanceRaw;
3541
- if (tokenAddress === "native") {
3546
+ if (tokenInfo.address === "native") {
3542
3547
  balanceRaw = await evmClient.getBalance(user.evmAddress);
3543
3548
  } else {
3544
3549
  balanceRaw = await evmClient.readContract({
3545
- address: tokenAddress,
3550
+ address: tokenInfo.address,
3546
3551
  abi: erc20Abi,
3547
3552
  functionName: "balanceOf",
3548
3553
  args: [user.evmAddress]
3549
3554
  });
3550
3555
  }
3551
- const balanceNum = Number(balanceRaw) / Math.pow(10, payment.token.decimals);
3556
+ const balanceNum = Number(balanceRaw) / Math.pow(10, tokenInfo.decimals);
3552
3557
  const formattedBalance = balanceNum.toLocaleString(void 0, {
3553
3558
  minimumFractionDigits: 0,
3554
- maximumFractionDigits: payment.token.decimals > 6 ? 6 : payment.token.decimals
3559
+ maximumFractionDigits: tokenInfo.decimals > 6 ? 6 : tokenInfo.decimals
3555
3560
  });
3556
3561
  dispatch({ type: "SET_BALANCE", balance: formattedBalance });
3557
3562
  } catch (err) {
@@ -3573,72 +3578,74 @@ function usePaymentModalState(open, onOpenChange) {
3573
3578
  const fetchPaymentConfig = useCallback(async () => {
3574
3579
  dispatch({ type: "SET_CONFIG_LOADING", loading: true });
3575
3580
  try {
3576
- const response = await client.get(
3577
- "/payments/config"
3578
- );
3579
- dispatch({
3580
- type: "SET_RECEIVER_ADDRESS",
3581
- receiverAddress: response.receiverAddress
3582
- });
3581
+ const response = await client.get("/payments/config");
3582
+ dispatch({ type: "SET_RECEIVER_ADDRESS", receiverAddress: response.receiverAddress });
3583
+ dispatch({ type: "SET_TOKEN_INFO", tokenInfo: response.token });
3584
+ if (response.token) {
3585
+ fetchBalance(response.token);
3586
+ }
3583
3587
  } catch (err) {
3584
3588
  console.error("Failed to fetch payment config:", err);
3585
3589
  dispatch({ type: "SET_RECEIVER_ADDRESS", receiverAddress: null });
3586
3590
  } finally {
3587
3591
  dispatch({ type: "SET_CONFIG_LOADING", loading: false });
3588
3592
  }
3589
- }, [client]);
3593
+ }, [client, fetchBalance]);
3590
3594
  useEffect(() => {
3591
- if (open && paymentOptions) {
3595
+ if (open && paymentOptions?.options) {
3592
3596
  if (state.step === "processing" || state.step === "result") {
3593
3597
  return;
3594
3598
  }
3595
- dispatch({ type: "INIT_PAYMENT", payment: paymentOptions.payment });
3596
- fetchBalance(paymentOptions.payment);
3599
+ dispatch({ type: "INIT", options: paymentOptions.options });
3597
3600
  fetchBranding();
3598
3601
  fetchPaymentConfig();
3599
3602
  } else if (!open) {
3600
3603
  dispatch({ type: "RESET" });
3601
3604
  }
3602
- }, [open, paymentOptions?.payment?.id]);
3605
+ }, [open, paymentOptions?.options?.amount]);
3603
3606
  const handlePay = useCallback(async () => {
3604
- const { currentPayment, receiverAddress } = state;
3605
- if (!currentPayment || !user?.evmAddress || !paymentOptions || !receiverAddress) {
3607
+ const { payOptions, receiverAddress, tokenInfo } = state;
3608
+ if (!payOptions || !user?.evmAddress || !paymentOptions || !receiverAddress || !tokenInfo) {
3606
3609
  return;
3607
3610
  }
3608
3611
  dispatch({ type: "START_PAYMENT" });
3612
+ let createdPaymentId = null;
3609
3613
  try {
3610
- const evmClient = evm(currentPayment.token.chainId);
3611
- const tokenAddress = currentPayment.token.id.split("_")[1];
3614
+ const payment = await createPayment(payOptions);
3615
+ createdPaymentId = payment.id;
3616
+ dispatch({ type: "SET_CREATED_PAYMENT", payment });
3617
+ paymentOptions.options.handlers?.onCreated?.({ id: payment.id });
3618
+ const evmClient = evm(tokenInfo.chainId);
3612
3619
  dispatch({ type: "SET_PROCESSING_STEP", step: "broadcasting" });
3613
3620
  let result;
3614
- if (tokenAddress === "native") {
3621
+ if (tokenInfo.address === "native") {
3615
3622
  result = await evmClient.sendTransaction({
3616
3623
  to: receiverAddress,
3617
3624
  data: "0x",
3618
- value: BigInt(currentPayment.amount)
3625
+ value: BigInt(payment.amount)
3619
3626
  });
3620
3627
  } else {
3621
3628
  result = await evmClient.sendBatch([
3622
3629
  {
3623
- target: tokenAddress,
3630
+ target: tokenInfo.address,
3624
3631
  abi: erc20Abi,
3625
3632
  functionName: "transfer",
3626
3633
  args: [
3627
3634
  receiverAddress,
3628
- BigInt(currentPayment.amount)
3635
+ BigInt(payment.amount)
3629
3636
  ]
3630
3637
  }
3631
3638
  ]);
3632
3639
  }
3633
3640
  dispatch({ type: "SET_TX_HASH", txHash: result.txHash ?? "" });
3634
3641
  dispatch({ type: "SET_PROCESSING_STEP", step: "confirming" });
3635
- await updatePaymentToProcessing(currentPayment.id, result.txId);
3642
+ await updatePaymentToProcessing(payment.id, result.txId);
3636
3643
  paymentOptions.onProcessing?.({
3637
- ...currentPayment,
3644
+ ...payment,
3638
3645
  txHash: result.txHash ?? "",
3639
3646
  status: "PROCESSING"
3640
3647
  });
3641
- const confirmedPayment = await pollPaymentStatus(currentPayment.id);
3648
+ const confirmedPayment = await pollPaymentStatus(payment.id);
3642
3649
  dispatch({ type: "PAYMENT_SUCCESS", payment: confirmedPayment });
3643
3650
  if (confirmedPayment.status === "CONFIRMED") {
3644
3651
  paymentOptions.onComplete?.(confirmedPayment);
@@ -3652,6 +3659,13 @@ function usePaymentModalState(open, onOpenChange) {
3652
3659
  }
3653
3660
  } catch (err) {
3654
3661
  console.error("Payment failed:", err);
3662
+ if (createdPaymentId) {
3663
+ try {
3664
+ await failPendingPayment(createdPaymentId);
3665
+ } catch (failErr) {
3666
+ console.error("Failed to mark payment as failed:", failErr);
3667
+ }
3668
+ }
3655
3669
  const paymentError = {
3656
3670
  code: err.code || "PAYMENT_FAILED",
3657
3671
  message: err.message || "Payment failed. Please try again."
@@ -3664,8 +3678,10 @@ function usePaymentModalState(open, onOpenChange) {
3664
3678
  user,
3665
3679
  paymentOptions,
3666
3680
  evm,
3681
+ createPayment,
3667
3682
  updatePaymentToProcessing,
3668
- pollPaymentStatus
3683
+ pollPaymentStatus,
3684
+ failPendingPayment
3669
3685
  ]);
3670
3686
  const handleDeposit = useCallback(() => {
3671
3687
  dispatch({ type: "SHOW_DEPOSIT" });
@@ -3674,25 +3690,25 @@ function usePaymentModalState(open, onOpenChange) {
3674
3690
  (depositOpen) => {
3675
3691
  if (!depositOpen) {
3676
3692
  dispatch({ type: "HIDE_DEPOSIT" });
3677
- if (state.currentPayment) {
3678
- fetchBalance(state.currentPayment);
3693
+ if (state.tokenInfo) {
3694
+ fetchBalance(state.tokenInfo);
3679
3695
  }
3680
3696
  }
3681
3697
  },
3682
- [state.currentPayment, fetchBalance]
3698
+ [state.tokenInfo, fetchBalance]
3683
3699
  );
3684
3700
  const handleDone = useCallback(() => {
3685
- if (state.currentPayment?.status === "CONFIRMED") {
3686
- paymentOptions?.onComplete?.(state.currentPayment);
3701
+ if (state.createdPayment?.status === "CONFIRMED") {
3702
+ paymentOptions?.onComplete?.(state.createdPayment);
3687
3703
  }
3688
3704
  onOpenChange(false);
3689
- }, [state.currentPayment, paymentOptions, onOpenChange]);
3705
+ }, [state.createdPayment, paymentOptions, onOpenChange]);
3690
3706
  const handleRetry = useCallback(() => {
3691
3707
  dispatch({ type: "RETRY" });
3692
- if (state.currentPayment) {
3693
- fetchBalance(state.currentPayment);
3708
+ if (state.tokenInfo) {
3709
+ fetchBalance(state.tokenInfo);
3694
3710
  }
3695
- }, [state.currentPayment, fetchBalance]);
3711
+ }, [state.tokenInfo, fetchBalance]);
3696
3712
  const handleClose = useCallback(() => {
3697
3713
  if (state.step === "processing") {
3698
3714
  return;
@@ -3703,19 +3719,19 @@ function usePaymentModalState(open, onOpenChange) {
3703
3719
  onOpenChange(false);
3704
3720
  }, [state.step, paymentOptions, onOpenChange]);
3705
3721
  const handleReport = useCallback(async () => {
3706
- const { currentPayment, error, step, txHash } = state;
3707
- if (!currentPayment || !error) return;
3722
+ const { createdPayment, error, step, txHash, tokenInfo } = state;
3723
+ if (!createdPayment || !error) return;
3708
3724
  try {
3709
- await client.post(`/payments/${currentPayment.id}/report`, {
3725
+ await client.post(`/payments/${createdPayment.id}/report`, {
3710
3726
  errorCode: error.code,
3711
3727
  errorMessage: error.message,
3712
3728
  platform: "web",
3713
3729
  context: {
3714
3730
  step,
3715
3731
  txHash,
3716
- tokenId: currentPayment.token.id,
3717
- chainId: currentPayment.token.chainId,
3718
- amount: currentPayment.amount
3732
+ tokenId: tokenInfo?.id,
3733
+ chainId: tokenInfo?.chainId,
3734
+ amount: createdPayment.amount
3719
3735
  }
3720
3736
  });
3721
3737
  alert("Error report submitted. Thank you for your feedback.");
@@ -3731,7 +3747,8 @@ Please contact support with this information.`
3731
3747
  }
3732
3748
  }, [state, client]);
3733
3749
  const canClose = state.step !== "processing";
3734
- const isConfigured = state.receiverAddress !== null;
3750
+ const isConfigured = state.receiverAddress !== null && state.tokenInfo !== null;
3751
+ const isReady = !state.isConfigLoading && !state.isBalanceLoading && isConfigured;
3735
3752
  return {
3736
3753
  state,
3737
3754
  handlePay,
@@ -3742,7 +3759,8 @@ Please contact support with this information.`
3742
3759
  handleClose,
3743
3760
  handleReport,
3744
3761
  canClose,
3745
- isConfigured
3762
+ isConfigured,
3763
+ isReady
3746
3764
  };
3747
3765
  }
3748
3766
  var PaymentSkeleton = () => {
@@ -3845,7 +3863,12 @@ var ItemDisplay = ({
3845
3863
  ] });
3846
3864
  };
3847
3865
  var PaymentInfoView = ({
3848
- payment,
3866
+ amount,
3867
+ tokenSymbol,
3868
+ tokenDecimals,
3869
+ itemName,
3870
+ itemDescription,
3871
+ itemImage,
3849
3872
  balance,
3850
3873
  isBalanceLoading,
3851
3874
  logoUrl,
@@ -3853,22 +3876,20 @@ var PaymentInfoView = ({
3853
3876
  onDeposit,
3854
3877
  isPaying
3855
3878
  }) => {
3856
- const { token, itemName, itemDescription, itemImage } = payment;
3857
- const amountInUnits = Number(payment.amount) / Math.pow(10, token.decimals);
3858
- const formattedAmount = amountInUnits.toLocaleString(void 0, {
3879
+ const formattedAmount = amount.toLocaleString(void 0, {
3859
3880
  minimumFractionDigits: 0,
3860
- maximumFractionDigits: token.decimals > 6 ? 6 : token.decimals
3881
+ maximumFractionDigits: tokenDecimals > 6 ? 6 : tokenDecimals
3861
3882
  });
3862
3883
  const balanceNum = parseFloat(balance.replace(/,/g, "") || "0");
3863
- const isInsufficient = !isBalanceLoading && balanceNum < amountInUnits;
3884
+ const isInsufficient = !isBalanceLoading && balanceNum < amount;
3864
3885
  return /* @__PURE__ */ jsxs("div", { className: "volr:space-y-6", children: [
3865
3886
  itemName && /* @__PURE__ */ jsxs(Fragment, { children: [
3866
3887
  /* @__PURE__ */ jsx(
3867
3888
  ItemDisplay,
3868
3889
  {
3869
3890
  name: itemName,
3870
- description: itemDescription ?? void 0,
3871
- image: itemImage ?? void 0,
3891
+ description: itemDescription,
3892
+ image: itemImage,
3872
3893
  logoUrl
3873
3894
  }
3874
3895
  ),
@@ -3878,12 +3899,7 @@ var PaymentInfoView = ({
3878
3899
  /* @__PURE__ */ jsx("p", { className: "volr:text-sm volr:text-slate-500", children: "Amount to Pay" }),
3879
3900
  /* @__PURE__ */ jsxs("div", { className: "volr:flex volr:items-baseline volr:gap-2", children: [
3880
3901
  /* @__PURE__ */ jsx("span", { className: "volr:text-2xl volr:font-bold volr:text-slate-900", children: formattedAmount }),
3881
- /* @__PURE__ */ jsx("span", { className: "volr:text-lg volr:font-medium volr:text-slate-600", children: token.symbol })
3882
- ] }),
3883
- payment.totalUsd && /* @__PURE__ */ jsxs("p", { className: "volr:text-sm volr:text-slate-400", children: [
3884
- "\u2248 $",
3885
- parseFloat(payment.totalUsd).toFixed(2),
3886
- " USD"
3902
+ /* @__PURE__ */ jsx("span", { className: "volr:text-lg volr:font-medium volr:text-slate-600", children: tokenSymbol })
3887
3903
  ] })
3888
3904
  ] }),
3889
3905
  isBalanceLoading ? /* @__PURE__ */ jsxs("div", { className: "volr:flex volr:justify-between volr:items-center volr:p-3 volr:bg-slate-50 volr:rounded-lg volr:animate-pulse", children: [
@@ -3893,7 +3909,7 @@ var PaymentInfoView = ({
3893
3909
  BalanceDisplay,
3894
3910
  {
3895
3911
  balance,
3896
- symbol: token.symbol,
3912
+ symbol: tokenSymbol,
3897
3913
  required: formattedAmount,
3898
3914
  isInsufficient
3899
3915
  }
@@ -3929,12 +3945,12 @@ var PaymentInfoView = ({
3929
3945
  )
3930
3946
  ] }),
3931
3947
  "Processing..."
3932
- ] }) : isInsufficient ? "Insufficient Balance" : `Pay ${formattedAmount} ${token.symbol}`
3948
+ ] }) : isInsufficient ? "Insufficient Balance" : `Pay ${formattedAmount} ${tokenSymbol}`
3933
3949
  }
3934
3950
  ),
3935
3951
  isInsufficient && /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: onDeposit, className: "volr:w-full", children: [
3936
3952
  "Deposit ",
3937
- token.symbol
3953
+ tokenSymbol
3938
3954
  ] })
3939
3955
  ] }),
3940
3956
  /* @__PURE__ */ jsx(PoweredBy, {})
@@ -4113,8 +4129,7 @@ var PaymentModal = ({
4113
4129
  handleClose,
4114
4130
  handleReport,
4115
4131
  canClose,
4116
- isConfigured
4117
- } = usePaymentModalState(open, onOpenChange);
4132
+ isConfigured} = usePaymentModalState(open, onOpenChange);
4118
4133
  const {
4119
4134
  step,
4120
4135
  processingStep,
@@ -4122,26 +4137,28 @@ var PaymentModal = ({
4122
4137
  isBalanceLoading,
4123
4138
  isConfigLoading,
4124
4139
  isPaying,
4125
- currentPayment,
4140
+ payOptions,
4141
+ tokenInfo,
4142
+ createdPayment,
4126
4143
  txHash,
4127
4144
  error,
4128
4145
  logoUrl,
4129
4146
  showDeposit
4130
4147
  } = state;
4131
- if (showDeposit && currentPayment) {
4148
+ if (showDeposit && tokenInfo) {
4132
4149
  return /* @__PURE__ */ jsx(
4133
4150
  DepositModal,
4134
4151
  {
4135
4152
  open: true,
4136
4153
  onOpenChange: handleDepositClose,
4137
4154
  asset: {
4138
- chainId: currentPayment.token.chainId,
4139
- symbol: currentPayment.token.symbol
4155
+ chainId: tokenInfo.chainId,
4156
+ symbol: tokenInfo.symbol
4140
4157
  }
4141
4158
  }
4142
4159
  );
4143
4160
  }
4144
- if (!paymentOptions || !currentPayment || isConfigLoading) {
4161
+ if (!paymentOptions || !payOptions || isConfigLoading) {
4145
4162
  return /* @__PURE__ */ jsxs(Modal, { open, onOpenChange, children: [
4146
4163
  /* @__PURE__ */ jsx(ModalHeader, { onClose: () => onOpenChange(false) }),
4147
4164
  /* @__PURE__ */ jsx(PaymentSkeleton, {})
@@ -4161,10 +4178,15 @@ var PaymentModal = ({
4161
4178
  title: step === "info" ? "Confirm Payment" : void 0
4162
4179
  }
4163
4180
  ),
4164
- step === "info" && /* @__PURE__ */ jsx(
4181
+ step === "info" && tokenInfo && /* @__PURE__ */ jsx(
4165
4182
  PaymentInfoView,
4166
4183
  {
4167
- payment: currentPayment,
4184
+ amount: payOptions.amount,
4185
+ tokenSymbol: tokenInfo.symbol,
4186
+ tokenDecimals: tokenInfo.decimals,
4187
+ itemName: payOptions.item?.name,
4188
+ itemDescription: payOptions.item?.description,
4189
+ itemImage: payOptions.item?.image,
4168
4190
  balance,
4169
4191
  isBalanceLoading,
4170
4192
  logoUrl,
@@ -4174,10 +4196,10 @@ var PaymentModal = ({
4174
4196
  }
4175
4197
  ),
4176
4198
  step === "processing" && /* @__PURE__ */ jsx(PaymentProcessingView, { step: processingStep, txHash }),
4177
- step === "result" && /* @__PURE__ */ jsx(
4199
+ step === "result" && createdPayment && /* @__PURE__ */ jsx(
4178
4200
  PaymentResultView,
4179
4201
  {
4180
- payment: currentPayment,
4202
+ payment: createdPayment,
4181
4203
  error,
4182
4204
  onDone: handleDone,
4183
4205
  onRetry: handleRetry,
@@ -4623,42 +4645,32 @@ async function getCurrentChainId() {
4623
4645
  });
4624
4646
  return parseInt(chainIdHex, 16);
4625
4647
  }
4626
- var paymentPromiseResolvers = /* @__PURE__ */ new Map();
4648
+ var paymentPromiseResolver = null;
4627
4649
  function useVolrPay() {
4628
- const { open: openModal } = useVolrModal();
4629
- const { createPayment, checkPayment, getPaymentHistory, cancelPayment } = useVolrPaymentApi();
4630
- const currentPaymentIdRef = useRef(null);
4650
+ const { open: openModal, close: closeModal } = useVolrModal();
4651
+ const { checkPayment, getPaymentHistory } = useVolrPaymentApi();
4652
+ const isInProgressRef = useRef(false);
4631
4653
  const pay = useCallback(
4632
- async (options) => {
4633
- const payment = await createPayment({
4634
- amount: options.amount,
4635
- item: options.item,
4636
- referenceId: options.referenceId,
4637
- metadata: options.metadata,
4638
- idempotencyKey: options.idempotencyKey,
4639
- expiresInSec: options.expiresInSec
4640
- });
4641
- currentPaymentIdRef.current = payment.id;
4642
- options.handlers?.onCreated?.({ id: payment.id });
4654
+ (options) => {
4655
+ isInProgressRef.current = true;
4643
4656
  const waitPromise = new Promise((resolve, reject) => {
4644
- paymentPromiseResolvers.set(payment.id, { resolve, reject });
4657
+ paymentPromiseResolver = { resolve, reject };
4645
4658
  });
4646
4659
  const modalOptions = {
4647
- payment,
4648
4660
  options: {
4649
4661
  amount: options.amount,
4650
4662
  item: options.item,
4651
4663
  referenceId: options.referenceId,
4652
4664
  metadata: options.metadata,
4653
4665
  idempotencyKey: options.idempotencyKey,
4654
- expiresInSec: options.expiresInSec
4666
+ expiresInSec: options.expiresInSec,
4667
+ handlers: options.handlers
4655
4668
  },
4656
4669
  onComplete: (result) => {
4657
- currentPaymentIdRef.current = null;
4658
- const resolver = paymentPromiseResolvers.get(payment.id);
4659
- if (resolver) {
4660
- resolver.resolve(result);
4661
- paymentPromiseResolvers.delete(payment.id);
4670
+ isInProgressRef.current = false;
4671
+ if (paymentPromiseResolver) {
4672
+ paymentPromiseResolver.resolve(result);
4673
+ paymentPromiseResolver = null;
4662
4674
  }
4663
4675
  if (result.status === "CONFIRMED") {
4664
4676
  options.handlers?.onSuccess?.(result);
@@ -4671,54 +4683,43 @@ function useVolrPay() {
4671
4683
  });
4672
4684
  },
4673
4685
  onError: (error) => {
4674
- currentPaymentIdRef.current = null;
4675
- const resolver = paymentPromiseResolvers.get(payment.id);
4676
- if (resolver) {
4677
- resolver.reject(new Error(error.message));
4678
- paymentPromiseResolvers.delete(payment.id);
4686
+ isInProgressRef.current = false;
4687
+ if (paymentPromiseResolver) {
4688
+ paymentPromiseResolver.reject(new Error(error.message));
4689
+ paymentPromiseResolver = null;
4679
4690
  }
4680
4691
  options.handlers?.onError?.(error);
4681
4692
  },
4682
4693
  onCancel: () => {
4683
- currentPaymentIdRef.current = null;
4684
- const resolver = paymentPromiseResolvers.get(payment.id);
4685
- if (resolver) {
4686
- resolver.resolve({
4687
- ...payment,
4688
- status: "CANCELLED"
4689
- });
4690
- paymentPromiseResolvers.delete(payment.id);
4694
+ isInProgressRef.current = false;
4695
+ if (paymentPromiseResolver) {
4696
+ paymentPromiseResolver.reject(new Error("Payment cancelled by user"));
4697
+ paymentPromiseResolver = null;
4691
4698
  }
4692
4699
  options.handlers?.onCancel?.();
4693
4700
  }
4694
4701
  };
4695
4702
  openModal({ mode: "payment", payment: modalOptions });
4696
4703
  return {
4697
- id: payment.id,
4698
- status: payment.status,
4699
4704
  wait: () => waitPromise,
4700
- cancel: async () => {
4701
- await cancelPayment(payment.id);
4702
- currentPaymentIdRef.current = null;
4703
- const resolver = paymentPromiseResolvers.get(payment.id);
4704
- if (resolver) {
4705
- resolver.resolve({
4706
- ...payment,
4707
- status: "CANCELLED"
4708
- });
4709
- paymentPromiseResolvers.delete(payment.id);
4705
+ cancel: () => {
4706
+ closeModal();
4707
+ isInProgressRef.current = false;
4708
+ if (paymentPromiseResolver) {
4709
+ paymentPromiseResolver.reject(new Error("Payment cancelled by user"));
4710
+ paymentPromiseResolver = null;
4710
4711
  }
4711
4712
  options.handlers?.onCancel?.();
4712
4713
  }
4713
4714
  };
4714
4715
  },
4715
- [createPayment, cancelPayment, openModal]
4716
+ [openModal, closeModal]
4716
4717
  );
4717
4718
  return {
4718
4719
  pay,
4719
4720
  checkPayment,
4720
4721
  getPaymentHistory,
4721
- isPaymentInProgress: currentPaymentIdRef.current !== null
4722
+ isPaymentInProgress: isInProgressRef.current
4722
4723
  };
4723
4724
  }
4724
4725