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)); }
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!"); } } }
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!"); } } }
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(); }