cs-codex-dist-tests/ProjectPlugins/CodexContractsPlugin/CodexContractsStarter.cs

129 lines
4.5 KiB
C#
Raw Normal View History

2023-09-15 14:27:08 +00:00
using Core;
using GethPlugin;
using KubernetesWorkflow;
using Logging;
using Nethereum.Contracts;
2023-09-15 14:27:08 +00:00
using Utils;
namespace CodexContractsPlugin
{
public class CodexContractsStarter
{
private readonly IPluginTools tools;
public CodexContractsStarter(IPluginTools tools)
{
this.tools = tools;
}
public CodexContractsDeployment Deploy(CoreInterface ci, IGethNode gethNode)
2023-09-15 14:27:08 +00:00
{
Log("Starting Codex SmartContracts container...");
2023-09-15 14:27:08 +00:00
var workflow = tools.CreateWorkflow();
var startupConfig = CreateStartupConfig(gethNode);
startupConfig.NameOverride = "codex-contracts";
2023-09-15 14:27:08 +00:00
var containers = workflow.Start(1, Location.Unspecified, new CodexContractsContainerRecipe(), startupConfig);
if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Codex contracts container to be created. Test infra failure.");
var container = containers.Containers[0];
Log("Container started.");
try
{
return DeployContract(container, workflow, gethNode);
}
catch
{
Log("Failed to deploy contract.");
Log("Downloading Codex SmartContracts container log...");
ci.DownloadLog(container);
throw;
}
}
public ICodexContracts Wrap(CodexContractsDeployment deployment)
{
return new CodexContractsAccess(tools.GetLog(), deployment);
}
private CodexContractsDeployment DeployContract(RunningContainer container, IStartupWorkflow workflow, IGethNode gethNode)
{
Log("Deploying SmartContract...");
2023-09-15 14:27:08 +00:00
WaitUntil(() =>
{
var logHandler = new ContractsReadyLogHandler(tools.GetLog());
workflow.DownloadContainerLog(container, logHandler, null);
return logHandler.Found;
});
Log("Contracts deployed. Extracting addresses...");
var extractor = new ContractsContainerInfoExtractor(tools.GetLog(), workflow, container);
var marketplaceAddress = extractor.ExtractMarketplaceAddress();
var abi = extractor.ExtractMarketplaceAbi();
2023-09-19 11:39:24 +00:00
var interaction = new ContractInteractions(tools.GetLog(), gethNode);
2023-09-15 14:27:08 +00:00
var tokenAddress = interaction.GetTokenAddress(marketplaceAddress);
2023-09-19 11:58:45 +00:00
Log("Extract completed. Checking sync...");
Time.WaitUntil(() => interaction.IsSynced(marketplaceAddress, abi));
Log("Synced. Codex SmartContracts deployed.");
2023-09-15 14:27:08 +00:00
return new CodexContractsDeployment(marketplaceAddress, abi, tokenAddress);
}
2023-09-15 14:27:08 +00:00
private void Log(string msg)
{
tools.GetLog().Log(msg);
}
private void WaitUntil(Func<bool> predicate)
{
Time.WaitUntil(predicate, TimeSpan.FromMinutes(3), TimeSpan.FromSeconds(2));
}
2023-09-19 08:24:43 +00:00
private StartupConfig CreateStartupConfig(IGethNode gethNode)
2023-09-15 14:27:08 +00:00
{
var startupConfig = new StartupConfig();
var contractsConfig = new CodexContractsContainerConfig(gethNode);
startupConfig.Add(contractsConfig);
return startupConfig;
}
}
public class ContractsReadyLogHandler : LogHandler
{
// Log should contain 'Compiled 15 Solidity files successfully' at some point.
private const string RequiredCompiledString = "Solidity files successfully";
// When script is done, it prints the ready-string.
private const string ReadyString = "Done! Sleeping indefinitely...";
private readonly ILog log;
public ContractsReadyLogHandler(ILog log)
{
this.log = log;
log.Debug($"Looking for '{RequiredCompiledString}' and '{ReadyString}' in container logs...");
}
public bool SeenCompileString { get; private set; }
public bool Found { get; private set; }
protected override void ProcessLine(string line)
{
log.Debug(line);
if (line.Contains(RequiredCompiledString)) SeenCompileString = true;
if (line.Contains(ReadyString))
{
if (!SeenCompileString) throw new Exception("CodexContracts deployment failed. " +
"Solidity files not compiled before process exited.");
Found = true;
}
}
}
}