// Initialize XChainClient, must call this method after XChainClient instance created. /// <summary>Initialize XChainClient, must call this method after XChainClient instance created.</summary> /// <param name="keypath">the folder contains user's address and private key</param> /// <param name="targetHost">the GRPC endpoint of xuperchain node, e.g. 127.0.0.1:37101</param> /// <returns>the balance of given address</returns> public bool Init(string keypath, string targetHost) { try { AppContext.SetSwitch(SwitchName, true); var channel = GrpcChannel.ForAddress("http://" + targetHost); this.client = new Pb.Xchain.XchainClient(channel); this.account = new XCAccount(); return(SetAccountByPath(keypath)); } catch (Exception e) { Console.WriteLine("Init failed, err=" + e.ToString()); return(false); } }
private Transaction AssembleTx(Pb.UtxoOutput utxo, XCAccount account, List <string> authRequire, string to, BigInteger amount, Pb.InvokeResponse contractInvoke, string desc) { var tx = new Transaction(); // check param if (amount < 0 || account == null) { return(null); } // if have utxo, assemble utxo input/ouput if (utxo != null) { // assemble TxInputs tx.TxInputs = new List <TxInput>(); var total = BigInteger.Parse(utxo.TotalSelected); for (var i = 0; i < utxo.UtxoList.Count; i++) { var utxoItem = utxo.UtxoList[i]; var input = new TxInput { FromAddr = utxoItem.ToAddr.ToByteArray(), Amount = utxoItem.Amount.ToByteArray(), RefTxid = utxoItem.RefTxid.ToByteArray(), RefOffset = utxoItem.RefOffset, }; tx.TxInputs.Add(input); } tx.TxOutputs = new List <TxOutput>(); // Assemble utxo Output for transferring to if (amount > 0 && to != "") { // utxo check if (amount > total) { Console.WriteLine("Utxo use greater than utxo selected" + ", selected=" + total + ", use=", amount); return(null); } var output = new TxOutput() { ToAddr = Encoding.ASCII.GetBytes(to), Amount = amount.ToByteArray(), }; Array.Reverse(output.Amount, 0, output.Amount.Length); tx.TxOutputs.Add(output); total -= amount; } // Assemble contract fee if (contractInvoke != null && contractInvoke.GasUsed > 0) { var gasUsed = new BigInteger(contractInvoke.GasUsed); if (gasUsed > total) { Console.WriteLine("Utxo use greater than utxo selected" + ", selected=" + total + ", use=", gasUsed); return(null); } var output = new TxOutput() { ToAddr = Encoding.ASCII.GetBytes("$"), Amount = gasUsed.ToByteArray(), }; Array.Reverse(output.Amount, 0, output.Amount.Length); tx.TxOutputs.Add(output); total -= gasUsed; } // charge utxo to user if (total > 0) { var chargeOutput = new TxOutput() { ToAddr = Encoding.ASCII.GetBytes(account.Address), Amount = total.ToByteArray(), }; Array.Reverse(chargeOutput.Amount, 0, chargeOutput.Amount.Length); tx.TxOutputs.Add(chargeOutput); } } // Assemble contracts if (contractInvoke != null) { if (contractInvoke.Inputs.Count > 0) { tx.TxInputsExt = new List <TxInputExt>(); } if (contractInvoke.Outputs.Count > 0) { tx.TxOutputsExt = new List <TxOutputExt>(); } if (contractInvoke.Requests.Count > 0) { tx.ContractRequests = new List <InvokeRequest>(); } // TODO: transfer within contract is not supported foreach (var input in contractInvoke.Inputs) { var inputExt = new TxInputExt { Bucket = input.Bucket, Key = input.Key.ToByteArray(), RefTxid = input.RefTxid.ToByteArray(), RefOffset = input.RefOffset, }; tx.TxInputsExt.Add(inputExt); } foreach (var output in contractInvoke.Outputs) { var outputExt = new TxOutputExt { Bucket = output.Bucket, Key = output.Key.ToByteArray(), Value = output.Value.ToByteArray(), }; tx.TxOutputsExt.Add(outputExt); } foreach (var request in contractInvoke.Requests) { var invoke = new InvokeRequest { ModuleName = request.ModuleName, ContractName = request.ContractName, MethodName = request.MethodName, }; foreach (var arg in request.Args) { invoke.Args.Add(arg.Key, arg.Value.ToByteArray()); } foreach (var limit in request.ResourceLimits) { invoke.ResourceLimits.Add(new ResourceLimit { Type = (ResourceType)limit.Type, Limit = limit.Limit, }); } tx.ContractRequests.Add(invoke); } } // Assemble other data tx.Desc = Encoding.ASCII.GetBytes(desc); tx.Version = 1; tx.Coinbase = false; tx.Autogen = false; tx.Initiator = account.Address; if (authRequire != null && authRequire.Count > 0) { tx.AuthRequire = authRequire; } var digestHash = XDigest.MakeDigestHash(tx); var sign = XCrypto.SignHash(account.PrivateKey, digestHash); var signInfo = new SignatureInfo() { PublicKey = account.PublicKey.RawKey, Sign = sign, }; tx.InitiatorSigns = new List <SignatureInfo>(); tx.InitiatorSigns.Add(signInfo); if (authRequire != null && authRequire.Count > 0) { tx.AuthRequireSigns = new List <SignatureInfo>(); tx.AuthRequireSigns.Add(signInfo); } var txid = XDigest.MakeTransactionID(tx); tx.Txid = txid; return(tx); }