protected override async Task InvokeAsyncBase(InvocationContext context) { var name = context.ParseResult.CommandResult.GetArgumentValueOrDefault <string>("name")?.Trim(); if (name is null) { throw new CommandOptionRequiredException("name"); } var dlc = await GetDLC("name", name); if (dlc?.BuilderState is null || dlc?.OracleInfo is null) { throw new CommandException("name", "This DLC does not exist"); } var builder = new DLCTransactionBuilder(dlc.BuilderState.ToString(), Network); var psbt = context.ParsePSBT("signedpsbt", Network); if (!builder.State.IsInitiator) { context.AssertState("name", dlc, false, DLCNextStep.Fund, Network); var fullySigned = builder.Finalize(psbt); dlc.BuilderState = builder.ExportStateJObject(); await Repository.SaveDLC(dlc); context.WriteTransaction(fullySigned, builder.State.Funding?.FundCoin, Network); } else { context.AssertState("name", dlc, true, DLCNextStep.Fund, Network); var key = await Repository.GetKey(dlc.FundKeyPath !); try { var sign = builder.Sign2(key, psbt); dlc.Sign = sign; dlc.BuilderState = builder.ExportStateJObject(); await Repository.SaveDLC(dlc); context.WriteObject(sign, Repository.JsonSettings); } catch (Exception ex) { throw new CommandException("signedpsbt", $"Invalid PSBT. ({ex.Message})"); } } }
public async Task <DLCState> NewDLC(OracleInfo oracleInfo, DLCTransactionBuilder builder) { var dir = Path.Combine(RepositoryDirectory, "DLCs"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } var s = new DLCState() { OracleInfo = oracleInfo, BuilderState = builder.ExportStateJObject(), Id = RandomUtils.GetUInt256() }; var file = GetDLCFilePath(s.Id); await File.WriteAllTextAsync(file, JsonConvert.SerializeObject(s, JsonSettings)); return(s); }
protected override async Task InvokeAsyncBase(InvocationContext context) { var offer = DLCHelpers.GetOffer(context, Repository.JsonSettings); var name = context.ParseResult.CommandResult.GetArgumentValueOrDefault <string>("name")?.Trim(); if (name is null) { throw new CommandOptionRequiredException("name"); } if (await this.TryGetDLC(name) != null) { throw new CommandException("name", "This DLC already exists"); } if (offer.OracleInfo is null) { throw new CommandException("offer", "Missing oracleInfo"); } if (offer.Timeouts is null) { throw new CommandException("offer", "Missing timeouts"); } if (offer.ContractInfo is null) { throw new CommandException("offer", "Missing contractInfos"); } var oracle = await Repository.GetOracle(offer.OracleInfo.PubKey); if (oracle is null) { throw new CommandException("offer", "Unknown oracle"); } var evt = await Repository.GetEvent(offer.OracleInfo.PubKey, offer.OracleInfo.RValue); if (evt is null) { throw new CommandException("offer", "Unknown event"); } var maturity = new LockTimeEstimation(offer.Timeouts.ContractMaturity, Network); var refund = new LockTimeEstimation(offer.Timeouts.ContractTimeout, Network); if (!refund.UnknownEstimation) { if (refund.EstimatedRemainingBlocks == 0) { throw new CommandException("offer", "The refund should not be immediately valid"); } if (refund.EstimatedRemainingBlocks < maturity.EstimatedRemainingBlocks) { throw new CommandException("offer", "The refund should not be valid faster than the contract execution transactions"); } } offer.SetContractPreimages(evt.Outcomes); try { var builder = new DLCTransactionBuilder(false, null, null, null, Network); builder.Accept(offer); var dlc = await Repository.NewDLC(offer.OracleInfo, builder); dlc.BuilderState = builder.ExportStateJObject(); dlc.Offer = JObject.FromObject(offer, JsonSerializer.Create(Repository.JsonSettings)); await NameRepository.AsDLCNameRepository().SetMapping(name, dlc.Id); await Repository.SaveDLC(dlc); context.Console.Out.Write($"Contract accepted, you now need to setup the DLC. For more information, run `dlc show \"{name}\"`."); } catch (Exception ex) { throw new CommandException("offer", $"Invalid offer or PSBT. ({ex.Message})"); } }