normalizeInputs method
Implementation
Future<void> normalizeInputs(BuildOptions options) async {
final inputs = _blockData.inputs;
final commands = _blockData.commands;
final moveCallsToResolve = [];
final moveFunctionsToResolve = <String>{};
for (var command in commands) {
if (command["MoveCall"] != null) {
// Determine if any of the arguments require encoding.
// - If they don't, then this is good to go.
// - If they do, then we need to fetch the normalized move module.
// If we already know the argument types, we don't need to resolve them again
if (command["MoveCall"]?["_argumentTypes"] != null) {
continue;
}
final inputs = (command["MoveCall"]["arguments"] as Iterable).map((arg) {
if (arg is Map && arg["Input"] != null) {
return _blockData.inputs[arg["Input"]];
}
return null;
}).toList();
final needsResolution = inputs.firstWhere(
(input) => input?["UnresolvedPure"] != null || input?["UnresolvedObject"] != null,
orElse: () => null
);
if (needsResolution != null) {
final functionName = "${command["MoveCall"]["package"]}::${command["MoveCall"]["module"]}::${command["MoveCall"]["function"]}";
moveFunctionsToResolve.add(functionName);
moveCallsToResolve.add(command["MoveCall"]);
}
}
// Special handling for values that where previously encoded using the wellKnownEncoding pattern.
// This should only happen when transaction data was hydrated from an old version of the SDK
if (command["SplitCoins"] != null) {
command["SplitCoins"]["amounts"].forEach((amount) {
normalizeRawArgument(amount, SuiBcs.U64);
});
} else if (command["TransferObjects"] != null) {
normalizeRawArgument(command["TransferObjects"]["address"], SuiBcs.Address);
}
}
final moveFunctionParameters = <String, List<dynamic>>{};
if (moveFunctionsToResolve.isNotEmpty) {
final client = expectClient(options);
await Future.wait(
[...moveFunctionsToResolve].map((functionName) async {
final [packageId, moduleId, functionId] = functionName.split('::');
final def = await client.getNormalizedMoveFunction(
packageId,
moduleId,
functionId,
);
moveFunctionParameters[functionName] = def.parameters.map((param) => normalizedTypeToMoveTypeSignature(param)).toList();
}),
);
}
if (moveCallsToResolve.isNotEmpty) {
moveCallsToResolve.forEach((moveCall) {
final parameters = moveFunctionParameters["${moveCall["package"]}::${moveCall["module"]}::${moveCall["function"]}"];
if (parameters != null && parameters.isNotEmpty) {
// Entry functions can have a mutable reference to an instance of the TxContext
// struct defined in the TxContext module as the last parameter. The caller of
// the function does not need to pass it in as an argument.
final hasTxContext = isTxContext(parameters.last!);
final params = hasTxContext ? parameters.sublist(0, parameters.length - 1) : parameters;
moveCall["_argumentTypes"] = params;
}
});
}
for (var command in commands) {
if (command["MoveCall"] == null) {
continue;
}
final moveCall = command["MoveCall"];
final fnName = "${moveCall["package"]}::${moveCall["module"]}::${moveCall["function"]}";
final params = moveCall["_argumentTypes"];
if (params == null) {
continue;
}
if (params.length != command["MoveCall"]["arguments"].length) {
throw ArgumentError("Incorrect number of arguments for $fnName");
}
final callArgs = moveCall["arguments"].toList();
for (var i = 0; i < params.length; i++) {
final param = params[i];
final arg = callArgs[i];
if (arg["Input"] == null) continue;
final input = inputs[arg["Input"]];
// Skip if the input is already resolved
if (input["UnresolvedPure"] == null && input["UnresolvedObject"] == null) {
continue;
}
final inputValue = input["UnresolvedPure"]?["value"] ?? input["UnresolvedObject"]?["objectId"];
final schema = getPureBcsSchema(param["body"]);
if (schema != null) {
arg["type"] = 'pure';
inputs[inputs.indexOf(input)] = Inputs.pure(schema.serialize(inputValue));
continue;
}
if (inputValue is! String) {
throw ArgumentError("Expect the argument to be an object id string, got $inputValue");
}
arg["type"] = 'object';
final unresolvedObject = input["UnresolvedPure"] != null
? {
"UnresolvedObject": {
"objectId": inputValue,
},
}
: input;
inputs[arg["Input"]] = unresolvedObject;
}
}
}