resolveRecord function

Future<ResolvedRecordResponse?> resolveRecord(
  1. String domain,
  2. String context,
  3. String directive,
  4. bool proven,
  5. StateApi state,
  6. StatusApi status,
  7. EntityDetails entities,
)

Implementation

Future<ResolvedRecordResponse?> resolveRecord(
  String domain,
  String context,
  String directive,
  bool proven,
  StateApi state,
  StatusApi status,
  EntityDetails entities,
) async {
  try {
    final domainId = await domainToNonFungId(domain);
    final parsedContext = context.isNotEmpty ? '-$context' : '';
    final parsedDirective = directive.isNotEmpty ? '-$directive' : '';
    final recordId =
        await domainToNonFungId('$domainId$parsedContext$parsedDirective');

    final nft = await state.nonFungibleData(
      stateNonFungibleDataRequest: StateNonFungibleDataRequest((builder) {
        builder.resourceAddress = entities.resolverRecordResource;
        builder.nonFungibleIds.add(recordId);
      }),
    ).then((response) => response.data?.nonFungibleIds.first);

    if (nft?.data?.programmaticJson.kind ==
        ProgrammaticScryptoSborValueKind.tuple) {
      final value =
          (nft?.data?.programmaticJson as ProgrammaticScryptoSborValueTuple)
              .fields
              .where((field) =>
                  field.fieldName == 'value' &&
                  field.kind == ProgrammaticScryptoSborValueKind.enum_)
              .map((field) {
        if (field.fieldName == 'value' &&
            field.kind == ProgrammaticScryptoSborValueKind.enum_) {
          return ((field as ProgrammaticScryptoSborValueEnum).fields[0]
                  as ProgrammaticScryptoSborValueString)
              .value;
        }
        return null;
      }).first;

      if (!proven) {
        return ResolvedRecordResponse(value: value!);
      }

      if (!value!.startsWith('(') || !value.endsWith(')')) {
        return null;
      }

      final provenResources =
          RegExp(r'\(\"(.+)\"\)').firstMatch(value)?.group(1);

      if (provenResources == null) {
        return null;
      }

      final domainDetails =
          await requestDomainDetails(domain, state: state, entities: entities);

      final accountAddress = domainDetails?.address;

      final provenResourcesList = provenResources
          .split(',')
          .fold<List<Map<String, dynamic>>>([], (acc, resource) {
        final parts = resource.split(':');
        final resourceAddress = parts[0];
        final id = parts.length > 1 ? parts[1] : null;

        final foundResource = acc.firstWhere(
          (a) => a['resourceAddress'] == resourceAddress,
          orElse: () => {
            'resourceAddress': resourceAddress,
            'ids': <String>[],
          },
        );

        if (id != null) {
          foundResource['ids'].add(id);
        }

        if (!acc.contains(foundResource)) {
          acc.add(foundResource);
        }

        return acc;
      });

      final fungibleResourcesAddresses = provenResourcesList
          .where((r) => r['ids'].isEmpty)
          .map((r) => r['resourceAddress'])
          .toList();

      final accountNonFungibleVaultIds = await Future.wait([
        fungibleVaults(
            accountAddress: accountAddress!, state: state, status: status),
        nonFungibleVaults(
            accountAddress: accountAddress, state: state, status: status)
      ]).then((r) {
        final fungibleVaultList = r[0] as List<FungibleResourcesCollectionItem>;
        final nonFungibleVaultList =
            r[1] as List<NonFungibleResourcesCollectionItem>;

        final nonFungibleVaultAddresses = nonFungibleVaultList
            .map((v) => (v as NonFungibleResourcesCollectionItemVaultAggregated)
                .vaults
                .items[0]
                .vaultAddress)
            .toSet();

        final areAllResourcesProven =
            fungibleResourcesAddresses.every((resource) {
          return fungibleVaultList.any((v) =>
              v.resourceAddress == resource &&
              double.parse((v as FungibleResourcesCollectionItemVaultAggregated)
                      .vaults
                      .items[0]
                      .amount) >
                  0);
        });

        if (!areAllResourcesProven) {
          return null;
        }

        return nonFungibleVaultAddresses.toList();
      });

      if (accountNonFungibleVaultIds == null) {
        return null;
      }

      final nonFungibleLocationResponse = await Future.wait(
          provenResourcesList.where((r) => r['ids'].isNotEmpty).map((resource) {
        return state.nonFungibleLocation(stateNonFungibleLocationRequest:
            StateNonFungibleLocationRequest((builder) {
          builder.resourceAddress = resource['resourceAddress'];
          builder.nonFungibleIds.addAll(resource['ids']);
        }));
      })).then(
          (s) => s.map((r) => r.data?.nonFungibleIds.toList() ?? []).toList());

      final requiredVaultIds = nonFungibleLocationResponse
          .expand((r) => r)
          .map((r) => r.owningVaultAddress)
          .toSet();

      final areAllNftsProven = requiredVaultIds
          .every((vaultId) => accountNonFungibleVaultIds.contains(vaultId));

      if (!areAllNftsProven) {
        return null;
      }

      final nftDataList = await Future.wait(provenResourcesList.map((r) {
        return state.nonFungibleData(
          stateNonFungibleDataRequest: StateNonFungibleDataRequest((builder) {
            builder.resourceAddress = r['resourceAddress'];
            builder.nonFungibleIds.addAll(r['ids']);
          }),
        ).then((response) =>
            response.data?.nonFungibleIds.toList() ??
            [] as List<StateNonFungibleDetailsResponseItem>);
      }));

      return ResolvedRecordResponse(
        value: value,
        nonFungibleDataList: nftDataList.expand((r) => r).toList(),
      );
    }

    return null;
  } catch (e) {
    print(e);
    return null;
  }
}