diff --git a/.gitignore b/.gitignore index e663d96..ae95915 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ devtools_options.yaml untranslated.txt generate_protos.sh update_dep.sh -.vscode/ \ No newline at end of file +.vscode/ +GeneratedPluginRegistrant.swift \ No newline at end of file diff --git a/api/fx/oracle/internal/service/oracle/calculator.go b/api/fx/oracle/internal/service/oracle/calculator.go index 599d61c..2a0eb87 100644 --- a/api/fx/oracle/internal/service/oracle/calculator.go +++ b/api/fx/oracle/internal/service/oracle/calculator.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/tech/sendico/fx/storage/model" "github.com/tech/sendico/pkg/merrors" + smodel "github.com/tech/sendico/pkg/model" fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1" moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" tracev1 "github.com/tech/sendico/pkg/proto/common/trace/v1" @@ -138,11 +139,11 @@ func (qc *quoteComputation) buildModelQuote(firm bool, expiryMillis int64, req * Pair: qc.pair.Pair, Side: qc.sideModel, Price: formatRat(qc.priceRounded, qc.priceScale), - BaseAmount: model.Money{ + BaseAmount: smodel.Money{ Currency: qc.pair.Pair.Base, Amount: formatRat(qc.baseRounded, qc.baseScale), }, - QuoteAmount: model.Money{ + QuoteAmount: smodel.Money{ Currency: qc.pair.Pair.Quote, Amount: formatRat(qc.quoteRounded, qc.quoteScale), }, diff --git a/api/fx/oracle/internal/service/oracle/math.go b/api/fx/oracle/internal/service/oracle/math.go index f3d9822..da1bc5a 100644 --- a/api/fx/oracle/internal/service/oracle/math.go +++ b/api/fx/oracle/internal/service/oracle/math.go @@ -3,7 +3,6 @@ package oracle import ( "math/big" "strings" - "time" "github.com/tech/sendico/fx/storage/model" "github.com/tech/sendico/pkg/decimal" @@ -61,7 +60,3 @@ func priceFromRate(rate *model.RateSnapshot, side fxv1.Side) (*big.Rat, error) { return ratFromString(priceStr) } - -func timeFromUnixMilli(ms int64) time.Time { - return time.Unix(0, ms*int64(time.Millisecond)) -} diff --git a/api/fx/oracle/internal/service/oracle/service_test.go b/api/fx/oracle/internal/service/oracle/service_test.go index 00497b0..02ea1f8 100644 --- a/api/fx/oracle/internal/service/oracle/service_test.go +++ b/api/fx/oracle/internal/service/oracle/service_test.go @@ -9,6 +9,7 @@ import ( "github.com/tech/sendico/fx/storage" "github.com/tech/sendico/fx/storage/model" "github.com/tech/sendico/pkg/merrors" + smodel "github.com/tech/sendico/pkg/model" fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1" moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" tracev1 "github.com/tech/sendico/pkg/proto/common/trace/v1" @@ -381,8 +382,8 @@ func TestServiceValidateQuote(t *testing.T) { Pair: model.CurrencyPair{Base: "USD", Quote: "EUR"}, Side: model.QuoteSideBuyBaseSellQuote, Price: "1.10", - BaseAmount: model.Money{Currency: "USD", Amount: "100"}, - QuoteAmount: model.Money{Currency: "EUR", Amount: "110"}, + BaseAmount: smodel.Money{Currency: "USD", Amount: "100"}, + QuoteAmount: smodel.Money{Currency: "EUR", Amount: "110"}, ExpiresAtUnixMs: now.UnixMilli(), Status: model.QuoteStatusIssued, }, nil diff --git a/api/fx/oracle/internal/service/oracle/transform.go b/api/fx/oracle/internal/service/oracle/transform.go index a505a0c..bdc11b0 100644 --- a/api/fx/oracle/internal/service/oracle/transform.go +++ b/api/fx/oracle/internal/service/oracle/transform.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/tech/sendico/fx/storage/model" + smodel "github.com/tech/sendico/pkg/model" fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1" moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1" tracev1 "github.com/tech/sendico/pkg/proto/common/trace/v1" @@ -49,7 +50,7 @@ func quoteModelToProto(q *model.Quote) *oraclev1.Quote { } } -func moneyModelToProto(m *model.Money) *moneyv1.Money { +func moneyModelToProto(m *smodel.Money) *moneyv1.Money { if m == nil { return nil } diff --git a/frontend/pshared/lib/provider/account.dart b/frontend/pshared/lib/provider/account.dart index 9413913..644907c 100644 --- a/frontend/pshared/lib/provider/account.dart +++ b/frontend/pshared/lib/provider/account.dart @@ -27,6 +27,7 @@ class AccountProvider extends ChangeNotifier { Resource get resource => _resource; late LocaleProvider _localeProvider; PendingLogin? _pendingLogin; + Future? _restoreFuture; Account? get account => _resource.data; PendingLogin? get pendingLogin => _pendingLogin; @@ -34,6 +35,7 @@ class AccountProvider extends ChangeNotifier { bool get isLoading => _resource.isLoading; Object? get error => _resource.error; bool get isReady => (!isLoading) && (account != null); + Future? get restoreFuture => _restoreFuture; Account? currentUser() { final acc = account; @@ -220,4 +222,12 @@ class AccountProvider extends ChangeNotifier { rethrow; } } + + Future restoreIfPossible() { + return _restoreFuture ??= () async { + final hasAuth = await AuthorizationService.isAuthorizationStored(); + if (!hasAuth) return; + await restore(); + }(); + } } diff --git a/frontend/pweb/lib/pages/loaders/account.dart b/frontend/pweb/lib/pages/loaders/account.dart index d891e1c..14200d9 100644 --- a/frontend/pweb/lib/pages/loaders/account.dart +++ b/frontend/pweb/lib/pages/loaders/account.dart @@ -17,15 +17,34 @@ class AccountLoader extends StatelessWidget { @override Widget build(BuildContext context) => Consumer(builder: (context, provider, _) { - if (provider.isLoading) return const Center(child: CircularProgressIndicator()); - if (provider.error != null) { - postNotifyUserOfErrorX( - context: context, - errorSituation: AppLocalizations.of(context)!.errorLogin, - exception: provider.error!, - ); - navigateAndReplace(context, Pages.login); + if (provider.account != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + }); + return child; } + + if (provider.error != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + postNotifyUserOfErrorX( + context: context, + errorSituation: AppLocalizations.of(context)!.errorLogin, + exception: provider.error!, + ); + navigateAndReplace(context, Pages.login); + }); + return const Center(child: CircularProgressIndicator()); + } + + if (provider.restoreFuture == null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + provider.restoreIfPossible().catchError((error, stack) { + debugPrint('Account restore failed: $error'); + }); + }); + return const Center(child: CircularProgressIndicator()); + } + + if (provider.isLoading) return const Center(child: CircularProgressIndicator()); if (provider.account == null) { WidgetsBinding.instance.addPostFrameCallback((_) => navigateAndReplace(context, Pages.login)); return const Center(child: CircularProgressIndicator());