public static void ExecuteScript(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee) { 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 (!fileName.EndsWith(".tx")) { throw new CommandException($"Provided file is not a compiled transaction script"); } var txScript = File.ReadAllBytes(fileName); var sb = new ScriptBuilder(); sb.AllowGas(Keys.Address, Address.Null, minFee, 9999); sb.EmitRaw(txScript); sb.SpendGas(Keys.Address); var script = sb.EndScript(); var hash = ExecuteTransaction(settings, api, script, ProofOfWork.Minimal, Keys); }
public static void Finish(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee) { string hashStr = null; try { hashStr = args[0]; } catch { throw new CommandException("Could not obtain sale hash"); } Hash saleHash; if (!Hash.TryParse(hashStr, out saleHash)) { throw new CommandException("Invalid sale hash"); } WalletModule.DoChecks(api); var script = ScriptUtils.BeginScript(). AllowGas(WalletModule.Keys.Address, Address.Null, minFee, 9999). CallContract(Domain.NativeContractKind.Sale, nameof(SaleContract.CloseSale), WalletModule.Keys.Address, saleHash). SpendGas(WalletModule.Keys.Address). EndScript(); WalletModule.ExecuteTransaction(settings, api, script, ProofOfWork.None, WalletModule.Keys); }
private TestData CreateAPI(bool useMempool = false) { var owner = PhantasmaKeys.FromWIF(testWIF); var nexus = new Nexus("simnet", null, null); nexus.SetOracleReader(new OracleSimulator(nexus)); var sim = new NexusSimulator(nexus, owner, 1234); var mempool = useMempool? new Mempool(sim.Nexus, 2, 1, System.Text.Encoding.UTF8.GetBytes("TEST"), 0, new DummyLogger()) : null; mempool?.SetKeys(owner); var api = new NexusAPI(sim.Nexus); api.Mempool = mempool; var data = new TestData() { owner = owner, simulator = sim, nexus = sim.Nexus, api = api }; mempool?.StartInThread(); return(data); }
public static void Migrate(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee) { if (args.Length != 1) { throw new CommandException("Invalid number of arguments, expected new wif"); } DoChecks(api); var newWIF = args[0]; var newKeys = PhantasmaKeys.FromWIF(newWIF); var expectedLimit = 800; var sb = new ScriptBuilder(); sb.AllowGas(Keys.Address, Address.Null, minFee, expectedLimit); sb.CallContract("validator", "Migrate", Keys.Address, newKeys.Address); sb.SpendGas(Keys.Address); var script = sb.EndScript(); var hash = ExecuteTransaction(settings, api, script, ProofOfWork.None, Keys /*, newKeys*/); if (hash != Hash.Null) { logger.Message($"Migrated to " + newKeys.Address); Keys = newKeys; } }
public override void Init(MyObjectBuilder_SessionComponent sessionComponent) { Tools.Log(MyLogSeverity.Info, "Initializing"); MyAPIGateway.Multiplayer.RegisterSecureMessageHandler(8008, PluginHandleIncomingPacket); if (!NetworkAPI.IsInitialized) { NetworkAPI.Init(ComId, DisplayName, Keyword); } Network.RegisterChatCommand(string.Empty, Chat_Help); Network.RegisterChatCommand("help", Chat_Help); if (!MyAPIGateway.Session.IsServer) { Network.RegisterChatCommand("score", (args) => Network.SendCommand("score")); Network.RegisterChatCommand("save", (args) => Network.SendCommand("save")); Network.RegisterChatCommand("force-load", (args) => Network.SendCommand("force-load")); Network.RegisterNetworkCommand("score", ClientCallback_Score); //NEXUS: client message handler, recieves and shows messages forwarded from the sector if (!nexusCliInit) { MyAPIGateway.Multiplayer.RegisterMessageHandler(CliComId, HandleClientCrossServerComm); nexusCliInit = true; } } else { ZoneBlock.OnAwardPoints += AwardPoints; ZoneBlock.OnPlayerDied += PlayerDied; Network.RegisterChatCommand("score", (args) => { MyAPIGateway.Utilities.ShowMissionScreen(Network.ModName, "King of the Hill", "", FormatScores()); }); Network.RegisterChatCommand("save", (args) => { ServerCallback_Save(MyAPIGateway.Session.Player.SteamUserId, "save", null, DateTime.Now); }); Network.RegisterChatCommand("force-load", (args) => { ServerCallback_ForceLoad(MyAPIGateway.Session.Player.SteamUserId, "force_load", null, DateTime.Now); }); Network.RegisterNetworkCommand("score", ServerCallback_Score); Network.RegisterNetworkCommand("save", ServerCallback_Save); Network.RegisterNetworkCommand("force_load", ServerCallback_ForceLoad); if (MyAPIGateway.Multiplayer.IsServer && !nexusInit) { //NEXUS: registration of sector handlers and nexus instances for each Nexus2 = new NexusAPI(5431); // score message Nexus = new NexusAPI(5432); // text message MyAPIGateway.Multiplayer.RegisterMessageHandler(5431, HandleCrossServerScore); MyAPIGateway.Multiplayer.RegisterMessageHandler(5432, HandleCrossServerComm); nexusInit = true; } } MyAPIGateway.Entities.OnEntityAdd += EntityAdded; MyAPIGateway.Entities.OnEntityRemove += EntityRemoved; }
protected override void OnStart() { Console.CancelKeyPress += delegate { this.Terminate(); }; ValidateConfig(); Version = Assembly.GetAssembly(typeof(Spook)).GetVersion(); _nodeKeys = SetupNodeKeys(); if (!SetupNexus()) { this.OnStop(); return; } SetupOracleApis(); if (Settings.Node.HasMempool && !Settings.Node.Readonly) { _mempool = SetupMempool(); } _peerCaps = SetupPeerCaps(); _node = SetupNode(); _nexusApi = SetupNexusApi(); if (_node != null && Settings.App.NodeStart) { _node.StartInThread(); } _commandDispatcher = SetupCommandDispatcher(); if (Settings.Simulator.Enabled) { StartSimulator(_commandDispatcher); } else { MakeReady(_commandDispatcher); } if (!string.IsNullOrEmpty(Settings.Oracle.Swaps)) { _tokenSwapper = StartTokenSwapper(); } }
public static void GridOfferBought(MarketListing NewOffer, ulong Buyer) { if (!NexusSupport.RunningNexus) { return; } string Title = "Hangar Market - Offer Purchased"; if (!MySession.Static.Players.TryGetIdentityFromSteamID(NewOffer.SteamID, out MyIdentity Seller)) { return; } if (!MySession.Static.Players.TryGetIdentityFromSteamID(NewOffer.SteamID, out MyIdentity BuyerIdentity)) { return; } var Fac = MySession.Static.Factions.GetPlayerFaction(Seller.IdentityId); var BuyerFac = MySession.Static.Factions.GetPlayerFaction(BuyerIdentity.IdentityId); string Footer; if (Fac != null) { Footer = $"Seller: [{Fac.Tag}] {Seller.DisplayName}"; } else { Footer = $"Seller: {Seller.DisplayName}"; } StringBuilder Msg = new StringBuilder(); if (BuyerFac != null) { Msg.AppendLine($"Grid {NewOffer.Name} was purchased by [{BuyerFac.Tag}] {BuyerIdentity.DisplayName} for {NewOffer.Price}sc!"); } else { Msg.AppendLine($"Grid {NewOffer.Name} was purchased by {BuyerIdentity.DisplayName} for {NewOffer.Price}sc!"); } NexusAPI.SendEmbedMessageToDiscord(Hangar.Config.MarketUpdateChannel, Title, Msg.ToString(), Footer, "#FFFF00"); }
internal static void DoChecks(NexusAPI api) { if (Keys == null) { throw new CommandException("Please open a wallet first"); } if (api.Mempool == null && api.ProxyURL == null) { throw new CommandException("Need either mempool or proxy enabled!"); } }
public static void Airdrop(string[] args, NexusAPI api, BigInteger minFee) { if (args.Length != 1) { throw new CommandException("Invalid number of arguments, expected airdrop filename"); } DoChecks(api); var fileName = args[0]; if (!File.Exists(fileName)) { throw new CommandException("Airdrop file does not exist"); } var lines = File.ReadAllLines(fileName); var sb = new ScriptBuilder(); var expectedLimit = 100 + 600 * lines.Length; var expectedGas = UnitConversion.ToDecimal(expectedLimit * minFee, DomainSettings.FuelTokenDecimals); logger.Message($"This airdrop will require at least {expectedGas} {DomainSettings.FuelTokenSymbol}"); sb.AllowGas(Keys.Address, Address.Null, minFee, expectedLimit); int addressCount = 0; foreach (var line in lines) { var temp = line.Split(','); if (!Address.IsValidAddress(temp[0])) { continue; } addressCount++; var target = Address.FromText(temp[0]); var symbol = temp[1]; var amount = BigInteger.Parse(temp[2]); sb.TransferTokens(symbol, Keys.Address, target, amount); } sb.SpendGas(Keys.Address); var script = sb.EndScript(); logger.Message($"Sending airdrop to {addressCount} addresses..."); ExecuteTransaction(api, script, ProofOfWork.None, Keys); }
private NexusAPI SetupNexusApi() { var apiCache = Settings.Node.ApiCache; var apiLog = Settings.Node.ApiLog; var apiProxyURL = Settings.Node.ApiProxyUrl; var readOnlyMode = Settings.Node.Readonly; var hasRPC = Settings.Node.HasRpc; var hasREST = Settings.Node.HasRest; NexusAPI nexusApi = new NexusAPI(_nexus, apiCache, apiLog ? Logger : null); if (apiProxyURL != null) { nexusApi.ProxyURL = apiProxyURL; // TEMP Normal node needs a proxy url set to relay transactions to the BPs nexusApi.Node = _node; Logger.Message($"API will be acting as proxy for {apiProxyURL}"); } else { nexusApi.Node = _node; } if (readOnlyMode) { Logger.Warning($"Node will be running in read-only mode."); } else { nexusApi.Mempool = _mempool; } // RPC setup if (hasRPC) { var rpcPort = Settings.Node.RpcPort; Logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(nexusApi, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.StartInThread(ThreadPriority.AboveNormal); } // REST setup if (hasREST) { var restPort = Settings.Node.RestPort; Logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(nexusApi, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.StartInThread(ThreadPriority.AboveNormal); } return(nexusApi); }
private static TokenResult FetchTokenInfo(NexusAPI api, string symbol) { try { var resultStr = api.Execute("getToken", new object[] { symbol, false }); var tokenInfo = JsonConvert.DeserializeObject <TokenResult>(resultStr); return(tokenInfo); } catch (Exception e) { throw new CommandException(e.Message); } }
/* Following are for discord status messages */ public static void NewGridOfferListed(MarketListing NewOffer) { if (!NexusSupport.RunningNexus) { return; } string Title = "Hangar Market - New Offer"; StringBuilder Msg = new StringBuilder(); Msg.AppendLine($"GridName: {NewOffer.Name}"); Msg.AppendLine($"Price: {NewOffer.Price}sc"); Msg.AppendLine($"PCU: {NewOffer.PCU}"); Msg.AppendLine($"Mass: {NewOffer.GridMass}kg"); Msg.AppendLine($"Jump Distance: {NewOffer.JumpDistance}m"); Msg.AppendLine($"Number Of Blocks: {NewOffer.NumberofBlocks}"); Msg.AppendLine($"PowerOutput: {NewOffer.MaxPowerOutput / 1000}kW"); Msg.AppendLine($"Built-Percent: {NewOffer.GridBuiltPercent * 100}%"); Msg.AppendLine($"Total Grids: {NewOffer.NumberOfGrids}"); Msg.AppendLine($"Static Grids: {NewOffer.StaticGrids}"); Msg.AppendLine($"Large Grids: {NewOffer.LargeGrids}"); Msg.AppendLine($"Small Grids: {NewOffer.SmallGrids}"); Msg.AppendLine(); Msg.AppendLine($"Description: {NewOffer.Description}"); if (!MySession.Static.Players.TryGetIdentityFromSteamID(NewOffer.SteamID, out MyIdentity Player)) { return; } var Fac = MySession.Static.Factions.GetPlayerFaction(Player.IdentityId); string Footer; if (Fac != null) { Footer = $"Seller: [{Fac.Tag}] {Player.DisplayName}"; } else { Footer = $"Seller: {Player.DisplayName}"; } NexusAPI.SendEmbedMessageToDiscord(Hangar.Config.MarketUpdateChannel, Title, Msg.ToString(), Footer, "#FFFF00"); }
public void TestGetBotWrestler() { var owner = PhantasmaKeys.Generate(); var simulator = new NexusSimulator(owner, 1234); var nexus = simulator.Nexus; var api = new NexusAPI(nexus); var callScript = ScriptUtils.BeginScript().CallContract("nacho", "GetWrestler", new object[] { -1 }).EndScript(); var apiResult = (ScriptResult)api.InvokeRawScript("main", Base16.Encode(callScript)); var bytes = Base16.Decode(apiResult.results[0]); var objResult = Serialization.Unserialize <VMObject>(bytes); var nachoWrestler = objResult.ToStruct <NachoWrestler>(); }
public static void Balance(NexusAPI api, int phantasmaRestPort, NeoScanAPI neoScanAPI, string[] args) { if (phantasmaRestPort <= 0) { throw new CommandException("Please enable REST API on this node to use this feature"); } Address address; if (args.Length == 1) { address = Address.FromText(args[0]); } else { address = Keys.Address; } logger.Message("Fetching balances..."); var wallets = new List <CryptoWallet>(); wallets.Add(new PhantasmaWallet(Keys, $"http://*****:*****@ {entry.Chain}"); } if (empty) { logger.Message("Empty wallet."); } } else { logger.Message("Failed to fetch balances!"); } }); } }
private static void SettleSwap(SpookSettings settings, NexusAPI api, BigInteger minimumFee, string platform, string swapSymbol, Hash extHash, IKeyPair externalKeys, Address targetAddress) { var outputAddress = Address.FromKey(externalKeys); var script = new ScriptBuilder() .CallContract("interop", "SettleTransaction", outputAddress, platform, extHash) .CallContract("swap", "SwapFee", outputAddress, swapSymbol, UnitConversion.ToBigInteger(0.1m, DomainSettings.FuelTokenDecimals)) .TransferBalance(swapSymbol, outputAddress, targetAddress) .AllowGas(outputAddress, Address.Null, minimumFee, 500) .SpendGas(outputAddress).EndScript(); logger.Message("Settling swap on Phantasma"); ExecuteTransaction(settings, api, script, ProofOfWork.None, externalKeys); logger.Success($"Swap of {swapSymbol} is complete!"); }
public static void Stake(SpookSettings settings, NexusAPI api, BigInteger minFee, string[] args) { if (args.Length != 1) { throw new CommandException("Expected args: amount"); } DoChecks(api); var tempAmount = decimal.Parse(args[0]); var tokenSymbol = DomainSettings.StakingTokenSymbol; TokenResult tokenInfo; try { var result = api.GetToken(tokenSymbol); tokenInfo = (TokenResult)result; } catch (Exception e) { throw new CommandException(e.Message); } var amount = UnitConversion.ToBigInteger(tempAmount, tokenInfo.decimals); var script = ScriptUtils.BeginScript(). AllowGas(Keys.Address, Address.Null, minFee, 9999). CallContract("stake", "Stake", Keys.Address, amount). SpendGas(Keys.Address). EndScript(); var hash = ExecuteTransaction(settings, api, script, ProofOfWork.None, Keys); if (hash != Hash.Null) { var events = GetTransactionEvents(hash); if (events.Any(x => x.kind == EventKind.TokenStake.ToString())) { logger.Message($"Staked succesfully {tempAmount} {tokenSymbol} at {Keys.Address.Text}"); } else { throw new CommandException("Transaction was confirmed but missing stake event?"); } } }
private TestData CreateAPI() { var owner = KeyPair.FromWIF(testWIF); var sim = new ChainSimulator(owner, 1234, -1); var api = new NexusAPI(sim.Nexus); var data = new TestData() { owner = owner, simulator = sim, nexus = sim.Nexus, api = api }; return(data); }
private TestData CreateAPI(bool useMempool = false) { var owner = KeyPair.FromWIF(testWIF); var sim = new ChainSimulator(owner, 1234); var mempool = useMempool? new Mempool(owner, sim.Nexus, 2, 1) : null; var api = new NexusAPI(sim.Nexus, mempool); var data = new TestData() { owner = owner, simulator = sim, nexus = sim.Nexus, api = api }; mempool?.Start(); return(data); }
private TestData CreateAPI(bool useMempool = false) { var owner = PhantasmaKeys.FromWIF(testWIF); var sim = new NexusSimulator(owner, 1234); var mempool = useMempool? new Mempool(owner, sim.Nexus, 2, 1, System.Text.Encoding.UTF8.GetBytes("TEST")) : null; var api = new NexusAPI(sim.Nexus); api.Mempool = mempool; var data = new TestData() { owner = owner, simulator = sim, nexus = sim.Nexus, api = api }; mempool?.Start(); return(data); }
public static void Balance(Address address, NexusAPI api, Logger logger, string[] args) { if (args.Length == 1) { address = Address.FromText(args[0]); } var account = (AccountResult)api.GetAccount(address.Text); logger.Message($"Balance for {account.name} ({address.Text})"); if (account.balances.Any()) { foreach (var entry in account.balances) { var amount = BigInteger.Parse(entry.amount); logger.Success($"{entry.chain} => {UnitConversion.ToDecimal(amount, (int)entry.decimals)} {entry.symbol}"); } } else { logger.Warning("Empty wallet."); } }
public static void GirdOfferRemoved(MarketListing NewOffer) { if (!NexusSupport.RunningNexus) { return; } string Title = "Hangar Market - Offer Removed"; if (!MySession.Static.Players.TryGetIdentityFromSteamID(NewOffer.SteamID, out MyIdentity Player)) { return; } StringBuilder Msg = new StringBuilder(); Msg.AppendLine($"Grid {NewOffer.Name} is no longer for sale!"); var Fac = MySession.Static.Factions.GetPlayerFaction(Player.IdentityId); string Footer; if (Fac != null) { Footer = $"Seller: [{Fac.Tag}] {Player.DisplayName}"; } else { Footer = $"Seller: {Player.DisplayName}"; } NexusAPI.SendEmbedMessageToDiscord(Hangar.Config.MarketUpdateChannel, Title, Msg.ToString(), Footer, "#FFFF00"); }
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!"); } } }
static void Main(string[] args) { try { RestSharpAPI restSharpAPI = new RestSharpAPI(baseUrl); //RestClient client = restSharpAPI.getClient(); //works RestClient client = restSharpAPI.getClient(user, password); // works if (restSharpAPI == null || client == null) { Console.WriteLine("restSharpAPI or client is null"); Environment.Exit(1); } NexusAPI nexusAPI = new NexusAPI(restSharpAPI, client); //nexusAPI.testDelete(); //Console.ReadKey(true); List<NexusContent> contents = new List<NexusContent>(); string repository = "otpp-snapshots"; //string repository = "releases"; string pattern = ".zip"; int days = 0; contents = nexusAPI.getContent(repository, "/"); nexusAPI.findArtifacts(repository, contents, days, pattern); Console.WriteLine("Size of artifacts: {0}", nexusAPI.urls.Count); nexusAPI.removeLastFromList(repository); for (int i = nexusAPI.urls.Count - 1; i >= 0; i--) { nexusAPI.urls[i].TrimEnd('/'); int local = nexusAPI.urls[i].IndexOf("/local/"); nexusAPI.urls[i] = nexusAPI.urls[i].Substring(local + 6); Console.WriteLine("URL to be deleted: {0}", nexusAPI.urls[i]); } //nexusAPI.deleteArtifact(nexusAPI.urls, repository); Console.ReadKey(true); List<NexusRepo> repos = new List<NexusRepo>(); repos = nexusAPI.GetAllRepos(); if (repos == null) { Console.WriteLine("repos is null"); Console.ReadKey(true); Environment.Exit(1); } else { Console.WriteLine("Size of repos: {0}", repos.Count); } foreach (NexusRepo repo in repos) { // Console.WriteLine("Repo info: {0}", repo.ToString()); } //nexusAPI.uploadArtifact(); //nexusAPI.uploadArtifact1(); //nexusAPI.uploadArtifact2(); //nexusAPI.uploadArtifact3(); //List<NexusArtifact> artifacts = new List<NexusArtifact>(); //artifacts = nexusAPI.searchMetadata(); //if (artifacts == null) //{ // Console.WriteLine("artifacts is null"); // Console.ReadKey(true); // Environment.Exit(1); //} //else { // Console.WriteLine("Size of repos: {0}", artifacts.Count); //} Console.ReadKey(true); } catch (Exception ex) { Console.WriteLine("Exception caught: {0}", ex); Console.ReadKey(true); } }
public static void Upgrade(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee) { DeployOrUpgrade(args, settings, api, minFee, true); }
static void GenerateBindings(string inputPath, string outputPath) { inputPath = FixPath(inputPath); if (!Directory.Exists(inputPath)) { return; } var files = Directory.GetFiles(inputPath); outputPath = FixPath(outputPath); if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } string replacementFile = inputPath + "language.ini"; var replacements = new Dictionary <string, string>(); var replacementsRef = new Dictionary <string, string>(); if (File.Exists(replacementFile)) { var lines = File.ReadAllLines(replacementFile); foreach (var line in lines) { if (line.Contains(",")) { var temp = line.Split(new[] { ',' }, 2); if (temp[0].StartsWith("@")) { temp[0] = temp[0].Substring(1); replacementsRef[temp[0]] = temp[1]; } else { replacements[temp[0]] = temp[1]; } } } } var nexus = new Nexus("dummy"); var api = new NexusAPI(nexus); foreach (var v in replacements) { if (!replacementsRef.ContainsKey(v.Key)) { replacementsRef.Add(v.Key, v.Value); } } var typeDic = new Dictionary <string, IEnumerable <MetaField> >(); var apiTypes = api.GetType().Assembly.GetTypes().Where(x => !x.IsInterface && x != typeof(SingleResult) && x != typeof(ArrayResult) && x != typeof(ErrorResult) && typeof(IAPIResult).IsAssignableFrom(x)).ToList(); foreach (var entry in apiTypes) { typeDic[entry.Name /*.Replace("Result", "")*/] = GetMetaFields(entry); } var compiler = new Compiler(); compiler.ParseNewLines = true; compiler.RegisterCaseTags(); compiler.RegisterTag("fix-ref", (doc, x) => new FixTypeNode(doc, x, replacementsRef)); compiler.RegisterTag("fix-type", (doc, x) => new FixTypeNode(doc, x, replacements)); compiler.RegisterTag("fix-array", (doc, x) => new FixArrayNode(doc, x)); var data = new Dictionary <string, object>(); data["methods"] = api.Methods.Select(x => new MethodEntry() { Info = x, ResultFields = x.ReturnType.GetFields() }); data["types"] = typeDic; data["opcodes"] = Enum.GetValues(typeof(Opcode)).Cast <Opcode>().Select(x => new KeyValuePair <string, byte>(x.ToString(), (byte)x)); foreach (var file in files) { if (file == replacementFile) { continue; } var filePath = file; var content = File.ReadAllText(filePath); var template = compiler.CompileTemplate(content); var queue = new Queue <Document>(); var context = new RenderingContext(); context.DataRoot = data; context.DataStack = new List <object>(); context.DataStack.Add(data); context.queue = queue; context.output = new StringBuilder(); template.Execute(context); filePath = file.Replace(inputPath, outputPath); File.WriteAllText(filePath, context.output.ToString()); } }
public static void Airdrop(string[] args, SpookSettings settings, NexusAPI api, BigInteger minFee) { if (args.Length != 1) { throw new CommandException("Invalid number of arguments, expected airdrop filename"); } DoChecks(api); var fileName = args[0]; if (!File.Exists(fileName)) { throw new CommandException("Airdrop file does not exist"); } var lines = File.ReadAllLines(fileName); var sb = new ScriptBuilder(); var expectedLimit = 100 + 600 * lines.Length; var expectedGas = UnitConversion.ToDecimal(expectedLimit * minFee, DomainSettings.FuelTokenDecimals); logger.Message($"This airdrop will require at least {expectedGas} {DomainSettings.FuelTokenSymbol}"); sb.AllowGas(Keys.Address, Address.Null, minFee, expectedLimit); Dictionary <string, TokenResult> tokens = new Dictionary <string, TokenResult>(); int addressCount = 0; foreach (var line in lines) { var temp = line.Split(','); if (!Address.IsValidAddress(temp[0])) { continue; } addressCount++; var target = Address.FromText(temp[0]); var symbol = temp[1]; decimal val; if (!Decimal.TryParse(temp[2], NumberStyles.Any, new CultureInfo("en-US"), out val) || val <= 0) { throw new CommandException($"Invalid amount {val} for {target}"); } var token = tokens.ContainsKey(symbol) ? tokens[symbol] : FetchTokenInfo(api, symbol); tokens[symbol] = token; var amount = UnitConversion.ToBigInteger(val, token.decimals); sb.TransferTokens(symbol, Keys.Address, target, amount); } sb.SpendGas(Keys.Address); var script = sb.EndScript(); logger.Message($"Sending airdrop to {addressCount} addresses..."); ExecuteTransaction(settings, api, script, ProofOfWork.None, Keys); }
public TokenSwapper(PhantasmaKeys swapKey, NexusAPI nexusAPI, NeoScanAPI neoscanAPI, NeoAPI neoAPI, BigInteger minFee, Logger logger, Arguments arguments) { this.SwapKeys = swapKey; this.NexusAPI = nexusAPI; this.MinimumFee = minFee; this.neoAPI = neoAPI; this.neoscanAPI = neoscanAPI; this.logger = logger; this.Storage = new KeyStoreStorage(Nexus.CreateKeyStoreAdapter("swaps")); this.interopBlocks = new Dictionary <string, BigInteger>(); interopBlocks["phantasma"] = BigInteger.Parse(arguments.GetString("interop.phantasma.height", "0")); interopBlocks["neo"] = BigInteger.Parse(arguments.GetString("interop.neo.height", "4261049")); //interopBlocks["ethereum"] = BigInteger.Parse(arguments.GetString("interop.ethereum.height", "4261049")); InitWIF("neo", arguments); /* * foreach (var entry in interopBlocks) * { * BigInteger blockHeight = entry.Value; * * ChainInterop interop; * * switch (entry.Key) * { * case "phantasma": * interop = new PhantasmaInterop(this, swapKey, blockHeight, nexusAPI); * break; * * case "neo": * interop = new NeoInterop(this, swapKey, blockHeight, neoAPI, neoscanAPI); * break; * * case "ethereum": * interop = new EthereumInterop(this, swapKey, blockHeight); * break; * * default: * interop = null; * break; * } * * if (interop != null) * { * bool shouldAdd = true; * * if (!(interop is PhantasmaInterop)) * { * logger.Message($"{interop.Name}.Swap.Private: {interop.PrivateKey}"); * logger.Message($"{interop.Name}.Swap.{interop.Name}: {interop.LocalAddress}"); * logger.Message($"{interop.Name}.Swap.Phantasma: {interop.ExternalAddress}"); * * for (int i = 0; i < platforms.Length; i++) * { * var temp = platforms[i]; * if (temp.platform == interop.Name) * { * if (temp.address != interop.LocalAddress) * { * logger.Error($"{interop.Name} address mismatch, should be {temp.address}. Make sure you are using the proper swap seed."); * shouldAdd = false; * } * } * } * } * * if (shouldAdd) * { * AddInterop(interop); * } * } * }*/ }
public CLI(string[] args) { var culture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = culture; CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "default"); restartTime = settings.GetInt("node.reboot", 0); showWebLogs = settings.GetBool("web.log", false); bool apiLog = settings.GetBool("api.log", true); string apiProxyURL = settings.GetString("api.proxy", ""); if (string.IsNullOrEmpty(apiProxyURL)) { apiProxyURL = null; } bool hasSync = settings.GetBool("sync.enabled", true); bool hasMempool = settings.GetBool("mempool.enabled", true); bool hasEvents = settings.GetBool("events.enabled", true); bool hasRelay = settings.GetBool("relay.enabled", true); bool hasArchive = settings.GetBool("archive.enabled", true); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); var nexusName = settings.GetString("nexus.name", "simnet"); string profilePath = settings.GetString("mempool.profile", ""); if (string.IsNullOrEmpty(profilePath)) { profilePath = null; } bool isValidator = false; switch (mode) { case "sender": { string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); string wif = settings.GetString("node.wif"); RunSender(wif, nexusName, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; } case "validator": isValidator = true; break; case "default": break; default: { logger.Error("Unknown mode: " + mode); return; } } int port = settings.GetInt("node.port", 7073); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var defaultOraclePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Oracle"; var storagePath = FixPath(settings.GetString("storage.path", defaultStoragePath)); var oraclePath = FixPath(settings.GetString("storage.oracle", defaultOraclePath)); var storageBackend = settings.GetString("storage.backend", "file"); logger.Message("Storage backend: " + storageBackend); var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); logger.Message("Oracle path: " + oraclePath); switch (storageBackend) { case "file": nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".csv"), (n) => new SpookOracle(this, n, oraclePath) ); break; case "db": nexus = new Nexus(logger, (name) => new DBPartition(storagePath + name), (n) => new SpookOracle(this, n, oraclePath) ); break; default: throw new Exception("Backend has to be set to either \"db\" or \"file\""); } running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); int minimumFee; try { minimumFee = settings.GetInt("mempool.fee", 100000); if (minimumFee < 1) { logger.Error("Invalid mempool fee value. Expected a positive value."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } int minimumPow; try { minimumPow = settings.GetInt("mempool.pow", 0); int maxPow = 5; if (minimumPow < 0 || minimumPow > maxPow) { logger.Error($"Invalid mempool pow value. Expected a value between 0 and {maxPow}."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } if (apiProxyURL != null) { hasMempool = false; isValidator = false; hasSync = false; hasEvents = false; hasRelay = false; hasArchive = false; if (!hasRPC && !hasREST) { logger.Error("API proxy must have REST or RPC enabled."); return; } } if (hasMempool) { this.mempool = new Mempool(nexus, blockTime, minimumFee, System.Text.Encoding.UTF8.GetBytes(Identifier), 0, logger, profilePath); var mempoolLogging = settings.GetBool("mempool.log", true); if (mempoolLogging) { mempool.OnTransactionFailed += Mempool_OnTransactionFailed; mempool.OnTransactionAdded += (hash) => logger.Message($"Received transaction {hash}"); mempool.OnTransactionCommitted += (hash) => logger.Message($"Commited transaction {hash}"); mempool.OnTransactionDiscarded += (hash) => logger.Message($"Discarded transaction {hash}"); } mempool.Start(ThreadPriority.AboveNormal); } else { this.mempool = null; } if (!isValidator && !hasSync && apiProxyURL == null) { logger.Warning("Non-validator nodes require sync feature to be enabled, auto enabled now"); hasSync = true; } PeerCaps caps = PeerCaps.None; if (hasSync) { caps |= PeerCaps.Sync; } if (hasMempool) { caps |= PeerCaps.Mempool; } if (hasEvents) { caps |= PeerCaps.Events; } if (hasRelay) { caps |= PeerCaps.Relay; } if (hasArchive) { caps |= PeerCaps.Archive; } if (hasRPC) { caps |= PeerCaps.RPC; } if (hasREST) { caps |= PeerCaps.REST; } var possibleCaps = Enum.GetValues(typeof(PeerCaps)).Cast <PeerCaps>().ToArray(); foreach (var cap in possibleCaps) { if (cap != PeerCaps.None && caps.HasFlag(cap)) { logger.Message("Feature enabled: " + cap); } } PhantasmaKeys node_keys = null; bool bootstrap = false; if (hasSync) { string wif = settings.GetString("node.wif"); node_keys = PhantasmaKeys.FromWIF(wif); WalletModule.Keys = PhantasmaKeys.FromWIF(wif); try { if (this.mempool != null) { this.mempool.SetKeys(node_keys); } this.node = new Node("Spook v" + SpookVersion, nexus, mempool, node_keys, port, caps, seeds, logger); } catch (Exception e) { logger.Error(e.Message); return; } if (!nexus.HasGenesis) { if (isValidator) { if (settings.GetBool("nexus.bootstrap")) { if (!ValidationUtils.IsValidIdentifier(nexusName)) { logger.Error("Invalid nexus name: " + nexusName); this.Terminate(); return; } logger.Debug($"Boostraping {nexusName} nexus using {node_keys.Address}..."); var genesisTimestamp = new Timestamp(settings.GetUInt("genesis.timestamp", Timestamp.Now.Value)); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, genesisTimestamp)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GetGenesisHash(nexus.RootStorage)); } else { logger.Error("No Nexus found."); this.Terminate(); } } } else { var genesisAddress = nexus.GetGenesisAddress(nexus.RootStorage); if (isValidator && node_keys.Address != genesisAddress) { logger.Error("Specified node key does not match genesis address " + genesisAddress.Text); return; } else { logger.Success("Loaded Nexus with genesis " + nexus.GetGenesisHash(nexus.RootStorage)); //seeds.Add("127.0.0.1:7073"); } } } else { this.node = null; } if (mempool != null) { if (isValidator) { this.mempool.SetKeys(node_keys); } else { this.mempool.SubmissionCallback = (tx, chain) => { logger.Message($"Relaying tx {tx.Hash} to other node"); //this.node. }; } } var useAPICache = settings.GetBool("api.cache", true); if (apiProxyURL != null) { useAPICache = true; } logger.Message($"API cache is {(useAPICache ? "enabled" : "disabled")}."); nexusApi = new NexusAPI(nexus, useAPICache, apiLog ? logger : null); nexusApi.Mempool = mempool; if (!string.IsNullOrEmpty(apiProxyURL)) { nexusApi.ProxyURL = apiProxyURL; logger.Message($"API will be acting as proxy for {apiProxyURL}"); } else { nexusApi.Node = node; } var readOnlyMode = settings.GetBool("readonly", false); if (apiProxyURL != null) { readOnlyMode = true; } if (readOnlyMode) { logger.Warning($"Node will be running in read-only mode."); nexusApi.acceptTransactions = false; } // RPC setup if (hasRPC) { rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(nexusApi, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } else { rpcPort = 0; } // REST setup if (hasREST) { restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(nexusApi, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } else { restPort = 0; } if (node != null) { var neoScanURL = settings.GetString("neoscan.url", "https://api.neoscan.io"); var rpcList = settings.GetString("neo.rpc", "http://seed6.ngd.network:10332,http://seed.neoeconomy.io:10332"); var neoRpcURLs = rpcList.Split(','); this.neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoRpcURLs); this.neoAPI.SetLogger((s) => logger.Message(s)); this.neoScanAPI = new NeoScanAPI(neoScanURL, logger, nexus, node_keys); cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } node.Start(); } if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds if (settings.GetBool("plugin.tps", false)) { RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.ram", false)) { RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.mempool", false)) { RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } } Console.CancelKeyPress += delegate { Terminate(); }; useSimulator = settings.GetBool("simulator.enabled", false); var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); if (settings.GetBool("swaps.enabled")) { var tokenSwapper = new TokenSwapper(node_keys, nexusApi, neoScanAPI, neoAPI, minimumFee, logger, settings); nexusApi.TokenSwapper = tokenSwapper; new Thread(() => { logger.Message("Running token swapping service..."); while (running) { Thread.Sleep(5000); if (nodeReady) { tokenSwapper.Update(); } } }).Start(); } if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); simulator = new NexusSimulator(this.nexus, node_keys, 1234); simulator.MinimumFee = minimumFee; /* * logger.Message("Bootstrapping validators"); * simulator.BeginBlock(); * for (int i = 1; i < validatorWIFs.Length; i++) * { * simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, DomainSettings.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, DomainSettings.StakingTokenDecimals)); * } * simulator.EndBlock();*/ string[] dapps = settings.GetString("dapps", "").Split(','); DappServer.InitDapps(nexus, simulator, node_keys, dapps, minimumFee, logger); bool genBlocks = settings.GetBool("simulator.blocks", false); if (genBlocks) { int blockNumber = 0; while (running) { Thread.Sleep(5000); blockNumber++; logger.Message("Generating sim block #" + blockNumber); try { simulator.CurrentTime = DateTime.UtcNow; simulator.GenerateRandomBlock(); } catch (Exception e) { logger.Error("Fatal error: " + e.ToString()); Environment.Exit(-1); } } } MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }
public static void Transfer(SpookSettings settings, NexusAPI api, BigInteger minimumFee, NeoAPI neoAPI, string[] args) { if (args.Length != 4) { throw new CommandException("Expected args: source_address target_address amount symbol"); } DoChecks(api); var tempAmount = decimal.Parse(args[2]); var tokenSymbol = args[3]; var tokenInfo = FetchTokenInfo(api, tokenSymbol); if (!tokenInfo.flags.Contains("Fungible")) { throw new CommandException("Token must be fungible!"); } var amount = UnitConversion.ToBigInteger(tempAmount, tokenInfo.decimals); var sourceName = args[0]; string sourcePlatform; if (Address.IsValidAddress(sourceName)) { sourcePlatform = PhantasmaWallet.PhantasmaPlatform; } else if (NeoWallet.IsValidAddress(sourceName)) { sourcePlatform = NeoWallet.NeoPlatform; } else { throw new CommandException("Invalid source address " + sourceName); } var destName = args[1]; string destPlatform; if (Address.IsValidAddress(destName)) { destPlatform = PhantasmaWallet.PhantasmaPlatform; } else if (NeoWallet.IsValidAddress(destName)) { destPlatform = NeoWallet.NeoPlatform; } else { throw new CommandException("Invalid destination address " + destName); } if (destName == sourceName) { throw new CommandException("Cannot transfer to same address"); } if (sourcePlatform != PhantasmaWallet.PhantasmaPlatform) { if (destPlatform != PhantasmaWallet.PhantasmaPlatform) { if (sourcePlatform != destPlatform) { throw new CommandException($"Cannot transfer directly from {sourcePlatform} to {destPlatform}"); } else { switch (destPlatform) { case NeoWallet.NeoPlatform: { var neoKeys = new NeoKeys(Keys.PrivateKey); if (sourceName != neoKeys.Address) { throw new CommandException("The current open wallet does not have keys that match address " + sourceName); } var neoHash = NeoTransfer(neoKeys, destName, tokenSymbol, tempAmount, neoAPI); return; } default: throw new CommandException($"Not implemented yet :("); } } } else { logger.Message($"Source is {sourcePlatform} address, a swap will be performed using an interop address."); IPlatform platformInfo = api.Nexus.GetPlatformInfo(api.Nexus.RootStorage, sourcePlatform); Hash extHash; IKeyPair extKeys; switch (sourcePlatform) { case NeoWallet.NeoPlatform: { try { var neoKeys = new NeoKeys(Keys.PrivateKey); if (sourceName != neoKeys.Address) { throw new CommandException("The current open wallet does not have keys that match address " + sourceName); } extHash = NeoTransfer(neoKeys, platformInfo.InteropAddresses[0].ExternalAddress, tokenSymbol, tempAmount, neoAPI); if (extHash == Hash.Null) { return; } extKeys = neoKeys; } catch (Exception e) { logger.Message($"{sourcePlatform} error: " + e.Message); return; } break; } default: logger.Message($"Transactions using platform {sourcePlatform} are not supported yet"); return; } var destAddress = Address.FromText(destName); SettleSwap(settings, api, minimumFee, sourcePlatform, tokenSymbol, extHash, extKeys, destAddress); } return; } else { Address destAddress; if (destPlatform != PhantasmaWallet.PhantasmaPlatform) { switch (destPlatform) { case NeoWallet.NeoPlatform: destAddress = NeoWallet.EncodeAddress(destName); break; default: logger.Message($"Transactions to platform {destPlatform} are not supported yet"); return; } logger.Message($"Target is {destPlatform} address, a swap will be performed through interop address {destAddress}."); } else { destAddress = Address.FromText(destName); } var script = ScriptUtils.BeginScript(). CallContract("swap", "SwapFee", Keys.Address, tokenSymbol, UnitConversion.ToBigInteger(0.01m, DomainSettings.FuelTokenDecimals)). AllowGas(Keys.Address, Address.Null, minimumFee, 9999). TransferTokens(tokenSymbol, Keys.Address, destAddress, amount). SpendGas(Keys.Address). EndScript(); logger.Message($"Sending {tempAmount} {tokenSymbol} to {destAddress.Text}..."); ExecuteTransaction(settings, api, script, ProofOfWork.None, Keys); } }
protected override void OnStart() { Console.CancelKeyPress += delegate { this.Terminate(); }; ValidateConfig(); Version = Assembly.GetAssembly(typeof(Spook)).GetVersion(); _nodeKeys = SetupNodeKeys(); if (Settings.Node.Mode != NodeMode.Proxy && !SetupNexus()) { this.OnStop(); return; } SetupOracleApis(); if (Settings.Node.HasMempool && !Settings.Node.Readonly) { _mempool = SetupMempool(); } if (Settings.Node.Mode != NodeMode.Proxy) { _availablePorts.Add(new PeerPort("sync", Settings.Node.NodePort)); } if (Settings.Node.HasRpc) { _availablePorts.Add(new PeerPort("rpc", Settings.Node.RpcPort)); } if (Settings.Node.HasRest) { _availablePorts.Add(new PeerPort("rest", Settings.Node.RestPort)); } _peerCaps = SetupPeerCaps(); _node = SetupNode(); _nexusApi = SetupNexusApi(); if (_node != null && Settings.App.NodeStart) { if (_peerCaps.HasFlag(PeerCaps.Sync) && Settings.Node.NodeHost.Contains("localhost")) { Logger.Warning($"This node host external endpoint is not properly configured and it won't appear on other nodes GetPeers API call."); } _node.StartInThread(); } _commandDispatcher = SetupCommandDispatcher(); if (Settings.Simulator.Enabled) { StartSimulator(_commandDispatcher); } else { MakeReady(_commandDispatcher); } var enabledSwapPlatforms = Settings.Oracle.SwapPlatforms.Select(x => x.Chain != SwapPlatformChain.Phantasma && x.Enabled); if (enabledSwapPlatforms.Any()) { _tokenSwapper = StartTokenSwapper(); } else { Logger.Warning("No swap platforms found in config, token swapper won't be available"); } }
public CLI(string[] args) { var culture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); /* * for (int i = 0; i < 20; i++) * { * var k = KeyPair.Generate(); * Console.WriteLine(k.ToWIF() + " => " + k.Address.Text); * }*/ var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "validator"); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); string wif = settings.GetString("node.wif"); var nexusName = settings.GetString("nexus.name", "simnet"); switch (mode) { case "sender": string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); RunSender(wif, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; case "validator": break; default: { logger.Error("Unknown mode: " + mode); return; } } int defaultPort = 0; for (int i = 0; i < validatorWIFs.Length; i++) { if (validatorWIFs[i] == wif) { defaultPort = (7073 + i); } } if (defaultPort == 0) { defaultPort = (7073 + validatorWIFs.Length); } int port = settings.GetInt("node.port", defaultPort); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var storagePath = settings.GetString("storage.path", defaultStoragePath); storagePath = storagePath.Replace("\\", "/"); if (!storagePath.EndsWith('/')) { storagePath += '/'; } var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); var node_keys = KeyPair.FromWIF(wif); nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".txt")); bool bootstrap = false; if (wif == validatorWIFs[0]) { if (!nexus.Ready) { logger.Debug("Boostraping nexus..."); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, Timestamp.Now)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GenesisHash); } } else { //nexus = new Nexus(nexusName, genesisAddress, logger); nexus = new Nexus(logger); seeds.Add("127.0.0.1:7073"); } // TODO this should be later optional to enable nexus.AddPlugin(new ChainAddressesPlugin()); nexus.AddPlugin(new TokenTransactionsPlugin()); nexus.AddPlugin(new AddressTransactionsPlugin()); nexus.AddPlugin(new UnclaimedTransactionsPlugin()); running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); this.mempool = new Mempool(node_keys, nexus, blockTime, ReadFromOracle); mempool.Start(ThreadPriority.AboveNormal); mempool.OnTransactionFailed += Mempool_OnTransactionFailed; api = new NexusAPI(nexus, mempool); // RPC setup if (hasRPC) { int rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } // REST setup if (hasREST) { int restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } // node setup this.node = new Node(nexus, mempool, node_keys, port, seeds, logger); node.Start(); if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } Console.CancelKeyPress += delegate { Terminate(); }; var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); bool useSimulator = settings.GetBool("simulator.enabled", false); if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); var simulator = new ChainSimulator(this.nexus, node_keys, 1234); logger.Message("Bootstrapping validators"); simulator.BeginBlock(); for (int i = 1; i < validatorWIFs.Length; i++) { simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, Nexus.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, Nexus.StakingTokenDecimals)); } simulator.EndBlock(); for (int i = 0; i < 3; i++) { logger.Message("Generating sim block #" + i); simulator.GenerateRandomBlock(); } NachoServer.InitNachoServer(nexus, simulator, node_keys, logger); MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }