public string SerializeTransaction(bool signed = true) { var tx = this; var result = new StringBuilder(); result.Append(num2hexstring(tx.type)); result.Append(num2hexstring(tx.version)); // excluusive data if (tx.type == 0xd1) { result.Append(num2VarInt(tx.script.Length)); result.Append(Neo.Emulator.Helper.ToHexString(tx.script)); if (tx.version >= 1) { result.Append(LuxUtils.num2fixed8(tx.gas)); } } // Don't need any attributes result.Append("00"); result.Append(num2VarInt(tx.inputs.Length)); foreach (var input in tx.inputs) { result.Append(SerializeTransactionInput(input)); } result.Append(num2VarInt(tx.outputs.Length)); foreach (var output in tx.outputs) { result.Append(SerializeTransactionOutput(output)); } if (signed && tx.witnesses != null && tx.witnesses.Length > 0) { result.Append(num2VarInt(tx.witnesses.Length)); foreach (var script in tx.witnesses) { result.Append(SerializeWitness(script)); } } return(result.ToString().ToLowerInvariant()); }
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); } } }