public void SwapToken(Address buyer, Address seller, string baseSymbol, string quoteSymbol, BigInteger tokenID, BigInteger price, byte[] signature) { Runtime.Expect(IsWitness(buyer), "invalid witness"); Runtime.Expect(seller != buyer, "invalid seller"); Runtime.Expect(Runtime.Nexus.TokenExists(baseSymbol), "invalid base token"); var baseToken = Runtime.Nexus.GetTokenInfo(baseSymbol); Runtime.Expect(!baseToken.Flags.HasFlag(TokenFlags.Fungible), "token must be non-fungible"); var ownerships = new OwnershipSheet(baseSymbol); var owner = ownerships.GetOwner(this.Storage, tokenID); Runtime.Expect(owner == seller, "invalid owner"); var swap = new TokenSwap() { baseSymbol = baseSymbol, quoteSymbol = quoteSymbol, buyer = buyer, seller = seller, price = price, value = tokenID, }; var msg = Serialization.Serialize(swap); Runtime.Expect(Ed25519.Verify(signature, msg, seller.PublicKey), "invalid signature"); Runtime.Expect(Runtime.Nexus.TokenExists(quoteSymbol), "invalid quote token"); var quoteToken = Runtime.Nexus.GetTokenInfo(quoteSymbol); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "token must be fungible"); var balances = new BalanceSheet(quoteSymbol); var balance = balances.Get(this.Storage, buyer); Runtime.Expect(balance >= price, "invalid balance"); Runtime.Expect(Runtime.Nexus.TransferTokens(quoteSymbol, this.Storage, Runtime.Chain, buyer, owner, price), "payment failed"); Runtime.Expect(Runtime.Nexus.TransferToken(baseSymbol, this.Storage, Runtime.Chain, owner, buyer, tokenID), "transfer failed"); Runtime.Notify(EventKind.TokenSend, seller, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = baseSymbol, value = tokenID }); Runtime.Notify(EventKind.TokenSend, buyer, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = quoteSymbol, value = price }); Runtime.Notify(EventKind.TokenReceive, seller, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = quoteSymbol, value = price }); Runtime.Notify(EventKind.TokenReceive, buyer, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = baseSymbol, value = tokenID }); }
public void SwapTokens(Address buyer, Address seller, string baseSymbol, string quoteSymbol, BigInteger amount, BigInteger price, byte[] signature) { Runtime.Expect(IsWitness(buyer), "invalid witness"); Runtime.Expect(seller != buyer, "invalid seller"); var baseToken = Runtime.Nexus.FindTokenBySymbol(baseSymbol); Runtime.Expect(baseToken != null, "invalid base token"); Runtime.Expect(baseToken.Flags.HasFlag(TokenFlags.Fungible), "token must be fungible"); var baseBalances = Runtime.Chain.GetTokenBalances(baseToken); var baseBalance = baseBalances.Get(seller); Runtime.Expect(baseBalance >= amount, "invalid amount"); var swap = new TokenSwap() { baseSymbol = baseSymbol, quoteSymbol = quoteSymbol, buyer = buyer, seller = seller, price = price, value = amount, }; var msg = Serialization.Serialize(swap); Runtime.Expect(Ed25519.Verify(signature, msg, seller.PublicKey), "invalid signature"); var quoteToken = Runtime.Nexus.FindTokenBySymbol(quoteSymbol); Runtime.Expect(quoteToken != null, "invalid base token"); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "token must be fungible"); var quoteBalances = Runtime.Chain.GetTokenBalances(quoteToken); var quoteBalance = quoteBalances.Get(buyer); Runtime.Expect(quoteBalance >= price, "invalid balance"); Runtime.Expect(quoteToken.Transfer(quoteBalances, buyer, seller, price), "payment failed"); Runtime.Expect(baseToken.Transfer(baseBalances, seller, buyer, amount), "transfer failed"); Runtime.Notify(EventKind.TokenSend, seller, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = baseSymbol, value = amount }); Runtime.Notify(EventKind.TokenSend, buyer, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = quoteSymbol, value = price }); Runtime.Notify(EventKind.TokenReceive, seller, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = quoteSymbol, value = price }); Runtime.Notify(EventKind.TokenReceive, buyer, new TokenEventData() { chainAddress = Runtime.Chain.Address, symbol = baseSymbol, value = amount }); }