github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/sdk/bank/handler.go (about) 1 package bank 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/gnolang/gno/tm2/pkg/amino" 8 abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" 9 "github.com/gnolang/gno/tm2/pkg/crypto" 10 "github.com/gnolang/gno/tm2/pkg/sdk" 11 "github.com/gnolang/gno/tm2/pkg/std" 12 ) 13 14 type bankHandler struct { 15 bank BankKeeper 16 } 17 18 // NewHandler returns a handler for "bank" type messages. 19 func NewHandler(bank BankKeeper) bankHandler { 20 return bankHandler{ 21 bank: bank, 22 } 23 } 24 25 func (bh bankHandler) Process(ctx sdk.Context, msg std.Msg) sdk.Result { 26 switch msg := msg.(type) { 27 case MsgSend: 28 return bh.handleMsgSend(ctx, msg) 29 30 case MsgMultiSend: 31 return bh.handleMsgMultiSend(ctx, msg) 32 33 default: 34 errMsg := fmt.Sprintf("unrecognized bank message type: %T", msg) 35 return abciResult(std.ErrUnknownRequest(errMsg)) 36 } 37 } 38 39 // Handle MsgSend. 40 func (bh bankHandler) handleMsgSend(ctx sdk.Context, msg MsgSend) sdk.Result { 41 /* 42 if !bh.bank.GetSendEnabled(ctx) { 43 return abciResult(ErrSendDisabled()) 44 } 45 if bh.bank.BlacklistedAddr(msg.ToAddress) { 46 return std.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", msg.ToAddress)).Result() 47 } 48 */ 49 50 err := bh.bank.SendCoins(ctx, msg.FromAddress, msg.ToAddress, msg.Amount) 51 if err != nil { 52 return abciResult(err) 53 } 54 55 /* 56 ctx.EventManager().EmitEvent( 57 sdk.NewEvent( 58 sdk.EventTypeMessage, 59 sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), 60 ), 61 ) 62 */ 63 64 return sdk.Result{} 65 } 66 67 // Handle MsgMultiSend. 68 func (bh bankHandler) handleMsgMultiSend(ctx sdk.Context, msg MsgMultiSend) sdk.Result { 69 // NOTE: totalIn == totalOut should already have been checked 70 /* 71 if !k.GetSendEnabled(ctx) { 72 return abciResult(std.ErrSendDisabled()) 73 } 74 for _, out := range msg.Outputs { 75 if bh.bank.BlacklistedAddr(out.Address) { 76 return abciResult(std.ErrUnauthorized(fmt.Sprintf("%s is not allowed to receive transactions", out.Address))) 77 } 78 } 79 */ 80 81 err := bh.bank.InputOutputCoins(ctx, msg.Inputs, msg.Outputs) 82 if err != nil { 83 return abciResult(err) 84 } 85 86 /* 87 ctx.EventManager().EmitEvent( 88 sdk.NewEvent( 89 sdk.EventTypeMessage, 90 sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), 91 ), 92 ) 93 */ 94 95 return sdk.Result{} 96 } 97 98 //---------------------------------------- 99 // Query 100 101 // query balance path 102 const QueryBalance = "balances" 103 104 func (bh bankHandler) Query(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { 105 switch secondPart(req.Path) { 106 case QueryBalance: 107 return bh.queryBalance(ctx, req) 108 default: 109 res = sdk.ABCIResponseQueryFromError( 110 std.ErrUnknownRequest("unknown bank query endpoint")) 111 return 112 } 113 } 114 115 // queryBalance fetch an account's balance for the supplied height. 116 // Account address is passed as path component. 117 func (bh bankHandler) queryBalance(ctx sdk.Context, req abci.RequestQuery) (res abci.ResponseQuery) { 118 // parse addr from path. 119 b32addr := thirdPart(req.Path) 120 addr, err := crypto.AddressFromBech32(b32addr) 121 if err != nil { 122 res = sdk.ABCIResponseQueryFromError( 123 std.ErrInvalidAddress("invalid query address " + b32addr)) 124 } 125 126 // get coins from addr. 127 bz, err := amino.MarshalJSONIndent(bh.bank.GetCoins(ctx, addr), "", " ") 128 if err != nil { 129 res = sdk.ABCIResponseQueryFromError( 130 std.ErrInternal(fmt.Sprintf("could not marshal result to JSON: %s", err.Error()))) 131 return 132 } 133 134 res.Data = bz 135 return 136 } 137 138 //---------------------------------------- 139 // misc 140 141 func abciResult(err error) sdk.Result { 142 return sdk.ABCIResultFromError(err) 143 } 144 145 // returns the second component of a path. 146 func secondPart(path string) string { 147 parts := strings.Split(path, "/") 148 if len(parts) < 2 { 149 return "" 150 } else { 151 return parts[1] 152 } 153 } 154 155 // returns the third component of a path. 156 func thirdPart(path string) string { 157 parts := strings.Split(path, "/") 158 if len(parts) < 3 { 159 return "" 160 } else { 161 return parts[2] 162 } 163 }