github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/stellar/stellargregor/stellargregor.go (about)

     1  package stellargregor
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/keybase/client/go/gregor"
    10  	"github.com/keybase/client/go/libkb"
    11  	"github.com/keybase/client/go/protocol/gregor1"
    12  	"github.com/keybase/client/go/protocol/stellar1"
    13  	"github.com/keybase/client/go/stellar"
    14  )
    15  
    16  type Handler struct {
    17  	libkb.Contextified
    18  	walletState *stellar.WalletState
    19  }
    20  
    21  var _ libkb.GregorInBandMessageHandler = (*Handler)(nil)
    22  
    23  func New(g *libkb.GlobalContext, walletState *stellar.WalletState) *Handler {
    24  	return &Handler{
    25  		Contextified: libkb.NewContextified(g),
    26  		walletState:  walletState,
    27  	}
    28  }
    29  
    30  func (h *Handler) Create(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) {
    31  	mctx := libkb.NewMetaContextBackground(h.G()).WithLogTag("WAIBM")
    32  	switch category {
    33  	case stellar1.PushAutoClaim:
    34  		go h.autoClaim(mctx, cli, category, item)
    35  		return true, nil
    36  	case stellar1.PushPaymentStatus:
    37  		go h.paymentStatus(mctx, cli, category, item)
    38  		return true, nil
    39  	case stellar1.PushPaymentNotification:
    40  		go h.paymentNotification(mctx, cli, category, item)
    41  		return true, nil
    42  	case stellar1.PushRequestStatus:
    43  		go h.requestStatus(mctx, cli, category, item)
    44  		return true, nil
    45  	case stellar1.PushAccountChange:
    46  		go h.accountChange(mctx, cli, category, item)
    47  		return true, nil
    48  	default:
    49  		if strings.HasPrefix(category, "stellar.") {
    50  			return false, fmt.Errorf("unknown handler category: %q", category)
    51  		}
    52  		return false, nil
    53  	}
    54  }
    55  
    56  func (h *Handler) Dismiss(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) {
    57  	return false, nil
    58  }
    59  
    60  func (h *Handler) IsAlive() bool {
    61  	return true
    62  }
    63  
    64  func (h *Handler) Name() string {
    65  	return "stellarHandler"
    66  }
    67  
    68  // The server is telling the client to claim relay payments.
    69  func (h *Handler) autoClaim(mctx libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) {
    70  	mctx.Debug("%v: %v received", h.Name(), category)
    71  	mctx.G().GetStellar().KickAutoClaimRunner(mctx, item.Metadata().MsgID())
    72  }
    73  
    74  type accountChangeMsg struct {
    75  	AccountID string `json:"account_id"`
    76  	Reason    string `json:"reason"`
    77  }
    78  
    79  func (h *Handler) accountChange(mctx libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) {
    80  	mctx.Debug("%v: %v received", h.Name(), category)
    81  
    82  	if item.Body() == nil {
    83  		mctx.Debug("stellar handler for account_change: nil message body")
    84  		return
    85  	}
    86  	var msgBody accountChangeMsg
    87  	if err := json.Unmarshal(item.Body().Bytes(), &msgBody); err != nil {
    88  		mctx.Debug("stellar handler for account_change: json.Unmarshal error: %s", err)
    89  		return
    90  	}
    91  
    92  	if msgBody.AccountID != "" {
    93  		if err := h.walletState.Refresh(mctx, stellar1.AccountID(msgBody.AccountID), "accountChange gregor"); err != nil {
    94  			mctx.Debug("failed to Refresh wallet state: %s", err)
    95  		}
    96  		account, err := stellar.WalletAccount(mctx, h.walletState, stellar1.AccountID(msgBody.AccountID))
    97  		if err == nil {
    98  			h.G().NotifyRouter.HandleWalletAccountDetailsUpdate(mctx.Ctx(), stellar1.AccountID(msgBody.AccountID), account)
    99  		} else {
   100  			mctx.Debug("failed to HandleWalletAccountDetailsUpdate: %s", err)
   101  		}
   102  	} else {
   103  		if err := h.walletState.RefreshAll(mctx, "accountChange gregor"); err != nil {
   104  			mctx.Debug("failed to RefreshAll wallet state: %s", err)
   105  		}
   106  		accounts, err := stellar.AllWalletAccounts(mctx, h.walletState)
   107  		if err == nil {
   108  			h.G().NotifyRouter.HandleWalletAccountsUpdate(mctx.Ctx(), accounts)
   109  		} else {
   110  			mctx.Debug("failed to HandleWalletAccountsUpdate: %s", err)
   111  		}
   112  	}
   113  
   114  	// We will locally dismiss for now so that each client only plays them once:
   115  	if err := h.G().GregorState.LocalDismissItem(mctx.Ctx(), item.Metadata().MsgID()); err != nil {
   116  		mctx.Debug("failed to local dismiss account_change: %s", err)
   117  	}
   118  }
   119  
   120  // paymentStatus is an old IBM and shouldn't happen anymore
   121  func (h *Handler) paymentStatus(mctx libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) {
   122  	mctx.Debug("%v: %v received IBM, ignoring it", h.Name(), category)
   123  
   124  	// We will locally dismiss for now so that each client only plays them once:
   125  	if err := h.G().GregorState.LocalDismissItem(mctx.Ctx(), item.Metadata().MsgID()); err != nil {
   126  		h.G().Log.CDebugf(mctx.Ctx(), "failed to local dismiss payment_status: %s", err)
   127  	}
   128  }
   129  
   130  // paymentNotification is an old IBM and shouldn't happen anymore
   131  func (h *Handler) paymentNotification(mctx libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) {
   132  	mctx.Debug("%s: %s received IBM, ignoring it", h.Name(), category)
   133  
   134  	// We will locally dismiss for now so that each client only plays them once:
   135  	if err := h.G().GregorState.LocalDismissItem(mctx.Ctx(), item.Metadata().MsgID()); err != nil {
   136  		h.G().Log.CDebugf(mctx.Ctx(), "failed to local dismiss payment_notification: %s", err)
   137  	}
   138  }
   139  
   140  // requestStatus is an old IBM and shouldn't happen anymore
   141  func (h *Handler) requestStatus(mctx libkb.MetaContext, cli gregor1.IncomingInterface, category string, item gregor.Item) {
   142  	mctx.Debug("%v: %v received IBM, ignoring it", h.Name(), category)
   143  
   144  	// We will locally dismiss for now so that each client only plays them once:
   145  	if err := h.G().GregorState.LocalDismissItem(mctx.Ctx(), item.Metadata().MsgID()); err != nil {
   146  		h.G().Log.CDebugf(mctx.Ctx(), "failed to local dismiss request_status: %s", err)
   147  	}
   148  }