Example #1
0
        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":
                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));
            }
        }
Example #2
0
        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 "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(),
                        Benz    = Fixed8.Parse(result["benz_consumed"].AsString())
                    };
                    tx.Benz -= Fixed8.FromDecimal(10);
                    if (tx.Benz < Fixed8.Zero)
                    {
                        tx.Benz = Fixed8.Zero;
                    }
                    tx.Benz = tx.Benz.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));
            }
        }
Example #3
0
        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 "eagle":
            case "ans":
                assetId = Blockchain.GoverningToken.Hash;
                break;

            case "benz":
            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);
        }
Example #4
0
        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 = (KeyPair)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        = (KeyPair)Program.Wallet.GetKeyByScriptHash(scriptHash);
                    return(key.Export());
                }

            default:
                return(base.Process(method, _params));
            }
        }
Example #5
0
        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 "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 "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));
            }
        }
Example #6
0
        public bool InvokeTransactionOnBlockchain(InvocationTransaction tx, UInt160 contractHash, InvokeOptions options)
        {
            Blockchain.PersistCompleted += Blockchain_PersistCompleted;
            if (options.AttachedNeo > Fixed8.Zero)
            {
                var neoOutput = new TransactionOutput();
                neoOutput.AssetId    = Blockchain.GoverningToken.Hash;
                neoOutput.Value      = options.AttachedNeo;
                neoOutput.ScriptHash = contractHash;
                var transactionOutputs = tx.Outputs.ToList();
                transactionOutputs.Add(neoOutput);
                tx.Outputs = transactionOutputs.ToArray();
            }

            if (options.AttachedGas > Fixed8.Zero)
            {
                var neoOutput = new TransactionOutput();
                neoOutput.AssetId    = Blockchain.UtilityToken.Hash;
                neoOutput.Value      = options.AttachedGas;
                neoOutput.ScriptHash = contractHash;
                var transactionOutputs = tx.Outputs.ToList();
                transactionOutputs.Add(neoOutput);
                tx.Outputs = transactionOutputs.ToArray();
            }

//            if (Client.CurrentWallet.WalletHeight > Blockchain.Default.HeaderHeight)
//            {
//                throw new ApplicationException("Wallet height is ahead of the blockchain height! It may need a rebuild");
//            }

            var walletSyncAttempts = 0;

            while (Client.CurrentWallet.NeoWallet.WalletHeight < Blockchain.Default.HeaderHeight)
            {
                walletSyncAttempts++;
                Thread.Sleep(1000); //get the wallet in sync or else MakeTransaction will fail
                if (walletSyncAttempts >= 30)
                {
                    throw new WalletException("could not get the wallet in sync after 30 attempts");
                }
            }


            var walletTx = Client.CurrentWallet.NeoWallet.MakeTransaction(new InvocationTransaction
            {
                Version    = tx.Version,
                Script     = tx.Script,
                Gas        = tx.Gas,
                Attributes = tx.Attributes,
                Inputs     = tx.Inputs,
                Outputs    = tx.Outputs
            }, fee: options.Fee); //include a small fee

            if (walletTx == null)
            {
                throw new NeoTransactionBuildException("Wallet TX was null. Possibly insufficient funds. If not wallet may need a rebuild");
            }

            var context = new ContractParametersContext(walletTx);
            var sign    = Client.CurrentWallet.NeoWallet.Sign(context); //fail here with index out of bounds

            if (context.Completed)
            {
                context.Verifiable.Scripts = context.GetScripts();
                Client.CurrentWallet.NeoWallet.ApplyTransaction(walletTx); //changes with different versions of NEO
                //Wallet.ApplyTransaction(walletTx);

                var relay = _node.Relay(walletTx);

                //var originalHeight = Blockchain.Default.Height; //store the height we sent at then wait for the next block
                //possibly check if sign/relay/save has actually worked?

                //while (Blockchain.Default.Height <= originalHeight + 2) Thread.Sleep(1000); //wait for next block
                //while (this._wallet.WalletHeight <= originalHeight + 2) Thread.Sleep(1000); //wait for wallet to sync too!

                TxFound    = false;
                WatchForTx = walletTx.Hash;

                Console.WriteLine(walletTx.Hash);
                //Console.WriteLine(tx.Hash);

                var count = 0;
                while (TxFound == false) //wait until the transaction is confirmed
                {
                    Thread.Sleep(1000);
                    count++;
                    if (count > 30)
                    {
                        Blockchain.PersistCompleted -= Blockchain_PersistCompleted;
                        return(false);
                    }
                }

//                while(Client.CurrentWallet.WalletHeight < TxFoundInBlock && WalletIndexer.IndexHeight < TxFoundInBlock) //make sure the wallet gets this block
//                {
//                    Thread.Sleep(1000);
//                }

                //ensure we have an unspent coin back to use?
                //seems like the WalletIndexer is running on a background thread so the block may not be fully processed
                //e.g. the unconfirmed array in the wallet may not be updated in real time. The only event we have is that BlockChain.PersistCompleted was done which means we have the block stored to disk locally, this does not mean
                //that the wallet has completed updating based on the new block!
                while (Client.CurrentWallet.NeoWallet.FindUnspentCoins(Blockchain.UtilityToken.Hash, walletTx.NetworkFee, new UInt160[] { Client.CurrentWallet.GetAddresses().First() }) == null)
                {
                    Thread.Sleep(500);
                }
            }
            else
            {
                Blockchain.PersistCompleted -= Blockchain_PersistCompleted;
                throw new ApplicationException("Incompleted Signature");
            }

            Blockchain.PersistCompleted -= Blockchain_PersistCompleted;
            return(true);
        }
Example #7
0
        //SGAS MintTokens
        public static void MintTokens()
        {
            var inputs = new List <CoinReference> {
                //coin reference A
                new CoinReference()
                {
                    PrevHash  = new UInt256("0xf5088ce508d86197c991ff0ef7651ddf01f3e555f257039c972082250e899210".Remove(0, 2).HexToBytes().Reverse().ToArray()),
                    PrevIndex = 0 //16639 GAS
                }
            }.ToArray();

            var outputs = new List <TransactionOutput> {
                new TransactionOutput()
                {
                    AssetId    = Blockchain.UtilityToken.Hash,                 //Asset Id, this is GAS
                    ScriptHash = SgasAddress,                                  //SGAS 地址
                    Value      = new Fixed8((long)(1 * (long)Math.Pow(10, 8))) //Value
                }
            }.ToArray();

            Transaction tx = null;

            using (ScriptBuilder sb = new ScriptBuilder())
            {
                sb.EmitAppCall(ScriptHash, "mintTokens");
                sb.Emit(OpCode.THROWIFNOT);

                byte[] nonce = new byte[8];
                Random rand  = new Random();
                rand.NextBytes(nonce);
                sb.Emit(OpCode.RET, nonce);
                tx = new InvocationTransaction
                {
                    Version    = 1,
                    Script     = sb.ToArray(),
                    Outputs    = outputs,
                    Inputs     = inputs,
                    Attributes = new TransactionAttribute[0],
                    Scripts    = new Witness[0]
                };
            }

            if (tx == null)
            {
                Console.WriteLine("Create Transaction Failed");
                Console.ReadLine();
                return;
            }

            //Open wallet
            var wallet = new Neo.Implementations.Wallets.NEP6.NEP6Wallet("0.json");

            try
            {
                wallet.Unlock("1");
            }
            catch (Exception)
            {
                Console.WriteLine("password error");
            }

            //Sign in wallet
            var context = new ContractParametersContext(tx);

            wallet.Sign(context);
            if (context.Completed)
            {
                Console.WriteLine("Sign Successful");
                tx.Scripts = context.GetScripts();
            }
            else
            {
                Console.WriteLine("Sign Faild");
            }

            try
            {
                tx = Transaction.DeserializeFrom(tx.ToArray());
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid Transaction Format");
            }

            Console.WriteLine("Verify Transaction:" + tx.Verify(new List <Transaction> {
                tx
            }));

            Console.WriteLine("Raw Transaction:");
            Console.WriteLine(tx.ToArray().ToHexString());

            //Then Call neo-cli API:sendrawtransaction in postman.
        }
Example #8
0
        public static void SignAndShowInformation(Transaction tx)
        {
            if (tx == null)
            {
                //MessageBox.Show(Strings.InsufficientFunds);
                throw new InvalidOperationException("Insufficient Funds");
                //return;
            }
            ContractParametersContext context;

            try
            {
                context = new ContractParametersContext(tx);
            }
            catch (InvalidOperationException)
            {
                //MessageBox.Show(Strings.UnsynchronizedBlock);
                throw new InvalidOperationException("Unsynchronized Block");
                //return;
            }

            if (tx.Type == TransactionType.AnonymousContractTransaction)
            {
                if (tx.Inputs.Length > 0)
                {
                    Constant.CurrentWallet.Sign(context);

                    if (context.Completed)
                    {
                        context.Verifiable.Scripts = context.GetScripts();
                        Constant.CurrentWallet.SaveTransaction(tx);
                        Constant.LocalNode.Relay(tx);
                        //InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle);
                    }
                    else
                    {
                        //InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle);
                        throw new InvalidOperationException("Incompleted signature");
                    }
                }
                else
                {
                    Constant.CurrentWallet.SaveTransaction(tx);
                    Constant.LocalNode.Relay(tx);
                }
            }
            else if (tx.Type == TransactionType.RingConfidentialTransaction)
            {
                if (tx.Inputs.Length > 0)
                {
                    Constant.CurrentWallet.Sign(context);

                    if (context.Completed)
                    {
                        context.Verifiable.Scripts = context.GetScripts();
                        Constant.CurrentWallet.SaveTransaction(tx);
                        Constant.LocalNode.Relay(tx);
                        //InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle);
                    }
                    else
                    {
                        //InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle);
                        throw new InvalidOperationException("Incompleted signature");
                    }
                }
                else
                {
                    Constant.CurrentWallet.SaveTransaction(tx);
                    Constant.LocalNode.Relay(tx);
                }
            }
            else
            {
                Constant.CurrentWallet.Sign(context);

                if (context.Completed)
                {
                    context.Verifiable.Scripts = context.GetScripts();
                    Constant.CurrentWallet.SaveTransaction(tx);
                    Constant.LocalNode.Relay(tx);
                    //InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle);
                }
                else
                {
                    //InformationBox.Show(context.ToString(), Strings.IncompletedSignatureMessage, Strings.IncompletedSignatureTitle);
                    throw new InvalidOperationException("Incompleted signature");
                }
            }
        }