diff --git a/Converter/Converter.csproj b/Converter/Converter.csproj index 844453f..e86e0f1 100644 --- a/Converter/Converter.csproj +++ b/Converter/Converter.csproj @@ -2,13 +2,13 @@ Exe - net5.0 + net7.0 - + diff --git a/Fura/Cache/Cache.cs b/Fura/Cache/Cache.cs index b397220..0ee85ed 100644 --- a/Fura/Cache/Cache.cs +++ b/Fura/Cache/Cache.cs @@ -34,12 +34,14 @@ public static DBCache Ins } public CacheAddress cacheAddress { get; } public CacheAddressAsset cacheAddressAsset { get; } + public CacheMarket cacheMarket { get; } public CacheAsset cacheAsset { get; } public CacheCandidate cacheCandidate { get; } public CacheContract cacheContract { get; } public CacheNep11TransferNotification cacheNep11TransferNotification { get; } public CacheScVoteCall cacheScVoteCall { get; } public CacheTransferNotification cacheTransferNotification; + public CacheMatketNotification cacheMatketNotification; public CacheVote cacheVote { get; } public CacheScCall cacheScCall { get; } public CacheExecution cacheExecution { get; } @@ -57,6 +59,9 @@ public DBCache() cacheAddressAsset = new CacheAddressAsset(); caches.Add(cacheAddressAsset); + cacheMarket = new CacheMarket(); + caches.Add(cacheMarket); + cacheAsset = new CacheAsset(); caches.Add(cacheAsset); @@ -75,6 +80,9 @@ public DBCache() cacheTransferNotification = new CacheTransferNotification(); caches.Add(cacheTransferNotification); + cacheMatketNotification = new CacheMatketNotification(); + caches.Add(cacheMatketNotification); + cacheVote = new CacheVote(); caches.Add(cacheVote); diff --git a/Fura/Cache/Cache_AddressAsset.cs b/Fura/Cache/Cache_AddressAsset.cs index d12eba6..212de38 100644 --- a/Fura/Cache/Cache_AddressAsset.cs +++ b/Fura/Cache/Cache_AddressAsset.cs @@ -86,7 +86,7 @@ public void AddOrUpdate(UInt160 address, UInt160 asset, BigInteger balance, stri } else { - addressAssetModel.Balance = BsonDecimal128.Create(balance.ToString()); + addressAssetModel.Balance = BsonDecimal128.Create(balance.ToString().WipeNumStrToFitDecimal128()); } D_AddressAssetModel[(address, asset, tokenid)] = addressAssetModel; } diff --git a/Fura/Cache/Cache_Asset.cs b/Fura/Cache/Cache_Asset.cs index 70fc92d..ed4ec89 100644 --- a/Fura/Cache/Cache_Asset.cs +++ b/Fura/Cache/Cache_Asset.cs @@ -85,7 +85,7 @@ public void AddOrUpdate(UInt160 contractHash, ulong firstTransferTime, string to assetModel.TokenName = tokenName; assetModel.Decimals = decimals; assetModel.Symbol = symbol; - assetModel.TotalSupply = BsonDecimal128.Create(totalSupply.ToString()); + assetModel.TotalSupply = BsonDecimal128.Create(totalSupply.ToString().WipeNumStrToFitDecimal128()); } D_AssetModel[contractHash] = assetModel; } diff --git a/Fura/Cache/Cache_Contract.cs b/Fura/Cache/Cache_Contract.cs index 30dd00c..8a038e6 100644 --- a/Fura/Cache/Cache_Contract.cs +++ b/Fura/Cache/Cache_Contract.cs @@ -14,6 +14,7 @@ public class CacheContractParams public UInt160 Hash; public ulong Time; public UInt256 Txid; + public bool IsDestroy; } public class CacheContract : IDBCache @@ -33,9 +34,9 @@ public void Clear() D_Contract = new ConcurrentDictionary(); } - public void AddNeedUpdate(UInt160 contractHash, ulong createTime, UInt256 txid) + public void AddNeedUpdate(UInt160 contractHash, ulong createTime, UInt256 txid, bool isDestroy = false) { - D_Contract[contractHash] = new() { Hash = contractHash, Time = createTime, Txid = txid }; + D_Contract[contractHash] = new() { Hash = contractHash, Time = createTime, Txid = txid , IsDestroy = isDestroy }; } public List GetNeedUpdate() @@ -48,7 +49,7 @@ public void Update(NeoSystem system, DataCache snapshot) List list = GetNeedUpdate(); Parallel.For(0, list.Count, (i) => { - AddOrUpdate(list[i].Hash, snapshot, list[i].Time, list[i].Txid); + AddOrUpdate(list[i].Hash, snapshot, list[i].Time, list[i].Txid, list[i].IsDestroy); }); } @@ -64,24 +65,21 @@ public ContractModel Get(UInt160 contractHash) } } - public void AddOrUpdate(UInt160 contractHash, DataCache snapshot, ulong createTime, UInt256 txid) + public void AddOrUpdate(UInt160 contractHash, DataCache snapshot, ulong createTime, UInt256 txid, bool isDestroy) { ContractModel contractModel = Get(contractHash); - if (contractModel is null) + + if (isDestroy) { - StorageKey key = new KeyBuilder(Neo.SmartContract.Native.NativeContract.ContractManagement.Id, 8).Add(contractHash); - ContractState contract = snapshot.TryGet(key)?.GetInteroperable(); - contractModel = new(contractHash, contract.Manifest.Name, contract.Id, contract.UpdateCounter, contract.Nef.ToJson(), contract.Manifest.ToJson(), createTime, txid); + contractModel = new ContractModel() { UpdateCounter = -1, CreateTime = createTime, Hash = contractHash, _ID = -999, CreateTxid = txid, Manifest = "", Name = "", Nef = ""}; } else { - if (contractModel.CreateTime == createTime) - return; StorageKey key = new KeyBuilder(Neo.SmartContract.Native.NativeContract.ContractManagement.Id, 8).Add(contractHash); ContractState contract = snapshot.TryGet(key)?.GetInteroperable(); - if (contractModel.UpdateCounter == contract.UpdateCounter) + if (contractModel is not null && (contract is null || contractModel.CreateTxid == txid || contractModel.UpdateCounter == contract.UpdateCounter)) return; - contractModel = new(contractHash, contract.Manifest.Name, contract.Id, contract.UpdateCounter, contract.Nef.ToJson(), contract.Manifest.ToJson(), createTime, txid); + contractModel = new(contractHash, contract.Manifest.Name, contract.Id, (short)contract.UpdateCounter, contract.Nef.ToJson(), contract.Manifest.ToJson(), createTime, txid); } D_ContractModel[contractHash] = contractModel; } diff --git a/Fura/Cache/Cache_GasMintBurn.cs b/Fura/Cache/Cache_GasMintBurn.cs index bacde1a..5a9ade0 100644 --- a/Fura/Cache/Cache_GasMintBurn.cs +++ b/Fura/Cache/Cache_GasMintBurn.cs @@ -31,11 +31,24 @@ public void Clear() public void Save(Transaction tran) { - if(GasMintBurnParams.BlockIndex > 0 || GasMintBurnParams.BurnAmount > 0 || GasMintBurnParams.MintAmount > 0) + BigInteger totalBurnAmount = 0; + BigInteger totalMintAmount = 0; + if(GasMintBurnParams.BlockIndex > 0) { - GasMintBurnModel gasMintBurnModel = new GasMintBurnModel() { BurnAmount = BsonDecimal128.Create(GasMintBurnParams.BurnAmount.ToString()), MintAmount = BsonDecimal128.Create(GasMintBurnParams.MintAmount.ToString()), BlockIndex = GasMintBurnParams.BlockIndex }; - tran.SaveAsync(gasMintBurnModel).Wait(); + //获取上一个块的total来计算本块的数据 + GasMintBurnModel gasMintBurnModel_Pre = GasMintBurnModel.Get(GasMintBurnParams.BlockIndex - 1); + totalBurnAmount = BigInteger.Parse(gasMintBurnModel_Pre.TotalBurnAmount.ToString()); + totalMintAmount = BigInteger.Parse(gasMintBurnModel_Pre.TotalMintAmount.ToString()); } + GasMintBurnModel gasMintBurnModel = new GasMintBurnModel() + { + BurnAmount = BsonDecimal128.Create(GasMintBurnParams.BurnAmount.ToString().WipeNumStrToFitDecimal128()), + TotalBurnAmount = BsonDecimal128.Create((totalBurnAmount + GasMintBurnParams.BurnAmount).ToString().WipeNumStrToFitDecimal128()), + MintAmount = BsonDecimal128.Create(GasMintBurnParams.MintAmount.ToString().WipeNumStrToFitDecimal128()), + TotalMintAmount = BsonDecimal128.Create((totalMintAmount + GasMintBurnParams.MintAmount).ToString().WipeNumStrToFitDecimal128()), + BlockIndex = GasMintBurnParams.BlockIndex + }; + tran.SaveAsync(gasMintBurnModel).Wait(); } public void Add(uint blockIndex, BigInteger burnAmount, BigInteger mintAmount) diff --git a/Fura/Cache/Cache_Market.cs b/Fura/Cache/Cache_Market.cs new file mode 100644 index 0000000..10929f5 --- /dev/null +++ b/Fura/Cache/Cache_Market.cs @@ -0,0 +1,173 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using MongoDB.Entities; +using Neo.Persistence; +using Neo.Plugins.Models; +using System.Numerics; +using System.Threading.Tasks; + +namespace Neo.Plugins.Cache +{ + public class CacheMarketParams + { + public int NotificationIndex; + public bool SimpleUpdate; + public UInt160 Owner; + public UInt160 Asset; + public string TokenId; + public BigInteger Amount; + public UInt160 Market; + public uint AuctionType; + public UInt160 Auctor; + public UInt160 AuctionAsset; + public BigInteger AuctionAmount; + public ulong Deadline; + public UInt160 Bidder; + public BigInteger BidAmount; + public BigInteger Timestamp; + } + + public class CacheMarket : IDBCache + { + private ConcurrentDictionary<(UInt160, UInt160, string), CacheMarketParams> D_Market; + + private ConcurrentDictionary<(UInt160, UInt160, string), MarketModel> D_MarketModel; + + public void AddNeedUpdate(int notificationIndex, bool simpleUpdate, UInt160 asset, UInt160 owner, string tokenid, BigInteger timestamp) + { + lock (D_Market) + { + if (!D_Market.ContainsKey((asset, owner, tokenid)) || notificationIndex > D_Market[(asset, owner, tokenid)].NotificationIndex ) + { + D_Market[(asset, owner, tokenid)] = new() + { + NotificationIndex = notificationIndex, + SimpleUpdate = simpleUpdate, + Asset = asset, + TokenId = tokenid, + Owner = owner, + Timestamp = timestamp + }; + } + } + + } + + public void AddNeedUpdate(int notificationIndex, bool simpleUpdate, UInt160 asset, UInt160 owner, string tokenid, UInt160 market, BigInteger auctionType, UInt160 auctor, UInt160 auctionAsset, BigInteger auctionAmount, BigInteger deadline, UInt160 bidder, BigInteger bidAmount, BigInteger timestamp) + { + lock (D_Market) + { + if (!D_Market.ContainsKey((asset, owner, tokenid)) || notificationIndex > D_Market[(asset, owner, tokenid)].NotificationIndex) + { + D_Market[(asset, owner, tokenid)] = new() + { + SimpleUpdate = simpleUpdate, + Asset = asset, + TokenId = tokenid, + Owner = owner, + Market = market, + AuctionType = (uint)auctionType, + Auctor = auctor, + AuctionAsset = auctionAsset, + AuctionAmount = auctionAmount, + Deadline = (ulong)deadline, + Bidder = bidder, + BidAmount = bidAmount, + Timestamp = timestamp, + NotificationIndex = notificationIndex + }; + } + } + } + + public List GetNeedUpdate() + { + return D_Market.Values.ToList(); + } + + public void Update(NeoSystem system, DataCache snapshot) + { + List list = GetNeedUpdate(); + Parallel.For(0, list.Count, (i) => + { + list[i].Amount = Neo.Plugins.VM.Helper.GetNep11BalanceOf(system, snapshot, list[i].Asset, list[i].TokenId, list[i].Owner); + AddOrUpdate(list[i]); + }); + } + + public MarketModel Get(UInt160 owner, UInt160 asset, string tokenid) + { + if (D_MarketModel.ContainsKey((owner, asset, tokenid))) + { + return D_MarketModel[(owner, asset, tokenid)]; + } + else + { + return MarketModel.Get(owner, asset, tokenid); + } + } + + public void AddOrUpdate(CacheMarketParams cacheMarketParams) + { + if (cacheMarketParams.Owner == null || cacheMarketParams.Asset == null) + return; + MarketModel marketModel = Get(cacheMarketParams.Owner, cacheMarketParams.Asset, cacheMarketParams.TokenId); + if (marketModel is null) + { + marketModel = new MarketModel() + { + Asset = cacheMarketParams.Asset, + TokenId = cacheMarketParams.TokenId, + Owner = cacheMarketParams.Owner, + Amount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.Amount.ToString().WipeNumStrToFitDecimal128()), + Market = cacheMarketParams.Market, + AuctionType = cacheMarketParams.AuctionType, + AuctionAmount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.AuctionAmount.ToString().WipeNumStrToFitDecimal128()), + AuctionAsset = cacheMarketParams.AuctionAsset, + Auctor = cacheMarketParams.Auctor, + BidAmount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.BidAmount.ToString().WipeNumStrToFitDecimal128()), + Bidder = cacheMarketParams.Bidder, + Deadline = cacheMarketParams.Deadline, + Timestamp = (ulong)cacheMarketParams.Timestamp + }; + } + else if(cacheMarketParams.SimpleUpdate) + { + marketModel.Timestamp = (ulong)cacheMarketParams.Timestamp; + marketModel.Amount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.Amount.ToString().WipeNumStrToFitDecimal128()); + } + else + { + marketModel.Asset = cacheMarketParams.Asset; + marketModel.TokenId = cacheMarketParams.TokenId; + marketModel.Owner = cacheMarketParams.Owner; + marketModel.Amount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.Amount.ToString().WipeNumStrToFitDecimal128()); + marketModel.Market = cacheMarketParams.Market; + marketModel.AuctionType = cacheMarketParams.AuctionType; + marketModel.AuctionAmount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.AuctionAmount.ToString().WipeNumStrToFitDecimal128()); + marketModel.AuctionAsset = cacheMarketParams.AuctionAsset; + marketModel.Auctor = cacheMarketParams.Auctor; + marketModel.BidAmount = MongoDB.Bson.BsonDecimal128.Create(cacheMarketParams.BidAmount.ToString().WipeNumStrToFitDecimal128()); + marketModel.Bidder = cacheMarketParams.Bidder; + marketModel.Deadline = cacheMarketParams.Deadline; + marketModel.Timestamp = (ulong)cacheMarketParams.Timestamp; + } + D_MarketModel[((marketModel.Owner, marketModel.Asset, marketModel.TokenId))] = marketModel; + } + + public void Clear() + { + D_Market = new ConcurrentDictionary<(UInt160, UInt160, string), CacheMarketParams>(); + D_MarketModel = new ConcurrentDictionary<(UInt160, UInt160, string), MarketModel>(); + } + + public void Save(Transaction tran) + { + if (D_MarketModel.Values.Count > 0) + tran.SaveAsync(D_MarketModel.Values).Wait(); + } + } +} + diff --git a/Fura/Cache/Cache_MarketNotification.cs b/Fura/Cache/Cache_MarketNotification.cs new file mode 100644 index 0000000..09a8768 --- /dev/null +++ b/Fura/Cache/Cache_MarketNotification.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using Neo.Plugins.Models; +using System.Numerics; +using MongoDB.Entities; +using System.Collections.Concurrent; +using Neo.Persistence; + +namespace Neo.Plugins.Cache +{ + public class CacheMatketNotification : IDBCache + { + private ConcurrentBag L_MarketNotificationModel; + + public CacheMatketNotification() + { + L_MarketNotificationModel = new ConcurrentBag(); + } + + public void Clear() + { + L_MarketNotificationModel = new ConcurrentBag(); + } + + public void Add(UInt256 txid, UInt256 blockHash, UInt160 market, BigInteger nonce, UInt160 user, UInt160 asset, string tokenId, string eventName, string extendData, ulong timestamp) + { + MarketNotificationModel marketNotificationModel = new(txid, blockHash, nonce, user, market, asset, tokenId, eventName, extendData, timestamp); + L_MarketNotificationModel.Add(marketNotificationModel); + } + + public void Update(NeoSystem system, DataCache snapshot) + { + } + + public void Save(Transaction tran) + { + if (L_MarketNotificationModel.Count > 0) + tran.SaveAsync(L_MarketNotificationModel).Wait(); + } + } +} diff --git a/Fura/Cache/Cache_Nep11Properties.cs b/Fura/Cache/Cache_Nep11Properties.cs index acb14d1..545b4e8 100644 --- a/Fura/Cache/Cache_Nep11Properties.cs +++ b/Fura/Cache/Cache_Nep11Properties.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Akka.Configuration.Hocon; using MongoDB.Entities; using Neo.Persistence; using Neo.Plugins.Models; +using System.Numerics; namespace Neo.Plugins.Cache { @@ -20,21 +22,33 @@ public class CacheNep11Properties : IDBCache private ConcurrentDictionary<(UInt160, string), CacheNep11PropertiesParams> D_Nep11Properties; private ConcurrentDictionary<(UInt160, string), Nep11PropertiesModel> D_Nep11PropertiesModel; + private ConcurrentDictionary<(UInt160, string), NNSPropertiesModel> D_NNSPropertiesModel; + + private ConcurrentDictionary<(UInt160, string), IlexPropertiesModel> D_IlexPropertiesModel; + + private ConcurrentDictionary<(UInt160, string), MetaPropertiesModel> D_MetaPropertiesModel; + public CacheNep11Properties() { D_Nep11Properties = new ConcurrentDictionary<(UInt160, string), CacheNep11PropertiesParams>(); D_Nep11PropertiesModel = new ConcurrentDictionary<(UInt160, string), Nep11PropertiesModel>(); + D_NNSPropertiesModel = new ConcurrentDictionary<(UInt160, string), NNSPropertiesModel>(); + D_IlexPropertiesModel = new ConcurrentDictionary<(UInt160, string), IlexPropertiesModel>(); + D_MetaPropertiesModel = new ConcurrentDictionary<(UInt160, string), MetaPropertiesModel>(); } public void Clear() { D_Nep11Properties = new ConcurrentDictionary<(UInt160, string), CacheNep11PropertiesParams>(); D_Nep11PropertiesModel = new ConcurrentDictionary<(UInt160, string), Nep11PropertiesModel>(); + D_NNSPropertiesModel = new ConcurrentDictionary<(UInt160, string), NNSPropertiesModel>(); + D_IlexPropertiesModel = new ConcurrentDictionary<(UInt160, string), IlexPropertiesModel>(); + D_MetaPropertiesModel = new ConcurrentDictionary<(UInt160, string), MetaPropertiesModel>(); } - public void AddNeedUpdate( UInt160 asset, string tokenid) + public void AddNeedUpdate(UInt160 asset, string tokenid) { - D_Nep11Properties[(asset, tokenid)] = new() {Asset = asset, Tokenid = tokenid }; + D_Nep11Properties[(asset, tokenid)] = new() { Asset = asset, Tokenid = tokenid }; } public List GetNeedUpdate() @@ -49,7 +63,8 @@ public void Update(NeoSystem system, DataCache snapshot) { //从vm中获取properties var properties = Neo.Plugins.VM.Helper.GetNep11Properties(system, snapshot, list[i].Asset, list[i].Tokenid); - AddOrUpdate(list[i].Asset, list[i].Tokenid, properties); + var isSelfControl = Neo.Plugins.VM.Helper.IsSelfControl(system, snapshot, list[i].Asset); + AddOrUpdate(list[i].Asset, list[i].Tokenid, properties, isSelfControl); }); } @@ -65,7 +80,60 @@ public Nep11PropertiesModel Get(UInt160 asset, string tokenid) } } - public void AddOrUpdate(UInt160 asset, string tokenid, string properties) + public IlexPropertiesModel GetIlex(UInt160 asset, string tokenid) + { + if (D_IlexPropertiesModel.ContainsKey((asset, tokenid))) + { + return D_IlexPropertiesModel[(asset, tokenid)]; + } + else + { + return IlexPropertiesModel.Get(asset, tokenid); + } + } + + public MetaPropertiesModel GetMeta(UInt160 asset, string tokenid) + { + if (D_MetaPropertiesModel.ContainsKey((asset, tokenid))) + { + return D_MetaPropertiesModel[(asset, tokenid)]; + } + else + { + return MetaPropertiesModel.Get(asset, tokenid); + } + } + + public NNSPropertiesModel GetNNS(UInt160 asset, string tokenid) + { + if (D_NNSPropertiesModel.ContainsKey((asset, tokenid))) + { + return D_NNSPropertiesModel[(asset, tokenid)]; + } + else + { + return NNSPropertiesModel.Get(asset, tokenid); + } + } + + public void AddOrUpdate(UInt160 asset, string tokenid, string properties, BigInteger selfControl) + { + AddOrUpdateNep11(asset, tokenid, properties); + if (Settings.Default.IlexContractHashes.Contains(asset.ToString()) || selfControl == 1) + { + AddOrUpdateIlex(asset, tokenid, properties); + } + if (Settings.Default.MetaContractHashes.Contains(asset.ToString()) || selfControl == 2) + { + AddOrUpdateMeta(asset, tokenid, properties); + } + if (Settings.Default.NNS == asset.ToString()) + { + AddOrUpdateNNS(asset, tokenid, properties); + } + } + + private void AddOrUpdateNep11(UInt160 asset, string tokenid, string properties) { Nep11PropertiesModel nep11PropertiesModel = Get(asset, tokenid); if (nep11PropertiesModel is null) @@ -79,10 +147,58 @@ public void AddOrUpdate(UInt160 asset, string tokenid, string properties) D_Nep11PropertiesModel[(asset, tokenid)] = nep11PropertiesModel; } + private void AddOrUpdateIlex(UInt160 asset, string tokenid, string properties) + { + IlexPropertiesModel ilexPropertiesModel = GetIlex(asset, tokenid); + if (ilexPropertiesModel is null) + { + ilexPropertiesModel = new(asset, tokenid, properties); + } + else + { + ilexPropertiesModel.UpdateProperties(properties); + } + D_IlexPropertiesModel[(asset, tokenid)] = ilexPropertiesModel; + } + + private void AddOrUpdateMeta(UInt160 asset, string tokenid, string properties) + { + MetaPropertiesModel metaPropertiesModel = GetMeta(asset, tokenid); + if (metaPropertiesModel is null) + { + metaPropertiesModel = new(asset, tokenid, properties); + } + else + { + metaPropertiesModel.UpdateProperties(properties); + } + D_MetaPropertiesModel[(asset, tokenid)] = metaPropertiesModel; + } + + private void AddOrUpdateNNS(UInt160 asset, string tokenid, string properties) + { + NNSPropertiesModel nnsPropertiesModel = GetNNS(asset, tokenid); + if (nnsPropertiesModel is null) + { + nnsPropertiesModel = new(asset, tokenid, properties); + } + else + { + nnsPropertiesModel.Properties = properties; + } + D_NNSPropertiesModel[(asset, tokenid)] = nnsPropertiesModel; + } + public void Save(Transaction tran) { if (D_Nep11PropertiesModel.Values.Count > 0) tran.SaveAsync(D_Nep11PropertiesModel.Values).Wait(); + if (D_IlexPropertiesModel.Values.Count > 0) + tran.SaveAsync(D_IlexPropertiesModel.Values).Wait(); + if (D_MetaPropertiesModel.Values.Count > 0) + tran.SaveAsync(D_MetaPropertiesModel.Values).Wait(); + if (D_NNSPropertiesModel.Values.Count > 0) + tran.SaveAsync(D_NNSPropertiesModel.Values).Wait(); } } } diff --git a/Fura/DB/MongoClient.cs b/Fura/DB/MongoClient.cs index 6746716..bff6522 100644 --- a/Fura/DB/MongoClient.cs +++ b/Fura/DB/MongoClient.cs @@ -35,7 +35,7 @@ public static async Task InitDB(string dbName, string url) public static async Task InitCollectionAndIndex() { - var assembly = Assembly.Load(File.ReadAllBytes("Plugins/Fura.dll")); + var assembly = Assembly.Load(File.ReadAllBytes("Plugins/Fura/Fura.dll")); foreach (Type type in assembly.ExportedTypes) { diff --git a/Fura/Fura.cs b/Fura/Fura.cs index c620ee5..48ec0bd 100644 --- a/Fura/Fura.cs +++ b/Fura/Fura.cs @@ -13,15 +13,29 @@ using System.Threading.Tasks; using System.IO; using System.Reflection; +using Neo.Plugins.Notification; namespace Neo.Plugins { - public class Fura : Plugin, IPersistencePlugin + public class Fura : Plugin { public override string Name => "Fura"; public override string Description => "Analyze the data and store it in MongoDB"; + public Fura() + { + Blockchain.Committing += OnCommitting; + Blockchain.Committed += OnCommitted; + } + + + public override void Dispose() + { + Blockchain.Committing -= OnCommitting; + Blockchain.Committed -= OnCommitted; + } + protected override void Configure() { Settings.Load(GetConfiguration()); @@ -42,8 +56,9 @@ protected override void OnSystemLoaded(NeoSystem system) MongoClient.InitBasicData(system).Wait(); } - void IPersistencePlugin.OnPersist(NeoSystem system, Block block, DataCache snapshot, IReadOnlyList applicationExecutedList) + void OnCommitting(NeoSystem system, Block block, DataCache snapshot, IReadOnlyList applicationExecutedList) { + Loger.Common(string.Format("OnPersist------ {0} 高度的数据正在录入-- 总计有{1}比交易", block.Index, applicationExecutedList.Count)); bool loop = true; uint errLoopTimes = 0; while (loop) @@ -68,9 +83,18 @@ void IPersistencePlugin.OnPersist(NeoSystem system, Block block, DataCache snaps { Parallel.For(0, applicationExecutedList.Count, (i) => { - ExecApplicationExecuted(applicationExecutedList[i], system, block, snapshot); + try + { + ExecApplicationExecuted(applicationExecutedList[i], system, block, snapshot); + } + catch (Exception e) + { + DebugModel debugModel = new(e.Message); + debugModel.SaveAsync().Wait(); + } }); } + Loger.Common(String.Format("application exec done")); //标记此块已经结束 RecordPersistModel recordPersistModel = RecordPersistModel.Get(block.Index); recordPersistModel.State = EnumRecordState.Confirm.ToString(); @@ -88,12 +112,13 @@ void IPersistencePlugin.OnPersist(NeoSystem system, Block block, DataCache snaps errLoopTimes++; DebugModel debugModel = new(string.Format("{0}---ExecApplicationExecuted----block: {1}, loopTimes:{2}, error: {3}", Settings.Default.PName, block.Index, errLoopTimes, e)); debugModel.SaveAsync().Wait(); - if (errLoopTimes < 100) + if (errLoopTimes < 30) { System.Threading.Thread.Sleep(Settings.Default.SleepTime * 100); } else { + loop = false; throw; } } @@ -109,8 +134,9 @@ void IPersistencePlugin.OnPersist(NeoSystem system, Block block, DataCache snaps } } - void IPersistencePlugin.OnCommit(NeoSystem system, Block block, DataCache snapshot) + void OnCommitted(NeoSystem system, Block block) { + Loger.Common(string.Format("OnCommit------ {0} 高度的数据正在录入", block.Index)); bool loop = true; uint errLoopTimes = 0; while (loop) @@ -128,7 +154,7 @@ void IPersistencePlugin.OnCommit(NeoSystem system, Block block, DataCache snapsh { try { - ExecBlock(transaction, system, block, snapshot); + ExecBlock(transaction, system, block); var time1 = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; Loger.Common(string.Format("OnCommit------ {0} 高度的数据录入耗时 {1} ms", block.Index, time1 - time0)); loop = false; @@ -248,7 +274,7 @@ void ExecApplicationExecuted(Blockchain.ApplicationExecuted applicationExecuted, if(executionModel.VmState == "HALT") { //通过解析script得到调用了哪些合约哪些方法,从而处理一些特殊数据 - list_ScCall = VM.Helper.Script2ScCallModels(applicationExecuted.Transaction.Script, applicationExecuted.Transaction.Hash, applicationExecuted.Transaction.Sender, applicationExecuted.VMState.ToString()); + list_ScCall = VM.Helper.Script2ScCallModels(applicationExecuted.Transaction.Script.ToArray(), applicationExecuted.Transaction.Hash, applicationExecuted.Transaction.Sender, applicationExecuted.VMState.ToString()); } } else @@ -270,14 +296,14 @@ void ExecApplicationExecuted(Blockchain.ApplicationExecuted applicationExecuted, var notificationModel = new NotificationModel(executionModel.Txid, i, executionModel.BlockHash, executionModel.Timestamp, n.ScriptHash, n.EventName, executionModel.VmState, n.State); notificationModels.Add(notificationModel); } - if (notificationModels.Count > 0) + if (notificationModels.Count > 0 && notificationModels.Count < 1500) { DBCache.Ins.cacheNotification.Add(notificationModels); NotificationMgr.Ins.Filter(notificationModels, system, block, snapshot); } } - void ExecBlock(MongoDB.Entities.Transaction transaction, NeoSystem system, Block block, DataCache snapshot) + void ExecBlock(MongoDB.Entities.Transaction transaction, NeoSystem system, Block block) { //如果这个高度的block数据能在数据库中查到,证明已经录入过了(防止重启重录) BlockModel blockModel = BlockModel.Get(block.Hash); @@ -318,21 +344,24 @@ void ExecBlock(MongoDB.Entities.Transaction transaction, NeoSystem system, Block candidateModel_old = candidateModel_old.Select(c => { c.IsCommittee = false; return c; }).ToList(); transaction.SaveAsync(candidateModel_old).Wait(); } - //更新新的一批次 - ECPoint[] committees = Neo.SmartContract.Native.NeoToken.NEO.GetCommittee(snapshot); - CandidateModel[] candidateModels_new = committees.Select(c => + using(var snapshot = system.GetSnapshot()) { - var hash = Contract.CreateSignatureContract(c).ScriptHash; - var candidateModel = CandidateModel.Get(hash); - if (candidateModel is null) + //更新新的一批次 + ECPoint[] committees = Neo.SmartContract.Native.NeoToken.NEO.GetCommittee(snapshot); + CandidateModel[] candidateModels_new = committees.Select(c => { - var votes = Neo.Plugins.VM.Helper.GetCandidateVotes(c, system, snapshot); - candidateModel = new CandidateModel(hash, false, votes.ToString(), true); - } - candidateModel.IsCommittee = true; - return candidateModel; - }).ToArray(); - transaction.SaveAsync(candidateModels_new).Wait(); + var hash = Contract.CreateSignatureContract(c).ScriptHash; + var candidateModel = CandidateModel.Get(hash); + if (candidateModel is null) + { + var votes = Neo.Plugins.VM.Helper.GetCandidateVotes(c, system, snapshot); + candidateModel = new CandidateModel(hash, false, votes.ToString(), true); + } + candidateModel.IsCommittee = true; + return candidateModel; + }).ToArray(); + transaction.SaveAsync(candidateModels_new).Wait(); + } } //将此块的record标记为完成 diff --git a/Fura/Fura.csproj b/Fura/Fura.csproj index 9433b05..d8434c2 100644 --- a/Fura/Fura.csproj +++ b/Fura/Fura.csproj @@ -1,11 +1,11 @@ - net5.0 + net7.0 Neo.Plugins - + @@ -14,21 +14,15 @@ + - + - + - - - - - - - PreserveNewest @@ -37,4 +31,7 @@ + + + diff --git a/Fura/Fura/config.json b/Fura/Fura/config.json index d1bb5a6..7e82269 100644 --- a/Fura/Fura/config.json +++ b/Fura/Fura/config.json @@ -8,6 +8,12 @@ "Log": false, "SleepTime": 10, "WaitTime": 120, - "ConnectionString": "" + "ConnectionString": "", + "MarketContractIds": [ 0, 0 ], + "Nep11ContractIds": [], + "Nep17ContractIds": [], + "IlexContractHashes": [], + "MetaContractHashes": [], + "NNS": "" } } diff --git a/Fura/Helper.cs b/Fura/Helper.cs new file mode 100644 index 0000000..9cb9416 --- /dev/null +++ b/Fura/Helper.cs @@ -0,0 +1,25 @@ +using System; +using System.Numerics; +using MongoDB.Bson; + +namespace Neo.Plugins +{ + public static class Helper + { + public static string WipeNumStrToFitDecimal128(this string str) + { + if(BigInteger.TryParse(str, out BigInteger bigint)) + { + var maxLength = 34; + if (str.Length > maxLength) + { + var t = bigint / (BigInteger)Math.Pow(10, str.Length - maxLength); + t = t * (BigInteger)Math.Pow(10, str.Length - maxLength); + str = t.ToString(); + } + } + return str; + } + } +} + diff --git a/Fura/Models/AddressAssetModel.cs b/Fura/Models/AddressAssetModel.cs index 16e7cf0..9a2b650 100644 --- a/Fura/Models/AddressAssetModel.cs +++ b/Fura/Models/AddressAssetModel.cs @@ -52,6 +52,8 @@ public async static Task InitCollectionAndIndex() await DB.Index().Key(a => a.Balance, KeyType.Ascending).Key(a => a.Asset, KeyType.Ascending).Option(o => { o.Name = "_balance_asset_"; }).CreateAsync(); await DB.Index().Key(a => a.Balance, KeyType.Ascending).Key(a => a.Address, KeyType.Ascending).Option(o => { o.Name = "_balance_address_"; }).CreateAsync(); await DB.Index().Key(a => a.Address, KeyType.Ascending).Option(o => { o.Name = "_address_"; }).CreateAsync(); + await DB.Index().Key(a => a.Balance, KeyType.Ascending).Option(o => { o.Name = "_balance_"; }).CreateAsync(); + await DB.Index().Key(a => a.Asset, KeyType.Ascending).Option(o => { o.Name = "_asset_"; }).CreateAsync(); } } } diff --git a/Fura/Models/AssetModel.cs b/Fura/Models/AssetModel.cs index eb6c034..e06e8e0 100644 --- a/Fura/Models/AssetModel.cs +++ b/Fura/Models/AssetModel.cs @@ -53,7 +53,7 @@ public AssetModel(UInt160 hash,ulong firstTransferTime, string tokenName, byte d TokenName = tokenName; Decimals = decimals; Symbol = symbol; - TotalSupply = BsonDecimal128.Create(totalSupply.ToString()); + TotalSupply = BsonDecimal128.Create(totalSupply.ToString().WipeNumStrToFitDecimal128()); Type = enumAssetType.ToString(); } diff --git a/Fura/Models/ContractModel.cs b/Fura/Models/ContractModel.cs index 4dbca53..e59fc38 100644 --- a/Fura/Models/ContractModel.cs +++ b/Fura/Models/ContractModel.cs @@ -3,7 +3,7 @@ using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; using MongoDB.Entities; -using Neo.IO.Json; +using Neo.Json; using Neo.Plugins.Attribute; namespace Neo.Plugins.Models @@ -19,7 +19,7 @@ public class ContractModel : Entity public int _ID { get; set; } [BsonElement("updatecounter")] - public ushort UpdateCounter { get; set; } + public short UpdateCounter { get; set; } [BsonElement("nef")] public BsonString Nef { get; set; } @@ -39,7 +39,7 @@ public class ContractModel : Entity public ContractModel() { } - public ContractModel(UInt160 hash,string name, int id, ushort updateCounter, JObject nef,JObject manifest, ulong createTime, UInt256 txid) + public ContractModel(UInt160 hash,string name, int id, short updateCounter, JObject nef,JObject manifest, ulong createTime, UInt256 txid) { Hash = hash; Name = name; @@ -53,7 +53,7 @@ public ContractModel(UInt160 hash,string name, int id, ushort updateCounter, JOb public static ContractModel Get(UInt160 hash) { - ContractModel contractModel = DB.Find().Match(c => c.Hash == hash).ExecuteFirstAsync().Result; + ContractModel contractModel = DB.Find().Match(c => c.Hash == hash).Sort(c => c.CreateTime, Order.Descending).ExecuteFirstAsync().Result; return contractModel; } @@ -61,7 +61,8 @@ public async static Task InitCollectionAndIndex() { await DB.CreateCollection(new CreateCollectionOptions()); await DB.Index().Key(a => a.Hash, KeyType.Ascending).Option(o => { o.Name = "_hash_"; }).CreateAsync(); - await DB.Index().Key(a => a.Hash, KeyType.Ascending).Key(a => a.UpdateCounter, KeyType.Ascending).Option(o => { o.Name = "_hash_updatecounter_unique_"; o.Unique = true; }).CreateAsync(); + await DB.Index().Key(a => a.CreateTime, KeyType.Descending).Option(o => { o.Name = "_createtime_"; }).CreateAsync(); + await DB.Index().Key(a => a.Hash, KeyType.Ascending).Key(a => a.UpdateCounter, KeyType.Ascending).Key(a => a.CreateTxid, KeyType.Ascending).Option(o => { o.Name = "_hash_updatecounter_createtxid_unique_"; o.Unique = true; }).CreateAsync(); } } } diff --git a/Fura/Models/ExecutionModel.cs b/Fura/Models/ExecutionModel.cs index 041fbc1..628ddd6 100644 --- a/Fura/Models/ExecutionModel.cs +++ b/Fura/Models/ExecutionModel.cs @@ -48,7 +48,24 @@ public ExecutionModel(UInt256 txid, UInt256 blockHash, ulong timestamp, string t Exception = exception; GasConsumed = gasconsumed; Timestamp = timestamp; - Stacks = stack.Select(p => p.ToJson().ToString()).ToArray(); + if(stack.Length < 500) + { + Stacks = stack.Select(p => + { + try + { + return p.ToJson().ToString(); + } + catch + { + return ""; + } + }).ToArray(); + } + else + { + Stacks = new string[] { }; + } } public static ExecutionModel Get(UInt256 txid,UInt256 blockHash, string trigger) diff --git a/Fura/Models/GasMintBurnModel.cs b/Fura/Models/GasMintBurnModel.cs index 2b63bdf..5abc477 100644 --- a/Fura/Models/GasMintBurnModel.cs +++ b/Fura/Models/GasMintBurnModel.cs @@ -13,9 +13,15 @@ public class GasMintBurnModel : Entity [BsonElement("burnAmount")] public BsonDecimal128 BurnAmount { get; set; } + [BsonElement("totalBurnAmount")] + public BsonDecimal128 TotalBurnAmount { get; set; } + [BsonElement("mintAmount")] public BsonDecimal128 MintAmount { get; set; } + [BsonElement("totalMintAmount")] + public BsonDecimal128 TotalMintAmount { get; set; } + [BsonElement("blockIndex")] public uint BlockIndex { get; set; } @@ -23,6 +29,12 @@ public GasMintBurnModel() { } + public static GasMintBurnModel Get(uint BlockIndex) + { + GasMintBurnModel gasMintBurnModel = DB.Find().Match(g => g.BlockIndex == BlockIndex).ExecuteFirstAsync().Result; + return gasMintBurnModel; + } + public async static Task InitCollectionAndIndex() { await DB.CreateCollection(new CreateCollectionOptions()); diff --git a/Fura/Models/HeaderModel.cs b/Fura/Models/HeaderModel.cs index 0255aa5..26b14db 100644 --- a/Fura/Models/HeaderModel.cs +++ b/Fura/Models/HeaderModel.cs @@ -79,8 +79,8 @@ public class WitnessModel public WitnessModel(Witness witness) { - Invocation_B64String = Convert.ToBase64String(witness.InvocationScript); - Verification_B64String = Convert.ToBase64String(witness.VerificationScript); + Invocation_B64String = Convert.ToBase64String(witness.InvocationScript.ToArray()); + Verification_B64String = Convert.ToBase64String(witness.VerificationScript.ToArray()); } public static WitnessModel[] ToModels(Witness[] witnesses) diff --git a/Fura/Models/IlexPropertiesModel.cs b/Fura/Models/IlexPropertiesModel.cs new file mode 100644 index 0000000..bd432bd --- /dev/null +++ b/Fura/Models/IlexPropertiesModel.cs @@ -0,0 +1,71 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using MongoDB.Entities; +using Neo.Network.P2P.Payloads; +using Neo.Plugins.Attribute; +using static System.Net.Mime.MediaTypeNames; + +namespace Neo.Plugins.Models +{ + [Collection("SelfControlNep11Properties")] + public class IlexPropertiesModel : Entity + { + [UInt160AsString] + [BsonElement("asset")] + public UInt160 Asset { get; set; } + + [BsonElement("tokenid")] + public string TokenId { get; set; } + + [BsonElement("properties")] + public string Properties { get; set; } + + [BsonElement("name")] + public string Name { get; set; } + + [BsonElement("tokenURI")] + public string TokenURI { get; set; } + + public IlexPropertiesModel() { } + + public IlexPropertiesModel(UInt160 asset, string tokenid, string properties) + { + Asset = asset; + TokenId = tokenid; + Properties = properties; + try + { + Json.JObject jObject = (Json.JObject)Json.JObject.Parse(properties); + Name = jObject["name"].GetString(); + TokenURI = jObject["tokenURI"].GetString(); + } + catch + { + + } + } + + public void UpdateProperties(string properties) + { + Properties = Properties; + try + { + Json.JObject jObject = (Json.JObject)Json.JObject.Parse(properties); + Name = jObject["name"].GetString(); + TokenURI = jObject["tokenURI"].GetString(); + } + catch + { + + } + } + + public static IlexPropertiesModel Get(UInt160 asset, string tokenid) + { + IlexPropertiesModel model = DB.Find().Match(a => a.Asset == asset && a.TokenId == tokenid).ExecuteFirstAsync().Result; + return model; + } + } +} diff --git a/Fura/Models/MarketModel.cs b/Fura/Models/MarketModel.cs new file mode 100644 index 0000000..97f4029 --- /dev/null +++ b/Fura/Models/MarketModel.cs @@ -0,0 +1,302 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using MongoDB.Entities; +using Neo.Plugins.Attribute; +using System.Numerics; +using System.Threading.Tasks; + +namespace Neo.Plugins.Models +{ + [Collection("Market")] + public class MarketModel : Entity + { + [UInt160AsString] + [BsonElement("asset")] + public UInt160 Asset { get; set; } + + [BsonElement("tokenid")] + public string TokenId { get; set; } + + [BsonElement("amount")] + public BsonDecimal128 Amount { get; set; } + + [UInt160AsString] + [BsonElement("owner")] + public UInt160 Owner { get; set; } + + [UInt160AsString] + [BsonElement("market")] + public UInt160 Market { get; set; } + + [BsonElement("auctionType")] + public uint AuctionType { get; set; } + + [UInt160AsString] + [BsonElement("auctor")] + public UInt160 Auctor { get; set; } + + [UInt160AsString] + [BsonElement("auctionAsset")] + public UInt160 AuctionAsset { get; set; } + + [BsonElement("auctionAmount")] + public BsonDecimal128 AuctionAmount { get; set; } + + [BsonElement("deadline")] + public ulong Deadline { get; set; } + + [UInt160AsString] + [BsonElement("bidder")] + public UInt160 Bidder { get; set; } + + [BsonElement("bidAmount")] + public BsonDecimal128 BidAmount { get; set; } + + [BsonElement("timestamp")] + public ulong Timestamp; + + public static MarketModel Get(UInt160 owner, UInt160 asset, string tokenid) + { + MarketModel marketModel = DB.Find().Match(a => a.Owner == owner && a.Asset == asset && a.TokenId == tokenid).ExecuteFirstAsync().Result; + return marketModel; + } + + public static void Delete(UInt160 owner, UInt160 asset, string tokenid) + { + } + + public async static Task InitCollectionAndIndex() + { + await DB.CreateCollection(new CreateCollectionOptions()); + + await DB.Index() + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Option(o => { o.Name = "_tokenid_amount_auctionType_asset_market_deadline_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_asset_tokenid_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Option(o => { o.Name = "_asset_market_amount_owner_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_market_owner_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_market_auctionType_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Option(o => { o.Name = "_asset_amount_tokenid_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_amount_auctionType_deadline_asset_tokenid_market_owner_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Option(o => { o.Name = "_auctionType_deadline_asset_amount_tokenid_market_owner_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_market_asset_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_amount_auctor_auctionType_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_amount_auctor_auctionType_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.AuctionType, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_amount_auctor_auctionType_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_deadline_owner_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_deadline_owner_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_deadline_owner_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Option(o => { o.Name = "_owner_market_amount_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_auctor_bidAmount_amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_auctor_bidAmount__amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_auctor_bidAmount_amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Bidder, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_bidder_bidAmount_amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Bidder, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_bidder_bidAmount_amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Bidder, KeyType.Ascending) + .Key(a => a.BidAmount, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_bidder_bidAmount_amount_deadline_owner_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_asset_auctionAsset_deadline_auctor_owner_amount_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.AuctionAsset, KeyType.Ascending) + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_auctionAsset_deadline_auctor_owner_amount_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Deadline, KeyType.Ascending) + .Key(a => a.Auctor, KeyType.Ascending) + .Key(a => a.Owner, KeyType.Ascending) + .Key(a => a.Amount, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_deadline_auctor_owner_amount_market_"; }).CreateAsync(); + + } + } +} diff --git a/Fura/Models/MetaPropertiesModel.cs b/Fura/Models/MetaPropertiesModel.cs new file mode 100644 index 0000000..e994d8f --- /dev/null +++ b/Fura/Models/MetaPropertiesModel.cs @@ -0,0 +1,91 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using MongoDB.Entities; +using Neo.Network.P2P.Payloads; +using Neo.Plugins.Attribute; + +namespace Neo.Plugins.Models +{ + [Collection("SelfControlNep11Properties")] + public class MetaPropertiesModel : Entity + { + [UInt160AsString] + [BsonElement("asset")] + public UInt160 Asset { get; set; } + + [BsonElement("tokenid")] + public string TokenId { get; set; } + + [BsonElement("properties")] + public string Properties { get; set; } + + [BsonElement("name")] + public string Name { get; set; } + + [BsonElement("image")] + public string Image { get; set; } + + [BsonElement("series")] + public string Series { get; set; } + + [BsonElement("supply")] + public string Supply { get; set; } + + [BsonElement("thumbnail")] + public string Thumbnail { get; set; } + + public MetaPropertiesModel() { } + + public MetaPropertiesModel(UInt160 asset, string tokenid, string properties) + { + Asset = asset; + TokenId = tokenid; + Properties = properties; + try + { + Json.JObject jObject = (Json.JObject)Json.JObject.Parse(properties); + Name = jObject["name"].GetString(); + Image = jObject["image"].GetString(); + Series = jObject["series"].GetString(); + Supply = jObject["supply"].GetString(); + Thumbnail = jObject["thumbnail"].GetString(); + } + catch + { + + } + } + + public void UpdateProperties(string properties) + { + Properties = Properties; + try + { + Json.JObject jObject = (Json.JObject)Json.JObject.Parse(properties); + Name = jObject["name"].GetString(); + Image = jObject["image"].GetString(); + Series = jObject["series"].GetString(); + Supply = jObject["supply"].GetString(); + Thumbnail = jObject["thumbnail"].GetString(); + } + catch + { + + } + } + + public static MetaPropertiesModel Get(UInt160 asset, string tokenid) + { + MetaPropertiesModel model = DB.Find().Match(a => a.Asset == asset && a.TokenId == tokenid).ExecuteFirstAsync().Result; + return model; + } + + public async static Task InitCollectionAndIndex() + { + await DB.CreateCollection(new CreateCollectionOptions()); + await DB.Index().Key(a => a.Asset, KeyType.Ascending).Key(a => a.TokenId, KeyType.Ascending).Option(o => { o.Name = "_asset_tokenid_unique_"; o.Unique = true; }).CreateAsync(); + } + } +} diff --git a/Fura/Models/NNSPropertiesModel.cs b/Fura/Models/NNSPropertiesModel.cs new file mode 100644 index 0000000..82d3cc6 --- /dev/null +++ b/Fura/Models/NNSPropertiesModel.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using MongoDB.Entities; +using Neo.Network.P2P.Payloads; +using Neo.Plugins.Attribute; + +namespace Neo.Plugins.Models +{ + [Collection("SelfControlNep11Properties")] + public class NNSPropertiesModel : Entity + { + [UInt160AsString] + [BsonElement("asset")] + public UInt160 Asset { get; set; } + + [BsonElement("tokenid")] + public string TokenId { get; set; } + + [BsonElement("properties")] + public string Properties { get; set; } + + public NNSPropertiesModel() { } + + public NNSPropertiesModel(UInt160 asset, string tokenid, string properties) + { + Asset = asset; + TokenId = tokenid; + Properties = properties; + } + + public static NNSPropertiesModel Get(UInt160 asset, string tokenid) + { + NNSPropertiesModel nnsPropertiesModel = DB.Find().Match(a => a.Asset == asset && a.TokenId == tokenid).ExecuteFirstAsync().Result; + return nnsPropertiesModel; + } + } +} diff --git a/Fura/Models/Notification/MarketNotificationModel.cs b/Fura/Models/Notification/MarketNotificationModel.cs new file mode 100644 index 0000000..08c63ca --- /dev/null +++ b/Fura/Models/Notification/MarketNotificationModel.cs @@ -0,0 +1,150 @@ +using System.Numerics; +using System.Threading.Tasks; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using MongoDB.Entities; +using Neo.Plugins.Attribute; + +namespace Neo.Plugins.Models +{ + [Collection("MarketNotification")] + public class MarketNotificationModel : Entity + { + [BsonElement("nonce")] + public ulong Nonce { get; set; } + + [UInt256AsString] + [BsonElement("txid")] + public UInt256 Txid { get; set; } + + [UInt256AsString] + [BsonElement("blockhash")] + public UInt256 BlockHash { get; set; } + + [UInt160AsString] + [BsonElement("user")] + public UInt160 User { get; set; } + + [UInt160AsString] + [BsonElement("market")] + public UInt160 Market { get; set; } + + [UInt160AsString] + [BsonElement("asset")] + public UInt160 Asset { get; set; } + + [BsonElement("tokenid")] + public string TokenId { get; set; } + + [BsonElement("eventname")] + public string EventName { get; set; } + + [BsonElement("extendData")] + public string ExtendData { get; set; } + + [BsonElement("timestamp")] + public ulong Timestamp { get; set; } + + public MarketNotificationModel(UInt256 txid, UInt256 blockhash, BigInteger nonce, UInt160 user, UInt160 market, UInt160 asset, string tokenId, string eventName, string extendData, ulong timestamp) + { + Nonce = (ulong)nonce; + Txid = txid; + BlockHash = blockhash; + User = user; + Market = market; + Asset = asset; + TokenId = tokenId; + EventName = eventName; + ExtendData = extendData; + Timestamp = timestamp; + } + + public async static Task InitCollectionAndIndex() + { + await DB.CreateCollection(new CreateCollectionOptions()); + + await DB.Index() + .Key(a => a.Nonce, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_nonce_asset_tokenid_eventname_timestamp_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Nonce, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_nonce_asset_eventname_timestamp_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Nonce, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Key(a => a.User, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_nonce_asset_eventname_timestamp_user_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Nonce, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.User, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_nonce_asset_user_eventname_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Nonce, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.User, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_nonce_asset_user_eventname_tokenid_market_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Option(o => { o.Name = "_eventname_market_asset_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.EventName, KeyType.Ascending) + .Option(o => { o.Name = "_asset_tokenid_market_eventname_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Option(o => { o.Name = "_market_timestamp_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.User, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Option(o => { o.Name = "_user_market_timestamp_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Option(o => { o.Name = "_eventname_asset_tokenid_timestamp_"; }).CreateAsync(); + + await DB.Index() + .Key(a => a.EventName, KeyType.Ascending) + .Key(a => a.Asset, KeyType.Ascending) + .Key(a => a.TokenId, KeyType.Ascending) + .Key(a => a.Timestamp, KeyType.Ascending) + .Key(a => a.Market, KeyType.Ascending) + .Option(o => { o.Name = "_eventname_asset_tokenid_market_timestamp_"; }).CreateAsync(); + } + } +} diff --git a/Fura/Models/Notification/Nep11TransferNotificationModel.cs b/Fura/Models/Notification/Nep11TransferNotificationModel.cs index 13f3966..673c398 100644 --- a/Fura/Models/Notification/Nep11TransferNotificationModel.cs +++ b/Fura/Models/Notification/Nep11TransferNotificationModel.cs @@ -56,9 +56,9 @@ public Nep11TransferNotificationModel(UInt256 txid, UInt256 blockHash, ulong tim TokenId = tokenId; From = from; To = to; - Value = BsonDecimal128.Create(value.ToString()); - FromBalanceOf = BsonDecimal128.Create(fromBalanceOf.ToString()); - ToBalanceOf = BsonDecimal128.Create(toBalanceOf.ToString()); + Value = BsonDecimal128.Create(value.ToString().WipeNumStrToFitDecimal128()); + FromBalanceOf = BsonDecimal128.Create(fromBalanceOf.ToString().WipeNumStrToFitDecimal128()); + ToBalanceOf = BsonDecimal128.Create(toBalanceOf.ToString().WipeNumStrToFitDecimal128()); Timestamp = timestamp; } diff --git a/Fura/Models/Notification/TransferNotificationModel.cs b/Fura/Models/Notification/TransferNotificationModel.cs index 819511d..75fc4d8 100644 --- a/Fura/Models/Notification/TransferNotificationModel.cs +++ b/Fura/Models/Notification/TransferNotificationModel.cs @@ -52,9 +52,9 @@ public TransferNotificationModel(UInt256 txid, UInt256 blockHash, ulong timestam AssetHash = assetHash; From = from; To = to; - Value = BsonDecimal128.Create(value.ToString()); - FromBalanceOf = BsonDecimal128.Create(fromBalanceOf.ToString()); - ToBalanceOf = BsonDecimal128.Create(toBalanceOf.ToString()); + Value = BsonDecimal128.Create(value.ToString().WipeNumStrToFitDecimal128()); + FromBalanceOf = BsonDecimal128.Create(fromBalanceOf.ToString().WipeNumStrToFitDecimal128()); + ToBalanceOf = BsonDecimal128.Create(toBalanceOf.ToString().WipeNumStrToFitDecimal128()); Timestamp = timestamp; } diff --git a/Fura/Models/ScCall/CandidateModel.cs b/Fura/Models/ScCall/CandidateModel.cs index 52ff7cd..aa7888b 100644 --- a/Fura/Models/ScCall/CandidateModel.cs +++ b/Fura/Models/ScCall/CandidateModel.cs @@ -30,7 +30,7 @@ public CandidateModel(UInt160 candidate, bool state, string votesOfCandidate, bo { Candidate = candidate; State = state; - VotesOfCandidate = BsonDecimal128.Create(votesOfCandidate); + VotesOfCandidate = BsonDecimal128.Create(votesOfCandidate.WipeNumStrToFitDecimal128()); IsCommittee = isCommittee; } diff --git a/Fura/Models/ScCall/VoteModel.cs b/Fura/Models/ScCall/VoteModel.cs index ab04a9e..8c7245f 100644 --- a/Fura/Models/ScCall/VoteModel.cs +++ b/Fura/Models/ScCall/VoteModel.cs @@ -50,7 +50,7 @@ public VoteModel(UInt256 lastVoteTxid, uint blockNumber, UInt160 voter, UInt160 Voter = voter; Candidate = candidate; CandidatePubKey = candidatePubKey; - BalanceOfVoter = BsonDecimal128.Create(balanceOfVoter); + BalanceOfVoter = BsonDecimal128.Create(balanceOfVoter.WipeNumStrToFitDecimal128()); LastTransferTxid = lastTransferTxid; } diff --git a/Fura/Models/TransactionModel.cs b/Fura/Models/TransactionModel.cs index 00d6529..8d1a586 100644 --- a/Fura/Models/TransactionModel.cs +++ b/Fura/Models/TransactionModel.cs @@ -74,7 +74,7 @@ public TransactionModel(Neo.Network.P2P.Payloads.Transaction transaction,UInt256 ValidUntilBlock = transaction.ValidUntilBlock; Signers = SignerModel.ToModels(transaction.Signers); Attributes = TransactionAttributeModel.ToModels(transaction.Attributes); - Script = transaction.Script; + Script = transaction.Script.ToArray(); Witnesses = WitnessModel.ToModels(transaction.Witnesses); BlockHash = blockHash; BlockTime = blockTime; diff --git a/Fura/Notification/NotificationMgr.Deploy.cs b/Fura/Notification/NotificationMgr.Deploy.cs new file mode 100644 index 0000000..2b2d5d4 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Deploy.cs @@ -0,0 +1,33 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteDeployNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + if (notificationModel.ContractHash == NativeContract.ContractManagement.Hash) + { + UInt160 contractHash = null; + bool succ = UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out contractHash); + if (!succ) return false; + DBCache.Ins.cacheContract.AddNeedUpdate(contractHash, block.Timestamp, notificationModel.Txid); + //如果合约还是asset,也一并更新了 + EnumAssetType assetType = GetAssetType(snapshot, contractHash); + if (assetType is EnumAssetType.NEP11 || assetType is EnumAssetType.NEP17) + { + DBCache.Ins.cacheAsset.AddNeedUpdate(contractHash, block.Timestamp, assetType); + } + } + return true; + } + + } +} + diff --git a/Fura/Notification/NotificationMgr.Destroy.cs b/Fura/Notification/NotificationMgr.Destroy.cs new file mode 100644 index 0000000..e36cd78 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Destroy.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteDestroyNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + if (notificationModel.ContractHash == NativeContract.ContractManagement.Hash) + { + UInt160 contractHash = null; + bool succ = UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out contractHash); + if (!succ) return false; + DBCache.Ins.cacheContract.AddNeedUpdate(contractHash, block.Timestamp, notificationModel.Txid, true); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.AddAsset.cs b/Fura/Notification/NotificationMgr.Market.AddAsset.cs new file mode 100644 index 0000000..f59a436 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.AddAsset.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteAddAssetNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + UInt160 asset = null; + BigInteger _feeRate = 0; + BigInteger _rewardRate = 0; + UInt160 _rewardReceiveAddress = null; + bool succ = true; + //asset + if (notificationModel.State.Values[0].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out asset); + } + //_feeRate + succ = succ && BigInteger.TryParse(notificationModel.State.Values[1].Value, out _feeRate); + //_rewardRate + succ = succ && BigInteger.TryParse(notificationModel.State.Values[2].Value, out _rewardRate); + //_rewardReceiveAddress + if (notificationModel.State.Values[3].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[3].Value).Reverse().ToArray().ToHexString(), out _rewardReceiveAddress); + } + + JObject json = new JObject(); + json["feeRate"] = _feeRate.ToString(); + json["rewardRate"] = _rewardRate.ToString(); + json["rewardReceiveAddress"] = _rewardReceiveAddress.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, 0, null, asset, "", "AddAsset", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.Auction.cs b/Fura/Notification/NotificationMgr.Market.Auction.cs new file mode 100644 index 0000000..f9cd1db --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.Auction.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteAuctionNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel= DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + BigInteger nonce = 0; + UInt160 user = null; + UInt160 asset = null; + string tokenId = ""; + BigInteger auctionType = 0; + UInt160 auctionAsset = null; + BigInteger auctionAmount = 0; + BigInteger deadline = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //asset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[3].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[3].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[3].Value; + } + //type + succ = succ && BigInteger.TryParse(notificationModel.State.Values[4].Value, out auctionType); + //auctionAsset + if (notificationModel.State.Values[5].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[5].Value).Reverse().ToArray().ToHexString(), out auctionAsset); + } + //auctionAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out auctionAmount); + //deadline + succ = succ && BigInteger.TryParse(notificationModel.State.Values[7].Value, out deadline); + + //暴露出通知的时候,nft的所有者已经变成了market了。 + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, false, asset, notificationModel.ContractHash, tokenId, notificationModel.ContractHash, auctionType, user, auctionAsset, auctionAmount, deadline, null, 0, block.Timestamp); + JObject json = new JObject(); + json["auctionType"] = auctionType.ToString(); + json["auctionAsset"] = auctionAsset?.ToString(); + json["auctionAmount"] = auctionAmount.ToString(); + json["deadline"] = deadline.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "Auction", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.Bid.cs b/Fura/Notification/NotificationMgr.Market.Bid.cs new file mode 100644 index 0000000..2972619 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.Bid.cs @@ -0,0 +1,67 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteBidNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + BigInteger nonce = 0; + UInt160 user = null; + UInt160 asset = null; + string tokenId = ""; + UInt160 auctionAsset = null; + BigInteger bidAmount = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //asset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[3].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[3].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[3].Value; + } + //auctionAsset + if (notificationModel.State.Values[4].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[4].Value).Reverse().ToArray().ToHexString(), out auctionAsset); + } + //auctionAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[5].Value, out bidAmount); + + MarketModel marketModel = DBCache.Ins.cacheMarket.Get(notificationModel.ContractHash, asset, tokenId); + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, false, asset, notificationModel.ContractHash, tokenId, notificationModel.ContractHash, marketModel.AuctionType, marketModel.Auctor, marketModel.AuctionAsset, BigInteger.Parse(marketModel.AuctionAmount.ToString()), marketModel.Deadline, user, bidAmount, block.Timestamp); + + JObject json = new JObject(); + json["auctionAsset"] = auctionAsset?.ToString(); + json["bidAmount"] = bidAmount.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "Bid", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.Cancel.cs b/Fura/Notification/NotificationMgr.Market.Cancel.cs new file mode 100644 index 0000000..03f0676 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.Cancel.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteCancelNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + BigInteger nonce = 0; + UInt160 user = null; + UInt160 asset = null; + string tokenId = ""; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //asset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[3].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[3].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[3].Value; + } + //暴露出通知的时候,nft的所有者已经变成了原先的用户了。 + MarketModel marketModel = DBCache.Ins.cacheMarket.Get(notificationModel.ContractHash, asset, tokenId); + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, false, asset, notificationModel.ContractHash, tokenId, null, 0, null, null, 0, 0, null, 0, block.Timestamp); + + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "Cancel", "{}", notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.CancelOffer.cs b/Fura/Notification/NotificationMgr.Market.CancelOffer.cs new file mode 100644 index 0000000..b4c6238 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.CancelOffer.cs @@ -0,0 +1,70 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteCancelOfferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 user = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + UInt160 asset = null; + string tokenId = ""; + BigInteger endTimestamp = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerAsset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[3].Value, out offerAmount); + //asset + if (notificationModel.State.Values[4].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[4].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[5].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[5].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[5].Value; + } + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out endTimestamp); + + + JObject json = new JObject(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "CancelOffer", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.CancelOfferCollection.cs b/Fura/Notification/NotificationMgr.Market.CancelOfferCollection.cs new file mode 100644 index 0000000..5d11c40 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.CancelOfferCollection.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteCancelOfferCollectionNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 user = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + UInt160 asset = null; + BigInteger count = 0; + BigInteger endTimestamp = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerAsset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[3].Value, out offerAmount); + //asset + if (notificationModel.State.Values[4].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[4].Value).Reverse().ToArray().ToHexString(), out asset); + } + //count + succ = succ && BigInteger.TryParse(notificationModel.State.Values[5].Value, out count); + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out endTimestamp); + + + JObject json = new JObject(); + json["count"] = count.ToString(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, "", "CancelOfferCollection", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.Claim.cs b/Fura/Notification/NotificationMgr.Market.Claim.cs new file mode 100644 index 0000000..de21d9f --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.Claim.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteClaimNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + BigInteger nonce = 0; + UInt160 user = null; + UInt160 asset = null; + string tokenId = ""; + BigInteger auctionType = 0; + UInt160 auctionAsset = null; + BigInteger bidAmount = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //asset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[3].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[3].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[3].Value; + } + //type + succ = succ && BigInteger.TryParse(notificationModel.State.Values[4].Value, out auctionType); + //auctionAsset + if (notificationModel.State.Values[5].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[5].Value).Reverse().ToArray().ToHexString(), out auctionAsset); + } + //auctionAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out bidAmount); + + MarketModel marketModel = DBCache.Ins.cacheMarket.Get(notificationModel.ContractHash, asset, tokenId); + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, false, asset, notificationModel.ContractHash, tokenId, null, 0, null, null, 0, 0, null, 0, block.Timestamp); + + JObject json = new JObject(); + json["auctionType"] = auctionType.ToString(); + json["auctionAsset"] = auctionAsset?.ToString(); + json["bidAmount"] = bidAmount.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "Claim", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} \ No newline at end of file diff --git a/Fura/Notification/NotificationMgr.Market.CompleteOffer.cs b/Fura/Notification/NotificationMgr.Market.CompleteOffer.cs new file mode 100644 index 0000000..46272a0 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.CompleteOffer.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteCompleteOfferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 offerer = null; + UInt160 user = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + UInt160 asset = null; + string tokenId = ""; + BigInteger endTimestamp = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerer + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerer); + } + //offerAsset + if (notificationModel.State.Values[3].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[3].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[4].Value, out offerAmount); + //asset + if (notificationModel.State.Values[5].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[5].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[6].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[6].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[6].Value; + } + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[7].Value, out endTimestamp); + + + JObject json = new JObject(); + json["offerer"] = offerer?.ToString(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "CompleteOffer", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.CompleteOfferCollection.cs b/Fura/Notification/NotificationMgr.Market.CompleteOfferCollection.cs new file mode 100644 index 0000000..09823c1 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.CompleteOfferCollection.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteCompleteOfferCollectionNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 offerer = null; + UInt160 user = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + UInt160 asset = null; + string tokenId = ""; + BigInteger endTimestamp = 0; + BigInteger count = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerer + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerer); + } + //offerAsset + if (notificationModel.State.Values[3].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[3].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[4].Value, out offerAmount); + //asset + if (notificationModel.State.Values[5].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[5].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[6].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[6].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[6].Value; + } + //count + succ = succ && BigInteger.TryParse(notificationModel.State.Values[7].Value, out count); + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[8].Value, out endTimestamp); + + + JObject json = new JObject(); + json["offerer"] = offerer?.ToString(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["count"] = count.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "CompleteOfferCollection", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.Offer.cs b/Fura/Notification/NotificationMgr.Market.Offer.cs new file mode 100644 index 0000000..a6a6cf3 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.Offer.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteOfferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 user = null; + UInt160 originOwner = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + UInt160 asset = null; + string tokenId = ""; + BigInteger endTimestamp = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerAsset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[3].Value, out offerAmount); + //asset + if (notificationModel.State.Values[4].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[4].Value).Reverse().ToArray().ToHexString(), out asset); + } + //tokenid + if (notificationModel.State.Values[5].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[5].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[5].Value; + } + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out endTimestamp); + //originOwner + if (notificationModel.State.Values[7].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[7].Value).Reverse().ToArray().ToHexString(), out originOwner); + } + + JObject json = new JObject(); + json["originOwner"] = originOwner?.ToString(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, tokenId, "Offer", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.OfferCollection.cs b/Fura/Notification/NotificationMgr.Market.OfferCollection.cs new file mode 100644 index 0000000..577b3b7 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.OfferCollection.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; +using System.Numerics; +using Neo.Json; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteOfferCollectionNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + //(nonce, 用户 ,求购使用的nep17资产,nep17数额,求购的nft的hash,求购的nfttokenid,求购截止日期) + BigInteger nonce = 0; + UInt160 user = null; + UInt160 offerAsset = null; + BigInteger offerAmount = 0; + BigInteger count = 0; + UInt160 asset = null; + BigInteger endTimestamp = 0; + bool succ = true; + succ = succ && BigInteger.TryParse(notificationModel.State.Values[0].Value, out nonce); + //user + if (notificationModel.State.Values[1].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out user); + } + //offerAsset + if (notificationModel.State.Values[2].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[2].Value).Reverse().ToArray().ToHexString(), out offerAsset); + } + //offerAmount + succ = succ && BigInteger.TryParse(notificationModel.State.Values[3].Value, out offerAmount); + //asset + if (notificationModel.State.Values[4].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[4].Value).Reverse().ToArray().ToHexString(), out asset); + } + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[5].Value, out count); + //endtimestamp + succ = succ && BigInteger.TryParse(notificationModel.State.Values[6].Value, out endTimestamp); + + JObject json = new JObject(); + json["count"] = count.ToString(); + json["offerAsset"] = offerAsset?.ToString(); + json["offerAmount"] = offerAmount.ToString(); + json["deadline"] = endTimestamp.ToString(); + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, nonce, user, asset, "", "OfferCollection", json.ToString(), notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.Market.RemoveAsset.cs b/Fura/Notification/NotificationMgr.Market.RemoveAsset.cs new file mode 100644 index 0000000..b50bac3 --- /dev/null +++ b/Fura/Notification/NotificationMgr.Market.RemoveAsset.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; + + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteRemoveAssetNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + ContractModel contractModel = DBCache.Ins.cacheContract.Get(notificationModel.ContractHash); + if (Settings.Default.MarketContractIds.Contains(contractModel._ID)) + { + UInt160 asset = null; + bool succ = true; + //asset + if (notificationModel.State.Values[0].Value is not null) + { + succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out asset); + } + + DBCache.Ins.cacheMatketNotification.Add(notificationModel.Txid, notificationModel.BlockHash, notificationModel.ContractHash, 0, null, asset, "", "RemoveAsset", "{}", notificationModel.Timestamp); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.NNS.Renew.cs b/Fura/Notification/NotificationMgr.NNS.Renew.cs new file mode 100644 index 0000000..2eb9889 --- /dev/null +++ b/Fura/Notification/NotificationMgr.NNS.Renew.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using System.Numerics; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteRenewNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + if (UInt160.Parse(Settings.Default.NNS) == notificationModel.ContractHash) + { + bool succ = true; + string tokenId = ""; + if (notificationModel.State.Values[0].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[0].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[0].Value; + } + + if (!succ) + { + return succ; + } + DBCache.Ins.cacheNep11Properties.AddNeedUpdate(notificationModel.ContractHash, tokenId); + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.NNS.SetAdmin.cs b/Fura/Notification/NotificationMgr.NNS.SetAdmin.cs new file mode 100644 index 0000000..dcd4c79 --- /dev/null +++ b/Fura/Notification/NotificationMgr.NNS.SetAdmin.cs @@ -0,0 +1,38 @@ +using System; +using System.Linq; +using System.Numerics; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteSetAdminNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + if (UInt160.Parse(Settings.Default.NNS) == notificationModel.ContractHash) + { + bool succ = true; + string tokenId = ""; + if (notificationModel.State.Values[0].Type == "Integer") //需要转换一下 + { + tokenId = Convert.ToBase64String(BigInteger.Parse(notificationModel.State.Values[0].Value).ToByteArray()); + } + else + { + tokenId = notificationModel.State.Values[0].Value; + } + + if (!succ) + { + return succ; + } + DBCache.Ins.cacheNep11Properties.AddNeedUpdate(notificationModel.ContractHash, tokenId); + } + return true; + } + } +} + diff --git a/Fura/NotificationMgr.cs b/Fura/Notification/NotificationMgr.Transfer.cs similarity index 50% rename from Fura/NotificationMgr.cs rename to Fura/Notification/NotificationMgr.Transfer.cs index c1c9a94..fbc6719 100644 --- a/Fura/NotificationMgr.cs +++ b/Fura/Notification/NotificationMgr.Transfer.cs @@ -1,81 +1,17 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; -using System.Threading.Tasks; -using MongoDB.Bson; -using Neo.Cryptography; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.Plugins.Cache; using Neo.Plugins.Models; -using Neo.SmartContract; using Neo.SmartContract.Native; -namespace Neo.Plugins +namespace Neo.Plugins.Notification { - public class NotificationMgr + public partial class NotificationMgr { - Dictionary> dic_filter = new Dictionary>(); - - private static NotificationMgr ins; - - private static Dictionary dic_AssetType = new Dictionary(); - - private static object lockObj = new object(); - - public static NotificationMgr Ins - { - get - { - if (ins is null) - { - lock (lockObj) - { - if (ins is null) - ins = new NotificationMgr(); - } - } - return ins; - } - - } - - public NotificationMgr() - { - Register("Transfer", ExecuteTransferNotification); - Register("Deploy", ExecuteDeployNotification); - Register("Update", ExecuteUpdateNotification); - } - - public void Register(string eventName, Func entity) - { - dic_filter.Add(GetKey(eventName), entity); - } - - public UInt256 GetKey(string eventName) - { - return new UInt256((UTF8Encoding.UTF8.GetBytes(eventName)).Sha256()); - } - - public void Filter(List notificationModels, NeoSystem system, Block block, DataCache snapshot) - { - Parallel.For(0, notificationModels.Count, (i) => - { - var notificationModel = notificationModels[i]; - if (notificationModel.Vmstate != "HALT") - { - return; - } - var key = GetKey(notificationModel.EventName); - if (dic_filter.ContainsKey(key)) - { - dic_filter[key](notificationModel, system, block, snapshot); - } - }); - } - private bool ExecuteTransferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) { if (notificationModel.State.Values.Count() == 3) @@ -113,21 +49,21 @@ private void UpdateVoteModelByTransfer(UInt256 txid, UInt160 voter, NeoSystem sy private void ExecuteGasSepical(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) { - if(notificationModel.State.Values[1].Value is null)//gas 销毁 + if (notificationModel.State.Values[1].Value is null)//gas 销毁 { BigInteger value = 0; BigInteger.TryParse(notificationModel.State.Values[2].Value, out value); - DBCache.Ins.cacheGasMintBurn.Add(block.Index,value, 0); + DBCache.Ins.cacheGasMintBurn.Add(block.Index, value, 0); } if (notificationModel.State.Values[0].Value is null)//gas 增发 { BigInteger value = 0; BigInteger.TryParse(notificationModel.State.Values[2].Value, out value); - DBCache.Ins.cacheGasMintBurn.Add(block.Index,0, value); + DBCache.Ins.cacheGasMintBurn.Add(block.Index, 0, value); } } - private (UInt160,UInt160) ExecuteNep17TransferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + private (UInt160, UInt160) ExecuteNep17TransferNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) { EnumAssetType assetType = GetAssetType(snapshot, notificationModel.ContractHash); if (assetType != EnumAssetType.NEP17) @@ -142,11 +78,12 @@ private void ExecuteGasSepical(NotificationModel notificationModel, NeoSystem sy bool succ = true; if (notificationModel.State.Values[0].Value is not null) { - succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out from); + succ = succ && TryParseBase64ToScriptHash(notificationModel.State.Values[0].Value, out from); + } if (notificationModel.State.Values[1].Value is not null) { - succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out to); + succ = succ && TryParseBase64ToScriptHash(notificationModel.State.Values[1].Value, out to); } succ = succ && BigInteger.TryParse(notificationModel.State.Values[2].Value, out value); if (!succ) @@ -160,7 +97,7 @@ private void ExecuteGasSepical(NotificationModel notificationModel, NeoSystem sy DBCache.Ins.cacheAddress.AddNeedUpdate(from, block.Timestamp); DBCache.Ins.cacheAddress.AddNeedUpdate(to, block.Timestamp); - if (from == UInt160.Zero || from is null) //如果from为0x0,意味着发行代币,这个时候需要更新资产的总量 + if (from == UInt160.Zero || from is null || to is null || to == UInt160.Zero) //如果from为0x0,意味着发行代币,这个时候需要更新资产的总量 { DBCache.Ins.cacheAsset.AddNeedUpdate(notificationModel.ContractHash, block.Timestamp, EnumAssetType.NEP17); } @@ -171,7 +108,7 @@ private void ExecuteNep11TransferNotification(NotificationModel notificationMode { EnumAssetType assetType = GetAssetType(snapshot, notificationModel.ContractHash); if (assetType != EnumAssetType.NEP11) - return ; + return; UInt256 txid = notificationModel.Txid; UInt256 blockHash = notificationModel.BlockHash; ulong timestamp = notificationModel.Timestamp; @@ -182,11 +119,11 @@ private void ExecuteNep11TransferNotification(NotificationModel notificationMode bool succ = true; if (notificationModel.State.Values[0].Value is not null) { - succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out from); + succ = succ && TryParseBase64ToScriptHash(notificationModel.State.Values[0].Value, out from); } if (notificationModel.State.Values[1].Value is not null) { - succ = succ && UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[1].Value).Reverse().ToArray().ToHexString(), out to); + succ = succ && TryParseBase64ToScriptHash(notificationModel.State.Values[1].Value, out to); } succ = succ && BigInteger.TryParse(notificationModel.State.Values[2].Value, out value); string tokenId = ""; @@ -212,79 +149,27 @@ private void ExecuteNep11TransferNotification(NotificationModel notificationMode DBCache.Ins.cacheAddressAsset.AddNeedUpdate(from, notificationModel.ContractHash, tokenId); DBCache.Ins.cacheAddressAsset.AddNeedUpdate(to, notificationModel.ContractHash, tokenId); + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, true, notificationModel.ContractHash, from, tokenId, block.Timestamp); + DBCache.Ins.cacheMarket.AddNeedUpdate(notificationModel.Index, true, notificationModel.ContractHash, to, tokenId, block.Timestamp); + DBCache.Ins.cacheAddress.Add(block.Timestamp, from, to); DBCache.Ins.cacheNep11Properties.AddNeedUpdate(notificationModel.ContractHash, tokenId); - if (from == UInt160.Zero || from is null) //如果from为0x0,意味着发行代币,这个时候需要更新资产的总量 + if (from == UInt160.Zero || from is null || to is null || to == UInt160.Zero) //如果from为0x0,意味着发行代币,这个时候需要更新资产的总量 { DBCache.Ins.cacheAsset.AddNeedUpdate(notificationModel.ContractHash, block.Timestamp, EnumAssetType.NEP11); } } - private bool ExecuteDeployNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + private bool TryParseBase64ToScriptHash(string base64String, out UInt160 addr) { - if(notificationModel.ContractHash == NativeContract.ContractManagement.Hash) + bool _succ = true; + _succ = UInt160.TryParse(Convert.FromBase64String(base64String).Reverse().ToArray().ToHexString(), out addr); + if (!_succ) { - UInt160 contractHash = null; - bool succ = UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out contractHash); - if (!succ) return false; - DBCache.Ins.cacheContract.AddNeedUpdate(contractHash, block.Timestamp, notificationModel.Txid); - //如果合约还是asset,也一并更新了 - EnumAssetType assetType = GetAssetType(snapshot, contractHash); - if (assetType is EnumAssetType.NEP11 || assetType is EnumAssetType.NEP17) - { - DBCache.Ins.cacheAsset.AddNeedUpdate(contractHash, block.Timestamp, assetType); - } + _succ = UInt160.TryParse(Encoding.UTF8.GetString(Convert.FromBase64String(base64String)), out addr); } - return true; - } - - private bool ExecuteUpdateNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) - { - if (notificationModel.ContractHash == NativeContract.ContractManagement.Hash) - { - UInt160 contractHash = null; - bool succ = UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out contractHash); - if (!succ) return false; - DBCache.Ins.cacheContract.AddNeedUpdate(contractHash, block.Timestamp, notificationModel.Txid); - //如果合约还是asset,也一并更新了 - EnumAssetType assetType = GetAssetType(snapshot, contractHash); - if (assetType is EnumAssetType.NEP11 || assetType is EnumAssetType.NEP17) - { - DBCache.Ins.cacheAsset.AddNeedUpdate(contractHash, block.Timestamp, assetType); - } - } - return true; - } - - private EnumAssetType GetAssetType(DataCache snapshot, UInt160 hash) - { - if (dic_AssetType.ContainsKey(hash)) - return dic_AssetType[hash]; - StorageKey key = new KeyBuilder(Neo.SmartContract.Native.NativeContract.ContractManagement.Id, 8).Add(hash); - ContractState contract = snapshot.TryGet(key)?.GetInteroperable(); - EnumAssetType assetType; - if (contract is null) - { - assetType = EnumAssetType.Unknown; - } - else if (contract.Manifest.SupportedStandards.Contains("NEP-17")) - { - assetType = EnumAssetType.NEP17; - } - else if (contract.Manifest.SupportedStandards.Contains("NEP-11")) - { - assetType = EnumAssetType.NEP11; - } - else - { - assetType = EnumAssetType.Unknown; - } - lock (dic_AssetType) - { - if (!dic_AssetType.ContainsKey(hash)) - dic_AssetType.Add(hash, assetType); - } - return assetType; + return _succ; } } } + diff --git a/Fura/Notification/NotificationMgr.Update.cs b/Fura/Notification/NotificationMgr.Update.cs new file mode 100644 index 0000000..7d187cc --- /dev/null +++ b/Fura/Notification/NotificationMgr.Update.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract.Native; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + private bool ExecuteUpdateNotification(NotificationModel notificationModel, NeoSystem system, Block block, DataCache snapshot) + { + if (notificationModel.ContractHash == NativeContract.ContractManagement.Hash) + { + UInt160 contractHash = null; + bool succ = UInt160.TryParse(Convert.FromBase64String(notificationModel.State.Values[0].Value).Reverse().ToArray().ToHexString(), out contractHash); + if (!succ) return false; + DBCache.Ins.cacheContract.AddNeedUpdate(contractHash, block.Timestamp, notificationModel.Txid); + //如果合约还是asset,也一并更新了 + EnumAssetType assetType = GetAssetType(snapshot, contractHash); + if (assetType is EnumAssetType.NEP11 || assetType is EnumAssetType.NEP17) + { + DBCache.Ins.cacheAsset.AddNeedUpdate(contractHash, block.Timestamp, assetType); + } + } + return true; + } + } +} + diff --git a/Fura/Notification/NotificationMgr.cs b/Fura/Notification/NotificationMgr.cs new file mode 100644 index 0000000..c12c202 --- /dev/null +++ b/Fura/Notification/NotificationMgr.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; +using MongoDB.Bson; +using Neo.Cryptography; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Plugins.Cache; +using Neo.Plugins.Models; +using Neo.SmartContract; +using Neo.SmartContract.Native; + +namespace Neo.Plugins.Notification +{ + public partial class NotificationMgr + { + Dictionary> dic_filter = new Dictionary>(); + + private static NotificationMgr ins; + + private static object lockObj = new object(); + + public static NotificationMgr Ins + { + get + { + if (ins is null) + { + lock (lockObj) + { + if (ins is null) + ins = new NotificationMgr(); + } + } + return ins; + } + + } + + public NotificationMgr() + { + Register("Transfer", ExecuteTransferNotification); + Register("Deploy", ExecuteDeployNotification); + Register("Update", ExecuteUpdateNotification); + Register("Destroy", ExecuteDestroyNotification); + + Register("Auction", ExecuteAuctionNotification); + Register("Bid", ExecuteBidNotification); + Register("Cancel", ExecuteCancelNotification); + Register("Claim", ExecuteClaimNotification); + Register("AddAsset", ExecuteAddAssetNotification); + Register("RemoveAsset", ExecuteRemoveAssetNotification); + Register("Offer", ExecuteOfferNotification); + Register("CancelOffer", ExecuteCancelOfferNotification); + Register("CompleteOffer", ExecuteCompleteOfferNotification); + Register("OfferCollection", ExecuteOfferCollectionNotification); + Register("CancelOfferCollection", ExecuteCancelOfferCollectionNotification); + Register("CompleteOfferCollection", ExecuteCompleteOfferCollectionNotification); + + + + Register("SetAdmin", ExecuteSetAdminNotification); + Register("Renew", ExecuteRenewNotification); + } + + public void Register(string eventName, Func entity) + { + dic_filter.Add(GetKey(eventName), entity); + } + + public UInt256 GetKey(string eventName) + { + return new UInt256((UTF8Encoding.UTF8.GetBytes(eventName)).Sha256()); + } + + public void Filter(List notificationModels, NeoSystem system, Block block, DataCache snapshot) + { + Parallel.For(0, notificationModels.Count, (i) => + { + var notificationModel = notificationModels[i]; + if (notificationModel.Vmstate != "HALT") + { + return; + } + var key = GetKey(notificationModel.EventName); + if (dic_filter.ContainsKey(key)) + { + dic_filter[key](notificationModel, system, block, snapshot); + } + }); + } + + private EnumAssetType GetAssetType(DataCache snapshot, UInt160 hash) + { + StorageKey key = new KeyBuilder(Neo.SmartContract.Native.NativeContract.ContractManagement.Id, 8).Add(hash); + ContractState contract = snapshot.TryGet(key)?.GetInteroperable(); + EnumAssetType assetType; + if (contract is null) + { + assetType = EnumAssetType.Unknown; + } + else if (contract.Manifest.SupportedStandards.Contains("NEP-17") || Settings.Default.Nep17ContractIds.Contains(contract.Id)) + { + assetType = EnumAssetType.NEP17; + } + else if (contract.Manifest.SupportedStandards.Contains("NEP-11") || Settings.Default.Nep11ContractIds.Contains(contract.Id)) + { + assetType = EnumAssetType.NEP11; + } + else + { + assetType = EnumAssetType.Unknown; + } + return assetType; + } + } +} diff --git a/Fura/Settings.cs b/Fura/Settings.cs index 3c02ddc..f765932 100644 --- a/Fura/Settings.cs +++ b/Fura/Settings.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using Microsoft.Extensions.Configuration; +using System.Linq; namespace Neo.Plugins { @@ -17,9 +19,21 @@ internal class Settings public static Settings Default { get; private set; } - public int SleepTime { get; set; } + public int SleepTime { get; } - public int WaitTime { get; set; } + public int WaitTime { get;} + + public IReadOnlyList MarketContractIds { get; } + + public IReadOnlyList Nep11ContractIds { get; } + + public IReadOnlyList Nep17ContractIds { get; } + + public IReadOnlyList IlexContractHashes { get; } + + public IReadOnlyList MetaContractHashes { get; } + + public string NNS { get; } private Settings(IConfigurationSection section) { @@ -27,13 +41,30 @@ private Settings(IConfigurationSection section) this.Host = section.GetValue("Host", "127.0.0.1"); this.Port = section.GetValue("Port", 27017); this.User = section.GetValue("User", "admin"); - this.Password = section.GetValue("Password","admin"); + this.Password = section.GetValue("Password", "admin"); this.ConnectionString = section.GetValue("ConnectionString", ""); this.Log = section.GetValue("Log", true); Console.WriteLine(Environment.CurrentDirectory); this.PName = section.GetValue("PName", Environment.CurrentDirectory); this.SleepTime = section.GetValue("SleepTime", 10); this.WaitTime = section.GetValue("WaitTime", 900); + this.MarketContractIds = section.GetSection("MarketContractIds").Exists() + ? section.GetSection("MarketContractIds").GetChildren().Select(p => int.Parse(p.Value)).ToArray() + : new[] { 0 }; + this.Nep11ContractIds = section.GetSection("Nep11ContractIds").Exists() + ? section.GetSection("Nep11ContractIds").GetChildren().Select(p => int.Parse(p.Value)).ToArray() + : new[] { 0 }; + this.Nep17ContractIds = section.GetSection("Nep17ContractIds").Exists() + ? section.GetSection("Nep17ContractIds").GetChildren().Select(p => int.Parse(p.Value)).ToArray() + : new[] { 0 }; + this.IlexContractHashes = section.GetSection("IlexContractHashes").Exists() + ? section.GetSection("IlexContractHashes").GetChildren().Select(p => p.Value).ToArray() + : new string[] { }; + this.MetaContractHashes = section.GetSection("MetaContractHashes").Exists() + ? section.GetSection("MetaContractHashes").GetChildren().Select(p => p.Value).ToArray() + : new string[] { }; + this.NNS = section.GetValue("NNS", ""); + } public static void Load(IConfigurationSection section) diff --git a/Fura/VM/Helper.cs b/Fura/VM/Helper.cs index 8f9c0a1..0451109 100644 --- a/Fura/VM/Helper.cs +++ b/Fura/VM/Helper.cs @@ -39,7 +39,7 @@ public static class Helper public static List Script2ScCallModels(byte[] script, UInt256 txid, UInt160 sender, string vmstate) { List scCalls = new List(); - List instructions = Script2Instruction(script).ToArray().Reverse().ToList(); ; + List instructions = Script2Instruction(txid, script).ToArray().Reverse().ToList(); for (var index = 0; index < instructions.Count; index++) { var instruction = instructions[index]; @@ -64,7 +64,15 @@ public static List Script2ScCallModels(byte[] script, UInt256 txid, string[] hexParams = new string[paramsCount]; for (var i = 0; i < paramsCount; i++) { - hexParams[i] = instructions[++index].Operand.Span.ToHexString(); + ++index; + if (instructions[index].OpCode >= OpCode.PUSH0 && instructions[index].OpCode <= OpCode.PUSH16) + { + hexParams[i] = (Convert.ToInt16(instructions[index].OpCode) - 16).ToString("X2"); + } + else + { + hexParams[i] = instructions[index].Operand.Span.ToHexString(); + } } scCalls.Add(new(vmstate, txid, sender, UInt160.Parse(contractHash), method, callFlags.ToString(), hexParams)); } @@ -72,16 +80,25 @@ public static List Script2ScCallModels(byte[] script, UInt256 txid, return scCalls; } - public static List Script2Instruction(byte[] script) + public static List Script2Instruction(UInt256 txid, byte[] script) { - List instructions = new List(); - Script s = new Script(script,true); - for (int ip = 0; ip < s.Length; ip += s.GetInstruction(ip).Size) + try + { + List instructions = new List(); + Script s = new Script(script, true); + for (int ip = 0; ip < s.Length; ip += s.GetInstruction(ip).Size) + { + var instruction = s.GetInstruction(ip); + instructions.Add(instruction); + } + return instructions; + } + catch { - var instruction = s.GetInstruction(ip); - instructions.Add(instruction); + DebugModel debugModel = new(string.Format("Script2Instruction----txid: {0}", txid)); + debugModel.SaveAsync().Wait(); } - return instructions; + return new List(); } public static CallFlags Opcode2CallFlags(OpCode opCode) @@ -155,7 +172,7 @@ public static BigInteger GetNeoBalanceOf(UInt160 user, NeoSystem system, DataCac script = sb.ToArray(); } - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { if (engine.State.HasFlag(VMState.FAULT)) { @@ -219,7 +236,7 @@ public static (string, byte, BigInteger) GetAssetInfo(NeoSystem system, DataCach script = sb.ToArray(); } (string, byte, BigInteger) t = new("", 0, 0); - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { if (engine.State.HasFlag(VMState.FAULT)) { @@ -229,7 +246,15 @@ public static (string, byte, BigInteger) GetAssetInfo(NeoSystem system, DataCach t.Item2 = (byte)engine.ResultStack.Pop().GetInteger(); t.Item1 = engine.ResultStack.Pop().GetString(); } - t.Item3 = GetAssetTotalSupply(system, snapshot, asset); + try + { + t.Item3 = GetAssetTotalSupply(system, snapshot, asset); + + } + catch + { + t.Item3 = 0; + } return t; } @@ -242,7 +267,7 @@ public static BigInteger GetAssetTotalSupply(NeoSystem system, DataCache snapsho script = sb.ToArray(); } BigInteger totalSupply = 0; - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { if (engine.State.HasFlag(VMState.FAULT)) { @@ -255,6 +280,32 @@ public static BigInteger GetAssetTotalSupply(NeoSystem system, DataCache snapsho } + public static BigInteger IsSelfControl(NeoSystem system, DataCache snapshot, UInt160 asset) + { + try + { + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + sb.EmitDynamicCall(asset, "selfControl"); + script = sb.ToArray(); + } + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) + { + if (engine.State.HasFlag(VMState.FAULT)) + { + Console.WriteLine("Error:GetNep11Info,VMState.FAULT" + asset.ToString()); //后面需要去掉,返回null + return 0; + } + return engine.ResultStack.Pop().GetInteger(); + } + } + catch + { + return 0; + } + } + public static string GetNep11Properties(NeoSystem system, DataCache snapshot, UInt160 asset, string TokenId) { byte[] script; @@ -272,14 +323,13 @@ public static string GetNep11Properties(NeoSystem system, DataCache snapshot, UI script = sb.ToArray(); } var properties = ""; - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { if (engine.State.HasFlag(VMState.HALT)) { properties = engine.ResultStack.Pop().ToJson().ToString(); } } - if (!string.IsNullOrEmpty(properties)) { try @@ -407,69 +457,92 @@ public static BigInteger GetNep11BalanceOf(NeoSystem system, DataCache snapshot, byte[] script; BigInteger decimals = 0; BigInteger balanceOf = 0; - //先获取decimals来确定是不是可以分割的nft,如果是可以分割的nft,那么balanceOf(usr,tokenid),反为balanceOf(usr) - using (ScriptBuilder sb = new ScriptBuilder()) - { - sb.EmitDynamicCall(asset, "decimals"); - script = sb.ToArray(); - } - - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) - { - if (engine.State.HasFlag(VMState.HALT)) - { - decimals = engine.ResultStack.Pop().GetInteger(); - } - } - //如果精度是0,那么tokenid一定只有一个地址拥有。查询ownerOf看是不是属于addr,是就返回1,不是就返回0 - if (decimals == 0) + try { - //如果是有精度的就查询balanceof + //先获取decimals来确定是不是可以分割的nft,如果是可以分割的nft,那么balanceOf(usr,tokenid),反为balanceOf(usr) using (ScriptBuilder sb = new ScriptBuilder()) { - try - { - sb.EmitDynamicCall(asset, "ownerOf", Convert.FromBase64String(TokenId)); - - } - catch - { - sb.EmitDynamicCall(asset, "ownerOf", TokenId); - } + sb.EmitDynamicCall(asset, "decimals"); script = sb.ToArray(); } - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { if (engine.State.HasFlag(VMState.HALT)) { - var owner = new UInt160(engine.ResultStack.Pop().GetSpan().ToArray()); - balanceOf = owner == addr ? 1 : 0; + var stackitem = engine.ResultStack.Pop(); + if (!stackitem.IsNull) + { + decimals = stackitem.GetInteger(); + } } } - } - else - { - //如果是有精度的就查询balanceof - using (ScriptBuilder sb = new ScriptBuilder()) + //如果精度是0,那么tokenid一定只有一个地址拥有。查询ownerOf看是不是属于addr,是就返回1,不是就返回0 + if (decimals == 0) { - try + //如果是有精度的就查询balanceof + using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitDynamicCall(asset, "balanceOf", addr == null ? UInt160.Parse("0x1100000000000000000220000000000000000011") : addr, Convert.FromBase64String(TokenId)); + try + { + sb.EmitDynamicCall(asset, "ownerOf", Convert.FromBase64String(TokenId)); + + } + catch + { + sb.EmitDynamicCall(asset, "ownerOf", TokenId); + } + script = sb.ToArray(); } - catch + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) { - sb.EmitDynamicCall(asset, "balanceOf", addr == null ? UInt160.Parse("0x1100000000000000000220000000000000000011") : addr, TokenId); + if (engine.State.HasFlag(VMState.HALT)) + { + var stackitem = engine.ResultStack.Pop(); + if (!stackitem.IsNull) + { + var bts = stackitem.GetSpan().ToArray(); + var owner_1 = new UInt160(bts); + UInt160 owner_2 = null; + UInt160.TryParse(UTF8Encoding.UTF8.GetString(bts), out owner_2); + balanceOf = owner_1 == addr || owner_2 == addr ? 1 : 0; + } + } } - script = sb.ToArray(); } - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + else { - if (engine.State.HasFlag(VMState.HALT)) + //如果是有精度的就查询balanceof + using (ScriptBuilder sb = new ScriptBuilder()) { - balanceOf = engine.ResultStack.Pop().GetInteger(); + try + { + sb.EmitDynamicCall(asset, "balanceOf", addr == null ? UInt160.Parse("0x1100000000000000000220000000000000000011") : addr, Convert.FromBase64String(TokenId)); + } + catch + { + sb.EmitDynamicCall(asset, "balanceOf", addr == null ? UInt160.Parse("0x1100000000000000000220000000000000000011") : addr, TokenId); + } + script = sb.ToArray(); + } + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000)) + { + if (engine.State.HasFlag(VMState.HALT)) + { + var stackitem = engine.ResultStack.Pop(); + if (!stackitem.IsNull) + { + balanceOf = stackitem.GetInteger(); + } + } } } } + catch(Exception e) + { + Loger.Warning(string.Format("Commit:{0}", e.Message)); + } + return balanceOf; } @@ -487,7 +560,7 @@ public static BigInteger[] GetNep17BalanceOf(NeoSystem system, DataCache snapsho } BigInteger[] balanceOfs = new BigInteger[addrs.Length]; - using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings)) + using (ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, settings: system.Settings, gas: 50000000 * addrs.Length)) { if (engine.State.HasFlag(VMState.HALT)) { diff --git a/UnitFuraTest/FuraTest.cs b/UnitFuraTest/FuraTest.cs index 6038ea3..bae5a39 100644 --- a/UnitFuraTest/FuraTest.cs +++ b/UnitFuraTest/FuraTest.cs @@ -12,6 +12,8 @@ using System.Collections.Generic; using System.Text.Json; using System.IO; +using Neo.VM; +using Neo.Cryptography; namespace UnitFuraTest { @@ -26,11 +28,44 @@ public void Init() [TestMethod] public void TestScript2Executions() { - var base64String = "7b226e616d65223a2247686f73744d61726b65742054657374204e4654222c226465736372697074696f6e223a224e6f74207265616c6c7920666f722073616c652c206e6f74206f726967696e616c20617274776f726b222c22696d616765223a22697066733a2f2f516d66527161414b6d53544153457a6f724234367145706236514a65656f784b6f3653566b4a7953363443767344222c22746f6b656e555249223a22222c2261747472696275746573223a5b7b2274797065223a22417274697374222c2276616c7565223a22556e6b6e6f776e222c22646973706c6179223a22227d2c7b2274797065223a224f726967696e616c222c2276616c7565223a224e6f7065222c22646973706c6179223a22227d2c7b2274797065223a22546573746e65742046756e222c2276616c7565223a22596573222c22646973706c6179223a22227d5d2c2270726f70657274696573223a7b226861735f6c6f636b6564223a747275652c2263726561746f72223a224e4c5a334b785864393838527633373473343231396877704d567175487841725944222c22726f79616c74696573223a323030302c2274797065223a317d7Q=="; - //var base64String = "DCEC13y+vWO9KxAxFwg0SF0rjAJoq/n2N89uNwqrDwi+WHsMFIU5Il4pKR6Kf5xyOLaNS67/1PekEsAfDAR2b3RlDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtS"; - var script = Convert.FromBase64String(base64String); - var str = Encoding.UTF8.GetString(script); - var scCalls = Neo.Plugins.VM.Helper.Script2ScCallModels(script, UInt256.Zero, UInt160.Zero, ""); + var aa = new UInt256((UTF8Encoding.UTF8.GetBytes("Auction")).Sha256()); + var ba = new UInt256((UTF8Encoding.UTF8.GetBytes("relaunch")).Sha256()); + + UInt160 asset = UInt160.Parse("0xd74d35311c2a20ba78cd12056d3017da5bd352a6"); + string TokenId = "1LDil6dnxse4WiGC+2nk/gi0mnazuu0aMGI9hYsilHs="; + byte[] script; + using (ScriptBuilder sb = new ScriptBuilder()) + { + try + { + sb.EmitDynamicCall(asset, "properties", Convert.FromBase64String(TokenId)); + + } + catch + { + sb.EmitDynamicCall(asset, "properties", TokenId); + } + script = sb.ToArray(); + } + var a = script.ToHexString(); + + //var base64String = "7b226e616d65223a2247686f73744d61726b65742054657374204e4654222c226465736372697074696f6e223a224e6f74207265616c6c7920666f722073616c652c206e6f74206f726967696e616c20617274776f726b222c22696d616765223a22697066733a2f2f516d66527161414b6d53544153457a6f724234367145706236514a65656f784b6f3653566b4a7953363443767344222c22746f6b656e555249223a22222c2261747472696275746573223a5b7b2274797065223a22417274697374222c2276616c7565223a22556e6b6e6f776e222c22646973706c6179223a22227d2c7b2274797065223a224f726967696e616c222c2276616c7565223a224e6f7065222c22646973706c6179223a22227d2c7b2274797065223a22546573746e65742046756e222c2276616c7565223a22596573222c22646973706c6179223a22227d5d2c2270726f70657274696573223a7b226861735f6c6f636b6564223a747275652c2263726561746f72223a224e4c5a334b785864393838527633373473343231396877704d567175487841725944222c22726f79616c74696573223a323030302c2274797065223a317d7Q=="; + ////var base64String = "DCEC13y+vWO9KxAxFwg0SF0rjAJoq/n2N89uNwqrDwi+WHsMFIU5Il4pKR6Kf5xyOLaNS67/1PekEsAfDAR2b3RlDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtS"; + //var script = Convert.FromBase64String(base64String); + //var str = Encoding.UTF8.GetString(script); + //var scCalls = Neo.Plugins.VM.Helper.Script2ScCallModels(script, UInt256.Zero, UInt160.Zero, ""); + } + + [TestMethod] + public void TestConvert() + { + //var a = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + //UInt160 from; + //bool succ = UInt160.TryParse(Convert.FromBase64String("krOcd6pg8ptXwXPO2Rfxf9Mhpus=").Reverse().ToArray().ToHexString(), out from); + //succ = UInt160.TryParse("d79888e16f9186e873b18a2bc80fd3ecf2ba74b3", out from); + + string properties = "{\"name\":\"CryptoFallen #6-19\",\"description\":\"CryptoFallen #6-19 \\\"Neo3 Series\\\" Follow @1Bigbagheera on twitter for updates!\",\"image\":\"ipfs://QmXZF4Pu1txhKo938X43RqrVJZ98p9QZyKnNGQ3ZR5Q3y3\",\"tokenURI\":\"\",\"attributes\":[{\"type\":\"Author\",\"value\":\"1Bigbagheera\",\"display\":\"\"},{\"type\":\"Date\",\"value\":\"8/25/21\",\"display\":\"\"},{\"type\":\"Series\",\"value\":\"Neo3\",\"display\":\"\"}],\"properties\":{\"has_locked\":false,\"creator\":\"NMV6PXumvk74JHkrrgynh932dQKd2p9vGF\",\"royalties\":1000,\"type\":2}}"; + Neo.Json.JObject jObject = (Neo.Json.JObject)Neo.Json.JObject.Parse(properties); } public static string TryParseByteString(string str) @@ -111,15 +146,6 @@ public static string GetValue(JsonElement element) return value; } - [TestMethod] - public void TestConvert() - { - var a = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; - UInt160 from; - bool succ = UInt160.TryParse(Convert.FromBase64String("krOcd6pg8ptXwXPO2Rfxf9Mhpus=").Reverse().ToArray().ToHexString(), out from); - succ = UInt160.TryParse("d79888e16f9186e873b18a2bc80fd3ecf2ba74b3", out from); - } - [TestMethod] public void TestECPointParse() { diff --git a/UnitFuraTest/UnitFuraTest.csproj b/UnitFuraTest/UnitFuraTest.csproj index 0dc3d85..b819de0 100644 --- a/UnitFuraTest/UnitFuraTest.csproj +++ b/UnitFuraTest/UnitFuraTest.csproj @@ -1,7 +1,7 @@ - net5.0 + net7.0 false