From 8b6065d97479543277a1f7b3084a5e2190cc3783 Mon Sep 17 00:00:00 2001 From: Shuai Date: Tue, 10 Aug 2021 11:24:07 +0800 Subject: [PATCH] fix transfer --- .../ClientApp/src/components/Chain/asset.js | 170 +++---- .../src/components/Chain/assetdetail.js | 238 ++++----- .../src/components/Chain/blockdetail.js | 456 ++++++++---------- .../src/components/Transaction/transaction.js | 128 ++--- .../neo3-gui/ClientApp/src/router/router.js | 12 +- neo3-gui/neo3-gui/Common/Storage/TrackDB.cs | 148 ++++-- neo3-gui/neo3-gui/Common/WebSocketHub.cs | 18 +- .../Models/Jobs/TransactionConfirmJob.cs | 4 +- .../neo3-gui/Services/NotificationService.cs | 20 +- 9 files changed, 566 insertions(+), 628 deletions(-) diff --git a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/asset.js b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/asset.js index b6661ab1..1d0821f7 100644 --- a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/asset.js +++ b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/asset.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import { Layout, @@ -11,104 +11,76 @@ import { Avatar, } from "antd"; import Sync from "../sync"; -import { withTranslation } from "react-i18next"; -import { post } from "../../core/request"; +import { withTranslation, useTranslation } from "react-i18next"; +import { postAsync } from "../../core/request"; import "../../static/css/chain.css"; -const { Content } = Layout; +export default function ChainAsset() { + const { Content } = Layout; + const { t } = useTranslation(); + const [assetlist, setAssetList] = useState([]); -@withTranslation() -class Chainasset extends React.Component { - constructor(props) { - super(props); - this.state = { - assetlist: [], - }; - } - componentDidMount() { - this.getAllblock(); - } - getAllblock = () => { - var _this = this; - const { t } = this.props; - post("GetAllAssets", {}) - .then((res) => { - var _data = res.data; - if (_data.msgType === -1) { - message.error(t("alert msg.no find")); - return; - } - _this.setState({ assetlist: _data.result }); - }) - .catch(function (error) { - console.log(error); - console.log("error"); - }); - }; - render() { - const { t } = this.props; - const { assetlist } = this.state; - return ( - - - - - - -
- - {t("blockchain.asset info")} - - {t("blockchain.initial time")} - - {t("blockchain.total")} -
- } - itemLayout="horizontal" - dataSource={assetlist} - className="font-s" - renderItem={(item) => ( - - - } - title={ - - {item.symbol} - {item.asset} - - } - /> - - {item.totalSupply ? item.totalSupply : "--"} - - - {item.createTime.substr(0, 10)} - - - )} - /> - - -
-
-
-
- ); - } -} - -export default Chainasset; + useEffect(() => { + postAsync("GetAllAssets", {}).then((data) => { + if (data.msgType < 0) { + message.error(t("alert msg.no find")); + return; + } + setAssetList(data.result); + }).catch(function (error) { + console.log(error); + }); + }); + return ( + + + + + + +
+ + {t("blockchain.asset info")} + + {t("blockchain.initial time")} + + {t("blockchain.total")} +
+ } + itemLayout="horizontal" + dataSource={assetlist} + className="font-s" + renderItem={(item) => ( + + } + title={ + + {item.symbol} + {item.asset} + + } + /> + + {item.totalSupply ? item.totalSupply : "--"} + + + {item.createTime.substr(0, 10)} + + + )} + /> + + +
+
+
+
+ ); +} \ No newline at end of file diff --git a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/assetdetail.js b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/assetdetail.js index d4dee51b..cc275ee9 100644 --- a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/assetdetail.js +++ b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/assetdetail.js @@ -1,153 +1,113 @@ /* eslint-disable */ //just test replace wallet// -import React from "react"; -import { Link } from "react-router-dom"; +import React, { useState, useEffect } from "react"; import { Layout, Row, Col, message, List, PageHeader } from "antd"; -import axios from "axios"; -import Intitle from "../Common/intitle"; import Transaction from "../Transaction/transaction"; import Sync from "../sync"; -import { withTranslation } from "react-i18next"; -import { post } from "../../core/request"; +import { withTranslation, useTranslation } from "react-i18next"; +import { postAsync } from "../../core/request"; -const { Content } = Layout; -@withTranslation() -class Assetdetail extends React.Component { - constructor(props) { - super(props); - this.state = { - assetdetail: {}, - height: 0, - witness: "", - nonce: 0, - }; - } - componentDidMount() { - this.getAsset((res) => { - console.log(res); - this.setState({ - assetdetail: res, - }); - }); - } - getAsset = (callback) => { - var _this = this; +export default function AssetDetail() { + const { Content } = Layout; + const [assetdetail, setAssetDetail] = useState({}); + const { t } = useTranslation(); + + useEffect(() => { let params = { asset: location.pathname.split(":").pop(), }; - post("GetAsset", params) - .then((res) => { - var _data = res.data; - - if (_data.msgType === -1) { - message.error("查询失败"); - return; - } else { - callback(_data.result); - } - }) - .catch(function (error) { - console.log("error"); - }); - }; - setHash = (h) => { - return () => { - this.setState( - { - hash: h, - }, - () => this.getAsset() - ); - }; - }; - render() { - const { assetdetail } = this.state; - const { t } = this.props; - return ( - - - - - - -
-
- Hash:     - {assetdetail.asset} -
- {assetdetail.asset ? ( - - -
    -
  • - {t("blockchain.name")}: - {assetdetail.name} -
  • -
  • - - {t("blockchain.total")}: - - {assetdetail.totalSupply - ? assetdetail.totalSupply - : "--"} -
  • -
  • - - {t("blockchain.publish time")}: - - {assetdetail.createTime.substr(0, 10)} -
  • -
- - -
    -
  • - - {t("blockchain.abbreviation")}: - - {assetdetail.symbol} -
  • -
  • - - {t("blockchain.precision")}: - - {assetdetail.decimals ? assetdetail.decimals : "0"} -
  • -
  • - - {t("blockchain.transaction count")}: - - {assetdetail.transactionCount - ? assetdetail.transactionCount - : "--"} -
  • -
- -
- ) : null} + postAsync("GetAsset", params).then((data) => { + if (data.msgType < 0) { + message.error(t("alert msg.no find")); + return; + } + setAssetDetail(data.result); + }).catch(function (error) { + console.log(error); + }); + }); + return ( + + + + + + +
+
+ Hash:     + {assetdetail.asset}
- - + {assetdetail.asset ? ( + + +
    +
  • + {t("blockchain.name")}: + {assetdetail.name} +
  • +
  • + + {t("blockchain.total")}: + + {assetdetail.totalSupply + ? assetdetail.totalSupply + : "--"} +
  • +
  • + + {t("blockchain.publish time")}: + + {assetdetail.createTime.substr(0, 10)} +
  • +
+ + +
    +
  • + + {t("blockchain.abbreviation")}: + + {assetdetail.symbol} +
  • +
  • + + {t("blockchain.precision")}: + + {assetdetail.decimals ? assetdetail.decimals : "0"} +
  • +
  • + + {t("blockchain.transaction count")}: + + {assetdetail.transactionCount + ? assetdetail.transactionCount + : "--"} +
  • +
+ +
+ ) : null} +
+ +
- - - - - - -
-
- ); - } + + + + + + + + + ); } -export default Assetdetail; diff --git a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/blockdetail.js b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/blockdetail.js index aa5d735f..c1c6ca4d 100644 --- a/neo3-gui/neo3-gui/ClientApp/src/components/Chain/blockdetail.js +++ b/neo3-gui/neo3-gui/ClientApp/src/components/Chain/blockdetail.js @@ -1,299 +1,229 @@ /* eslint-disable */ //just test replace wallet// -import React from "react"; +import React, { useState, useEffect } from "react"; import { Link } from "react-router-dom"; import { Layout, Row, Col, message, PageHeader, List } from "antd"; -import axios from "axios"; +import { SwapRightOutlined } from "@ant-design/icons"; import Sync from "../sync"; -import { withTranslation } from "react-i18next"; +import { postAsync } from "../../core/request"; +import { withTranslation, useTranslation } from "react-i18next"; -import { SwapRightOutlined } from "@ant-design/icons"; -const { Content } = Layout; +export default function BlockDetail() { + const { Content } = Layout; + const { t } = useTranslation(); -@withTranslation() -class Blockdetail extends React.Component { - constructor(props) { - super(props); - this.state = { - blockdetail: {}, - height: 0, - primaryIndex: 0, - translist: [], - }; - } - componentDidMount() { - let _h = Number(location.pathname.split(":").pop()); - this.setHeight(_h)(); - this.setState({ - local: location.pathname, - }); - } - getAllblock = (callback) => { - const { t } = this.props; - let _height = this.state.height; - axios - .post("http://localhost:8081", { - id: "1111", - method: "GetBlock", - params: { - index: _height, - }, - }) - .then(function (response) { - var _data = response.data; - if (_data.msgType === -1) { + const [height, setHeight] = useState(0); + const [blockdetail, setBlockDetail] = useState({}); + const [translist, setTransList] = useState([]); + let blockHeight = Number(location.pathname.split(":").pop()); + useEffect(() => { + postAsync("GetBlock", { index: blockHeight }) + .then(function (data) { + if (data.msgType < 0) { message.info(t("blockchain.height unexist")); return; - } else { - callback(_data); } + setBlockDetail(data.result); }) .catch(function (error) { console.log(error); - console.log("error"); }); - }; - setHeight = (h) => { - return () => { - this.setState({ height: h }, () => - this.getAllblock((res) => { - this.setState( - { - blockdetail: res.result, - witness: res.result.witness.scriptHash, - primaryIndex: res.result.primaryIndex, - height: res.result.blockHeight, - }, - () => { - this.getBlocktrans(); - } - ); - }) - ); - }; - }; - getBlocktrans = () => { - const { t } = this.props; - let _height = this.state.height; - let _this = this; - axios - .post("http://localhost:8081", { - id: "1111", - method: "QueryTransactions", - params: { - blockHeight: _height, - limit: 100, - }, - }) - .then(function (response) { - var _data = response.data; - if (_data.msgType === -1) { + + postAsync("QueryTransactions", { blockHeight: blockHeight, limit: 500, }) + .then((msg) => { + if (msg.msgType < 0) { message.info(t("blockchain.height unexist")); return; - } else { - _this.setState({ translist: _data.result.list }); } + setTransList(msg.result.list); }) .catch(function (error) { console.log(error); - console.log("error"); }); - }; - render() { - const { t } = this.props; - const { blockdetail, primaryIndex, height, translist } = this.state; - return ( - - - - - - -
-
- Hash:     - {blockdetail.blockHash} -
- {blockdetail.blockHash ? ( - - -
    -
  • - - {t("blockchain.height")}: - - {blockdetail.blockHeight} -
  • -
  • - - {t("blockchain.timestamp")}: - - {blockdetail.blockTime} -
  • -
  • - - {t("blockchain.network fee")}: - - {blockdetail.networkFee - ? blockdetail.networkFee - : "--"} -
  • -
  • - - {t("blockchain.confirmations")}: - - {blockdetail.confirmations} -
  • - {blockdetail.blockHeight !== 0 ? ( -
  • - - {t("blockchain.prev block")}: - - - {blockdetail.blockHeight - 1} - -
  • - ) : ( -
  • - - {t("blockchain.prev block")}: - - -- -
  • - )} -
- - -
    -
  • - {t("common.size")}: - {blockdetail.size} {t("common.bytes")} -
  • -
  • - - {t("blockchain.primary index")}: - - {primaryIndex} -
  • -
  • - - {t("blockchain.system fee")}: - - {blockdetail.systemFee ? blockdetail.systemFee : "--"} -
  • -
  • - - {t("blockchain.witness")}: - - {blockdetail.nextConsensus} -
  • + }, [height]); + return ( + + + + + + +
    +
    + Hash:     + {blockdetail.blockHash} +
    + {blockdetail.blockHash ? ( + + +
      +
    • + + {t("blockchain.height")}: + + {blockdetail.blockHeight} +
    • +
    • + + {t("blockchain.timestamp")}: + + {blockdetail.blockTime} +
    • +
    • + + {t("blockchain.network fee")}: + + {blockdetail.networkFee + ? blockdetail.networkFee + : "--"} +
    • +
    • + + {t("blockchain.confirmations")}: + + {blockdetail.confirmations} +
    • + {blockdetail.blockHeight !== 0 ? (
    • - {t("blockchain.next block")}: + {t("blockchain.prev block")}: setHeight(blockdetail.blockHeight - 1)} > - {blockdetail.blockHeight + 1} + {blockdetail.blockHeight - 1}
    • -
    - -
    - ) : null} -
    - -
    - - {/* */} - - - - - - - {t("blockchain.transaction.status")} - - {t("blockchain.transaction info")} - {t("common.time")} -
- } - footer={} - itemLayout="horizontal" - dataSource={translist} - className="font-s" - renderItem={(item) => ( - - - {t("blockchain.transaction.confirmed")} + ) : ( +
  • + + {t("blockchain.prev block")}: + + -- +
  • + )} + + + +
      +
    • + {t("common.size")}: + {blockdetail.size} {t("common.bytes")} +
    • +
    • + + {t("blockchain.primary index")}: + + {blockdetail.primaryIndex} +
    • +
    • + + {t("blockchain.system fee")}: + + {blockdetail.systemFee ? blockdetail.systemFee : "--"} +
    • +
    • + + {t("blockchain.witness")}: + + {blockdetail.nextConsensus} +
    • +
    • + + {t("blockchain.next block")}: - } - /> -
      -

      - {item.txId} + to={ + "/chain/detail:" + (blockdetail.blockHeight + 1) + } + onClick={() => setHeight(blockdetail.blockHeight + 1)} > + {blockdetail.blockHeight + 1} - {item.blockTime} -

      - {item.transfers[0] ? ( -
      - - {item.transfers[0].fromAddress - ? item.transfers[0].fromAddress - : "--"} - - - - {item.transfers[0].toAddress - ? item.transfers[0].toAddress - : "--"} - - - - {item.transfers[0].amount} - - {item.transfers[0].symbol} +
    • +
    + +
    + ) : null} +
    + +
    + + {/* */} + + + + + + + {t("blockchain.transaction.status")} + + {t("blockchain.transaction info")} + {t("common.time")} + + } + footer={} + itemLayout="horizontal" + dataSource={translist} + className="font-s" + renderItem={(item) => ( + + + {t("blockchain.transaction.confirmed")} + + } + /> +
    +

    + + {item.txId} + + {item.blockTime} +

    + {item.transfers?.length > 0 ? ( +
    + + {item.transfers[0].fromAddress + ? item.transfers[0].fromAddress + : "--"} + + + + {item.transfers[0].toAddress + ? item.transfers[0].toAddress + : "--"} + + + + {item.transfers[0].amount} -
    - ) : null} -
    -
    - )} - /> - -
    -
    -
    -
    - ); - } + {item.transfers[0].symbol} + + + ) : null} + + + )} + /> + +
    + + + + ); } - -export default Blockdetail; diff --git a/neo3-gui/neo3-gui/ClientApp/src/components/Transaction/transaction.js b/neo3-gui/neo3-gui/ClientApp/src/components/Transaction/transaction.js index 16ba28b7..9e714bfa 100644 --- a/neo3-gui/neo3-gui/ClientApp/src/components/Transaction/transaction.js +++ b/neo3-gui/neo3-gui/ClientApp/src/components/Transaction/transaction.js @@ -27,7 +27,7 @@ class Transaction extends React.Component { translist: [], loading: true, iswa: false, - show:false + show: false }; } componentDidMount() { @@ -44,31 +44,31 @@ class Transaction extends React.Component { this.allset(_params); } else if (page === "blockdetail") { _params.blockHeight = Number(_hash); - this.setState({params:_params}) + this.setState({ params: _params }) this.allset(_params); } else if (page === "reblockdetail") { _params.blockHeight = Number(_hash); - this.setState({params:_params}) + this.setState({ params: _params }) this.allset(_params); } else if (page === "addressdetail") { _params.address = Number(_hash); this.setState({ - params:_params, - local:"/wallet/transaction:" + params: _params, + local: "/wallet/transaction:" }) this.nepset(_params); } else if (page === "assetdetail") { _params.asset = _hash; - this.setState({params:_params}) + this.setState({ params: _params }) this.nepset(_params); } else if (page === "wallettrans") { - this.setState({local:"/wallet/transaction:"}); + this.setState({ local: "/wallet/transaction:" }); this.walletset(_params); } else if (page === "walletdetail") { - this.setState({local:"/wallet/transaction:"}); + this.setState({ local: "/wallet/transaction:" }); _params.address = _hash; this.walletset(_params); - } else{ + } else { this.allset(_params); } } @@ -121,19 +121,19 @@ class Transaction extends React.Component { "method": "GetMyTransactions", "params": params }) - .then(function (response) { - var _data = response.data; - if (_data.msgType === -1) { - message.error("查询失败"); - return; - } else { - callback(_data); - } - }) - .catch(function (error) { - console.log(error); - console.log("error"); - }); + .then(function (response) { + var _data = response.data; + if (_data.msgType === -1) { + message.error("查询失败"); + return; + } else { + callback(_data); + } + }) + .catch(function (error) { + console.log(error); + console.log("error"); + }); } getAlltrans = (params, callback) => { axios.post('http://localhost:8081', { @@ -141,20 +141,20 @@ class Transaction extends React.Component { "method": "QueryTransactions", "params": params }) - .then(function (response) { - var _data = response.data; - if (_data.msgType === -1) { - console.log(_data) - message.error("查询失败"); - return; - } else { - callback(_data); - } - }) - .catch(function (error) { - console.log(error); - console.log("error"); - }); + .then(function (response) { + var _data = response.data; + if (_data.msgType === -1) { + console.log(_data) + message.error("查询失败"); + return; + } else { + callback(_data); + } + }) + .catch(function (error) { + console.log(error); + console.log("error"); + }); }; getNeptrans = (params, callback) => { axios.post('http://localhost:8081', { @@ -162,19 +162,19 @@ class Transaction extends React.Component { "method": "QueryNep5Transactions", "params": params }) - .then(function (response) { - var _data = response.data; - if (_data.msgType === -1) { - message.error("查询失败"); - return; - } else { - callback(_data); - } - }) - .catch(function (error) { - console.log(error); - console.log("error"); - }); + .then(function (response) { + var _data = response.data; + if (_data.msgType === -1) { + message.error("查询失败"); + return; + } else { + callback(_data); + } + }) + .catch(function (error) { + console.log(error); + console.log("error"); + }); }; loadMore = () => { this.setState({ @@ -220,7 +220,7 @@ class Transaction extends React.Component { ); }); } - loadNepMore = () =>{ + loadNepMore = () => { this.setState({ loading: true, }); @@ -242,7 +242,7 @@ class Transaction extends React.Component { ); }); } - visi = () =>{ + visi = () => { this.setState({ show: !this.state.show, }); @@ -254,12 +254,12 @@ class Transaction extends React.Component { } render = () => { const { t } = this.props; - const { translist, local, loading, iswa,isnpe, page, allpage } = this.state; + const { translist, local, loading, iswa, isnpe, page, allpage } = this.state; const loadMore = !loading && page <= allpage ? (
    - {iswa ? () - :isnpe ? (): - ()} + {iswa ? () + : isnpe ? () : + ()}
    ) : null; return ( @@ -278,23 +278,25 @@ class Transaction extends React.Component { title={{t('blockchain.transaction.confirmed')}} /> */}
    -

    - {item.txId} - {item.blockTime} -

    - {item.transfers[0]? +

    + {item.txId} + {item.blockTime} +

    + {item.transfers?.length > 0 ?
    {item.transfers[0].fromAddress ? item.transfers[0].fromAddress : "--"} {item.transfers[0].toAddress ? item.transfers[0].toAddress : "--"} {item.transfers[0].amount}{item.transfers[0].symbol}
    - :null} + : null}
    )} - /> + /> {/*
    */} diff --git a/neo3-gui/neo3-gui/ClientApp/src/router/router.js b/neo3-gui/neo3-gui/ClientApp/src/router/router.js index 41abdb63..fd6512eb 100644 --- a/neo3-gui/neo3-gui/ClientApp/src/router/router.js +++ b/neo3-gui/neo3-gui/ClientApp/src/router/router.js @@ -5,11 +5,11 @@ import Sync from '../components/sync'; import Chain from '../components/Chain/chain'; import Chainlayout from '../components/Chain/chainlayout'; -import Blockdetail from '../components/Chain/blockdetail'; +import BlockDetail from '../components/Chain/blockdetail'; import Blockhashdetail from '../components/Chain/hashdetail'; import Chaintrans from '../components/Chain/trans'; -import Chainasset from '../components/Chain/asset'; -import Assetdetail from '../components/Chain/assetdetail'; +import ChainAsset from '../components/Chain/asset'; +import AssetDetail from '../components/Chain/assetdetail'; import Walletlayout from '../components/Wallet/walletlayout'; import Walletlist from '../components/Wallet/walletlist'; @@ -50,13 +50,13 @@ const BasicRoute = () => ( - + - - + + diff --git a/neo3-gui/neo3-gui/Common/Storage/TrackDB.cs b/neo3-gui/neo3-gui/Common/Storage/TrackDB.cs index 5393bdd0..7731f359 100644 --- a/neo3-gui/neo3-gui/Common/Storage/TrackDB.cs +++ b/neo3-gui/neo3-gui/Common/Storage/TrackDB.cs @@ -180,29 +180,29 @@ public void UpdateBalance(UInt160 addressHash, UInt160 assetHash, BigInteger bal - /// - /// update record will save after call method; - /// new record will save immediately - /// - /// - /// - /// - /// - public void UpdateBalanceIndex(UInt160 addressHash, AssetInfo assetInfo, BigInteger balance, uint height) - { - if (addressHash == null) return; - var address = GetOrCreateAddress(addressHash); - var asset = GetActiveContract(assetInfo.Asset); - var balanceRecord = GetOrCreateBalance(address, asset, balance, height); - - if (balanceRecord.BlockHeight >= height) - { - //no need update - return; - } - balanceRecord.Balance = balance.ToByteArray(); - balanceRecord.BlockHeight = height; - } + ///// + ///// update record will save after call method; + ///// new record will save immediately + ///// + ///// + ///// + ///// + ///// + //public void UpdateBalanceIndex(UInt160 addressHash, AssetInfo assetInfo, BigInteger balance, uint height) + //{ + // if (addressHash == null) return; + // var address = GetOrCreateAddress(addressHash); + // var asset = GetActiveContract(assetInfo.Asset); + // var balanceRecord = GetOrCreateBalance(address, asset, balance, height); + + // if (balanceRecord.BlockHeight >= height) + // { + // //no need update + // return; + // } + // balanceRecord.Balance = balance.ToByteArray(); + // balanceRecord.BlockHeight = height; + //} /// @@ -213,6 +213,10 @@ public void UpdateBalanceIndex(UInt160 addressHash, AssetInfo assetInfo, BigInte public PageList QueryTransactions(TransactionFilter filter, bool includeTransfers = false) { IQueryable query = _sqldb.Transactions; + if (includeTransfers) + { + query = query.Include(t => t.Transfers); + } if (filter.StartTime != null) { query = query.Where(r => r.Time >= filter.StartTime.Value.ToUniversalTime()); @@ -269,8 +273,38 @@ public PageList QueryTransactions(TransactionFilter filter, boo { var list = query.OrderByDescending(g => g.Time) .Skip(pageIndex * filter.PageSize) - .Take(filter.PageSize); - pageList.List.AddRange(includeTransfers ? list.Select(ToTransactionWithTransfer) : list.Select(ToTransactionWithoutTransfer)); + .Take(filter.PageSize).ToList(); + + foreach (var tx in list.ToList()) + { + var transaction = new TransactionInfo() + { + TxId = UInt256.Parse(tx.TxId), + BlockHeight = tx.BlockHeight, + Sender = tx.Sender != null ? UInt160.Parse(tx.Sender.Hash) : null, + Time = tx.Time.AsUtcTime(), + }; + if (tx.Transfers.NotEmpty()) + { + var time = tx.Time.ToTimestampMS(); + var transfers = new List(); + foreach (var t in tx.Transfers) + { + transfers.Add(new TransferInfo() + { + From = t.FromId != null ? UInt160.Parse(GetAddress(t.FromId.Value).Hash) : null, + To = t.ToId != null ? UInt160.Parse(GetAddress(t.ToId.Value).Hash) : null, + Amount = new BigInteger(t.Amount), + TxId = UInt256.Parse(t.TxId), + Asset = UInt160.Parse(GetContract(t.AssetId).Hash), + TimeStamp = time, + }); + } + + transaction.Transfers = transfers; + } + pageList.List.Add(transaction); + } } return pageList; } @@ -296,15 +330,24 @@ public PageList QueryTransactions(TransactionFilter filter, boo BlockHeight = tx.BlockHeight, Sender = tx.Sender != null ? UInt160.Parse(tx.Sender.Hash) : null, Time = tx.Time.AsUtcTime(), - Transfers = tx.Transfers.Select(t => new TransferInfo() - { - From = t.From != null ? UInt160.Parse(t.From.Hash) : null, - To = t.To != null ? UInt160.Parse(t.To.Hash) : null, - Amount = new BigInteger(t.Amount), - TxId = UInt256.Parse(t.TxId), - Asset = UInt160.Parse(t.Asset.Hash), - TimeStamp = t.Time.ToTimestampMS(), - }).ToList() + //Transfers = tx.Transfers.ToList(), + // .Select(t=>new TransferInfo(){ + // From = t.FromId != null ? UInt160.Parse(GetAddress(t.FromId.Value).Hash) : null, + // To = t.To != null ? UInt160.Parse(t.To.Hash) : null, + // Amount = new BigInteger(t.Amount), + // TxId = UInt256.Parse(t.TxId), + // Asset = UInt160.Parse(t.Asset.Hash), + // TimeStamp = t.Time.ToTimestampMS(), + //}), + //Transfers = tx.Transfers.Select(t => new TransferInfo() + //{ + // From = t.From != null ? UInt160.Parse(t.From.Hash) : null, + // To = t.To != null ? UInt160.Parse(t.To.Hash) : null, + // Amount = new BigInteger(t.Amount), + // TxId = UInt256.Parse(t.TxId), + // Asset = UInt160.Parse(t.Asset.Hash), + // TimeStamp = t.Time.ToTimestampMS(), + //}).ToList() }; @@ -538,7 +581,9 @@ public void MigrateContract(ContractEntity migrateContract) #region Private - private readonly ConcurrentDictionary _addressCache = new ConcurrentDictionary(); + private readonly ConcurrentDictionary _addressCache = new(); + private readonly ConcurrentDictionary _addressKeyCache = new(); + private AddressEntity GetOrCreateAddress(UInt160 address) { if (address == null) return null; @@ -555,6 +600,7 @@ private AddressEntity GetOrCreateAddress(UInt160 address) _sqldb.SaveChanges(); } _addressCache[address] = old; + _addressKeyCache[old.Id] = old; return old; } @@ -636,7 +682,39 @@ private TransferInfo ToNep5TransferInfo(Nep5TransferEntity entity) #endregion + #region AddressAndContractCache + + private readonly ConcurrentDictionary _contractCache = new(); + public ContractEntity GetContract(long id) + { + if (_contractCache.ContainsKey(id)) + { + return _contractCache[id]; + } + var contract = _sqldb.Contracts.FirstOrDefault(c => c.Id == id); + if (contract != null) + { + _contractCache[id] = contract; + } + return contract; + } + + + public AddressEntity GetAddress(long id) + { + if (_addressKeyCache.ContainsKey(id)) + { + return _addressKeyCache[id]; + } + var address = _sqldb.Addresses.FirstOrDefault(c => c.Id == id); + if (address != null) + { + _addressKeyCache[id] = address; + } + return address; + } + #endregion public void Dispose() diff --git a/neo3-gui/neo3-gui/Common/WebSocketHub.cs b/neo3-gui/neo3-gui/Common/WebSocketHub.cs index 5a193070..5dd47dac 100644 --- a/neo3-gui/neo3-gui/Common/WebSocketHub.cs +++ b/neo3-gui/neo3-gui/Common/WebSocketHub.cs @@ -12,14 +12,7 @@ namespace Neo.Common public class WebSocketHub { private int _limitCount = 10; - private readonly ConcurrentDictionary _clients = new ConcurrentDictionary(); - - public WebSocketHub() - { - //Task.Run(HeartBeatLoop); - } - - + private readonly ConcurrentDictionary _clients = new(); public bool Accept(WebSocketConnection connection) { @@ -69,12 +62,9 @@ private async Task HeartBeatLoop() /// public void PushAll(WsMessage msg) { - if (_clients.Any()) + foreach (var client in _clients.Keys) { - foreach (var client in _clients.Keys) - { - client.PushMessage(msg); - } + client.PushMessage(msg); } } @@ -84,6 +74,6 @@ public void StopHeartBeat() IsHeartBeating = false; } - + } } diff --git a/neo3-gui/neo3-gui/Models/Jobs/TransactionConfirmJob.cs b/neo3-gui/neo3-gui/Models/Jobs/TransactionConfirmJob.cs index 064e5365..e06769b8 100644 --- a/neo3-gui/neo3-gui/Models/Jobs/TransactionConfirmJob.cs +++ b/neo3-gui/neo3-gui/Models/Jobs/TransactionConfirmJob.cs @@ -10,9 +10,9 @@ namespace Neo.Models.Jobs { public class TransactionConfirmJob : Job { - private static readonly ConcurrentBag _confirmedTransactions = new ConcurrentBag(); + private static readonly ConcurrentBag _confirmedTransactions = new(); + - public TransactionConfirmJob(TimeSpan timeSpan) { IntervalTime = timeSpan; diff --git a/neo3-gui/neo3-gui/Services/NotificationService.cs b/neo3-gui/neo3-gui/Services/NotificationService.cs index 2ddf5a89..43bf014e 100644 --- a/neo3-gui/neo3-gui/Services/NotificationService.cs +++ b/neo3-gui/neo3-gui/Services/NotificationService.cs @@ -27,16 +27,22 @@ public async Task Start() { foreach (var job in _jobs) { - var now = DateTime.Now; - if (job.NextTriggerTime <= now) + try { - var msg = await job.Invoke(); - if (msg != null) + var now = DateTime.Now; + if (job.NextTriggerTime <= now) { - _hub.PushAll(msg); + var msg = await job.Invoke(); + if (msg != null) + { + _hub.PushAll(msg); + } + job.LastTriggerTime = now; } - - job.LastTriggerTime = now; + } + catch (Exception e) + { + Console.WriteLine($"Job Error[{job}]:{e}"); } } await Task.Delay(TimeSpan.FromSeconds(1));