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})"); } }
protected override async Task InvokeAsyncBase(InvocationContext context) { var offer = context.GetOffer(Network); 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); var oracleName = await NameRepository.GetName(Scopes.Oracles, new OracleId(offer.OracleInfo.PubKey).ToString()); if (oracle is null || oracleName is null) { throw new CommandException("offer", "Unknown oracle"); } var evt = await Repository.GetEvent(offer.OracleInfo.PubKey, offer.OracleInfo.RValue); if (evt?.EventId 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"); } } if (!offer.SetContractPreimages(evt.Outcomes)) { throw new CommandException("offer", "The contract info of the offer does not match the specification of the event"); } try { var review = new OfferReview(offer); var evtName = (await NameRepository.AsEventRepository().ResolveName(evt.EventId)) ?? new EventFullName("???", "???"); context.Console.Out.WriteLine($"Event: {evtName}"); context.Console.Out.WriteLine($"Fee rate: {offer.FeeRate!.SatoshiPerByte} sat/vbyte"); context.Console.Out.WriteLine($"The payoff function if you accept:"); PrintPayoffs(context, review.AcceptorPayoffs); context.Console.Out.WriteLine($"Your expected collateral: {review.AcceptorCollateral.ToString(false, false)}"); context.Console.Out.WriteLine($"Contract Execution validity: " + maturity.ToString()); context.Console.Out.WriteLine($"Refund validity: " + refund.ToString()); context.Console.Out.WriteLine($"How to accept this offer:"); context.Console.Out.WriteLine($"If your plan to accept this offer, you need to run 'dlc accept <dlcname> <offer>'. The DLC name is arbitrary and local, you will use it to manage your DLC."); } catch (Exception ex) { throw new CommandException("offer", $"Invalid offer. ({ex.Message})"); } }