title: Flutter: How to sync TOTP codes?
body: <p>I'm writing a very simple 2FA application, which generates TOTP codes for a given secret key, digits, interval and algorithm.</p>
  <p>However, I have a hard time with maths, and I do not know how to construct the algorithm for generating the TOTP code</p>
  <p>I'm writing the whole app in BLoC pattern using the Flutter BLoC library.</p>
  <p>Have a look at this video, the app generates a code which has an interval of 30 seconds, however the progress indicator doesn't start from 0 seconds, but it starts from a time every 30 seconds for example: 13:00:00 and when 30 seconds pass (13:00:30), it generates another code.</p>
  <p>Video: <a href="https://streamable.com/u7vhcg" rel="nofollow noreferrer">https://streamable.com/u7vhcg</a></p>
  <p>Now, when it comes to my application, it generates codes, but they're not synced. How do I do it like that, that it generates codes, but every code is synced?</p>
  <p>Vide of my app: <a href="https://streamable.com/zn3pnf" rel="nofollow noreferrer">https://streamable.com/zn3pnf</a></p>
  <p>As you see, the TOTP codes are not synced. How do I do that, so they will be synced?</p>
  <p>Let me know if you want to see more code.</p>
  <h1>Code</h1>
  <h2>totp_generator_bloc.dart</h2>
  <pre><code>import 'dart:async';
  
  import 'package:bloc/bloc.dart';
  import 'package:dart_otp/dart_otp.dart';
  import 'package:duckie/models/code/code_model.dart';
  import 'package:hive/hive.dart';
  import 'package:meta/meta.dart';
  
  part 'totp_generator_event.dart';
  part 'totp_generator_state.dart';
  
  class TotpGeneratorBloc extends Bloc&lt;TotpGeneratorEvent, TotpGeneratorState&gt; {
    TotpGeneratorBloc() : super(TotpGeneratorInitial());
  
    @override
    Stream&lt;TotpGeneratorState&gt; mapEventToState(
      TotpGeneratorEvent event,
    ) async* {
      if (event is GetTotpItemsEvent) {
        Box box = Hive.box('totpmodel');
        List totpItems = [];
  
        for (var totpItem in box.values) {
          final String secret = totpItem.secret;
          final int digits = int.parse(totpItem.digits);
          final int interval = int.parse(totpItem.interval);
          final String algorithmString = totpItem.algorithm;
          final String accountName = totpItem.accountName;
          int timeStamp = totpItem.timeStamp;
  
          OTPAlgorithm algorithm = OTPAlgorithm.SHA1;
  
          switch (algorithmString) {
            case 'sha1':
              algorithm = OTPAlgorithm.SHA1;
              break;
            case 'sha256':
              algorithm = OTPAlgorithm.SHA256;
              break;
            case 'sha384':
              algorithm = OTPAlgorithm.SHA384;
              break;
            case 'sha512':
              algorithm = OTPAlgorithm.SHA512;
              break;
          }
  
          final TOTP totp = TOTP(
            secret: secret,
            digits: digits,
            interval: interval,
            algorithm: algorithm,
          );
  
          try {
            final String otp =
                totp.value(date: DateTime.fromMillisecondsSinceEpoch(timeStamp));
  
            totpItems.add(CodeModel(otp, interval, 0, accountName));
  
            yield TotpGeneratorFinal(totpItems);
          } catch (error) {
            yield TotpGeneratorError('totp-fail-title', 'totp-fail-content');
          }
        }
      }
    }
  }
  
  </code></pre>