public async Task <(ClaimTransaction tx, decimal availiableGas, decimal unclaimedGas)> BuildClaimTransactions(string address)
        {
            var claimData = await _blockchainProvider.GetClaimableAsync(address);

            var unclaimedGas = await _blockchainProvider.GetUnclaimedAsync(address);

            var tx = new ClaimTransaction
            {
                Version = 0,
                Claims  = claimData.coinReferences.ToArray(),
                Inputs  = new CoinReference[0],
                Outputs = new[]
                {
                    new TransactionOutput
                    {
                        ScriptHash = address.ToScriptHash(),
                        AssetId    = Utils.GasToken,
                        Value      = Fixed8.FromDecimal(claimData.gasAmoumt),
                    }
                },
                Witnesses  = new Witness[0],
                Attributes = new TransactionAttribute[0]
            };

            return(tx, claimData.gasAmoumt, unclaimedGas);
        }
Example #2
0
        private bool OnClaimCommand(string[] args)
        {
            if (Program.Wallet == null)
            {
                Console.WriteLine($"Please open a wallet");
                return(true);
            }

            Coins coins = new Coins(Program.Wallet, LocalNode);

            switch (args[1].ToLower())
            {
            case "shipcoin":
            case "sc":
                ClaimTransaction tx = coins.Claim();
                if (tx is ClaimTransaction)
                {
                    Console.WriteLine($"Tranaction Suceeded: {tx.Hash.ToString()}");
                }
                return(true);

            default:
                return(base.OnCommand(args));
            }
        }
        // GET: ClaimTransactions/Create
        public async Task <IActionResult> Create(Guid productId, Guid clientId, Guid policyId, int claimNumber)
        {
            ClaimTransaction claimtransaction = new ClaimTransaction
            {
                ClaimNumber     = claimNumber,
                Taxable         = true,
                TaxAmount       = 0,
                RequisitionDate = DateTime.Now,
                InvoiceDate     = DateTime.Now
            };

            ClaimTransactionViewModel viewModel = new ClaimTransactionViewModel
            {
                ProductID        = productId,
                ClientID         = clientId,
                PolicyID         = policyId,
                ClaimNumber      = claimNumber,
                ClaimTransaction = claimtransaction,
                PayeeList        = new SelectList(await _context.Payees
                                                  .AsNoTracking()
                                                  .OrderBy(p => p.Name).ToListAsync(), "ID", "Name"),
                AccountList = new SelectList(await _context.AccountCharts
                                             .AsNoTracking()
                                             .OrderBy(p => p.AccountCode).ToListAsync(), "ID", "AccountCode"),
                AffectedList = new SelectList(await _context.Affecteds
                                              .AsNoTracking().ToListAsync(), "ID", "Name"),
                TransactionTypeList = new SelectList(await _context.TransactionTypes
                                                     .AsNoTracking().ToListAsync(), "ID", "Name")
            };

            return(View(viewModel));
        }
        public override Transaction Unwrap()
        {
            ClaimTransaction tx = (ClaimTransaction)base.Unwrap();

            tx.Claims = Claims.Select(p => p.Unwrap()).ToArray();
            return(tx);
        }
Example #5
0
        public ClaimTransaction Claim(UInt160 change_address = null)
        {
            if (this.AvailableBonus() == Fixed8.Zero)
            {
                Console.WriteLine($"no gas to claim");
                return(null);
            }

            CoinReference[] claims = current_wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                return(null);
            }

            using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
            {
                ClaimTransaction tx = new ClaimTransaction
                {
                    Claims     = claims.Take(MAX_CLAIMS_AMOUNT).ToArray(),
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = new[]
                    {
                        new TransactionOutput
                        {
                            AssetId    = Blockchain.UtilityToken.Hash,
                            Value      = snapshot.CalculateBonus(claims.Take(MAX_CLAIMS_AMOUNT)),
                            ScriptHash = change_address ?? current_wallet.GetChangeAddress()
                        }
                    }
                };

                return((ClaimTransaction)SignTransaction(tx));
            }
        }
Example #6
0
        public ClaimTransaction Claim()
        {
            if (this.AvailableBonus() == Fixed8.Zero)
            {
                Console.WriteLine($"no gas to claim");
                return(null);
            }

            CoinReference[] claims = current_wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                return(null);
            }

            ClaimTransaction tx = new ClaimTransaction
            {
                Claims     = claims,
                Attributes = new TransactionAttribute[0],
                Inputs     = new CoinReference[0],
                Outputs    = new[]
                {
                    new TransactionOutput
                    {
                        AssetId    = Blockchain.SystemCoin.Hash,
                        Value      = Blockchain.CalculateBonus(claims),
                        ScriptHash = current_wallet.GetChangeAddress()
                    }
                }
            };

            return((ClaimTransaction)SignTransaction(tx));
        }
Example #7
0
        public void SerializeDeserialize_ClaimTransaction()
        {
            var original = new ClaimTransaction()
            {
                Claims  = RandomCoinReferences(_random.Next(1, 255)).ToArray(),
                Version = 0x00,
            };

            FillRandomTx(original);

            var ret   = _serializer.Serialize(original);
            var copy  = _deserializer.Deserialize <Transaction>(ret);
            var copy2 = _deserializer.Deserialize <ClaimTransaction>(ret);

            // Check exclusive data

            foreach (var check in new ClaimTransaction[] { (ClaimTransaction)copy, copy2 })
            {
                CollectionAssert.AreEqual(original.Claims, check.Claims);
            }

            // Check base data

            EqualTx(original, copy, copy2);
        }
Example #8
0
        private JObject ClaimGas(UInt160 to)
        {
            CheckWallet();
            const int MAX_CLAIMS_AMOUNT = 50;

            CoinReference[] claims = Wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                throw new RpcException(-300, "No gas to claim");
            }
            ClaimTransaction tx;

            using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
            {
                tx = new ClaimTransaction
                {
                    Claims     = claims.Take(MAX_CLAIMS_AMOUNT).ToArray(),
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = new[]
                    {
                        new TransactionOutput
                        {
                            AssetId    = Blockchain.UtilityToken.Hash,
                            Value      = snapshot.CalculateBonus(claims.Take(MAX_CLAIMS_AMOUNT)),
                            ScriptHash = to ?? Wallet.GetChangeAddress()
                        }
                    }
                };
            }
            return(SignAndRelay(tx));
        }
Example #9
0
        public static Transaction Claim(Wallet wallet, SignDelegate sign)
        {
            CoinReference[] claims = wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                return(null);
            }

            using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
            {
                ClaimTransaction tx = new ClaimTransaction
                {
                    Claims     = claims,
                    Attributes = new TransactionAttribute[0],
                    Inputs     = new CoinReference[0],
                    Outputs    = new[]
                    {
                        new TransactionOutput
                        {
                            AssetId    = Blockchain.UtilityToken.Hash,
                            Value      = snapshot.CalculateBonus(claims),
                            ScriptHash = wallet.GetChangeAddress()
                        }
                    }
                };

                return(sign.Invoke(tx));
            }
        }
        public async Task <IActionResult> Edit(ClaimTransactionViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                ClaimTransaction claimTransaction = new ClaimTransaction();
                claimTransaction           = viewModel.ClaimTransaction;
                claimTransaction.TaxAmount = TaxAmount(claimTransaction.Taxable, claimTransaction.Amount, claimTransaction.ClaimNumber);

                try
                {
                    _context.Update(claimTransaction);
                    await _context.SaveChangesAsync();

                    return(RedirectToAction("Index", new { claimId = claimTransaction.ClaimNumber }));
                }
                catch (DbUpdateException ex)
                {
                    ModelState.AddModelError(string.Empty, ex.InnerException.Message.ToString());
                }
            }
            viewModel.AccountList         = new SelectList(_context.AccountCharts, "ID", "AccountCode", viewModel.ClaimTransaction.AccountID);
            viewModel.AffectedList        = new SelectList(_context.Affecteds, "ID", "Name", viewModel.ClaimTransaction.AffectedID);
            viewModel.PayeeList           = new SelectList(_context.Payees, "ID", "Name", viewModel.ClaimTransaction.PayeeID);
            viewModel.TransactionTypeList = new SelectList(_context.TransactionTypes, "ID", "Name", viewModel.ClaimTransaction.TransactionTypeID);
            return(View(viewModel));
        }
Example #11
0
        public ClaimTransaction[] ClaimAll(UInt160 change_address = null)
        {
            if (this.AvailableBonus() == Fixed8.Zero)
            {
                Console.WriteLine($"no gas to claim");
                return(null);
            }

            CoinReference[] claims = current_wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                return(null);
            }

            using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
            {
                int claim_count             = (claims.Length - 1) / MAX_CLAIMS_AMOUNT + 1;
                List <ClaimTransaction> txs = new List <ClaimTransaction>();
                if (claim_count > 1)
                {
                    Console.WriteLine($"total claims: {claims.Length}, processing(0/{claim_count})...");
                }
                for (int i = 0; i < claim_count; i++)
                {
                    if (i > 0)
                    {
                        Console.WriteLine($"{i * MAX_CLAIMS_AMOUNT} claims processed({i}/{claim_count})...");
                    }
                    ClaimTransaction tx = new ClaimTransaction
                    {
                        Claims     = claims.Skip(i * MAX_CLAIMS_AMOUNT).Take(MAX_CLAIMS_AMOUNT).ToArray(),
                        Attributes = new TransactionAttribute[0],
                        Inputs     = new CoinReference[0],
                        Outputs    = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = Blockchain.UtilityToken.Hash,
                                Value      = snapshot.CalculateBonus(claims.Skip(i * MAX_CLAIMS_AMOUNT).Take(MAX_CLAIMS_AMOUNT)),
                                ScriptHash = change_address ?? current_wallet.GetChangeAddress()
                            }
                        }
                    };

                    if ((tx = (ClaimTransaction)SignTransaction(tx)) != null)
                    {
                        txs.Add(tx);
                    }
                    else
                    {
                        break;
                    }
                }

                return(txs.ToArray());
            }
        }
Example #12
0
        public async Task Persist_ClaimTx_CallsClaimTxPersister()
        {
            var input = new ClaimTransaction();
            var claimTxPersisterMock = AutoMockContainer.GetMock <ITransactionPersister <ClaimTransaction> >();
            var testee = AutoMockContainer.Create <TransactionPersister>();

            await testee.Persist(input);

            claimTxPersisterMock.Verify(m => m.Persist(input));
        }
Example #13
0
        public async Task Process_ClaimTx_CallsClaimTxProcessor()
        {
            var input = new ClaimTransaction();
            var claimTxProcessorMock = AutoMockContainer.GetMock <IProcessor <ClaimTransaction> >();
            var testee = AutoMockContainer.Create <TransactionProcessor>();

            await testee.Process(input);

            claimTxProcessorMock.Verify(m => m.Process(input));
        }
Example #14
0
        /// <inheritdoc />
        public ClaimTransaction BuildClaimTransaction(IWallet from, TransactionAttribute[] attributes)
        {
            ClaimTransaction transaction = new ClaimTransaction();

            transaction.Attributes = attributes ?? new TransactionAttribute[0];
            //Exclusive Data
            //transaction.Claims = _repository.GetUnspent();


            return(transaction);
        }
        public async Task Persist_MarksClaimsFromMultipleTx()
        {
            var txHash1 = UInt256.Parse(RandomInt().ToString("X64"));
            var txHash2 = UInt256.Parse(RandomInt().ToString("X64"));
            var txHash3 = UInt256.Parse(RandomInt().ToString("X64"));
            var input   = new ClaimTransaction
            {
                Claims = new[]
                {
                    new CoinReference {
                        PrevHash = txHash1, PrevIndex = 0
                    },
                    new CoinReference {
                        PrevHash = txHash2, PrevIndex = 0
                    },
                    new CoinReference {
                        PrevHash = txHash3, PrevIndex = 0
                    }
                }
            };
            var coinStates = new[]
            {
                CoinState.Confirmed | CoinState.Spent,
                CoinState.Confirmed | CoinState.Spent,
                CoinState.Confirmed | CoinState.Spent
            };
            var repositoryMock = AutoMockContainer.GetMock <IRepository>();

            repositoryMock.Setup(m => m.GetCoinStates(txHash1))
            .ReturnsAsync(coinStates.Skip(0).Take(1).ToArray());
            repositoryMock.Setup(m => m.GetCoinStates(txHash2))
            .ReturnsAsync(coinStates.Skip(1).Take(1).ToArray());
            repositoryMock.Setup(m => m.GetCoinStates(txHash3))
            .ReturnsAsync(coinStates.Skip(2).Take(1).ToArray());
            var testee = AutoMockContainer.Create <ClaimTransactionPersister>();

            await testee.Persist(input);

            repositoryMock.Verify(m => m.AddCoinStates(
                                      It.Is <UInt256>(u => u.Equals(txHash1)),
                                      It.Is <CoinState[]>(c => c[0].HasFlag(CoinState.Confirmed | CoinState.Spent | CoinState.Claimed))
                                      ));
            repositoryMock.Verify(m => m.AddCoinStates(
                                      It.Is <UInt256>(u => u.Equals(txHash2)),
                                      It.Is <CoinState[]>(c => c[0].HasFlag(CoinState.Confirmed | CoinState.Spent | CoinState.Claimed))
                                      ));
            repositoryMock.Verify(m => m.AddCoinStates(
                                      It.Is <UInt256>(u => u.Equals(txHash3)),
                                      It.Is <CoinState[]>(c => c[0].HasFlag(CoinState.Confirmed | CoinState.Spent | CoinState.Claimed))
                                      ));
        }
Example #16
0
        /// <inheritdoc />
        public ClaimTransaction BuildClaimTransaction(CoinReference[] inputs, TransactionAttribute[] attributes)
        {
            if (inputs == null || inputs.Length == 0)
            {
                throw new ArgumentException();
            }

            ClaimTransaction transaction = new ClaimTransaction();

            transaction.Inputs     = inputs;
            transaction.Attributes = attributes ?? new TransactionAttribute[0];
            //TODO #395: Complete transaction

            return(transaction);
        }
Example #17
0
        /// <summary>
        /// Creates a 'ClaimTransaction', signs it and send a 'sendrawtransaction' RPC call to the connected node.
        /// This method does not put gas into claimable state. Can only claim 'unclaimable' amount.
        /// </summary>
        /// <returns></returns>
        public override async Task <ClaimTransaction> ClaimGas(UInt160 changeAddress = null)
        {
            var(claimable, amount) =
                await TransactionBuilderHelper.GetClaimable(AddressScriptHash.ToAddress(), _restService);

            if (amount <= 0)
            {
                throw new WalletException("No GAS available to claim at this address");
            }

            var tx = new ClaimTransaction();

            var references = new List <CoinReference>();

            foreach (var entry in claimable)
            {
                references.Add(new CoinReference
                {
                    PrevHash  = UInt256.Parse(entry.Txid),
                    PrevIndex = (ushort)entry.N,
                });
            }

            if (changeAddress == null)
            {
                changeAddress = AddressScriptHash;
            }
            var outputs = new List <TransactionOutput>
            {
                new TransactionOutput
                {
                    ScriptHash = changeAddress,
                    AssetId    = Utils.GasToken,
                    Value      = Fixed8.FromDecimal(amount),
                }
            };

            tx.Version    = 0;
            tx.Claims     = references.ToArray();
            tx.Inputs     = new CoinReference[0];
            tx.Outputs    = outputs.ToArray();
            tx.Attributes = new TransactionAttribute[0];

            var result = await SignAndSendTransaction(tx);

            return(result ? tx : null);
        }
Example #18
0
        private bool OnClaimCommand(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }

            Coins coins = new Coins(Program.Wallet, system);

            switch (args[1].ToLower())
            {
            case "gas":
                if (args.Length > 2)
                {
                    switch (args[2].ToLower())
                    {
                    case "all":
                        ClaimTransaction[] txs = coins.ClaimAll();
                        if (txs.Length > 0)
                        {
                            foreach (ClaimTransaction tx in txs)
                            {
                                Console.WriteLine($"Tranaction Suceeded: {tx.Hash}");
                            }
                        }
                        return(true);

                    default:
                        return(base.OnCommand(args));
                    }
                }
                else
                {
                    ClaimTransaction tx = coins.Claim();
                    if (tx != null)
                    {
                        Console.WriteLine($"Tranaction Suceeded: {tx.Hash}");
                    }
                    return(true);
                }

            default:
                return(base.OnCommand(args));
            }
        }
Example #19
0
        public static Transaction Claim(Wallet wallet)
        {
            CoinReference[] claims = wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
            if (claims.Length == 0)
            {
                return(null);
            }

            ClaimTransaction tx = new ClaimTransaction
            {
                Claims     = claims,
                Attributes = new TransactionAttribute[0],
                Inputs     = new CoinReference[0],
                Outputs    = new[]
                {
                    new TransactionOutput
                    {
                        AssetId    = Blockchain.UtilityToken.Hash,
                        Value      = Blockchain.CalculateBonus(claims),
                        ScriptHash = wallet.GetChangeAddress()
                    }
                }
            };

            //交易输入是 1 GAS
            var input = new CoinReference()
            {
                PrevHash  = new UInt256("0x51ac4f7f1662d8c9379ccce3fa7cd2085b9a865edfa53ad892352a41768dd1de".Remove(0, 2).HexToBytes().Reverse().ToArray()),
                PrevIndex = 0
            };
            //交易输出是 0.999 GAS,找回到原地址
            var output = new TransactionOutput()
            {
                AssetId    = Blockchain.UtilityToken.Hash,                              //Asset Id, this is NEO
                ScriptHash = Wallet.ToScriptHash("AJd31a8rYPEBkY1QSxpsGy8mdU4vTYTD4U"), //Receiver
                Value      = new Fixed8((long)(0.999 * (long)Math.Pow(10, 8)))          //Value (satoshi unit)
            };

            //则手续费是 0.001 GAS
            tx.Inputs.ToList().Add(input);
            tx.Outputs.ToList().Add(output);

            return(tx);
        }
Example #20
0
        private bool OnClaimCommand(string[] args)
        {
            if (NoWallet())
            {
                return(true);
            }

            Coins coins = new Coins(Program.Wallet, LocalNode);

            switch (args[1].ToLower())
            {
            case "gas":
                ClaimTransaction tx = coins.Claim();
                if (tx != null)
                {
                    Console.WriteLine($"Tranaction Suceeded: {tx.Hash}");
                }
                return(true);

            default:
                return(base.OnCommand(args));
            }
        }
        public async Task Persist_MarksCorrectCoinStateAsClaimed()
        {
            var txHash             = UInt256.Parse(RandomInt().ToString("X64"));
            var expectedClaimIndex = (ushort)RandomInt(3);
            var input = new ClaimTransaction
            {
                Claims = new[]
                {
                    new CoinReference {
                        PrevHash = txHash, PrevIndex = expectedClaimIndex
                    }
                }
            };
            var coinStates = new[]
            {
                CoinState.Confirmed | CoinState.Spent,
                CoinState.Confirmed | CoinState.Spent,
                CoinState.Confirmed | CoinState.Spent
            };
            var repositoryMock = AutoMockContainer.GetMock <IRepository>();

            repositoryMock.Setup(m => m.GetCoinStates(txHash)).ReturnsAsync(coinStates);
            var testee = AutoMockContainer.Create <ClaimTransactionPersister>();

            await testee.Persist(input);

            repositoryMock.Verify(m => m.AddCoinStates(It.Is <UInt256>(u => u.Equals(txHash)), coinStates));
            for (var i = 0; i < coinStates.Length; i++)
            {
                coinStates[i].Should().HaveFlag(CoinState.Confirmed);
                coinStates[i].Should().HaveFlag(CoinState.Spent);
                if (i == expectedClaimIndex)
                {
                    coinStates[i].Should().HaveFlag(CoinState.Claimed);
                }
            }
        }
Example #22
0
        private NeoTransaction ConvertOperations(Operation[] operations, Metadata metadata)
        {
            TransactionType type = metadata["tx_type"].AsString().ToTransactionType();

            // operations only contains utxo transfers, and in a special order
            List <CoinReference>     inputs  = new List <CoinReference>();
            List <TransactionOutput> outputs = new List <TransactionOutput>();

            for (int i = 0; i < operations.Length; i++)
            {
                var operation = operations[i];
                // handle from ops, CoinChange field should have values
                if (operation.RelatedOperations is null)
                {
                    if (operation.CoinChange is null || operation.CoinChange.CoinAction != CoinAction.CoinSpent)
                    {
                        throw new ArgumentException();
                    }
                    var coin = operation.CoinChange;
                    inputs.Add(new CoinReference()
                    {
                        PrevHash  = coin.CoinIdentifier.GetTxHash(),
                        PrevIndex = (ushort)coin.CoinIdentifier.GetIndex()
                    });
                }
                else // handle to ops, CoinChange field may be null
                {
                    string  symbol     = operation.Amount.Currency.Symbol.ToUpper();
                    UInt256 assetId    = symbol == "NEO" ? Blockchain.GoverningToken.Hash : symbol == "GAS" ? Blockchain.UtilityToken.Hash : throw new NotSupportedException();
                    Fixed8  value      = Fixed8.Parse(operation.Amount.Value);
                    UInt160 scriptHash = operation.Account.Address.ToScriptHash();
                    outputs.Add(new TransactionOutput()
                    {
                        AssetId    = assetId,
                        Value      = value,
                        ScriptHash = scriptHash
                    });
                }
            }

            NeoTransaction neoTx;

            // fetch exclusive data for each tx type
            switch (type)
            {
            case TransactionType.ClaimTransaction:
                neoTx = new ClaimTransaction();
                JArray          coins          = metadata["claims"] as JArray;
                CoinReference[] coinReferences = coins.Select(p => new CoinReference()
                {
                    PrevHash  = UInt256.Parse(p["txid"].AsString()),
                    PrevIndex = ushort.Parse(p["vout"].AsString())
                }).ToArray();
                ((ClaimTransaction)neoTx).Claims = coinReferences;
                break;

            case TransactionType.ContractTransaction:
                neoTx = new ContractTransaction();
                break;

            case TransactionType.InvocationTransaction:
                neoTx = new InvocationTransaction();
                byte[] script = metadata["script"].AsString().HexToBytes();
                Fixed8 gas    = Fixed8.Parse(metadata["gas"].AsString());
                ((InvocationTransaction)neoTx).Script = script;
                ((InvocationTransaction)neoTx).Gas    = gas;
                break;

            case TransactionType.StateTransaction:
                neoTx = new StateTransaction();
                JArray            descriptors      = metadata["descriptors"] as JArray;
                StateDescriptor[] stateDescriptors = descriptors.Select(p => new StateDescriptor()
                {
                    Type  = p["type"].TryGetEnum <StateType>(),
                    Key   = p["key"].AsString().HexToBytes(),
                    Field = p["field"].AsString(),
                    Value = p["value"].AsString().HexToBytes()
                }).ToArray();
                ((StateTransaction)neoTx).Descriptors = stateDescriptors;
                break;

            default:
                throw new NotSupportedException();
            }
            neoTx.Inputs     = inputs.ToArray();
            neoTx.Outputs    = outputs.ToArray();
            neoTx.Attributes = new TransactionAttribute[] { };
            return(neoTx);
        }
Example #23
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 "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 "getunclaimedgas":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    JObject json   = new JObject();
                    uint    height = Blockchain.Default.Height + 1;
                    Fixed8  unavailable;
                    try
                    {
                        unavailable = Blockchain.CalculateBonus(Program.Wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), height);
                    }
                    catch (Exception)
                    {
                        unavailable = Fixed8.Zero;
                    }
                    json["unavailable"] = unavailable.ToString();
                    Fixed8 available = Blockchain.CalculateBonus(Program.Wallet.GetUnclaimedCoins().Select(p => p.Reference));
                    json["available"] = available.ToString();
                    return(json);
                }

            case "claimgas":
                if (Program.Wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    Fixed8 availableBonus = Blockchain.CalculateBonus(Program.Wallet.GetUnclaimedCoins().Select(p => p.Reference));
                    if (availableBonus == Fixed8.Zero)
                    {
                        // no gas to claim
                        return(null);
                    }

                    CoinReference[] claims = Program.Wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
                    if (claims.Length == 0)
                    {
                        return(null);
                    }

                    ClaimTransaction tx = new ClaimTransaction
                    {
                        Claims     = claims,
                        Attributes = new TransactionAttribute[0],
                        Inputs     = new CoinReference[0],
                        Outputs    = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = Blockchain.UtilityToken.Hash,
                                Value      = Blockchain.CalculateBonus(claims),
                                ScriptHash = Program.Wallet.GetChangeAddress()
                            }
                        }
                    };

                    ContractParametersContext context;
                    try
                    {
                        context = new ContractParametersContext(tx);
                    }
                    catch (InvalidOperationException)
                    {
                        // unsynchronized block
                        return(null);
                    }
                    Program.Wallet.Sign(context);
                    if (context.Completed)
                    {
                        context.Verifiable.Scripts = context.GetScripts();
                        Program.Wallet.ApplyTransaction(tx);
                        bool relay_result = LocalNode.Relay(tx);

                        if (relay_result)
                        {
                            return(tx.ToJson());
                        }
                        else
                        {
                            throw new RpcException(-401, "Could not relay transaction");
                        }
                    }
                    else
                    {
                        return(context.ToJson());
                    }
                }

            default:
                return(base.Process(method, _params));
            }
        }
Example #24
0
        private JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "claimgas":
                if (wallet == null || WalletLocker.Locked())
                {
                    throw new RpcException(-400, "Access denied.");
                }
                using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    if (snapshot.CalculateBonus(wallet.GetUnclaimedCoins().Select(p => p.Reference)) == Fixed8.Zero)
                    {
                        throw new RpcException(-100, "No gas to claim");
                    }
                    CoinReference[] claims = wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray();
                    if (claims.Length == 0)
                    {
                        throw new RpcException(-100, "No gas to claim");
                    }

                    ClaimTransaction tx = new ClaimTransaction
                    {
                        Claims     = claims.Take(MAX_CLAIMS_AMOUNT).ToArray(),
                        Attributes = new TransactionAttribute[0],
                        Inputs     = new CoinReference[0],
                        Outputs    = new[]
                        {
                            new TransactionOutput
                            {
                                AssetId    = Blockchain.UtilityToken.Hash,
                                Value      = snapshot.CalculateBonus(claims.Take(MAX_CLAIMS_AMOUNT)),
                                ScriptHash = _params.Count > 0 ? _params[0].AsString().ToScriptHash() : wallet.GetChangeAddress()
                            }
                        }
                    };
                    ContractParametersContext context;
                    try
                    {
                        context = new ContractParametersContext(tx);
                    }
                    catch (InvalidOperationException)
                    {
                        throw new RpcException(-400, "Access denied");
                    }
                    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 "dumpprivkey":
                if (wallet == null || WalletLocker.Locked())
                {
                    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:         //NEP-5 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].AsBoolean();
                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].AsBoolean();
                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 || WalletLocker.Locked())
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    WalletAccount account = Wallet.CreateAccount();
                    if (Wallet is NEP6Wallet nep6)
                    {
                        nep6.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":
            {
                bool shouldGetUnverified = _params.Count >= 1 && _params[0].AsBoolean();
                if (!shouldGetUnverified)
                {
                    return(new JArray(Blockchain.Singleton.MemPool.GetVerifiedTransactions().Select(p => (JObject)p.Hash.ToString())));
                }

                JObject json = new JObject();
                json["height"] = Blockchain.Singleton.Height;
                Blockchain.Singleton.MemPool.GetVerifiedAndUnverifiedTransactions(
                    out IEnumerable <Transaction> verifiedTransactions,
                    out IEnumerable <Transaction> unverifiedTransactions);
                json["verified"]   = new JArray(verifiedTransactions.Select(p => (JObject)p.Hash.ToString()));
                json["unverified"] = new JArray(unverifiedTransactions.Select(p => (JObject)p.Hash.ToString()));
                return(json);
            }

            case "getrawtransaction":
            {
                UInt256     hash    = UInt256.Parse(_params[0].AsString());
                bool        verbose = _params.Count >= 2 && _params[1].AsBoolean();
                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 "gettransactionheight":
            {
                UInt256 hash   = UInt256.Parse(_params[0].AsString());
                uint?   height = Blockchain.Singleton.Store.GetTransactions().TryGet(hash)?.BlockIndex;
                if (height.HasValue)
                {
                    return(height.Value);
                }
                throw new RpcException(-100, "Unknown transaction");
            }

            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 "lockwallet":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    WalletLocker.Lock();
                    return(true);
                }

            case "sendfrom":
                if (wallet == null || WalletLocker.Locked())
                {
                    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 "sendmany":
                if (wallet == null || WalletLocker.Locked())
                {
                    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 || WalletLocker.Locked())
                {
                    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 "showgas":
                using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot())
                {
                    uint   height = snapshot.Height + 1;
                    Fixed8 unavailable;

                    try
                    {
                        unavailable = snapshot.CalculateBonus(wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), height);
                    }
                    catch (Exception)
                    {
                        unavailable = Fixed8.Zero;
                    }

                    return(new JObject
                    {
                        ["available"] = snapshot.CalculateBonus(wallet.GetUnclaimedCoins().Select(p => p.Reference)).ToString(),
                        ["unavailable"] = unavailable.ToString()
                    });
                }

            case "submitblock":
            {
                Block             block  = _params[0].AsString().HexToBytes().AsSerializable <Block>();
                RelayResultReason reason = system.Blockchain.Ask <RelayResultReason>(block).Result;
                return(GetRelayResult(reason));
            }

            case "unlockwallet":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    try
                    {
                        if (_params.Count > 1)
                        {
                            WalletLocker.Unlock(wallet, _params[0].AsString(), uint.Parse(_params[1].AsString()));
                        }
                        else
                        {
                            WalletLocker.Unlock(wallet, _params[0].AsString(), DEFAULT_UNLOCK_TIME);
                        }
                    }
                    catch (FormatException)
                    {
                        throw new RpcException(-32602, "Invalid params");
                    }
                    return(true);
                }

            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");
            }
        }
        public async Task <IActionResult> Create(ClaimTransactionViewModel viewModel)
        {
            var invoiceNumber      = viewModel.ClaimTransaction.InvoiceNumber;
            var currentProductId   = viewModel.ProductID;
            var currentClientId    = viewModel.ClientID;
            var currentPolicyId    = viewModel.PolicyID;
            var currentClaimNumber = viewModel.ClaimTransaction.ClaimNumber;

            try
            {
                if (ModelState.IsValid)
                {
                    ClaimTransaction   claimTransaction  = new ClaimTransaction();
                    TransactionNumbers transactionnumber = new TransactionNumbers();

                    claimTransaction                   = viewModel.ClaimTransaction;
                    claimTransaction.ID                = Guid.NewGuid();
                    claimTransaction.ClaimNumber       = viewModel.ClaimNumber;
                    claimTransaction.TransactionNumber = transactionnumber.GetTransactionNumber(_context);
                    claimTransaction.TaxAmount         = TaxAmount(claimTransaction.Taxable, claimTransaction.Amount, claimTransaction.ClaimNumber);
                    _context.Add(claimTransaction);
                    await _context.SaveChangesAsync();

                    var tranParam = claimTransaction.TransactionNumber;

                    await _context.Database.ExecuteSqlCommandAsync(
                        "INSERT INTO ClaimTransactionGenerator(TransactionNumber) " +
                        "Values ({0})",
                        parameters : tranParam);

                    return(RedirectToAction("Index", new {
                        productId = currentProductId, clientId = currentClientId,
                        policyId = currentPolicyId, claimId = currentClaimNumber
                    }));
                }
            }
            catch (DbUpdateException ex)
            {
                var errorMsg = ex.InnerException.Message.ToString();

                viewModel.ErrMsg = errorMsg;

                if (errorMsg.Contains("IX_ClaimTransaction_InvoiceNumber"))
                {
                    viewModel.ErrMsg = $"Duplicate Invoice Number {invoiceNumber} exists.";
                    ModelState.AddModelError(string.Empty, viewModel.ErrMsg);
                }

                ModelState.AddModelError(string.Empty, ex.InnerException.Message.ToString());
            }

            viewModel.PayeeList = new SelectList(await _context.Payees.OrderBy(p => p.Name)
                                                 .AsNoTracking()
                                                 .ToListAsync(), "ID", "Name", viewModel.ClaimTransaction.ID);
            viewModel.AccountList = new SelectList(await _context.AccountCharts
                                                   .AsNoTracking()
                                                   .OrderBy(p => p.AccountCode).ToListAsync(), "ID", "AccountCode", viewModel.ClaimTransaction.AccountID);
            viewModel.AffectedList = new SelectList(await _context.Affecteds
                                                    .AsNoTracking()
                                                    .OrderBy(p => p.Name).ToListAsync(), "ID", "Name", viewModel.ClaimTransaction.AffectedID);
            viewModel.TransactionTypeList = new SelectList(await _context.TransactionTypes
                                                           .AsNoTracking()
                                                           .OrderByDescending(p => p.Name).ToListAsync(), "ID", "Name", viewModel.ClaimTransaction.TransactionTypeID);
            return(View(viewModel));
        }
Example #26
0
        public void Verify_ClaimTransacWithNegativeResultOfUtilityToken()
        {
            var testee = AutoMockContainer.Create <TransactionOperationManager>();

            var transaction = new ClaimTransaction
            {
                Attributes = new []
                {
                    new TransactionAttribute
                    {
                        Usage = TransactionAttributeUsage.ContractHash
                    }
                },
                Inputs = new[]
                {
                    new CoinReference
                    {
                        PrevHash  = UInt256.Zero,
                        PrevIndex = 1
                    },
                    new CoinReference
                    {
                        PrevHash  = UInt256.Zero,
                        PrevIndex = 2
                    }
                },
                Outputs = new[]
                {
                    new TransactionOutput
                    {
                        AssetId = UInt256.Zero,
                        Value   = Fixed8.One
                    }
                }
            };

            var transactionOfPreviousHash = new Transaction
            {
                Outputs = new []
                {
                    new TransactionOutput(), // it's not using the first because PrevIndex is 1
                    new TransactionOutput
                    {
                        AssetId = UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"),
                        Value   = new Fixed8(-5)
                    }
                }
            };

            var transactionModelMock = this.AutoMockContainer.GetMock <ITransactionRepository>();

            transactionModelMock
            .Setup(b => b.IsDoubleSpend(transaction))
            .Returns(false);
            transactionModelMock
            .Setup(x => x.GetTransaction(It.IsAny <UInt256>()))
            .ReturnsAsync(() => transactionOfPreviousHash);

            this.AutoMockContainer
            .GetMock <IAssetRepository>()
            .Setup(b => b.GetAsset(It.IsAny <UInt256>()))
            .ReturnsAsync(() => new Asset
            {
                AssetType = AssetType.GoverningToken
            });

            var transactionContextMock = this.AutoMockContainer.GetMock <ITransactionContext>();

            transactionContextMock
            .SetupGet(x => x.UtilityTokenHash)
            .Returns(UInt256.Parse("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"));
            transactionContextMock
            .Setup(x => x.GetSystemFee(It.IsAny <Transaction>()))
            .Returns(Fixed8.Zero);

            var result = testee.Verify(transaction);

            result.Should().BeFalse();
        }
Example #27
0
        /// <summary>
        /// Combine creates a network-specific transaction from an unsigned transaction and an array of provided signatures.
        /// The signed transaction returned from this method will be sent to the `/construction/submit` endpoint by the caller.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public JObject ConstructionCombine(ConstructionCombineRequest request)
        {
            NeoTransaction neoTx;

            try
            {
                byte[]          unsigned = request.UnsignedTransaction.HexToBytes();
                TransactionType type     = (TransactionType)unsigned[0];
                switch (type)
                {
                case TransactionType.ClaimTransaction:
                    neoTx = new ClaimTransaction();
                    break;

                case TransactionType.ContractTransaction:
                    neoTx = new ContractTransaction();
                    break;

                case TransactionType.StateTransaction:
                    neoTx = new StateTransaction();
                    break;

                case TransactionType.InvocationTransaction:
                    neoTx = new InvocationTransaction();
                    break;

                default:
                    throw new ArgumentException();
                }
                using (MemoryStream ms = new MemoryStream(unsigned, false))
                    using (BinaryReader br = new BinaryReader(ms, Encoding.UTF8))
                    {
                        (neoTx as IVerifiable).DeserializeUnsigned(br);
                    }
            }
            catch (Exception)
            {
                return(Error.TX_DESERIALIZE_ERROR.ToJson());
            }

            if (neoTx.Witnesses != null && neoTx.Witnesses.Length > 0)
            {
                return(Error.TX_ALREADY_SIGNED.ToJson());
            }

            if (request.Signatures.Length == 0)
            {
                return(Error.NO_SIGNATURE.ToJson());
            }

            Witness witness;

            if (request.Signatures.Length == 1) // single signed
            {
                witness = CreateSignatureWitness(request.Signatures[0]);
            }
            else
            {
                witness = CreateMultiSignatureWitness(request.Signatures);
            }

            if (witness is null)
            {
                return(Error.INVALID_SIGNATURES.ToJson());
            }

            neoTx.Witnesses = new Witness[] { witness };
            byte[] signed = neoTx.ToArray();
            ConstructionCombineResponse response = new ConstructionCombineResponse(signed.ToHexString());

            return(response.ToJson());
        }
Example #28
0
        public void TestFilterForBlock_ClaimHasPriority()
        {
            // Should contain "ClaimTransaction" in "HighPriorityTxType"
            Settings.Default.HighPriorityTxType.Contains(TransactionType.ClaimTransaction).Should().Be(true);

            ClaimTransaction claimTxZero1 = GetClaimTransaction(0);

            claimTxZero1.Size.Should().Be(7 + 21); // 7 + 21 (random script)
            claimTxZero1.Hash.ToString().Should().Be("0x60037520be0fd903703c2b67973296f22cac8932db07a2723addf79478aea75f");
            ClaimTransaction claimTxZero2 = GetClaimTransaction(0);

            claimTxZero2.Size.Should().Be(7 + 21); // 7 + 21 (random script)
            claimTxZero2.Hash.ToString().Should().Be("0xb29426673b3ef5c226bd35d53c2cb2242e09c06f0efe9c0d5be2034f41cb85ba");
            ClaimTransaction claimTxZero3 = GetClaimTransaction(0);

            claimTxZero3.Size.Should().Be(7 + 21); // 7 + 21 (random script)
            claimTxZero3.Hash.ToString().Should().Be("0x01027faead9a0538048db7ac5657172f6e2240bff3f7d902e490bb1bd75c2df7");

            //ClaimTransaction claimTxTwo = GetClaimTransaction(2);
            //claimTxTwo.Size.Should().Be(75 + 21); // 2*34 + 7 + 21

            ClaimTransaction claimTx30 = GetClaimTransaction(30);

            claimTx30.Size.Should().Be(1027 + 21);     // 30*34 + 7 + 21
            claimTx30.NetworkFee.Should().Be(Fixed8.Zero);
            claimTx30.IsLowPriority.Should().Be(true); // by default is Low Priority, but plugin makes it High Priority
            //uut.IsLowPriority -> cannot inspect because it's private... no problem!

            List <Transaction> TxList = new List <Transaction>();

            TxList.Insert(0, claimTxZero1);
            TxList.Insert(0, claimTxZero2);
            TxList.Insert(0, claimTxZero3);
            TxList.Insert(0, claimTx30);

            //Console.WriteLine("Tx List Claim");
            //foreach(var tx in TxList)
            //    Console.WriteLine($"Claim TX fee: {tx.NetworkFee} size: {tx.Size} ratio: {tx.FeePerByte} hash: {tx.Hash}" );


            // ======================== BEGIN TESTS ============================

            // insert 100 paid invocation transactions
            for (var i = 0; i < 100; i++)
            {
                TxList.Insert(0, MockGenerateInvocationTransaction(Fixed8.One, 50).Object);
            }

            // insert 100 low priority invocation transactions (18 satoshi + 82 zero)
            for (var i = 0; i < 100; i++)
            {
                if (i < 18)
                {
                    TxList.Insert(0, MockGenerateInvocationTransaction(Fixed8.Satoshi, 50).Object);
                }
                else
                {
                    TxList.Insert(0, MockGenerateInvocationTransaction(Fixed8.Zero, 50).Object);
                }
            }

            TxList.Count().Should().Be(204);                                                    // 100 free + 100 paid + 4 claims
            TxList.Where(tx => tx.NetworkFee == Fixed8.Zero).Count().Should().Be(100 - 18 + 4); // 82 fully free + 4 claims

            IEnumerable <Transaction> filteredTxList = uut.FilterForBlock(TxList);

            //filteredTxList.Count().Should().Be(124); // 20 free + 100 paid + 4 claims
            filteredTxList.Count().Should().Be(120);                                         // 20 free (including 2 claims) + 100 paid
            filteredTxList.Where(tx => tx.NetworkFee == Fixed8.Zero).Count().Should().Be(2); // 2 fully free (2 claims)

            // will select 20 low priority (including Claims)
            var vx = filteredTxList.Where(tx => tx.IsLowPriority == true);

            vx.Count().Should().Be(20);

            // two Claim Transaction will survive
            vx = filteredTxList.Where(tx => tx.Type == TransactionType.ClaimTransaction);
            vx.Count().Should().Be(2);

            // =================================================================

            // insert more paid invocation transactions (400 of each)
            for (var i = 0; i < 400; i++)
            {
                TxList.Insert(0, MockGenerateInvocationTransaction(Fixed8.One, 50).Object);
            }

            // insert more free invocation transactions (400 of each)
            for (var i = 0; i < 400; i++)
            {
                TxList.Insert(0, MockGenerateInvocationTransaction(Fixed8.Zero, 50).Object);
            }

            TxList.Count().Should().Be(1004);                                                         // 500 free + 500 paid + 4 claims
            TxList.Where(tx => tx.NetworkFee == Fixed8.Zero).Count().Should().Be(400 + 100 - 18 + 4); // 500-18 fully free + 4 claims

            filteredTxList = uut.FilterForBlock(TxList);
            filteredTxList.Count().Should().Be(499); // full block

            // will select 20 low priority (including Claims)
            vx = filteredTxList.Where(tx => tx.IsLowPriority == true);
            vx.Count().Should().Be(20);

            // will still select Claim Transactions
            vx = filteredTxList.Where(tx => tx.Type == TransactionType.ClaimTransaction);
            vx.Count().Should().Be(2);

            // there are 3 tied Claim tx, will solve it based on smaller hash (0x01, 0x60) => 0xb2 is excluded
            // 0x01027faead9a0538048db7ac5657172f6e2240bff3f7d902e490bb1bd75c2df7
            // 0x60037520be0fd903703c2b67973296f22cac8932db07a2723addf79478aea75f
            // 0xb29426673b3ef5c226bd35d53c2cb2242e09c06f0efe9c0d5be2034f41cb85ba
            vx = filteredTxList.Where(tx => tx.Hash.ToString() == "0x01027faead9a0538048db7ac5657172f6e2240bff3f7d902e490bb1bd75c2df7");
            vx.Count().Should().Be(1);
            vx = filteredTxList.Where(tx => tx.Hash.ToString() == "0x60037520be0fd903703c2b67973296f22cac8932db07a2723addf79478aea75f");
            vx.Count().Should().Be(1);
            vx = filteredTxList.Where(tx => tx.Hash.ToString() == "0xb29426673b3ef5c226bd35d53c2cb2242e09c06f0efe9c0d5be2034f41cb85ba");
            vx.Count().Should().Be(0);

            //Console.WriteLine("filtered");
            //foreach(var tx in filteredTxList)
            //    Console.WriteLine($"TX fee: {tx.NetworkFee} size: {tx.Size} ratio: {tx.FeePerByte} hash: {tx.Hash}" );
        }
Example #29
0
 public void TestSetup()
 {
     uut = new ClaimTransaction();
 }
        private static JArray GetMempoolTransaction(UInt160 ScriptHash)
        {
            JArray result = new JArray();

            foreach (Transaction tx in LocalNode.GetMemoryPool())
            {
                UInt160 from_script = null;
                UInt160 to_script   = null;
                JObject obj         = new JObject();

                if (tx is ContractTransaction)
                {
                    try
                    {
                        foreach (CoinReference input in tx.Inputs)
                        {
                            Transaction inputTx = Blockchain.Default.GetTransaction(input.PrevHash);
                            if (inputTx != null)
                            {
                                from_script = inputTx.Outputs[input.PrevIndex].ScriptHash;
                            }
                            else
                            {
                                foreach (Transaction inTx in LocalNode.GetMemoryPool())
                                {
                                    if (inTx.Hash.Equals(input.PrevHash))
                                    {
                                        from_script = inTx.Outputs[input.PrevIndex].ScriptHash;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex) { }

                    if (tx.Outputs.Length > 0)
                    {
                        to_script = tx.Outputs[0].ScriptHash;
                    }

                    Dictionary <UInt256, Fixed8> balance = new Dictionary <UInt256, Fixed8>();
                    Dictionary <UInt256, Fixed8> fee     = new Dictionary <UInt256, Fixed8>();
                    for (int i = 0; i < tx.Outputs.Length; i++)
                    {
                        AssetState state = Blockchain.Default.GetAssetState(tx.Outputs[i].AssetId);
                        if (tx.Outputs[i].ScriptHash.Equals(to_script))
                        {
                            if (balance.ContainsKey(tx.Outputs[i].AssetId))
                            {
                                balance[tx.Outputs[i].AssetId] += tx.Outputs[i].Value;
                            }
                            else
                            {
                                balance[tx.Outputs[i].AssetId] = tx.Outputs[i].Value;
                            }
                        }

                        if (!fee.ContainsKey(tx.Outputs[i].AssetId))
                        {
                            if (tx.Outputs[i].Fee != Fixed8.Zero)
                            {
                                fee[tx.Outputs[i].AssetId] = tx.Outputs[i].Fee;
                            }
                        }
                    }
                    Fixed8 qrgFee = fee.Sum(p => p.Value);
                    if (balance.Count > 0)
                    {
                        UInt256 assetId = balance.First().Key;
                        Fixed8  value   = balance.Sum(p => p.Value);

                        AssetState assetState = Blockchain.Default.GetAssetState(assetId);
                        obj["asset"]  = assetState.GetName();
                        obj["amount"] = value.ToString();
                        obj["fee"]    = qrgFee.ToString();
                    }
                }
                else if (tx is ClaimTransaction)
                {
                    ClaimTransaction claimTx = (ClaimTransaction)tx;
                    if (claimTx.Outputs.Length > 0)
                    {
                        from_script = to_script = tx.Outputs[0].ScriptHash;
                    }

                    Dictionary <UInt256, Fixed8> balance = new Dictionary <UInt256, Fixed8>();
                    Dictionary <UInt256, Fixed8> fee     = new Dictionary <UInt256, Fixed8>();

                    for (int i = 0; i < tx.Outputs.Length; i++)
                    {
                        AssetState state = Blockchain.Default.GetAssetState(tx.Outputs[i].AssetId);
                        if (tx.Outputs[i].ScriptHash.Equals(to_script))
                        {
                            if (balance.ContainsKey(tx.Outputs[i].AssetId))
                            {
                                balance[tx.Outputs[i].AssetId] += tx.Outputs[i].Value;
                            }
                            else
                            {
                                balance[tx.Outputs[i].AssetId] = tx.Outputs[i].Value;
                            }
                        }

                        if (!fee.ContainsKey(tx.Outputs[i].AssetId))
                        {
                            if (tx.Outputs[i].Fee != Fixed8.Zero)
                            {
                                fee[tx.Outputs[i].AssetId] = tx.Outputs[i].Fee;
                            }
                        }
                    }
                    obj["asset"]  = Blockchain.UtilityToken.Name;
                    obj["amount"] = balance[Blockchain.UtilityToken.Hash].value.ToString();
                    obj["fee"]    = Fixed8.Zero.ToString();
                }
                else if (tx is InvocationTransaction)
                {
                    InvocationTransaction invocTx = (InvocationTransaction)tx;
                    try
                    {
                        foreach (CoinReference input in tx.Inputs)
                        {
                            from_script = tx.References[input].ScriptHash;
                        }
                    }
                    catch (Exception ex) { }
                    obj["asset"]  = Blockchain.UtilityToken.Name;
                    obj["amount"] = invocTx.Gas.ToString();
                    obj["fee"]    = Fixed8.Zero.ToString();
                }
                else if (tx is IssueTransaction)
                {
                    AssetState       state   = Blockchain.Default.GetAssetState(Blockchain.UtilityToken.Hash);
                    IssueTransaction issueTx = (IssueTransaction)tx;

                    try
                    {
                        foreach (CoinReference input in tx.Inputs)
                        {
                            from_script = tx.References[input].ScriptHash;
                        }
                    }
                    catch (Exception ex) { }

                    if (tx.Outputs.Length > 0)
                    {
                        to_script = tx.Outputs[0].ScriptHash;
                    }


                    if (tx.Outputs.Length > 0)
                    {
                        state = Blockchain.Default.GetAssetState(tx.Outputs[0].AssetId);
                    }

                    Fixed8 totalAmount = Fixed8.Zero;
                    foreach (TransactionOutput output in tx.Outputs)
                    {
                        if (output.AssetId != Blockchain.UtilityToken.Hash)
                        {
                            totalAmount += output.Value;
                        }
                    }

                    Fixed8 fee = issueTx.NetworkFee + issueTx.SystemFee;

                    obj["asset"]  = state.GetName();
                    obj["amount"] = totalAmount.ToString();
                    obj["fee"]    = fee.ToString();
                }

                if (!ScriptHash.Equals(from_script) && !ScriptHash.Equals(to_script))
                {
                    continue;
                }

                if (from_script != null)
                {
                    obj["from"] = Wallet.ToAddress(from_script);
                }
                else
                {
                    obj["from"] = "";
                }

                if (to_script != null)
                {
                    obj["to"] = Wallet.ToAddress(to_script);
                }
                else
                {
                    obj["to"] = "";
                }

                obj["txType"]      = tx.Type;
                obj["blockHeight"] = Fixed8.Zero.ToString();
                obj["txid"]        = tx.Hash.ToString();
                obj["timestamp"]   = DateTime.Now.ToTimestamp();
                obj["status"]      = 0;
                result.Add(obj);
            }
            return(result);
        }