public bool SendAsset(KeyPair fromKey, string toAddress, Dictionary <string, decimal> amounts) { List <Transaction.Input> inputs; List <Transaction.Output> outputs; var scriptHash = LuxUtils.reverseHex(Neo.Emulator.Helper.ToHexString(toAddress.GetScriptHashFromAddress())); GenerateInputsOutputs(fromKey, scriptHash, amounts, out inputs, out outputs); Transaction tx = new Transaction() { type = 128, version = 0, script = null, gas = -1, inputs = inputs.ToArray(), outputs = outputs.ToArray() }; tx = tx.Sign(fromKey); var hexTx = tx.SerializeTransaction(true); return(SendRawTransaction(hexTx)); /* * var account = getAccountFromWIFKey(fromWif); * var toScriptHash = getScriptHashFromAddress(toAddress); * var balances = getBalance(net, account.address); * // TODO: maybe have transactions handle this construction? * var intents = _.map(assetAmounts, (v, k) => * { * return { assetId: tx.ASSETS[k], value: v, scriptHash: toScriptHash } * }); * var unsignedTx = tx.create.contract(account.publicKeyEncoded, balances, intents); * var signedTx = tx.signTransaction(unsignedTx, account.privateKey); * var hexTx = tx.serializeTransaction(signedTx); * return queryRPC(net, "sendrawtransaction", new object[] { hexTx }, 4);*/ }
private static string SerializeTransactionOutput(Output output) { var value = LuxUtils.num2fixed8(output.value); return(LuxUtils.reverseHex(output.assetID) + value + LuxUtils.reverseHex(output.scriptHash)); }
private static string SerializeTransactionInput(Input input) { return(LuxUtils.reverseHex(input.prevHash) + LuxUtils.reverseHex(num2hexstring(input.prevIndex, 4))); }
private void GenerateInputsOutputs(KeyPair key, string outputHash, Dictionary <string, decimal> ammounts, out List <Transaction.Input> inputs, out List <Transaction.Output> outputs) { if (ammounts == null || ammounts.Count == 0) { throw new NeoException("Invalid amount list"); } //var outputHash = toAddress.GetScriptHashFromAddress().ToHexString(); var unspent = GetUnspent(key.address); inputs = new List <Transaction.Input>(); outputs = new List <Transaction.Output>(); foreach (var entry in ammounts) { var symbol = entry.Key; if (!unspent.ContainsKey(symbol)) { throw new NeoException($"Not enough {symbol} in address {key.address}"); } } foreach (var entry in ammounts) { var symbol = entry.Key; var cost = entry.Value; string assetID; var info = GetAssetsInfo(); if (info.ContainsKey(symbol)) { assetID = info[symbol]; } else { throw new NeoException($"{symbol} is not a valid blockchain asset."); } var sources = unspent[symbol]; decimal selected = 0; foreach (var src in sources) { selected += src.value; var input = new Transaction.Input() { prevHash = src.txid, prevIndex = src.index, }; inputs.Add(input); if (selected >= cost) { break; } } if (selected < cost) { throw new NeoException($"Not enough {symbol}"); } if (cost > 0) { var output = new Transaction.Output() { assetID = assetID, scriptHash = outputHash, value = cost }; outputs.Add(output); } if (selected > cost) { var left = selected - cost; var change = new Transaction.Output() { assetID = assetID, scriptHash = LuxUtils.reverseHex(key.signatureHash.ToArray().ByteToHex()), value = left }; outputs.Add(change); } } }