/// <summary> /// Method that SendNativeAsset, TransferNep5 and CallContract uses to create the inputs and outputs of the transaction. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tx"></param> /// <param name="from"></param> /// <param name="changeAddress"></param> /// <param name="fee"></param> /// <returns></returns> private T MakeTransaction <T>(T tx, UInt160 from = null, UInt160 changeAddress = null, Fixed8 fee = default(Fixed8)) where T : Transaction { if (tx.Outputs == null) { tx.Outputs = new TransactionOutput[0]; } if (tx.Attributes == null) { tx.Attributes = new TransactionAttribute[0]; } if (from == null) { from = AddressScriptHash; } fee += tx.SystemFee; var payTotal = tx.Outputs.GroupBy(p => p.AssetId, (k, g) => new { AssetId = k, Value = g.Sum(p => p.Value) }).ToDictionary(p => p.AssetId); if (fee > Fixed8.Zero) { if (payTotal.ContainsKey(Utils.GasToken)) { payTotal[Utils.GasToken] = new { AssetId = Utils.GasToken, Value = payTotal[Utils.GasToken].Value + fee }; } else { payTotal.Add(Utils.GasToken, new { AssetId = Utils.GasToken, Value = fee }); } } var payCoins = payTotal.Select(async p => new { AssetId = p.Key, Unspents = await TransactionBuilderHelper.FindUnspentCoins(p.Key, p.Value.Value, from, _restService) }).Select(x => x.Result).ToDictionary(p => p.AssetId); if (payCoins.Any(p => p.Value.Unspents == null)) { return(null); } var inputSum = payCoins.Values.ToDictionary(p => p.AssetId, p => new { p.AssetId, Value = p.Unspents.Sum(q => q.Output.Value) }); if (changeAddress == null) { changeAddress = from; } List <TransactionOutput> outputsNew = new List <TransactionOutput>(tx.Outputs); foreach (UInt256 assetId in inputSum.Keys) { if (inputSum[assetId].Value > payTotal[assetId].Value) { outputsNew.Add(new TransactionOutput { AssetId = assetId, Value = inputSum[assetId].Value - payTotal[assetId].Value, ScriptHash = changeAddress }); } } tx.Inputs = payCoins.Values.SelectMany(p => p.Unspents).Select(p => p.Reference).ToArray(); tx.Outputs = outputsNew.ToArray(); return(tx); }