getMigrateWalletChecks method

Future<MigrateWalletChecks> getMigrateWalletChecks({
  1. required String fromAddress,
  2. required String toAddress,
})

Implementation

Future<MigrateWalletChecks> getMigrateWalletChecks({
  required String fromAddress,
  required String toAddress,
}) async {
  final errors = <MigrateWalletValidationError>{};
  OwnerKeyBondInfo? ownerKeyBondInfo;

  if (fromAddress.isEmpty) {
    final toIdtyStatus = await getIdtyStatus(toAddress);

    return MigrateWalletChecks(
      fromBalance: WalletBalance.empty(),
      fromIdtyStatus: IdtyStatus.none,
      toIdtyStatus: toIdtyStatus,
      errors: {MigrateWalletValidationError.sourceAccountIsEmpty},
    );
  }

  final results = await Future.wait([
    getBalance(fromAddress),
    getIdtyStatusMulti([fromAddress, toAddress]),
    getIdentityIndexOf(fromAddress),
  ]);

  final fromBalance = results[0] as WalletBalance;
  final statusList = results[1] as List<IdtyStatus>;
  final fromIdtyIndex = results[2] as int?;

  final fromIdtyStatus = statusList[0];
  final toIdtyStatus = statusList[1];

  if (fromIdtyIndex != null) {
    // Detect the "owner key changed too recently" cool-down. The identity
    // pallet stores `oldOwnerKey = Some((oldKey, blockOfChange))` for the
    // duration of `changeOwnerKeyPeriod` after a change_owner_key; any new
    // migration during that window is rejected with
    // `OwnerKeyAlreadyRecentlyChanged`. (The previous implementation read the
    // SMITH `reportLongevity`/`lastOnline`, which is unrelated to identity
    // owner-key changes and produced a meaningless bond period.)
    final idtyData = await _chain.query.identity.identities(fromIdtyIndex);
    final oldOwnerKey = idtyData?.oldOwnerKey;

    if (oldOwnerKey != null) {
      final currentBlock = await getCurrentBlockHeight();
      final int changeBlock = oldOwnerKey.value1;
      final int changeOwnerKeyPeriod = currencyConstants.changeOwnerKeyPeriod;
      final bondEndBlock = changeBlock + changeOwnerKeyPeriod;

      log.d(
        'getMigrateWalletChecks - oldOwnerKey present: changeBlock: $changeBlock, '
        'changeOwnerKeyPeriod: $changeOwnerKeyPeriod, bondEndBlock: $bondEndBlock, currentBlock: $currentBlock',
      );

      if (currentBlock < bondEndBlock) {
        final now = DateTime.now();
        // Guard against stale/rolled-back chain data where currentBlock could
        // be < changeBlock, which would otherwise push changeDate into the future.
        final elapsedBlocks =
            currentBlock > changeBlock ? currentBlock - changeBlock : 0;
        final changeDate = now.subtract(
          Duration(seconds: elapsedBlocks * _blockTime),
        );
        final bondEndDate = now.add(
          Duration(seconds: (bondEndBlock - currentBlock) * _blockTime),
        );

        ownerKeyBondInfo = OwnerKeyBondInfo(
          changeDate: changeDate,
          bondEndDate: bondEndDate,
        );
        log.d(
          'getMigrateWalletChecks - In owner-key cool-down! hasEnded=${ownerKeyBondInfo.hasEnded}, remaining=${ownerKeyBondInfo.remainingTime}',
        );
      }
    }
  }

  if (fromBalance.transferableBalance == BigInt.zero) {
    errors.add(MigrateWalletValidationError.sourceAccountIsEmpty);
  }
  if (fromIdtyStatus != IdtyStatus.none && toIdtyStatus != IdtyStatus.none) {
    errors.add(MigrateWalletValidationError.cannotMigrateIdentityToIdentity);
  }

  return MigrateWalletChecks(
    fromBalance: fromBalance,
    fromIdtyStatus: fromIdtyStatus,
    toIdtyStatus: toIdtyStatus,
    errors: errors,
    ownerKeyBondInfo: ownerKeyBondInfo,
  );
}