Esempio n. 1
0
        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})");
            }
        }
Esempio n. 2
0
        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})");
            }
        }