public async Task <object> InvokeContract(InvokeContractParameterModel para) { if (CurrentWallet == null) { return(Error(ErrorCode.WalletNotOpen)); } if (para.ContractHash == null || para.Method.IsNull()) { return(Error(ErrorCode.ParameterIsNull)); } var contract = para.ContractHash.GetContract(); if (contract == null) { return(Error(ErrorCode.UnknownContract)); } ContractParameter[] contractParameters = null; try { contractParameters = para.Parameters?.Select(JsonToContractParameter).ToArray(); } catch (Exception e) { return(Error(ErrorCode.InvalidPara)); } var signers = new List <Signer>(); if (para.Cosigners.NotEmpty()) { signers.AddRange(para.Cosigners.Select(s => new Signer() { Account = s.Account, Scopes = s.Scopes, AllowedContracts = new UInt160[0] })); } Transaction tx = null; using ScriptBuilder sb = new ScriptBuilder(); sb.EmitDynamicCall(para.ContractHash, para.Method, contractParameters); try { tx = CurrentWallet.InitTransaction(sb.ToArray(), null, signers.ToArray()); } catch (InvalidOperationException ex) { return(Error(ErrorCode.EngineFault, $"{ex.Message}\r\n InnerError:{ex.InnerException}")); } catch (Exception ex) { if (ex.Message.Contains("Insufficient GAS")) { return(Error(ErrorCode.GasNotEnough)); } throw; } var(signSuccess, context) = CurrentWallet.TrySignTx(tx); if (!signSuccess) { return(Error(ErrorCode.SignFail, context.SafeSerialize())); } var result = new InvokeResultModel(); using ApplicationEngine engine = tx.Script.RunTestMode(null, tx); result.VmState = engine.State; result.GasConsumed = new BigDecimal((BigInteger)tx.SystemFee, NativeContract.GAS.Decimals); result.ResultStack = engine.ResultStack.Select(p => JStackItem.FromJson(p.ToContractParameter().ToJson())).ToList(); result.Notifications = engine.Notifications?.Select(ConvertToEventModel).ToList(); if (engine.State.HasFlag(VMState.FAULT)) { return(Error(ErrorCode.EngineFault)); } if (!para.SendTx) { return(result); } await tx.Broadcast(); result.TxId = tx.Hash; return(result); }