// CloseIMChannelContext closes the direct message channel with a custom context
339068
func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (bool, bool, error) {
	values := url.Values{
		"token":   {api.token},
		"channel": {channel},
	}

	response, err := api.imRequest(ctx, "im.close", values)
	if err != nil {
		return false, false, err
	}
	return response.NoOp, response.AlreadyClosed, nil
}
143577
func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string) error {
	values := url.Values{
		"token":   {api.token},
		"channel": {channel},
		"ts":      {ts},
	}

	_, err := api.imRequest(ctx, "im.mark", values)
	return err
}
180943
func (api *Client) JoinConversationContext(ctx context.Context, channelID string) (*Channel, string, []string, error) {
	values := url.Values{"token": {api.token}, "channel": {channelID}}
	response := struct {
		Channel          *Channel `json:"channel"`
		Warning          string   `json:"warning"`
		ResponseMetaData *struct {
			Warnings []string `json:"warnings"`
		} `json:"response_metadata"`
		SlackResponse
	}{}
	err := api.postMethod(ctx, "conversations.join", values, &response)
	if err != nil {
		return nil, "", nil, err
	}
	if response.Err() != nil {
		return nil, "", nil, response.Err()
	}
	var warnings []string
	if response.ResponseMetaData != nil {
		warnings = response.ResponseMetaData.Warnings
	}
	return response.Channel, response.Warning, warnings, nil
}
324395
func (api *Client) MarkIMChannel(channel, ts string) (err error) {
	return api.MarkIMChannelContext(context.Background(), channel, ts)
}
677300
func (api *Client) CreateChannelContext(ctx context.Context, channelName string) (*Channel, error) {
	values := url.Values{
		"token": {api.token},
		"name":  {channelName},
	}

	response, err := api.channelRequest(ctx, "channels.create", values)
	if err != nil {
		return nil, err
	}
	return &response.Channel, nil
}
249613
func (call *MulticastCall) WithContext(ctx context.Context) *MulticastCall {
	call.ctx = ctx
	return call
}
1158948
func (api *Client) GetIMChannelsContext(ctx context.Context) ([]IM, error) {
	values := url.Values{
		"token": {api.token},
	}

	response, err := api.imRequest(ctx, "im.list", values)
	if err != nil {
		return nil, err
	}
	return response.IMs, nil
}
1078829
func (c *contextGroup) closeOnContextDone() {
	<-c.Context().Done() // wait until parent (context) is done.
	c.internalClose()
	c.Children().Done()
}
382402
func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purpose string) (string, error) {
	values := url.Values{
		"token":   {api.token},
		"channel": {channelID},
		"purpose": {purpose},
	}

	response, err := api.channelRequest(ctx, "channels.setPurpose", values)
	if err != nil {
		return "", err
	}
	return response.Purpose, nil
}
381029
func (p *DefaultChannelClient) Close() error {
	p.usersMutex.RLock()
	defer p.usersMutex.RUnlock()
	for _, user := range p.users {
		user.close()
	}
	return p.client.closeChannel(p)
}
286048
func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
	updateStream lnrpc.Lightning_CloseChannelServer) error {

	// If the user didn't specify a channel point, then we'll reject this
	// request all together.
	if in.GetChannelPoint() == nil {
		return fmt.Errorf("must specify channel point in close channel")
	}

	force := in.Force
	index := in.ChannelPoint.OutputIndex
	txid, err := getChanPointFundingTxid(in.GetChannelPoint())
	if err != nil {
		rpcsLog.Errorf("[closechannel] unable to get funding txid: %v", err)
		return err
	}
	chanPoint := wire.NewOutPoint(txid, index)

	rpcsLog.Tracef("[closechannel] request for ChannelPoint(%v), force=%v",
		chanPoint, force)

	var (
		updateChan chan interface{}
		errChan    chan error
	)

	// TODO(roasbeef): if force and peer online then don't force?

	// First, we'll fetch the channel as is, as we'll need to examine it
	// regardless of if this is a force close or not.
	channel, err := r.fetchActiveChannel(*chanPoint)
	if err != nil {
		return err
	}

	// If a force closure was requested, then we'll handle all the details
	// around the creation and broadcast of the unilateral closure
	// transaction here rather than going to the switch as we don't require
	// interaction from the peer.
	if force {
		_, bestHeight, err := r.server.cc.chainIO.GetBestBlock()
		if err != nil {
			return err
		}

		// As we're force closing this channel, as a precaution, we'll
		// ensure that the switch doesn't continue to see this channel
		// as eligible for forwarding HTLC's. If the peer is online,
		// then we'll also purge all of its indexes.
		remotePub := &channel.StateSnapshot().RemoteIdentity
		if peer, err := r.server.FindPeer(remotePub); err == nil {
			// TODO(roasbeef): actually get the active channel
			// instead too?
			//  * so only need to grab from database
			peer.WipeChannel(channel.ChannelPoint())
		} else {
			chanID := lnwire.NewChanIDFromOutPoint(channel.ChannelPoint())
			r.server.htlcSwitch.RemoveLink(chanID)
		}

		// With the necessary indexes cleaned up, we'll now force close
		// the channel.
		chainArbitrator := r.server.chainArb
		closingTx, err := chainArbitrator.ForceCloseContract(
			*chanPoint,
		)
		if err != nil {
			rpcsLog.Errorf("unable to force close transaction: %v", err)
			return err
		}

		closingTxid := closingTx.TxHash()

		// With the transaction broadcast, we send our first update to
		// the client.
		updateChan = make(chan interface{}, 2)
		updateChan <- &pendingUpdate{
			Txid: closingTxid[:],
		}

		errChan = make(chan error, 1)
		notifier := r.server.cc.chainNotifier
		go waitForChanToClose(uint32(bestHeight), notifier, errChan, chanPoint,
			&closingTxid, closingTx.TxOut[0].PkScript, func() {
				// Respond to the local subsystem which
				// requested the channel closure.
				updateChan <- &channelCloseUpdate{
					ClosingTxid: closingTxid[:],
					Success:     true,
				}
			})
	} else {
		// If the link is not known by the switch, we cannot gracefully close
		// the channel.
		channelID := lnwire.NewChanIDFromOutPoint(chanPoint)
		if _, err := r.server.htlcSwitch.GetLink(channelID); err != nil {
			rpcsLog.Debugf("Trying to non-force close offline channel with "+
				"chan_point=%v", chanPoint)
			return fmt.Errorf("unable to gracefully close channel while peer "+
				"is offline (try force closing it instead): %v", err)
		}

		// Based on the passed fee related parameters, we'll determine
		// an appropriate fee rate for the cooperative closure
		// transaction.
		satPerKw := lnwallet.SatPerKVByte(
			in.SatPerByte * 1000,
		).FeePerKWeight()
		feeRate, err := sweep.DetermineFeePerKw(
			r.server.cc.feeEstimator, sweep.FeePreference{
				ConfTarget: uint32(in.TargetConf),
				FeeRate:    satPerKw,
			},
		)
		if err != nil {
			return err
		}

		rpcsLog.Debugf("Target sat/kw for closing transaction: %v",
			int64(feeRate))

		// Before we attempt the cooperative channel closure, we'll
		// examine the channel to ensure that it doesn't have a
		// lingering HTLC.
		if len(channel.ActiveHtlcs()) != 0 {
			return fmt.Errorf("cannot co-op close channel " +
				"with active htlcs")
		}

		// Otherwise, the caller has requested a regular interactive
		// cooperative channel closure. So we'll forward the request to
		// the htlc switch which will handle the negotiation and
		// broadcast details.
		updateChan, errChan = r.server.htlcSwitch.CloseLink(
			chanPoint, htlcswitch.CloseRegular, feeRate,
		)
	}
out:
	for {
		select {
		case err := <-errChan:
			rpcsLog.Errorf("[closechannel] unable to close "+
				"ChannelPoint(%v): %v", chanPoint, err)
			return err
		case closingUpdate := <-updateChan:
			rpcClosingUpdate, err := createRPCCloseUpdate(
				closingUpdate,
			)
			if err != nil {
				return err
			}

			rpcsLog.Tracef("[closechannel] sending update: %v",
				rpcClosingUpdate)

			if err := updateStream.Send(rpcClosingUpdate); err != nil {
				return err
			}

			// If a final channel closing updates is being sent,
			// then we can break out of our dispatch loop as we no
			// longer need to process any further updates.
			switch closeUpdate := closingUpdate.(type) {
			case *channelCloseUpdate:
				h, _ := chainhash.NewHash(closeUpdate.ClosingTxid)
				rpcsLog.Infof("[closechannel] close completed: "+
					"txid(%v)", h)
				break out
			}
		case <-r.quit:
			return nil
		}
	}

	return nil
}
778390
func ChannelClose(ch chan *Message) bool {
	select {
	case _, ok := <-ch:
		if ok {
			close(ch)
			return true
		}
	default:
	}
	return false
}
187069
func (a *Agent) OnChannelClose(closedChans ...lnwire.ShortChannelID) {
	a.wg.Add(1)
	go func() {
		defer a.wg.Done()

		select {
		case a.stateUpdates <- &chanCloseUpdate{closedChans: closedChans}:
		case <-a.quit:
		}
	}()
}
828306
func (call *ReplyMessageCall) WithContext(ctx context.Context) *ReplyMessageCall {
	call.ctx = ctx
	return call
}
1202175
func (c *ChannelListCall) Context(ctx context.Context) *ChannelListCall {
	c.ctx_ = ctx
	return c
}
1197534
func (call *GetMessageQuotaCall) WithContext(ctx context.Context) *GetMessageQuotaCall {
	call.ctx = ctx
	return call
}
579438
func (d *DB) FetchWaitingCloseChannels() ([]*OpenChannel, error) {
	waitingClose, err := fetchChannels(d, false, true)
	if err != nil {
		return nil, err
	}
	pendingWaitingClose, err := fetchChannels(d, true, true)
	if err != nil {
		return nil, err
	}

	return append(waitingClose, pendingWaitingClose...), nil
}