resolveObjectReferences method

Future<void> resolveObjectReferences(
  1. BuildOptions options
)

Implementation

Future<void> resolveObjectReferences(BuildOptions options) async {
  // Keep track of the object references that will need to be resolved at the end of the transaction.
  // We keep the input by-reference to avoid needing to re-resolve it:
  final objectsToResolve = _blockData.inputs.where((input) {
    return (input["UnresolvedObject"] != null &&
        (input["UnresolvedObject"]["version"] == null &&
            input["UnresolvedObject"]["initialSharedVersion"] == null));
  });

  final dedupedIds = Set.from(
    objectsToResolve.map(
      (input) => normalizeSuiObjectId(input["UnresolvedObject"]["objectId"]),
    ),
  ).toList();

  final objectChunks = dedupedIds.isNotEmpty
      ? chunk(dedupedIds, MAX_OBJECTS_PER_FETCH)
      : [];

  final resolved = <SuiObjectResponse>[];
  final objectsResult = (await Future.wait(
    objectChunks.map(
      (chunk) => expectClient(options).multiGetObjects(
        chunk.cast<String>(),
        options: SuiObjectDataOptions(showOwner: true),
      ),
    ),
  ));
  for (var item in objectsResult) {
    resolved.addAll(item);
  }

  final responsesById = Map.fromIterables(
    dedupedIds,
    dedupedIds
        .asMap()
        .map((index, id) => MapEntry(index, resolved[index]))
        .values,
  );

  final invalidObjects = responsesById.entries
      .where((entry) => entry.value.error != null)
      .map((entry) => entry.value.error?.toJson())
      .toList();

  if (invalidObjects.isNotEmpty) {
    throw ArgumentError(
      "The following input objects are invalid: ${invalidObjects.join(', ')}",
    );
  }

  final objects = resolved.map((object) {
    if (object.error != null || object.data == null) {
      throw ArgumentError("Failed to fetch object: ${object.error}");
    }
    final owner = object.data?.owner;
    final initialSharedVersion = owner?.shared?.initialSharedVersion;

    return {
      "objectId": object.data?.objectId,
      "digest": object.data?.digest,
      "version": object.data?.version,
      "initialSharedVersion": initialSharedVersion,
    };
  }).toList();

  final objectsById = Map.fromIterables(
    dedupedIds,
    dedupedIds
        .asMap()
        .map((index, id) => MapEntry(index, objects[index]))
        .values,
  );

  for (int index = 0; index < _blockData.inputs.length; index++) {
    final input = _blockData.inputs[index];
    if (input["UnresolvedObject"] == null) {
      continue;
    }

    CallArg updated;
    final id = normalizeSuiAddress(input["UnresolvedObject"]["objectId"]);
    final object = objectsById[id];

    if ((input["UnresolvedObject"]?["initialSharedVersion"] ??
            object?["initialSharedVersion"]) !=
        null) {
      updated = Inputs.sharedObjectRef({
        "objectId": id,
        "initialSharedVersion":
            input["UnresolvedObject"]["initialSharedVersion"] ??
            object?["initialSharedVersion"],
        "mutable": isUsedAsMutable(_blockData, index),
      });
    } else if (isUsedAsReceiving(_blockData, index)) {
      updated = Inputs.receivingRef(
        SuiObjectRef(
          input["UnresolvedObject"]["digest"] ?? object?["digest"],
          id,
          input["UnresolvedObject"]["version"] ?? object?["version"],
        ),
      );
    }

    _blockData.inputs[_blockData.inputs.indexOf(input)] =
        updated ??
        Inputs.objectRef(
          SuiObjectRef(
            input["UnresolvedObject"]["digest"] ?? object?["digest"],
            id,
            input["UnresolvedObject"]["version"] ?? object?["version"],
          ),
        );
  }
}