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 }