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"],
        )
      );
  }
}