public void BuyToken(Address from, string symbol, BigInteger tokenID) { Runtime.Expect(Runtime.IsWitness(from), "invalid witness"); var auctionID = symbol + "." + tokenID; Runtime.Expect(_auctionMap.ContainsKey <string>(auctionID), "invalid auction"); var auction = _auctionMap.Get <string, MarketAuction>(auctionID); Runtime.Expect(Runtime.TokenExists(auction.BaseSymbol), "invalid base token"); var baseToken = Runtime.GetToken(auction.BaseSymbol); Runtime.Expect(!baseToken.Flags.HasFlag(TokenFlags.Fungible), "token must be non-fungible"); var nft = Runtime.ReadToken(symbol, tokenID); Runtime.Expect(nft.CurrentChain == Runtime.Chain.Name, "token not currently in this chain"); Runtime.Expect(nft.CurrentOwner == this.Address, "invalid owner"); if (auction.Creator != from) { Runtime.Expect(Runtime.TokenExists(auction.QuoteSymbol), "invalid quote token"); var quoteToken = Runtime.GetToken(auction.QuoteSymbol); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "quote token must be fungible"); var balance = Runtime.GetBalance(quoteToken.Symbol, from); Runtime.Expect(balance >= auction.Price, "not enough balance"); Runtime.Expect(Runtime.TransferTokens(quoteToken.Symbol, from, auction.Creator, auction.Price), "payment failed"); } Runtime.Expect(Runtime.TransferToken(baseToken.Symbol, this.Address, from, auction.TokenID), "transfer failed"); _auctionMap.Remove <string>(auctionID); _auctionIDs.Remove(auctionID); if (auction.Creator == from) { Runtime.Notify(EventKind.OrderCancelled, from, new MarketEventData() { ID = auction.TokenID, BaseSymbol = auction.BaseSymbol, QuoteSymbol = auction.QuoteSymbol, Price = 0 }); } else { Runtime.Notify(EventKind.TokenSend, from, new TokenEventData() { chainAddress = this.Address, symbol = auction.QuoteSymbol, value = auction.Price }); Runtime.Notify(EventKind.TokenReceive, auction.Creator, new TokenEventData() { chainAddress = this.Address, symbol = auction.QuoteSymbol, value = auction.Price }); Runtime.Notify(EventKind.OrderFilled, from, new MarketEventData() { ID = auction.TokenID, BaseSymbol = auction.BaseSymbol, QuoteSymbol = auction.QuoteSymbol, Price = auction.Price }); } Runtime.Notify(EventKind.TokenReceive, from, new TokenEventData() { chainAddress = this.Address, symbol = auction.BaseSymbol, value = auction.TokenID }); }