Example #1
0
        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
            });
        }
Example #2
0
        // 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);
        }
Example #3
0
        // 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);
        }
Example #4
0
        // 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));
        }
Example #5
0
        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);
        }
Example #6
0
        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());
        }
Example #7
0
        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
                });
            }
        }
Example #9
0
        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?");
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
 // 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);
        }
Example #14
0
        // 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);
            }
        }
Example #15
0
        // 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);
        }
Example #16
0
        // 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);
        }
Example #17
0
        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
            });
        }
Example #18
0
        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);
        }
Example #19
0
        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);
        }
Example #20
0
        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");
        }
Example #21
0
        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");
        }
Example #22
0
        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?");
        }
Example #23
0
        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);
        }
Example #24
0
        // 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));
        }
Example #25
0
        // 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());
        }