@volr/react-ui 0.1.98 → 0.1.99

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