@@ -96,6 +96,72 @@ export const Bitrefill = ({ accounts, code }: TProps) => {
96
96
} ;
97
97
} , [ onResize ] ) ;
98
98
99
+ const handlePaymentRequest = useCallback ( async ( event : MessageEvent ) => {
100
+ if ( ! account || pendingPayment ) {
101
+ return ;
102
+ }
103
+ setPendingPayment ( true ) ;
104
+
105
+ const data = typeof event . data === 'string' ? JSON . parse ( event . data ) : event . data ;
106
+
107
+ // User clicked "Pay" in checkout
108
+ const {
109
+ invoiceId,
110
+ paymentMethod,
111
+ paymentAmount,
112
+ paymentAddress,
113
+ } = data ;
114
+
115
+ const parsedAmount = await parseExternalBtcAmount ( paymentAmount . toString ( ) ) ;
116
+ if ( ! parsedAmount . success ) {
117
+ alertUser ( t ( 'unknownError' , { errorMessage : 'Invalid amount' } ) ) ;
118
+ setPendingPayment ( false ) ;
119
+ return ;
120
+ }
121
+ // Ensure expected payment method matches account
122
+ if ( coinMapping [ account . coinCode ] !== paymentMethod ) {
123
+ alertUser ( t ( 'unknownError' , { errorMessage : 'Payment method mismatch' } ) ) ;
124
+ setPendingPayment ( false ) ;
125
+ }
126
+
127
+ const txInput : TTxInput = {
128
+ address : paymentAddress ,
129
+ amount : parsedAmount . amount ,
130
+ // Always use highest fee rate for Bitrefill spend
131
+ useHighestFee : true ,
132
+ sendAll : 'no' ,
133
+ selectedUTXOs : [ ] ,
134
+ paymentRequest : null
135
+ } ;
136
+
137
+ let result = await proposeTx ( code , txInput ) ;
138
+ if ( result . success ) {
139
+ const txNote = t ( 'generic.paymentRequestNote' , {
140
+ name : 'Bitrefill' ,
141
+ orderId : invoiceId ,
142
+ } ) ;
143
+
144
+ setVerifyPaymentRequest ( {
145
+ address : paymentAddress ,
146
+ ...result
147
+ } ) ;
148
+ const sendResult = await sendTx ( code , txNote ) ;
149
+ setVerifyPaymentRequest ( false ) ;
150
+ if ( ! sendResult . success && ! ( 'aborted' in sendResult ) ) {
151
+ alertUser ( t ( 'unknownError' , { errorMessage : sendResult . errorMessage } ) ) ;
152
+ }
153
+ } else {
154
+ if ( result . errorCode === 'insufficientFunds' ) {
155
+ alertUser ( t ( 'buy.bitrefill.error.' + result . errorCode ) ) ;
156
+ } else if ( result . errorCode ) {
157
+ alertUser ( t ( 'send.error.' + result . errorCode ) ) ;
158
+ } else {
159
+ alertUser ( t ( 'genericError' ) ) ;
160
+ }
161
+ }
162
+ setPendingPayment ( false ) ;
163
+ } , [ account , code , pendingPayment , t ] ) ;
164
+
99
165
const handleMessage = useCallback ( async ( event : MessageEvent ) => {
100
166
if (
101
167
! account
@@ -127,73 +193,14 @@ export const Bitrefill = ({ accounts, code }: TProps) => {
127
193
break ;
128
194
}
129
195
case 'payment_intent' : {
130
- if ( pendingPayment ) {
131
- return ;
132
- }
133
- setPendingPayment ( true ) ;
134
- // User clicked "Pay" in checkout
135
- const {
136
- invoiceId,
137
- paymentMethod,
138
- paymentAmount,
139
- paymentAddress,
140
- } = data ;
141
-
142
- const parsedAmount = await parseExternalBtcAmount ( paymentAmount . toString ( ) ) ;
143
- if ( ! parsedAmount . success ) {
144
- alertUser ( t ( 'unknownError' , { errorMessage : 'Invalid amount' } ) ) ;
145
- setPendingPayment ( false ) ;
146
- return ;
147
- }
148
- // Ensure expected payment method matches account
149
- if ( coinMapping [ account . coinCode ] !== paymentMethod ) {
150
- alertUser ( t ( 'unknownError' , { errorMessage : 'Payment method mismatch' } ) ) ;
151
- setPendingPayment ( false ) ;
152
- }
153
-
154
- const txInput : TTxInput = {
155
- address : paymentAddress ,
156
- amount : parsedAmount . amount ,
157
- // Always use highest fee rate for Bitrefill spend
158
- useHighestFee : true ,
159
- sendAll : 'no' ,
160
- selectedUTXOs : [ ] ,
161
- paymentRequest : null
162
- } ;
163
-
164
- let result = await proposeTx ( code , txInput ) ;
165
- if ( result . success ) {
166
- const txNote = t ( 'generic.paymentRequestNote' , {
167
- name : 'Bitrefill' ,
168
- orderId : invoiceId ,
169
- } ) ;
170
-
171
- setVerifyPaymentRequest ( {
172
- address : paymentAddress ,
173
- ...result
174
- } ) ;
175
- const sendResult = await sendTx ( code , txNote ) ;
176
- setVerifyPaymentRequest ( false ) ;
177
- if ( ! sendResult . success && ! ( 'aborted' in sendResult ) ) {
178
- alertUser ( t ( 'unknownError' , { errorMessage : sendResult . errorMessage } ) ) ;
179
- }
180
- } else {
181
- if ( result . errorCode === 'insufficientFunds' ) {
182
- alertUser ( t ( 'buy.bitrefill.error.' + result . errorCode ) ) ;
183
- } else if ( result . errorCode ) {
184
- alertUser ( t ( 'send.error.' + result . errorCode ) ) ;
185
- } else {
186
- alertUser ( t ( 'genericError' ) ) ;
187
- }
188
- }
189
- setPendingPayment ( false ) ;
196
+ handlePaymentRequest ( event ) ;
190
197
break ;
191
198
}
192
199
default : {
193
200
break ;
194
201
}
195
202
}
196
- } , [ account , bitrefillInfo , code , isDarkMode , pendingPayment , t ] ) ;
203
+ } , [ account , bitrefillInfo , handlePaymentRequest , isDarkMode ] ) ;
197
204
198
205
useEffect ( ( ) => {
199
206
window . addEventListener ( 'message' , handleMessage ) ;
0 commit comments