protected override JObject Process(string method, JArray _params) { switch (method) { case "getbalance": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { UInt256 assetId = UInt256.Parse(_params[0].AsString()); IEnumerable <Coin> coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId)); JObject json = new JObject(); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); return(json); } case "sendtoaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.SaveTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.SaveTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "getnewaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { KeyPair key = Program.Wallet.CreateKey(); VerificationContract contract = Program.Wallet.GetContracts(key.PublicKeyHash).First(p => p.IsStandard); return(contract.Address); } case "dumpprivkey": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); KeyPair key = Program.Wallet.GetKeyByScriptHash(scriptHash); return(key.Export()); } default: return(base.Process(method, _params)); } }
private JObject Process(string method, JArray _params) { switch (method) { /* * case "dumpprivkey": * if (wallet == null) * throw new RpcException(-400, "Access denied"); * else * { * UInt160 scriptHash = _params[0].AsString().ToScriptHash(); * WalletAccount account = wallet.GetAccount(scriptHash); * return account.GetKey().Export(); * } */ case "getaccountstate": { UInt160 script_hash = _params[0].AsString().ToScriptHash(); AccountState account = Blockchain.Singleton.Store.GetAccounts().TryGet(script_hash) ?? new AccountState(script_hash); return(account.ToJson()); } case "getassetstate": { UInt256 asset_id = UInt256.Parse(_params[0].AsString()); AssetState asset = Blockchain.Singleton.Store.GetAssets().TryGet(asset_id); return(asset?.ToJson() ?? throw new RpcException(-100, "Unknown asset")); } case "getbalance": if (wallet == null) { throw new RpcException(-400, "Access denied."); } else { JObject json = new JObject(); switch (UIntBase.Parse(_params[0].AsString())) { case UInt160 asset_id_160: //BRC5 balance json["balance"] = wallet.GetAvailable(asset_id_160).ToString(); break; case UInt256 asset_id_256: //Global Assets balance IEnumerable <Coin> coins = wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256)); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); break; } return(json); } case "getbestblockhash": return(Blockchain.Singleton.CurrentBlockHash.ToString()); case "getblock": { Block block; if (_params[0] is JNumber) { uint index = (uint)_params[0].AsNumber(); block = Blockchain.Singleton.Store.GetBlock(index); } else { UInt256 hash = UInt256.Parse(_params[0].AsString()); block = Blockchain.Singleton.Store.GetBlock(hash); } if (block == null) { throw new RpcException(-100, "Unknown block"); } bool verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false); if (verbose) { JObject json = block.ToJson(); json["confirmations"] = Blockchain.Singleton.Height - block.Index + 1; UInt256 hash = Blockchain.Singleton.Store.GetNextBlockHash(block.Hash); if (hash != null) { json["nextblockhash"] = hash.ToString(); } return(json); } return(block.ToArray().ToHexString()); } case "getblockcount": return(Blockchain.Singleton.Height + 1); case "getblockhash": { uint height = (uint)_params[0].AsNumber(); if (height <= Blockchain.Singleton.Height) { return(Blockchain.Singleton.GetBlockHash(height).ToString()); } throw new RpcException(-100, "Invalid Height"); } case "getblockheader": { Header header; if (_params[0] is JNumber) { uint height = (uint)_params[0].AsNumber(); header = Blockchain.Singleton.Store.GetHeader(height); } else { UInt256 hash = UInt256.Parse(_params[0].AsString()); header = Blockchain.Singleton.Store.GetHeader(hash); } if (header == null) { throw new RpcException(-100, "Unknown block"); } bool verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false); if (verbose) { JObject json = header.ToJson(); json["confirmations"] = Blockchain.Singleton.Height - header.Index + 1; UInt256 hash = Blockchain.Singleton.Store.GetNextBlockHash(header.Hash); if (hash != null) { json["nextblockhash"] = hash.ToString(); } return(json); } return(header.ToArray().ToHexString()); } case "getblocksysfee": { uint height = (uint)_params[0].AsNumber(); if (height <= Blockchain.Singleton.Height) { return(Blockchain.Singleton.Store.GetSysFeeAmount(height).ToString()); } throw new RpcException(-100, "Invalid Height"); } case "getconnectioncount": return(LocalNode.Singleton.ConnectedCount); case "getcontractstate": { UInt160 script_hash = UInt160.Parse(_params[0].AsString()); ContractState contract = Blockchain.Singleton.Store.GetContracts().TryGet(script_hash); return(contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract")); } case "getnewaddress": if (wallet == null) { throw new RpcException(-400, "Access denied"); } else { WalletAccount account = wallet.CreateAccount(); if (wallet is BRC6Wallet BRC6) { BRC6.Save(); } return(account.Address); } case "getpeers": { JObject json = new JObject(); json["unconnected"] = new JArray(LocalNode.Singleton.GetUnconnectedPeers().Select(p => { JObject peerJson = new JObject(); peerJson["address"] = p.Address.ToString(); peerJson["port"] = p.Port; return(peerJson); })); json["bad"] = new JArray(); //badpeers has been removed json["connected"] = new JArray(LocalNode.Singleton.GetRemoteNodes().Select(p => { JObject peerJson = new JObject(); peerJson["address"] = p.Remote.Address.ToString(); peerJson["port"] = p.ListenerPort; return(peerJson); })); return(json); } case "getrawmempool": return(new JArray(Blockchain.Singleton.GetMemoryPool().Select(p => (JObject)p.Hash.ToString()))); case "getrawtransaction": { UInt256 hash = UInt256.Parse(_params[0].AsString()); bool verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false); Transaction tx = Blockchain.Singleton.GetTransaction(hash); if (tx == null) { throw new RpcException(-100, "Unknown transaction"); } if (verbose) { JObject json = tx.ToJson(); uint? height = Blockchain.Singleton.Store.GetTransactions().TryGet(hash)?.BlockIndex; if (height != null) { Header header = Blockchain.Singleton.Store.GetHeader((uint)height); json["blockhash"] = header.Hash.ToString(); json["confirmations"] = Blockchain.Singleton.Height - header.Index + 1; json["blocktime"] = header.Timestamp; } return(json); } return(tx.ToArray().ToHexString()); } case "getstorage": { UInt160 script_hash = UInt160.Parse(_params[0].AsString()); byte[] key = _params[1].AsString().HexToBytes(); StorageItem item = Blockchain.Singleton.Store.GetStorages().TryGet(new StorageKey { ScriptHash = script_hash, Key = key }) ?? new StorageItem(); return(item.Value?.ToHexString()); } case "gettxout": { UInt256 hash = UInt256.Parse(_params[0].AsString()); ushort index = (ushort)_params[1].AsNumber(); return(Blockchain.Singleton.Store.GetUnspent(hash, index)?.ToJson(index)); } case "getvalidators": using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { var validators = snapshot.GetValidators(); return(snapshot.GetEnrollments().Select(p => { JObject validator = new JObject(); validator["publickey"] = p.PublicKey.ToString(); validator["votes"] = p.Votes.ToString(); validator["active"] = validators.Contains(p.PublicKey); return validator; }).ToArray()); } case "getversion": { JObject json = new JObject(); json["port"] = LocalNode.Singleton.ListenerPort; json["nonce"] = LocalNode.Nonce; json["useragent"] = LocalNode.UserAgent; return(json); } case "getwalletheight": if (wallet == null) { throw new RpcException(-400, "Access denied."); } else { return((wallet.WalletHeight > 0) ? wallet.WalletHeight - 1 : 0); } case "invoke": { UInt160 script_hash = UInt160.Parse(_params[0].AsString()); ContractParameter[] parameters = ((JArray)_params[1]).Select(p => ContractParameter.FromJson(p)).ToArray(); byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { script = sb.EmitAppCall(script_hash, parameters).ToArray(); } return(GetInvokeResult(script)); } case "invokefunction": { UInt160 script_hash = UInt160.Parse(_params[0].AsString()); string operation = _params[1].AsString(); ContractParameter[] args = _params.Count >= 3 ? ((JArray)_params[2]).Select(p => ContractParameter.FromJson(p)).ToArray() : new ContractParameter[0]; byte[] script; using (ScriptBuilder sb = new ScriptBuilder()) { script = sb.EmitAppCall(script_hash, operation, args).ToArray(); } return(GetInvokeResult(script)); } case "invokescript": { byte[] script = _params[0].AsString().HexToBytes(); return(GetInvokeResult(script)); } case "listaddress": if (wallet == null) { throw new RpcException(-400, "Access denied."); } else { return(wallet.GetAccounts().Select(p => { JObject account = new JObject(); account["address"] = p.Address; account["haskey"] = p.HasKey; account["label"] = p.Label; account["watchonly"] = p.WatchOnly; return account; }).ToArray()); } case "sendfrom": if (wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = _params[1].AsString().ToScriptHash(); UInt160 to = _params[2].AsString().ToScriptHash(); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 6 ? _params[5].AsString().ToScriptHash() : null; Transaction tx = wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); return(tx.ToJson()); } else { return(context.ToJson()); } } case "transfer": if (wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = _params[1].AsString().ToScriptHash(); UInt160 to = _params[2].AsString().ToScriptHash(); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 6 ? _params[5].AsString().ToScriptHash() : from; Transaction tx = wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = to[i]["address"].AsString().ToScriptHash() }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? _params[2].AsString().ToScriptHash() : null; Transaction tx = wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendrawtransaction": { Transaction tx = Transaction.DeserializeFrom(_params[0].AsString().HexToBytes()); RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(tx).Result; return(GetRelayResult(reason)); } case "sendtoaddress": if (wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = _params[1].AsString().ToScriptHash(); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? _params[4].AsString().ToScriptHash() : null; Transaction tx = wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); return(tx.ToJson()); } else { return(context.ToJson()); } } case "submitblock": { Block block = _params[0].AsString().HexToBytes().AsSerializable <Block>(); RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(block).Result; return(GetRelayResult(reason)); } case "validateaddress": { JObject json = new JObject(); UInt160 scriptHash; try { scriptHash = _params[0].AsString().ToScriptHash(); } catch { scriptHash = null; } json["address"] = _params[0]; json["isvalid"] = scriptHash != null; return(json); } default: throw new RpcException(-32601, "Method not found"); } }
protected override JObject Process(string method, JArray _params) { switch (method) { case "getapplicationlog": { UInt256 hash = UInt256.Parse(_params[0].AsString()); string path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{hash}.json"); return(File.Exists(path) ? JObject.Parse(File.ReadAllText(path)) : throw new RpcException(-100, "Unknown transaction")); } case "getbalance": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { JObject json = new JObject(); switch (UIntBase.Parse(_params[0].AsString())) { case UInt160 asset_id_160: //NEP-5 balance json["balance"] = Program.Wallet.GetAvailable(asset_id_160).ToString(); break; case UInt256 asset_id_256: //Global Assets balance IEnumerable <Coin> coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256)); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); break; } return(json); } case "listaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { return(Program.Wallet.GetAccounts().Select(p => { JObject account = new JObject(); account["address"] = p.Address; account["haskey"] = p.HasKey; account["label"] = p.Label; account["watchonly"] = p.WatchOnly; return account; }).ToArray()); } case "sendfrom": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = Wallet.ToScriptHash(_params[1].AsString()); UInt160 to = Wallet.ToScriptHash(_params[2].AsString()); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 6 ? Wallet.ToScriptHash(_params[5].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendtoaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "getnewaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { WalletAccount account = Program.Wallet.CreateAccount(); if (Program.Wallet is NEP6Wallet wallet) { wallet.Save(); } return(account.Address); } case "dumpprivkey": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); WalletAccount account = Program.Wallet.GetAccount(scriptHash); return(account.GetKey().Export()); } case "invoke": case "invokefunction": case "invokescript": JObject result = base.Process(method, _params); if (Program.Wallet != null) { InvocationTransaction tx = new InvocationTransaction { Version = 1, Script = result["script"].AsString().HexToBytes(), Gas = Fixed8.Parse(result["gas_consumed"].AsString()) }; tx.Gas -= Fixed8.FromDecimal(10); if (tx.Gas < Fixed8.Zero) { tx.Gas = Fixed8.Zero; } tx.Gas = tx.Gas.Ceiling(); tx = Program.Wallet.MakeTransaction(tx); if (tx != null) { ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); } else { tx = null; } } result["tx"] = tx?.ToArray().ToHexString(); } return(result); case "state": var state = new JObject { ["WalletHeight"] = 0, ["LocalBlockHeight"] = Blockchain.Default.Height, ["RemoteBlockHeight"] = Blockchain.Default.HeaderHeight, ["RemoteNodes"] = LocalNode.RemoteNodeCount }; if (Program.Wallet != null) { state["WalletHeight"] = (Program.Wallet.WalletHeight > 0) ? Program.Wallet.WalletHeight - 1 : 0; } return(state); default: return(base.Process(method, _params)); } }
private bool OnSendCommand(string[] args) { if (args.Length < 4 || args.Length > 5) { Console.WriteLine("error"); return(true); } if (Program.Wallet == null) { Console.WriteLine("You have to open the wallet first."); return(true); } string password = ReadPassword("password"); if (password.Length == 0) { Console.WriteLine("cancelled"); return(true); } if (!Program.Wallet.VerifyPassword(password)) { Console.WriteLine("Incorrect password"); return(true); } UIntBase assetId; switch (args[1].ToLower()) { case "neo": case "ans": assetId = Blockchain.GoverningToken.Hash; break; case "gas": case "anc": assetId = Blockchain.UtilityToken.Hash; break; default: assetId = UIntBase.Parse(args[1]); break; } UInt160 scriptHash = Wallet.ToScriptHash(args[2]); bool isSendAll = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase); Transaction tx; if (isSendAll) { Coin[] coins = Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(assetId)).ToArray(); tx = new ContractTransaction { Attributes = new TransactionAttribute[0], Inputs = coins.Select(p => p.Reference).ToArray(), Outputs = new[] { new TransactionOutput { AssetId = (UInt256)assetId, Value = coins.Sum(p => p.Output.Value), ScriptHash = scriptHash } } }; } else { AssetDescriptor descriptor = new AssetDescriptor(assetId); if (!BigDecimal.TryParse(args[3], descriptor.Decimals, out BigDecimal amount)) { Console.WriteLine("Incorrect Amount Format"); return(true); } Fixed8 fee = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero; tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } return(true); }
public JObject OnProcess(HttpContext context, string method, JArray _params) { switch (method) { case "claimgas": { UInt160 to = _params.Count >= 1 ? _params[0].AsString().ToScriptHash() : null; return(ClaimGas(to)); } case "dumpprivkey": { UInt160 scriptHash = _params[0].AsString().ToScriptHash(); return(DumpPrivKey(scriptHash)); } case "getbalance": { UIntBase asset_id = UIntBase.Parse(_params[0].AsString()); return(GetBalance(asset_id)); } case "getnewaddress": { return(GetNewAddress()); } case "getunclaimedgas": { return(GetUnclaimedGas()); } case "getwalletheight": { return(GetWalletHeight()); } case "importprivkey": { string privkey = _params[0].AsString(); return(ImportPrivKey(privkey)); } case "listaddress": { return(ListAddress()); } case "sendfrom": { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); UInt160 from = _params[1].AsString().ToScriptHash(); UInt160 to = _params[2].AsString().ToScriptHash(); string value = _params[3].AsString(); Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; UInt160 change_address = _params.Count >= 6 ? _params[5].AsString().ToScriptHash() : null; return(SendFrom(assetId, from, to, value, fee, change_address)); } case "sendmany": { int to_start = 0; UInt160 from = null; if (_params[0] is JString) { from = _params[0].AsString().ToScriptHash(); to_start = 1; } JArray to = (JArray)_params[to_start + 0]; Fixed8 fee = _params.Count >= to_start + 2 ? Fixed8.Parse(_params[to_start + 1].AsString()) : Fixed8.Zero; UInt160 change_address = _params.Count >= to_start + 3 ? _params[to_start + 2].AsString().ToScriptHash() : null; return(SendMany(from, to, fee, change_address)); } case "sendtoaddress": { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); UInt160 scriptHash = _params[1].AsString().ToScriptHash(); string value = _params[2].AsString(); Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; UInt160 change_address = _params.Count >= 5 ? _params[4].AsString().ToScriptHash() : null; return(SendToAddress(assetId, scriptHash, value, fee, change_address)); } default: return(null); } }
protected override JObject Process(string method, JArray _params) { switch (method) { case "getbalance": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { UInt256 assetId = UInt256.Parse(_params[0].AsString()); IEnumerable <Coin> coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId)); JObject json = new JObject(); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); return(json); } case "sendtoaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "getnewaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { return(Program.Wallet.CreateAccount().Address); } case "dumpprivkey": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); WalletAccount account = Program.Wallet.GetAccount(scriptHash); return(account.GetKey().Export()); } case "invoke": case "invokefunction": case "invokescript": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JObject result = base.Process(method, _params); InvocationTransaction tx = new InvocationTransaction { Version = 1, Script = result["script"].AsString().HexToBytes(), Gas = Fixed8.Parse(result["gas_consumed"].AsString()) }; tx.Gas -= Fixed8.FromDecimal(10); if (tx.Gas < Fixed8.Zero) { tx.Gas = Fixed8.Zero; } tx.Gas = tx.Gas.Ceiling(); tx = Program.Wallet.MakeTransaction(tx); if (tx != null) { ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); } else { tx = null; } } result["tx"] = tx?.ToArray().ToHexString(); return(result); } default: return(base.Process(method, _params)); } }
protected override JObject Process(string method, JArray _params) { switch (method) { case "getapplicationlog": { UInt256 hash = UInt256.Parse(_params[0].AsString()); string path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{hash}.json"); return(File.Exists(path) ? JObject.Parse(File.ReadAllText(path)) : throw new RpcException(-100, "Unknown transaction")); } case "getbalance": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { UInt256 assetId = UInt256.Parse(_params[0].AsString()); IEnumerable <Coin> coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId)); JObject json = new JObject(); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); return(json); } case "listaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { return(Program.Wallet.GetAccounts().Select(p => { JObject account = new JObject(); account["address"] = p.Address; account["haskey"] = p.HasKey; account["label"] = p.Label; account["watchonly"] = p.WatchOnly; return account; }).ToArray()); } case "sendfrom": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = Wallet.ToScriptHash(_params[1].AsString()); UInt160 to = Wallet.ToScriptHash(_params[2].AsString()); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 6 ? Wallet.ToScriptHash(_params[5].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendtoaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "getnewaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { WalletAccount account = Program.Wallet.CreateAccount(); if (Program.Wallet is NEP6Wallet wallet) { wallet.Save(); } return(account.Address); } case "dumpprivkey": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); WalletAccount account = Program.Wallet.GetAccount(scriptHash); return(account.GetKey().Export()); } case "signdata": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { byte[] data = System.Text.Encoding.UTF8.GetBytes(_params[0].AsString()); KeyPair keys = Program.Wallet.GetAccounts().First().GetKey(); using (keys.Decrypt()) { byte[] pubkey = keys.PublicKey.EncodePoint(false).Skip(1).ToArray(); return(Convert.ToBase64String(Crypto.Default.Sign(data, keys.PrivateKey, pubkey))); } } case "invoke": case "invokefunction": case "invokescript": JObject result = base.Process(method, _params); if (Program.Wallet != null) { InvocationTransaction tx = new InvocationTransaction { Version = 1, Script = result["script"].AsString().HexToBytes(), Gas = Fixed8.Parse(result["gas_consumed"].AsString()) }; tx.Gas -= Fixed8.FromDecimal(10); if (tx.Gas < Fixed8.Zero) { tx.Gas = Fixed8.Zero; } tx.Gas = tx.Gas.Ceiling(); tx = Program.Wallet.MakeTransaction(tx); if (tx != null) { ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); } else { tx = null; } } result["tx"] = tx?.ToArray().ToHexString(); } return(result); case "executescript": { if (Program.Wallet == null) { return(false); } byte[] script = _params[0].AsString().HexToBytes(); ApplicationEngine engine = ApplicationEngine.Run(script); Fixed8 gas = engine.GasConsumed - Fixed8.FromDecimal(10); if (gas < Fixed8.Zero) { gas = Fixed8.Zero; } gas = gas.Ceiling(); Fixed8 fee = gas.Equals(Fixed8.Zero) ? Fixed8.FromDecimal(0.001m) : Fixed8.Zero; InvocationTransaction tx = Program.Wallet.MakeTransaction(new InvocationTransaction { Version = 1, Script = script, Gas = gas, Attributes = new TransactionAttribute[0], Inputs = new CoinReference[0], Outputs = new TransactionOutput[0] }, fee: fee); if (tx == null) { return(false); } ContractParametersContext context; try { context = new ContractParametersContext(tx); } catch (Exception) { return(false); } Program.Wallet.Sign(context); if (!context.Completed) { return(false); } context.Verifiable.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); return(LocalNode.Relay(tx)); } default: return(base.Process(method, _params)); } }
private bool OnSendCommand(string[] args) { if (args.Length < 4 || args.Length > 6) { Console.WriteLine("error"); return(true); } if (NoWallet()) { return(true); } string password = ReadPassword("password"); if (password.Length == 0) { Console.WriteLine("cancelled"); return(true); } if (!Program.Wallet.VerifyPassword(password)) { Console.WriteLine("Incorrect password"); return(true); } UIntBase assetId; switch (args[1].ToLower()) { case "bhp": assetId = Blockchain.GoverningToken.Hash; break; case "bhpgas": assetId = Blockchain.UtilityToken.Hash; break; default: assetId = UIntBase.Parse(args[1]); break; } UInt160 scriptHash = args[2].ToScriptHash(); bool isSendAll = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase); Transaction tx; if (isSendAll) { Coin[] coins = Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(assetId)).ToArray(); tx = new ContractTransaction { Attributes = new TransactionAttribute[0], Inputs = coins.Select(p => p.Reference).ToArray(), Outputs = new[] { new TransactionOutput { AssetId = (UInt256)assetId, Value = coins.Sum(p => p.Output.Value), ScriptHash = scriptHash } } }; } else { AssetDescriptor descriptor = new AssetDescriptor(assetId); if (!BigDecimal.TryParse(args[3], descriptor.Decimals, out BigDecimal amount)) { Console.WriteLine("Incorrect Amount Format"); return(true); } Fixed8 fee = args.Length >= 5 ? Fixed8.Parse(args[4]) : Fixed8.Zero; string remark = args.Length >= 6 ? args[5].ToString() : null; tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = amount, ScriptHash = scriptHash } }, fee: fee); if (tx == null) { Console.WriteLine("Insufficient funds"); return(true); } if (!string.IsNullOrEmpty(remark)) { List <TransactionAttribute> attributes = new List <TransactionAttribute>(); attributes.Add(new TransactionAttribute { Usage = TransactionAttributeUsage.Remark, Data = Encoding.UTF8.GetBytes(remark) }); tx.Attributes = attributes.ToArray(); } } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Witnesses = context.GetWitnesses(); Program.Wallet.ApplyTransaction(tx); system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); Console.WriteLine($"TXID: {tx.Hash}"); } else { Console.WriteLine("SignatureContext:"); Console.WriteLine(context.ToString()); } return(true); }
private JObject SendMany(UInt160 from, JArray to, Fixed8 fee, UInt160 change_address) { CheckWallet(); if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = to[i]["address"].AsString().ToScriptHash() }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } Transaction tx = Wallet.MakeTransaction(null, outputs, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext transContext = new ContractParametersContext(tx); Wallet.Sign(transContext); if (!transContext.Completed) { return(transContext.ToJson()); } tx.Witnesses = transContext.GetWitnesses(); if (tx.Size > 1024) { Fixed8 calFee = Fixed8.FromDecimal(tx.Size * 0.00001m + 0.001m); if (fee < calFee) { fee = calFee; tx = Wallet.MakeTransaction(null, outputs, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } } } if (fee > Settings.Default.MaxFee) { throw new RpcException(-301, "The necessary fee is more than the Max_fee, this transaction is failed. Please increase your Max_fee value."); } return(SignAndRelay(tx)); }
protected override JObject Process(string method, JArray _params) { switch (method) { case "": case "getapplicationlog": { UInt256 hash = UInt256.Parse(_params[0].AsString()); string path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{hash}.json"); return(File.Exists(path) ? JObject.Parse(File.ReadAllText(path)) : throw new RpcException(-100, "Unknown transaction")); } case "balance": // 使用address查询余额 AddCode if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { JObject json = new JObject(); if (_params.Count() == 1) { // 查询NEO和GAS资产 string address = _params[0].AsString(); try { Wallet.ToScriptHash(address); } catch { json["code"] = -1; json["message"] = "NEO地址错误"; return(json); } IEnumerable <Coin> coins = Program.Wallet.GetCoins(address); // NEO var neoCoins = coins.Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(UInt256.Parse(Settings.Default.Asset.NEOAsset))); json["balance"] = neoCoins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = neoCoins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); // GAS var gasCoins = coins.Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(UInt256.Parse(Settings.Default.Asset.GASAsset))); json["gasbalance"] = gasCoins.Sum(p => p.Output.Value).ToString(); json["gasconfirmed"] = gasCoins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); return(json); } else // 查询指定资产余额 { string address = _params[1].AsString(); switch (UIntBase.Parse(_params[0].AsString())) { case UInt160 asset_id_160: //NEP-5 balance json["balance"] = Program.Wallet.GetAvailable(asset_id_160, address).ToString(); break; case UInt256 asset_id_256: //Global Assets balance IEnumerable <Coin> coins = Program.Wallet.GetCoins(address).Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256)); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); break; } return(json); } } case "getbalance": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { JObject json = new JObject(); switch (UIntBase.Parse(_params[0].AsString())) { case UInt160 asset_id_160: //NEP-5 balance json["balance"] = Program.Wallet.GetAvailable(asset_id_160).ToString(); break; case UInt256 asset_id_256: //Global Assets balance IEnumerable <Coin> coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256)); json["balance"] = coins.Sum(p => p.Output.Value).ToString(); json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString(); break; } return(json); } case "listaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied."); } else { return(Program.Wallet.GetAccounts().Select(p => { JObject account = new JObject(); account["address"] = p.Address; account["haskey"] = p.HasKey; account["label"] = p.Label; account["watchonly"] = p.WatchOnly; return account; }).ToArray()); } case "sendfrom": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = Wallet.ToScriptHash(_params[1].AsString()); UInt160 to = Wallet.ToScriptHash(_params[2].AsString()); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 6 ? Wallet.ToScriptHash(_params[5].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendfromto": // 从指定账号向指定账号转账 AddCode if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { // 参数顺序 资产类型 输出账号 输入账号 输出金额 输出账号私钥 手续费 找零地址 UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 from = Wallet.ToScriptHash(_params[1].AsString()); UInt160 to = Wallet.ToScriptHash(_params[2].AsString()); BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); string privatekey = _params[4].AsString(); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 6 ? Fixed8.Parse(_params[5].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 7 && !string.IsNullOrEmpty(_params[6].AsString()) ? Wallet.ToScriptHash(_params[6].AsString()) : from;// 找零地址 Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = to } }, from: from, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); //File.AppendAllText("wallet.log", context.ScriptHashes.Count().ToString()); //Program.Wallet.Sign(context); Program.Wallet.Sign(context, privatekey); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendtoaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UIntBase assetId = UIntBase.Parse(_params[0].AsString()); AssetDescriptor descriptor = new AssetDescriptor(assetId); UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); if (value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, new[] { new TransferOutput { AssetId = assetId, Value = value, ScriptHash = scriptHash } }, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "sendmany": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { JArray to = (JArray)_params[0]; if (to.Count == 0) { throw new RpcException(-32602, "Invalid params"); } TransferOutput[] outputs = new TransferOutput[to.Count]; for (int i = 0; i < to.Count; i++) { UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); AssetDescriptor descriptor = new AssetDescriptor(asset_id); outputs[i] = new TransferOutput { AssetId = asset_id, Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) }; if (outputs[i].Value.Sign <= 0) { throw new RpcException(-32602, "Invalid params"); } } Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; if (fee < Fixed8.Zero) { throw new RpcException(-32602, "Invalid params"); } UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); if (tx == null) { throw new RpcException(-300, "Insufficient funds"); } ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); Program.Wallet.ApplyTransaction(tx); LocalNode.Relay(tx); return(tx.ToJson()); } else { return(context.ToJson()); } } case "getnewaddress": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { WalletAccount account = Program.Wallet.CreateAccount(); if (Program.Wallet is NEP6Wallet wallet) { wallet.Save(); } return(account.Address); } case "newaddress": // 创建一个账号 AddCode if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { WalletAccount account = Program.Wallet.CreateAccount(); if (Program.Wallet is NEP6Wallet wallet) { wallet.Save(); } return(account.OutputJson()); } case "dumpprivkey": if (Program.Wallet == null) { throw new RpcException(-400, "Access denied"); } else { UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); WalletAccount account = Program.Wallet.GetAccount(scriptHash); return(account.GetKey().Export()); } case "invoke": // 使用给定的参数以散列值调用智能合约 case "invokefunction": case "invokescript": JObject result = base.Process(method, _params); if (Program.Wallet != null) { InvocationTransaction tx = new InvocationTransaction { Version = 1, Script = result["script"].AsString().HexToBytes(), Gas = Fixed8.Parse(result["gas_consumed"].AsString()) }; tx.Gas -= Fixed8.FromDecimal(10); if (tx.Gas < Fixed8.Zero) { tx.Gas = Fixed8.Zero; } tx.Gas = tx.Gas.Ceiling(); tx = Program.Wallet.MakeTransaction(tx); if (tx != null) { ContractParametersContext context = new ContractParametersContext(tx); Program.Wallet.Sign(context); if (context.Completed) { tx.Scripts = context.GetScripts(); } else { tx = null; } } result["tx"] = tx?.ToArray().ToHexString(); } return(result); default: return(base.Process(method, _params)); } }