public static ScriptBuilder CrossTransferNFT(this ScriptBuilder sb, Address destinationChain, string tokenSymbol, Address from, string to, BigInteger tokenId)
 {
     return(sb.CallInterop("Runtime.SendToken", destinationChain, from, to, tokenSymbol, tokenId));
 }
 public static ScriptBuilder TransferBalance(this ScriptBuilder sb, string tokenSymbol, Address from, Address to)
 {
     return(sb.CallInterop("Runtime.TransferBalance", from, to, tokenSymbol));
 }
 public static ScriptBuilder TransferNFT(this ScriptBuilder sb, string tokenSymbol, Address from, string to, BigInteger tokenId)//todo check if this is valid
 {
     return(sb.CallInterop("Runtime.TransferToken", from, to, tokenSymbol, tokenId));
 }
 public static ScriptBuilder TransferTokens(this ScriptBuilder sb, string tokenSymbol, Address from, Address to, BigInteger amount)
 {
     return(sb.CallInterop("Runtime.TransferTokens", from, to, tokenSymbol, amount));
 }
 public static ScriptBuilder MintTokens(this ScriptBuilder sb, string tokenSymbol, Address from, Address target, BigInteger amount)
 {
     return(sb.CallInterop("Runtime.MintTokens", from, target, tokenSymbol, amount));
 }
Example #6
0
        private static void DeployOrUpgrade(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee, bool isUpgrade)
        {
            if (args.Length != 1)
            {
                throw new CommandException("Invalid number of arguments, expected file name");
            }

            DoChecks(api);

            var fileName = args[0];

            if (!File.Exists(fileName))
            {
                throw new CommandException("Provided file does not exist");
            }

            if (!FileExistsCaseSensitive(fileName))
            {
                throw new CommandException("Provided file case does not match real file name case");
            }

            var extension = ScriptModule.ScriptExtension;

            if (!fileName.EndsWith(extension))
            {
                throw new CommandException($"Provided file is not a compiled {extension} script");
            }

            var abiFile = fileName.Replace(extension, ".abi");

            if (!File.Exists(abiFile))
            {
                throw new CommandException($"No ABI file {abiFile} that matches provided script file");
            }

            var contractName = Path.GetFileNameWithoutExtension(fileName);

            var contractScript = File.ReadAllBytes(fileName);
            var abiBytes       = File.ReadAllBytes(abiFile);

            var abi = ContractInterface.FromBytes(abiBytes);

            var sb = new ScriptBuilder();

            int nexusVersion = 0;

            try
            {
                var nexusDetails = api.Execute("getNexus", new object[] { false });
                var root         = LunarLabs.Parser.JSON.JSONReader.ReadFromString(nexusDetails);

                var governance = root["governance"];

                var entry = governance.Children.Where(x => x.GetNode("name").Value == "nexus.protocol.version").FirstOrDefault();
                entry = entry.GetNodeByIndex(1);

                nexusVersion = Int32.Parse(entry.Value);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                nexusVersion = -1;
            }

            if (nexusVersion <= 1)
            {
                throw new CommandException("Failed to obtain nexus version via API");
            }


            bool isToken        = ValidationUtils.IsValidTicker(contractName);
            var  availableFlags = Enum.GetValues(typeof(TokenFlags)).Cast <TokenFlags>().ToArray();

            sb.AllowGas(Keys.Address, Address.Null, minFee, 9999);

            if (isUpgrade)
            {
                // check for modification in flags
                if (isToken)
                {
                    var symbol    = contractName;
                    var resultStr = api.Execute("getToken", new[] { symbol, "false" });

                    logger.Debug($"{resultStr}");

                    //2021.08.27 sfichera: Fixed api obj deserialization.
                    //dynamic apiResult = System.Text.Json.JsonSerializer.Deserialize<TokenResult>(resultStr);
                    dynamic apiResult = JsonConvert.DeserializeObject <TokenResult>(resultStr);

                    if (apiResult is TokenResult)
                    {
                        var oldToken   = (TokenResult)apiResult;
                        var oldFlags   = TokenFlags.None;
                        var splitFlags = oldToken.flags.Split(',');
                        foreach (var entry in splitFlags)
                        {
                            TokenFlags flag;

                            if (Enum.TryParse <TokenFlags>(entry, true, out flag))
                            {
                                oldFlags |= flag;
                            }
                        }

                        foreach (var flag in availableFlags)
                        {
                            var propName = "is" + flag;
                            if (abi.HasMethod(propName))
                            {
                                var isSet  = ExecuteScript(contractScript, abi, propName).AsBool();
                                var wasSet = oldFlags.HasFlag(flag);
                                if (isSet != wasSet)
                                {
                                    throw new CommandException($"Detected '{flag}' flag change: {wasSet} => {isSet}");
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new CommandException("could not find any deployed token contract for " + symbol);
                    }
                }

                sb.CallInterop("Runtime.UpgradeContract", Keys.Address, contractName, contractScript, abiBytes);
            }
            else
            if (isToken)
            {
                if (!abi.HasMethod("getName"))
                {
                    throw new CommandException("token contract is missing required 'name' property");
                }

                string symbol = null;


                if (nexusVersion < 6)
                {
                    symbol = contractName;
                }
                else
                {
                    if (abi.HasMethod("getSymbol"))
                    {
                        symbol = ExecuteScript(contractScript, abi, "getSymbol").AsString();
                    }

                    if (string.IsNullOrEmpty(symbol))
                    {
                        throw new CommandException("token contract 'symbol' property is either missing or returning an empty value");
                    }
                }

                var name = ExecuteScript(contractScript, abi, "getName").AsString();

                if (string.IsNullOrEmpty(name))
                {
                    throw new CommandException("token contract 'name' property is either missing or returning an empty value");
                }

                BigInteger maxSupply = abi.HasMethod("getMaxSupply") ? ExecuteScript(contractScript, abi, "getMaxSupply").AsNumber() : 0;
                BigInteger decimals  = abi.HasMethod("getDecimals") ? ExecuteScript(contractScript, abi, "getDecimals").AsNumber() : 0;

                TokenFlags flags = TokenFlags.None;

                foreach (var flag in availableFlags)
                {
                    var propName = "is" + flag;
                    if (abi.HasMethod(propName) && ExecuteScript(contractScript, abi, propName).AsBool())
                    {
                        flags |= flag;
                    }
                }

                if (nexusVersion < 6)
                {
                    sb.CallInterop("Nexus.CreateToken", Keys.Address, symbol, name, maxSupply, decimals, flags, contractScript, abiBytes);
                }
                else
                {
                    sb.CallInterop("Nexus.CreateToken", Keys.Address, contractScript, abiBytes);
                }

                contractName = symbol;
            }
            else
            {
                sb.CallInterop("Runtime.DeployContract", Keys.Address, contractName, contractScript, abiBytes);
            }

            sb.SpendGas(Keys.Address);
            var script = sb.EndScript();

            if (!isUpgrade)
            {
                var upgradeTrigger = AccountContract.GetTriggerForABI(AccountTrigger.OnUpgrade);
                if (abi.Implements(upgradeTrigger))
                {
                    logger.Message($"{contractName} implements proper triggers, and can be upgraded later.");
                }
                else
                {
                    logger.Warning($"{contractName} does not implements proper triggers, can't be upgraded later.");
                }
            }

            var hash = ExecuteTransaction(settings, api, script, ProofOfWork.Minimal, Keys);

            if (hash != Hash.Null)
            {
                var expectedEvent    = isUpgrade ? EventKind.ContractUpgrade : (isToken ? EventKind.TokenCreate : EventKind.ContractDeploy);
                var expectedEventStr = expectedEvent.ToString();

                var events = GetTransactionEvents(hash);
                if (events.Any(x => x.kind == expectedEventStr))
                {
                    var contractAddress = SmartContract.GetAddressForName(contractName);

                    string action = isUpgrade ? "Upgraded" : "Deployed";

                    logger.Message($"{action} {contractName} at {contractAddress}");
                }
                else
                {
                    throw new CommandException("Transaction was confirmed but deployment event is missing!");
                }
            }
        }
Example #7
0
        private static void DeployOrUpgrade(string[] args, NexusAPI api, BigInteger minFee, bool isUpgrade)
        {
            if (args.Length != 1)
            {
                throw new CommandException("Invalid number of arguments, expected file name");
            }

            DoChecks(api);

            var fileName = args[0];

            if (!File.Exists(fileName))
            {
                throw new CommandException("Provided file does not exist");
            }

            var extension = ScriptModule.ScriptExtension;

            if (!fileName.EndsWith(extension))
            {
                throw new CommandException($"Provided file is not a compiled {extension} script");
            }

            var abiFile = fileName.Replace(extension, ".abi");

            if (!File.Exists(abiFile))
            {
                throw new CommandException($"No ABI file {abiFile} that matches provided script file");
            }

            var contractName = Path.GetFileNameWithoutExtension(fileName);

            var contractScript = File.ReadAllBytes(fileName);
            var abiBytes       = File.ReadAllBytes(abiFile);

            var abi = ContractInterface.FromBytes(abiBytes);

            var sb = new ScriptBuilder();

            bool isToken        = ValidationUtils.IsValidTicker(contractName);
            var  availableFlags = Enum.GetValues(typeof(TokenFlags)).Cast <TokenFlags>().ToArray();

            sb.AllowGas(Keys.Address, Address.Null, minFee, 9999);

            if (isUpgrade)
            {
                // check for modification in flags
                if (isToken)
                {
                    var     symbol    = contractName;
                    var     resultStr = api.Execute("getToken", new[] { symbol, "false" });
                    dynamic apiResult = JsonConvert.DeserializeObject <TokenResult>(resultStr);

                    if (apiResult is TokenResult)
                    {
                        var oldToken = (TokenResult)apiResult;

                        var oldFlags   = TokenFlags.None;
                        var splitFlags = oldToken.flags.Split(',');
                        foreach (var entry in splitFlags)
                        {
                            TokenFlags flag;

                            if (Enum.TryParse <TokenFlags>(entry, true, out flag))
                            {
                                oldFlags |= flag;
                            }
                        }

                        foreach (var flag in availableFlags)
                        {
                            var propName = "is" + flag;
                            if (abi.HasMethod(propName))
                            {
                                var isSet  = ExecuteScript(contractScript, abi, propName).AsBool();
                                var wasSet = oldFlags.HasFlag(flag);
                                if (isSet != wasSet)
                                {
                                    throw new CommandException($"Detected '{flag}' flag change: {wasSet} => {isSet}");
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new CommandException("could not find any deployed token contract for " + symbol);
                    }
                }

                sb.CallInterop("Runtime.UpgradeContract", Keys.Address, contractName, contractScript, abiBytes);
            }
            else
            if (isToken)
            {
                if (!abi.HasMethod("getName"))
                {
                    throw new CommandException("token contract is missing required 'name' property");
                }

                var symbol = contractName;
                var name   = ExecuteScript(contractScript, abi, "getName").AsString();

                if (string.IsNullOrEmpty(name))
                {
                    throw new CommandException("token contract 'name' property is returning an empty value");
                }

                BigInteger maxSupply = abi.HasMethod("getMaxSupply") ? ExecuteScript(contractScript, abi, "getMaxSupply").AsNumber() : 0;
                BigInteger decimals  = abi.HasMethod("getDecimals") ? ExecuteScript(contractScript, abi, "getDecimals").AsNumber() : 0;

                TokenFlags flags = TokenFlags.None;

                foreach (var flag in availableFlags)
                {
                    var propName = "is" + flag;
                    if (abi.HasMethod(propName) && ExecuteScript(contractScript, abi, propName).AsBool())
                    {
                        flags |= flag;
                    }
                }

                sb.CallInterop("Nexus.CreateToken", Keys.Address, symbol, name, maxSupply, decimals, flags, contractScript, abiBytes);

                contractName = symbol;
            }
            else
            {
                sb.CallInterop("Runtime.DeployContract", Keys.Address, contractName, contractScript, abiBytes);
            }

            sb.SpendGas(Keys.Address);
            var script = sb.EndScript();

            if (!isUpgrade)
            {
                var upgradeTrigger = AccountContract.GetTriggerForABI(AccountTrigger.OnUpgrade);
                if (abi.Implements(upgradeTrigger))
                {
                    logger.Message($"{contractName} implements proper triggers, and can be upgraded later.");
                }
                else
                {
                    logger.Warning($"{contractName} does not implements proper triggers, can't be upgraded later.");
                }
            }

            var hash = ExecuteTransaction(api, script, ProofOfWork.Minimal, Keys);

            if (hash != Hash.Null)
            {
                var expectedEvent    = isUpgrade ? EventKind.ContractUpgrade : (isToken ? EventKind.TokenCreate : EventKind.ContractDeploy);
                var expectedEventStr = expectedEvent.ToString();

                var events = GetTransactionEvents(hash);
                if (events.Any(x => x.kind == expectedEventStr))
                {
                    var contractAddress = SmartContract.GetAddressForName(contractName);

                    string action = isUpgrade ? "Upgraded" : "Deployed";

                    logger.Message($"{action} {contractName} at {contractAddress}");
                }
                else
                {
                    throw new CommandException("Transaction was confirmed but deployment event is missing!");
                }
            }
        }
Example #8
0
        static void Main(string[] args)
        {
            /*var obj = Serialization.Unserialize<VMObject>(Base16.Decode("0821204DBC2216A0EA109AA3436D23A67F381AE98282C040E5F117CDFDA80108733D04"));
             * var hash = obj.AsInterop<Hash>();
             * Console.WriteLine(hash);*/

            Console.Write($"Enter nexus name: ");
            nexusName = Console.ReadLine();

            Console.Write($"Enter WIF for signing transaction: ");
            var wif = Console.ReadLine();

            signerKeys = PhantasmaKeys.FromWIF(wif);

            Console.WriteLine("Select operation: ");
            Console.WriteLine("0 - Exit");
            Console.WriteLine("1 - DAO Transfer");
            Console.WriteLine("2 - Create token");
            Console.WriteLine("3 - Mint tokens");
            Console.WriteLine("4 - Create sale");
            Console.WriteLine("5 - Whitelist sale address");

            var str = Console.ReadLine();

            int option;

            if (!int.TryParse(str, out option))
            {
                Console.WriteLine("Invalid option...");
                return;
            }

            byte[] script;

            switch (option)
            {
            case 0:
                return;

            case 1:
                script = GenDAOTransfer();
                break;

            case 2:
                script = GenCreateToken();
                break;

            case 3:
                script = GenMintToken();
                break;

            case 4:
                script = GenCreateSale();
                break;

            case 5:
                script = GenWhitelist();
                break;

            case 6:
            {
                var sb = new ScriptBuilder().AllowGas(signerKeys.Address, Address.Null, 100000, 99999);

                //sb.CallContract(NativeContractKind.Sale, nameof(SaleContract.EditSalePrice), Hash.Parse("043D730801A8FDCD17F1E540C08282E91A387FA6236D43A39A10EAA01622BC4D"), 4);
                sb.CallInterop("Organization.Kill", signerKeys.Address, "exchange_pot");

                script = sb.SpendGas(signerKeys.Address).
                         EndScript();
                break;
            }

            default:
                Console.WriteLine("Unsupported option...");
                return;
            }

            if (script == null)
            {
                Console.WriteLine("Transaction generation failed...");
                return;
            }

            var expiration = new Timestamp(Timestamp.Now.Value + 1000);
            var tx         = new Transaction(nexusName, "main", script, expiration, "TXSNDER1.0");

            tx.Mine(ProofOfWork.Minimal);
            tx.Sign(signerKeys);

            var rawTx = tx.ToByteArray(true);

            var hexRawTx = Base16.Encode(rawTx);


            Console.Write("Node REST URL: ");
            var url = Console.ReadLine();

            if (!url.StartsWith("http"))
            {
                url = "http://" + url;
            }

            // check for port
            if (!url.Replace("http://", "").Contains(":"))
            {
                var defaultPort = 7078;
                Console.WriteLine("No port specified, using defaul port " + defaultPort);
                url += ":" + defaultPort;
            }

            var baseUrl = url;

            url = baseUrl + "/api/sendRawTransaction/" + hexRawTx;

            if (url.Length > 2040)
            {
                Console.WriteLine("Script is too big");
                return;
            }

            Hash txHash;

            using (var wb = new WebClient())
            {
                var response = wb.DownloadString(url);

                Console.WriteLine(response);

                if (response.StartsWith("\""))
                {
                    response = response.Substring(1, response.Length - 2);
                }

                if (!Hash.TryParse(response, out txHash))
                {
                    Console.WriteLine("Failed...");
                    return;
                }
            }

            Console.WriteLine("Confirming...");
            Thread.Sleep(1000 * 20);

            url = baseUrl + "/api/getTransaction/" + txHash.ToString();
            using (var wb = new WebClient())
            {
                var response = wb.DownloadString(url);

                Console.WriteLine(response);
            }

            Console.WriteLine("Finished.");
            Console.ReadLine();
        }