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 }); }
// NFT version internal bool BurnToken(string symbol, StorageContext storage, Address target, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { return(false); } var chain = RootChain; var supply = new SupplySheet(symbol, chain, this); if (!supply.Burn(storage, 1)) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Take(storage, target, tokenID)) { return(false); } return(true); }
// NFT version internal bool MintToken(string symbol, StorageContext storage, Chain chain, Address target, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { return(false); } var supply = new SupplySheet(symbol, chain, this); if (!supply.Mint(storage, 1, tokenInfo.MaxSupply)) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Give(storage, target, tokenID)) { return(false); } EditNFTLocation(symbol, tokenID, chain.Address, target); return(true); }
// NOTE this only works if the token is curently on this chain public Address GetTokenOwner(string tokenSymbol, BigInteger tokenID) { var tokenInfo = Nexus.GetTokenInfo(tokenSymbol); Throw.If(tokenInfo.IsFungible, "non fungible required"); var ownerships = new OwnershipSheet(tokenSymbol); return(ownerships.GetOwner(this.Storage, tokenID)); }
public void TestGetAccountNFT() { var test = CreateAPI(); var chain = test.nexus.RootChain; var symbol = "COOL"; var testUser = KeyPair.Generate(); // Create the token CoolToken as an NFT test.simulator.BeginBlock(); test.simulator.GenerateToken(test.owner, symbol, "CoolToken", DomainSettings.PlatformName, Hash.FromString(symbol), 0, 0, Domain.TokenFlags.None); test.simulator.EndBlock(); var token = test.simulator.Nexus.GetTokenInfo(symbol); Assert.IsTrue(test.simulator.Nexus.TokenExists(symbol), "Can't find the token symbol"); var tokenROM = new byte[] { 0x1, 0x3, 0x3, 0x7 }; var tokenRAM = new byte[] { 0x1, 0x4, 0x4, 0x6 }; // Mint a new CoolToken var simulator = test.simulator; simulator.BeginBlock(); simulator.MintNonFungibleToken(test.owner, testUser.Address, symbol, tokenROM, tokenRAM); simulator.EndBlock(); // obtain tokenID var ownerships = new OwnershipSheet(symbol); var ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the sender not have one now?"); var tokenID = ownedTokenList.First(); var account = (AccountResult)test.api.GetAccount(testUser.Address.Text); Assert.IsTrue(account.address == testUser.Address.Text); Assert.IsTrue(account.name == ValidationUtils.ANONYMOUS); Assert.IsTrue(account.balances.Length == 1); var balance = account.balances[0]; Assert.IsTrue(balance.symbol == symbol); Assert.IsTrue(balance.ids.Length == 1); var info = (TokenDataResult)test.api.GetTokenData(symbol, balance.ids[0]); Assert.IsTrue(info.ID == balance.ids[0]); var tokenStr = Base16.Encode(tokenROM); Assert.IsTrue(info.rom == tokenStr); }
public BigInteger[] GetTokens(Address address, string symbol) { Runtime.Expect(this.Runtime.Nexus.TokenExists(symbol), "invalid token"); var token = this.Runtime.Nexus.GetTokenInfo(symbol); Runtime.Expect(!token.IsFungible(), "token must be non-fungible"); var ownerships = new OwnershipSheet(symbol); return(ownerships.Get(this.Storage, address).ToArray()); }
public IAPIResult GetAccount([APIParameter("Address of account", "PDHcAHq1fZXuwDrtJGDhjemFnj2ZaFc7iu3qD4XjZG9eV")] string addressText) { if (!Address.IsValidAddress(addressText)) { return(new ErrorResult { error = "invalid address" }); } var result = new AccountResult(); var address = Address.FromText(addressText); result.address = address.Text; result.name = Nexus.LookUpAddress(address); var balanceList = new List <BalanceResult>(); foreach (var symbol in Nexus.Tokens) { foreach (var chainName in Nexus.Chains) { var chain = Nexus.FindChainByName(chainName); var balance = chain.GetTokenBalance(symbol, address); if (balance > 0) { var token = Nexus.GetTokenInfo(symbol); var balanceEntry = new BalanceResult { chain = chain.Name, amount = balance.ToString(), symbol = token.Symbol, decimals = (uint)token.Decimals, ids = new string[0] }; if (!token.IsFungible) { var ownerships = new OwnershipSheet(symbol); var idList = ownerships.Get(chain.Storage, address); if (idList != null && idList.Any()) { balanceEntry.ids = idList.Select(x => x.ToString()).ToArray(); } } balanceList.Add(balanceEntry); } } } result.balances = balanceList.ToArray(); return(result); }
public void BuyToken(Address from, string symbol, BigInteger tokenID) { Runtime.Expect(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.Nexus.TokenExists(auction.BaseSymbol), "invalid base token"); var baseToken = Runtime.Nexus.GetTokenInfo(auction.BaseSymbol); Runtime.Expect(!baseToken.Flags.HasFlag(TokenFlags.Fungible), "token must be non-fungible"); var ownerships = new OwnershipSheet(baseToken.Symbol); var owner = ownerships.GetOwner(this.Storage, auction.TokenID); Runtime.Expect(owner == Runtime.Chain.Address, "invalid owner"); if (auction.Creator != from) { Runtime.Expect(Runtime.Nexus.TokenExists(auction.QuoteSymbol), "invalid quote token"); var quoteToken = Runtime.Nexus.GetTokenInfo(auction.QuoteSymbol); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "quote token must be fungible"); var balances = new BalanceSheet(quoteToken.Symbol); var balance = balances.Get(this.Storage, from); Runtime.Expect(balance >= auction.Price, "not enough balance"); Runtime.Expect(Runtime.Nexus.TransferTokens(quoteToken.Symbol, this.Storage, Runtime.Chain, from, auction.Creator, auction.Price), "payment failed"); } Runtime.Expect(Runtime.Nexus.TransferToken(baseToken.Symbol, this.Storage, Runtime.Chain, Runtime.Chain.Address, from, auction.TokenID), "transfer failed"); _auctionMap.Remove <string>(auctionID); _auctionIDs.Remove(auctionID); if (auction.Creator == from) { Runtime.Notify(EventKind.AuctionCancelled, from, new MarketEventData() { ID = auction.TokenID, BaseSymbol = auction.BaseSymbol, QuoteSymbol = auction.QuoteSymbol, Price = 0 }); } else { Runtime.Notify(EventKind.AuctionFilled, from, new MarketEventData() { ID = auction.TokenID, BaseSymbol = auction.BaseSymbol, QuoteSymbol = auction.QuoteSymbol, Price = auction.Price }); } }
public void NftMint() { var owner = KeyPair.Generate(); var simulator = new ChainSimulator(owner, 1234); var nexus = simulator.Nexus; var chain = nexus.RootChain; var symbol = "COOL"; var testUser = KeyPair.Generate(); // Create the token CoolToken as an NFT simulator.BeginBlock(); simulator.GenerateToken(owner, symbol, "CoolToken", 0, 0, Blockchain.Tokens.TokenFlags.None); simulator.EndBlock(); var token = simulator.Nexus.GetTokenInfo(symbol); Assert.IsTrue(nexus.TokenExists(symbol), "Can't find the token symbol"); // verify nft presence on the user pre-mint var ownerships = new OwnershipSheet(symbol); var ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the sender already have a CoolToken?"); var tokenROM = new byte[] { 0x1, 0x3, 0x3, 0x7 }; var tokenRAM = new byte[] { 0x1, 0x4, 0x4, 0x6 }; // Mint a new CoolToken directly on the user simulator.BeginBlock(); simulator.GenerateNft(owner, testUser.Address, symbol, tokenROM, tokenRAM); simulator.EndBlock(); // verify nft presence on the user post-mint ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the sender not have one now?"); //verify that the present nft is the same we actually tried to create var tokenId = ownedTokenList.ElementAt(0); var nft = nexus.GetNFT(symbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenROM) && nft.RAM.SequenceEqual(tokenRAM), "And why is this NFT different than expected? Not the same data"); var currentSupply = nexus.GetTokenSupply(chain.Storage, symbol); Assert.IsTrue(currentSupply == 1, "why supply did not increase?"); }
public IAPIResult GetTokenBalance([APIParameter("Address of account", "PDHcAHq1fZXuwDrtJGDhjemFnj2ZaFc7iu3qD4XjZG9eV")] string addressText, [APIParameter("Token symbol", "SOUL")] string tokenSymbol, [APIParameter("Address or name of chain", "root")] string chainInput) { if (!Address.IsValidAddress(addressText)) { return(new ErrorResult { error = "invalid address" }); } if (!Nexus.TokenExists(tokenSymbol)) { return(new ErrorResult { error = "invalid token" }); } var tokenInfo = Nexus.GetTokenInfo(tokenSymbol); var chain = FindChainByInput(chainInput); if (chain == null) { return(new ErrorResult { error = "invalid chain" }); } var address = Address.FromText(addressText); var balance = chain.GetTokenBalance(tokenSymbol, address); var result = new BalanceResult() { amount = balance.ToString(), symbol = tokenSymbol, decimals = (uint)tokenInfo.Decimals, chain = chain.Address.Text }; if (!tokenInfo.IsFungible) { var ownerships = new OwnershipSheet(tokenSymbol); var idList = ownerships.Get(chain.Storage, address); if (idList != null && idList.Any()) { result.ids = idList.Select(x => x.ToString()).ToArray(); } } return(result); }
public OwnershipSheet GetTokenOwnerships(Token token) { Throw.If(token.Flags.HasFlag(TokenFlags.Fungible), "cannot be fungible"); if (_tokenOwnerships.ContainsKey(token)) { return(_tokenOwnerships[token]); } var sheet = new OwnershipSheet(); _tokenOwnerships[token] = sheet; return(sheet); }
// NOTE should never be used directly from a contract, instead use Runtime.GetBalance! public BigInteger GetTokenBalance(StorageContext storage, IToken token, Address address) { if (token.Flags.HasFlag(TokenFlags.Fungible)) { var balances = new BalanceSheet(token.Symbol); return(balances.Get(storage, address)); } else { var ownerships = new OwnershipSheet(token.Symbol); var items = ownerships.Get(storage, address); return(items.Length); } }
public OwnershipSheet GetTokenOwnerships(string tokenSymbol) { var tokenInfo = Nexus.GetTokenInfo(tokenSymbol); Throw.If(tokenInfo.Flags.HasFlag(TokenFlags.Fungible), "cannot be fungible"); if (_tokenOwnerships.ContainsKey(tokenSymbol)) { return(_tokenOwnerships[tokenSymbol]); } var sheet = new OwnershipSheet(tokenSymbol); _tokenOwnerships[tokenSymbol] = sheet; return(sheet); }
// NOTE should never be used directly from a contract, instead use Runtime.GetBalance! public BigInteger GetTokenBalance(string tokenSymbol, Address address) { var tokenInfo = Nexus.GetTokenInfo(tokenSymbol); if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { var balances = new BalanceSheet(tokenSymbol); return(balances.Get(Storage, address)); } else { var ownerships = new OwnershipSheet(tokenSymbol); var items = ownerships.Get(this.Storage, address); return(items.Length); } }
// NFT version internal bool MintToken(RuntimeVM runtimeVM, string symbol, Address target, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { return(false); } var supply = new SupplySheet(symbol, runtimeVM.Chain, this); if (!supply.Mint(runtimeVM.ChangeSet, 1, tokenInfo.MaxSupply)) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Give(runtimeVM.ChangeSet, target, tokenID)) { return(false); } var tokenTriggerResult = SmartContract.InvokeTrigger(runtimeVM, tokenInfo.Script, TokenContract.TriggerMint, target, tokenID); if (!tokenTriggerResult) { return(false); } var accountScript = this.LookUpAddressScript(target); var accountTriggerResult = SmartContract.InvokeTrigger(runtimeVM, accountScript, AccountContract.TriggerMint, target, tokenID); if (!accountTriggerResult) { return(false); } EditNFTLocation(symbol, tokenID, runtimeVM.Chain.Address, target); return(true); }
// NFT version internal bool BurnToken(RuntimeVM runtimeVM, string symbol, Address target, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { return(false); } var chain = RootChain; var supply = new SupplySheet(symbol, chain, this); if (!supply.Burn(runtimeVM.ChangeSet, 1)) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Take(runtimeVM.ChangeSet, target, tokenID)) { return(false); } var tokenTriggerResult = SmartContract.InvokeTrigger(runtimeVM, tokenInfo.Script, TokenContract.TriggerBurn, target, tokenID); if (!tokenTriggerResult) { return(false); } var accountScript = this.LookUpAddressScript(target); var accountTriggerResult = SmartContract.InvokeTrigger(runtimeVM, accountScript, AccountContract.TriggerBurn, target, tokenID); if (!accountTriggerResult) { return(false); } return(true); }
public void SellToken(Address from, string baseSymbol, string quoteSymbol, BigInteger tokenID, BigInteger price, Timestamp endDate) { Runtime.Expect(IsWitness(from), "invalid witness"); Runtime.Expect(endDate > Runtime.Time, "invalid end date"); var maxAllowedDate = Runtime.Time + TimeSpan.FromDays(30); Runtime.Expect(endDate <= maxAllowedDate, "end date is too distant"); Runtime.Expect(Runtime.Nexus.TokenExists(quoteSymbol), "invalid quote token"); var quoteToken = Runtime.Nexus.GetTokenInfo(quoteSymbol); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "quote token must be fungible"); Runtime.Expect(Runtime.Nexus.TokenExists(baseSymbol), "invalid base token"); var baseToken = Runtime.Nexus.GetTokenInfo(baseSymbol); Runtime.Expect(!baseToken.Flags.HasFlag(TokenFlags.Fungible), "base token must be non-fungible"); var ownerships = new OwnershipSheet(baseSymbol); var owner = ownerships.GetOwner(this.Storage, tokenID); Runtime.Expect(owner == from, "invalid owner"); Runtime.Expect(Runtime.Nexus.TransferToken(Runtime, baseToken.Symbol, from, Runtime.Chain.Address, tokenID), "transfer failed"); var auction = new MarketAuction(from, Runtime.Time, endDate, baseSymbol, quoteSymbol, tokenID, price); var auctionID = baseSymbol + "." + tokenID; _auctionMap.Set(auctionID, auction); _auctionIDs.Add(auctionID); Runtime.Notify(EventKind.OrderCreated, from, new MarketEventData() { ID = tokenID, BaseSymbol = baseSymbol, QuoteSymbol = quoteSymbol, Price = price }); Runtime.Notify(EventKind.TokenSend, from, new TokenEventData() { chainAddress = this.Runtime.Chain.Address, symbol = auction.BaseSymbol, value = tokenID }); }
internal bool TransferToken(string symbol, StorageContext storage, Chain chain, Address source, Address destination, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (!tokenInfo.Flags.HasFlag(TokenFlags.Transferable)) { throw new Exception("Not transferable"); } if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { throw new Exception("Should be non-fungible"); } if (tokenID <= 0) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Take(storage, source, tokenID)) { return(false); } if (!ownerships.Give(storage, destination, tokenID)) { return(false); } EditNFTLocation(symbol, tokenID, chain.Address, destination); return(true); }
internal bool TransferToken(RuntimeVM runtimeVM, string symbol, Address source, Address destination, BigInteger tokenID) { if (!TokenExists(symbol)) { return(false); } var tokenInfo = GetTokenInfo(symbol); if (!tokenInfo.Flags.HasFlag(TokenFlags.Transferable)) { throw new Exception("Not transferable"); } if (tokenInfo.Flags.HasFlag(TokenFlags.Fungible)) { throw new Exception("Should be non-fungible"); } if (tokenID <= 0) { return(false); } var ownerships = new OwnershipSheet(symbol); if (!ownerships.Take(runtimeVM.ChangeSet, source, tokenID)) { return(false); } if (!ownerships.Give(runtimeVM.ChangeSet, destination, tokenID)) { return(false); } var tokenTriggerResult = SmartContract.InvokeTrigger(runtimeVM, tokenInfo.Script, TokenContract.TriggerSend, source, tokenID); if (!tokenTriggerResult) { return(false); } tokenTriggerResult = SmartContract.InvokeTrigger(runtimeVM, tokenInfo.Script, TokenContract.TriggerReceive, destination, tokenID); if (!tokenTriggerResult) { return(false); } var accountScript = this.LookUpAddressScript(source); var accountTriggerResult = SmartContract.InvokeTrigger(runtimeVM, accountScript, AccountContract.TriggerSend, source, tokenID); if (!accountTriggerResult) { return(false); } accountScript = this.LookUpAddressScript(destination); accountTriggerResult = SmartContract.InvokeTrigger(runtimeVM, accountScript, AccountContract.TriggerSend, destination, tokenID); if (!accountTriggerResult) { return(false); } EditNFTLocation(symbol, tokenID, runtimeVM.Chain.Address, destination); return(true); }
public void SidechainNftTransfer() { var owner = KeyPair.Generate(); var simulator = new ChainSimulator(owner, 1234); var nexus = simulator.Nexus; var sourceChain = nexus.RootChain; var targetChain = nexus.FindChainByName("privacy"); var nftSymbol = "COOL"; var sender = KeyPair.Generate(); var receiver = KeyPair.Generate(); var fullAmount = UnitConversion.ToBigInteger(10, Nexus.FuelTokenDecimals); var smallAmount = fullAmount / 2; Assert.IsTrue(smallAmount > 0); // Send some SOUL to the test user (required for gas used in "transfer" transaction) simulator.BeginBlock(); simulator.GenerateTransfer(owner, sender.Address, sourceChain, Nexus.FuelTokenSymbol, fullAmount); simulator.EndBlock(); // Create the token CoolToken as an NFT simulator.BeginBlock(); simulator.GenerateToken(owner, nftSymbol, "CoolToken", 0, 0, TokenFlags.Transferable); simulator.EndBlock(); var token = simulator.Nexus.GetTokenInfo(nftSymbol); var tokenData = new byte[] { 0x1, 0x3, 0x3, 0x7 }; Assert.IsTrue(nexus.TokenExists(nftSymbol), "Can't find the token symbol"); // verify nft presence on the sender pre-mint var ownerships = new OwnershipSheet(nftSymbol); var ownedTokenList = ownerships.Get(sourceChain.Storage, sender.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the sender already have a CoolToken?"); // Mint a new CoolToken directly on the sender simulator.BeginBlock(); simulator.GenerateNft(owner, sender.Address, nftSymbol, tokenData, new byte[0]); simulator.EndBlock(); // verify nft presence on the sender post-mint ownedTokenList = ownerships.Get(sourceChain.Storage, sender.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the sender not have one now?"); //verify that the present nft is the same we actually tried to create var tokenId = ownedTokenList.ElementAt(0); var nft = nexus.GetNFT(nftSymbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenData) || nft.RAM.SequenceEqual(tokenData), "And why is this NFT different than expected? Not the same data"); // verify nft presence on the receiver pre-transfer ownedTokenList = ownerships.Get(targetChain.Storage, receiver.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the receiver already have a CoolToken?"); var extraFee = UnitConversion.ToBigInteger(0.001m, Nexus.FuelTokenDecimals); // transfer that nft from sender to receiver simulator.BeginBlock(); simulator.GenerateSideChainSend(sender, Nexus.FuelTokenSymbol, sourceChain, receiver.Address, targetChain, smallAmount, extraFee); var txA = simulator.GenerateNftSidechainTransfer(sender, receiver.Address, sourceChain, targetChain, nftSymbol, tokenId); simulator.EndBlock(); var blockA = nexus.RootChain.LastBlock; // finish the chain transfer simulator.BeginBlock(); simulator.GenerateSideChainSettlement(receiver, nexus.RootChain, targetChain, blockA.Hash); Assert.IsTrue(simulator.EndBlock().Any()); // verify the sender no longer has it ownedTokenList = ownerships.Get(sourceChain.Storage, sender.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the sender still have one?"); // verify nft presence on the receiver post-transfer ownedTokenList = ownerships.Get(targetChain.Storage, receiver.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the receiver not have one now?"); //verify that the transfered nft is the same we actually tried to create tokenId = ownedTokenList.ElementAt(0); nft = nexus.GetNFT(nftSymbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenData) || nft.RAM.SequenceEqual(tokenData), "And why is this NFT different than expected? Not the same data"); }
public void NftTransfer() { var owner = KeyPair.Generate(); var simulator = new ChainSimulator(owner, 1234); var nexus = simulator.Nexus; var chain = nexus.RootChain; var nftKey = KeyPair.Generate(); var nftSymbol = "COOL"; var nftName = "CoolToken"; var sender = KeyPair.Generate(); var receiver = KeyPair.Generate(); // Send some SOUL to the test user (required for gas used in "transfer" transaction) simulator.BeginBlock(); simulator.GenerateTransfer(owner, sender.Address, chain, Nexus.FuelTokenSymbol, UnitConversion.ToBigInteger(1, Nexus.FuelTokenDecimals)); simulator.EndBlock(); // Create the token CoolToken as an NFT simulator.BeginBlock(); simulator.GenerateToken(owner, nftSymbol, nftName, 0, 0, TokenFlags.Transferable); simulator.EndBlock(); var token = simulator.Nexus.GetTokenInfo(nftSymbol); var tokenData = new byte[] { 0x1, 0x3, 0x3, 0x7 }; Assert.IsTrue(nexus.TokenExists(nftSymbol), "Can't find the token symbol"); // verify nft presence on the sender pre-mint var ownerships = new OwnershipSheet(nftSymbol); var ownedTokenList = ownerships.Get(chain.Storage, sender.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the sender already have a CoolToken?"); // Mint a new CoolToken directly on the sender simulator.BeginBlock(); simulator.GenerateNft(owner, sender.Address, nftSymbol, tokenData, new byte[0]); simulator.EndBlock(); // verify nft presence on the sender post-mint ownedTokenList = ownerships.Get(chain.Storage, sender.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the sender not have one now?"); //verify that the present nft is the same we actually tried to create var tokenId = ownedTokenList.ElementAt(0); var nft = nexus.GetNFT(nftSymbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenData) || nft.RAM.SequenceEqual(tokenData), "And why is this NFT different than expected? Not the same data"); // verify nft presence on the receiver pre-transfer ownedTokenList = ownerships.Get(chain.Storage, receiver.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the receiver already have a CoolToken?"); // transfer that nft from sender to receiver simulator.BeginBlock(); var txA = simulator.GenerateNftTransfer(sender, receiver.Address, chain, nftSymbol, tokenId); simulator.EndBlock(); // verify nft presence on the receiver post-transfer ownedTokenList = ownerships.Get(chain.Storage, receiver.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the receiver not have one now?"); //verify that the transfered nft is the same we actually tried to create tokenId = ownedTokenList.ElementAt(0); nft = nexus.GetNFT(nftSymbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenData) || nft.RAM.SequenceEqual(tokenData), "And why is this NFT different than expected? Not the same data"); }
public void NftBurn() { var owner = KeyPair.Generate(); var simulator = new ChainSimulator(owner, 1234); var nexus = simulator.Nexus; var chain = nexus.RootChain; var symbol = "COOL"; var testUser = KeyPair.Generate(); // Create the token CoolToken as an NFT simulator.BeginBlock(); simulator.GenerateToken(owner, symbol, "CoolToken", 0, 0, TokenFlags.Burnable); simulator.EndBlock(); // Send some SOUL to the test user (required for gas used in "burn" transaction) simulator.BeginBlock(); simulator.GenerateTransfer(owner, testUser.Address, chain, Nexus.FuelTokenSymbol, UnitConversion.ToBigInteger(1, Nexus.FuelTokenDecimals)); simulator.EndBlock(); var token = simulator.Nexus.GetTokenInfo(symbol); var tokenData = new byte[] { 0x1, 0x3, 0x3, 0x7 }; Assert.IsTrue(nexus.TokenExists(symbol), "Can't find the token symbol"); // verify nft presence on the user pre-mint var ownerships = new OwnershipSheet(symbol); var ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the user already have a CoolToken?"); // Mint a new CoolToken directly on the user simulator.BeginBlock(); BigInteger tokenKCALWorth = 100; simulator.MintNonFungibleToken(owner, testUser.Address, symbol, tokenData, new byte[0], tokenKCALWorth); simulator.EndBlock(); // verify nft presence on the user post-mint ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(ownedTokenList.Count() == 1, "How does the user not have one now?"); var ownerAddress = ownerships.GetOwner(chain.Storage, 1); Assert.IsTrue(ownerAddress == testUser.Address); //verify that the present nft is the same we actually tried to create var tokenId = ownedTokenList.ElementAt(0); var nft = nexus.GetNFT(symbol, tokenId); Assert.IsTrue(nft.ROM.SequenceEqual(tokenData) || nft.RAM.SequenceEqual(tokenData), "And why is this NFT different than expected? Not the same data"); // burn the token simulator.BeginBlock(); simulator.GenerateNftBurn(testUser, chain, symbol, tokenId); simulator.EndBlock(); //verify the user no longer has the token ownedTokenList = ownerships.Get(chain.Storage, testUser.Address); Assert.IsTrue(!ownedTokenList.Any(), "How does the user still have it post-burn?"); }
private void DumpBalances(Chain chain, IToken token) { var symbol = token.Symbol; Console.WriteLine($"Analysing {symbol} balances on {chain.Name} chain"); var list = new List <BalanceEntry>(); balances[symbol] = list; var fungible = token.IsFungible(); var prefix = fungible ? BalanceSheet.MakePrefix(symbol) : OwnershipSheet.MakePrefix(symbol); var store = chain.Storage; var stakeMapKey = SmartContract.GetKeyForField(NativeContractKind.Stake, "_stakeMap", true); var stakeMap = new StorageMap(stakeMapKey, store); //var stakeCount = stakeMap.Count(); var addresses = new HashSet <Address>(); decimal total = 0; store.Visit((key, value) => { if (HasPrefix(prefix, key)) { var diff = key.Length - prefix.Length; if (diff < Address.LengthInBytes) { return; } var bytes = new byte[Address.LengthInBytes]; ByteArrayUtils.CopyBytes(key, prefix.Length, bytes, 0, bytes.Length); var addr = Address.FromBytes(bytes); BigInteger amount; if (!fungible) { if (addresses.Contains(addr)) { return; // already visited } var newKey = ByteArrayUtils.ConcatBytes(prefix, bytes); var map = new StorageMap(newKey, store); amount = map.Count(); } else { if (value.Length > 0) { amount = BigInteger.FromSignedArray(value); } else { amount = 0; } if (symbol == DomainSettings.StakingTokenSymbol && stakeMap.ContainsKey <Address>(addr)) { var temp = stakeMap.Get <Address, EnergyStake>(addr); amount += temp.stakeAmount; } } if (amount < 1) { return; } addresses.Add(addr); var dec = UnitConversion.ToDecimal(amount, token.Decimals); total += dec; list.Add(new BalanceEntry(addr.Text, dec)); } }, uint.MaxValue, new byte[0]); /* * if (symbol == DomainSettings.StakingTokenSymbol) * { * var masterListKey = GetKeyForField<StakeContract>("_mastersList"); * var masterList = new StorageList(masterListKey, storage); * var masterCount = masterList.Count(); * for (int i = 0; i < masterCount; i++) * { * var master = masterList.Get<EnergyMaster>(i); * if (addresses.Contains(master.address)) * { * continue; * } * * var temp = stakeMap.Get<Address, EnergyAction>(master.address); * * string s; * * if (PrettyPrint) * { * var stake = UnitConversion.ToDecimal(temp.totalAmount, decimals); * s = stake.ToString(); * total += stake; * } * else * { * s = temp.totalAmount.ToString(); * } * * Console.WriteLine($"{master.address.Text},{symbol},{s}"); * } * }*/ totals[symbol] = total; if (list.Count == 0) { return; } list.Sort((x, y) => y.value.CompareTo(x.value)); var lines = new List <string>(); list.ForEach(x => lines.Add($"{x.address},{symbol},{x.value}")); File.WriteAllLines($"{outputFolder}/{chain.Name}_balances_{symbol}.csv", lines); }
// NOTE this lists only nfts owned in this chain public IEnumerable <BigInteger> GetOwnedTokens(string tokenSymbol, Address address) { var ownership = new OwnershipSheet(tokenSymbol); return(ownership.Get(this.Storage, address)); }
// NOTE this lists only nfts owned in this chain public BigInteger[] GetOwnedTokens(StorageContext storage, string tokenSymbol, Address address) { var ownership = new OwnershipSheet(tokenSymbol); return(ownership.Get(storage, address).ToArray()); }