1
1
use crate :: errors:: Result ;
2
2
use crate :: fund_migration:: MigrationStatus ;
3
3
use crate :: migrations:: migrate;
4
- use crate :: { ExchangeRate , OfferKind , TzConfig , UserPreferences } ;
4
+ use crate :: { ExchangeRate , OfferKind , PocketOfferError , TzConfig , UserPreferences } ;
5
5
6
6
use chrono:: { DateTime , Utc } ;
7
+ use crow:: { PermanentFailureCode , TemporaryFailureCode } ;
7
8
use perro:: MapToError ;
8
9
use rusqlite:: Connection ;
9
10
use rusqlite:: Row ;
@@ -66,13 +67,14 @@ impl DataStore {
66
67
topup_value_minor_units,
67
68
exchange_fee_minor_units,
68
69
exchange_fee_rate_permyriad,
70
+ error,
69
71
} ) = offer
70
72
{
71
73
let exchanged_at: DateTime < Utc > = updated_at. into ( ) ;
72
74
tx. execute (
73
75
"\
74
- INSERT INTO offers (payment_hash, pocket_id, fiat_currency, rate, exchanged_at, topup_value_minor_units, exchange_fee_minor_units, exchange_fee_rate_permyriad)\
75
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)\
76
+ INSERT INTO offers (payment_hash, pocket_id, fiat_currency, rate, exchanged_at, topup_value_minor_units, exchange_fee_minor_units, exchange_fee_rate_permyriad, error )\
77
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9 )\
76
78
",
77
79
(
78
80
payment_hash,
@@ -82,7 +84,8 @@ impl DataStore {
82
84
& exchanged_at,
83
85
topup_value_minor_units,
84
86
exchange_fee_minor_units,
85
- exchange_fee_rate_permyriad
87
+ exchange_fee_rate_permyriad,
88
+ from_offer_error ( error)
86
89
) ,
87
90
)
88
91
. map_to_invalid_input ( "Failed to add new incoming pocket offer to offers db" ) ?;
@@ -99,7 +102,7 @@ impl DataStore {
99
102
" \
100
103
SELECT timezone_id, timezone_utc_offset_secs, payments.fiat_currency, h.rate, h.updated_at, \
101
104
o.pocket_id, o.fiat_currency, o.rate, o.exchanged_at, o.topup_value_minor_units, \
102
- o.exchange_fee_minor_units, o.exchange_fee_rate_permyriad \
105
+ o.exchange_fee_minor_units, o.exchange_fee_rate_permyriad, o.error \
103
106
FROM payments \
104
107
LEFT JOIN exchange_rates_history h on payments.exchange_rates_history_snaphot_id=h.snapshot_id \
105
108
AND payments.fiat_currency=h.fiat_currency \
@@ -262,6 +265,7 @@ fn offer_kind_from_row(row: &Row) -> rusqlite::Result<Option<OfferKind>> {
262
265
topup_value_minor_units,
263
266
exchange_fee_minor_units,
264
267
exchange_fee_rate_permyriad,
268
+ error : to_offer_error ( row. get ( 12 ) ?) ,
265
269
} ) )
266
270
}
267
271
None => Ok ( None ) ,
@@ -293,13 +297,80 @@ fn local_payment_data_from_row(row: &Row) -> rusqlite::Result<LocalPaymentData>
293
297
} )
294
298
}
295
299
300
+ pub fn from_offer_error ( error : Option < PocketOfferError > ) -> Option < String > {
301
+ error. map ( |e| {
302
+ match e {
303
+ PocketOfferError :: TemporaryFailure { code } => match code {
304
+ TemporaryFailureCode :: NoRoute => "no_route" . to_string ( ) ,
305
+ TemporaryFailureCode :: InvoiceExpired => "invoice_expired" . to_string ( ) ,
306
+ TemporaryFailureCode :: Unexpected => "error" . to_string ( ) ,
307
+ TemporaryFailureCode :: Unknown { msg } => msg,
308
+ } ,
309
+ PocketOfferError :: PermanentFailure { code } => match code {
310
+ PermanentFailureCode :: ThresholdExceeded => "threshold_exceeded" . to_string ( ) ,
311
+ PermanentFailureCode :: OrderInactive => "order_inactive" . to_string ( ) ,
312
+ PermanentFailureCode :: CompaniesUnsupported => "companies_unsupported" . to_string ( ) ,
313
+ PermanentFailureCode :: CountryUnsupported => "country_unsupported" . to_string ( ) ,
314
+ PermanentFailureCode :: OtherRiskDetected => "other_risk_detected" . to_string ( ) ,
315
+ PermanentFailureCode :: CustomerRequested => "customer_requested" . to_string ( ) ,
316
+ PermanentFailureCode :: AccountNotMatching => "account_not_matching" . to_string ( ) ,
317
+ PermanentFailureCode :: PayoutExpired => "payout_expired" . to_string ( ) ,
318
+ } ,
319
+ }
320
+ . to_string ( )
321
+ } )
322
+ }
323
+
324
+ pub fn to_offer_error ( code : Option < String > ) -> Option < PocketOfferError > {
325
+ code. map ( |c| match & * c {
326
+ "no_route" => PocketOfferError :: TemporaryFailure {
327
+ code : TemporaryFailureCode :: NoRoute ,
328
+ } ,
329
+ "invoice_expired" => PocketOfferError :: TemporaryFailure {
330
+ code : TemporaryFailureCode :: InvoiceExpired ,
331
+ } ,
332
+ "error" => PocketOfferError :: TemporaryFailure {
333
+ code : TemporaryFailureCode :: Unexpected ,
334
+ } ,
335
+ "threshold_exceeded" => PocketOfferError :: PermanentFailure {
336
+ code : PermanentFailureCode :: ThresholdExceeded ,
337
+ } ,
338
+ "order_inactive" => PocketOfferError :: PermanentFailure {
339
+ code : PermanentFailureCode :: OrderInactive ,
340
+ } ,
341
+ "companies_unsupported" => PocketOfferError :: PermanentFailure {
342
+ code : PermanentFailureCode :: CompaniesUnsupported ,
343
+ } ,
344
+ "country_unsupported" => PocketOfferError :: PermanentFailure {
345
+ code : PermanentFailureCode :: CountryUnsupported ,
346
+ } ,
347
+ "other_risk_detected" => PocketOfferError :: PermanentFailure {
348
+ code : PermanentFailureCode :: OtherRiskDetected ,
349
+ } ,
350
+ "customer_requested" => PocketOfferError :: PermanentFailure {
351
+ code : PermanentFailureCode :: CustomerRequested ,
352
+ } ,
353
+ "account_not_matching" => PocketOfferError :: PermanentFailure {
354
+ code : PermanentFailureCode :: AccountNotMatching ,
355
+ } ,
356
+ "payout_expired" => PocketOfferError :: PermanentFailure {
357
+ code : PermanentFailureCode :: PayoutExpired ,
358
+ } ,
359
+ e => PocketOfferError :: TemporaryFailure {
360
+ code : TemporaryFailureCode :: Unknown { msg : e. to_string ( ) } ,
361
+ } ,
362
+ } )
363
+ }
364
+
296
365
#[ cfg( test) ]
297
366
mod tests {
298
367
use crate :: config:: TzConfig ;
299
368
use crate :: data_store:: DataStore ;
300
369
use crate :: fund_migration:: MigrationStatus ;
301
370
use crate :: { ExchangeRate , OfferKind , UserPreferences } ;
302
371
372
+ use crow:: TemporaryFailureCode ;
373
+ use crow:: TopupError :: TemporaryFailure ;
303
374
use std:: fs;
304
375
use std:: thread:: sleep;
305
376
use std:: time:: { Duration , SystemTime } ;
@@ -342,6 +413,22 @@ mod tests {
342
413
topup_value_minor_units : 51245 ,
343
414
exchange_fee_minor_units : 123 ,
344
415
exchange_fee_rate_permyriad : 50 ,
416
+ error : Some ( TemporaryFailure {
417
+ code : TemporaryFailureCode :: NoRoute ,
418
+ } ) ,
419
+ } ;
420
+
421
+ let offer_kind_no_error = OfferKind :: Pocket {
422
+ id : "id" . to_string ( ) ,
423
+ exchange_rate : ExchangeRate {
424
+ currency_code : "EUR" . to_string ( ) ,
425
+ rate : 5123 ,
426
+ updated_at : SystemTime :: now ( ) ,
427
+ } ,
428
+ topup_value_minor_units : 51245 ,
429
+ exchange_fee_minor_units : 123 ,
430
+ exchange_fee_rate_permyriad : 50 ,
431
+ error : None ,
345
432
} ;
346
433
347
434
data_store
@@ -362,11 +449,20 @@ mod tests {
362
449
. store_payment_info (
363
450
"hash - no offer" ,
364
451
user_preferences. clone ( ) ,
365
- exchange_rates,
452
+ exchange_rates. clone ( ) ,
366
453
None ,
367
454
)
368
455
. unwrap ( ) ;
369
456
457
+ data_store
458
+ . store_payment_info (
459
+ "hash - no error" ,
460
+ user_preferences. clone ( ) ,
461
+ exchange_rates,
462
+ Some ( offer_kind_no_error. clone ( ) ) ,
463
+ )
464
+ . unwrap ( ) ;
465
+
370
466
assert ! ( data_store
371
467
. retrieve_payment_info( "non existent hash" )
372
468
. unwrap( )
@@ -398,6 +494,12 @@ mod tests {
398
494
user_preferences. fiat_currency
399
495
) ;
400
496
assert_eq ! ( local_payment_data. exchange_rate. rate, 4123 ) ;
497
+
498
+ let local_payment_data = data_store
499
+ . retrieve_payment_info ( "hash - no error" )
500
+ . unwrap ( )
501
+ . unwrap ( ) ;
502
+ assert_eq ! ( local_payment_data. offer. unwrap( ) , offer_kind_no_error) ;
401
503
}
402
504
403
505
#[ test]
0 commit comments