github.com/MetalBlockchain/metalgo@v1.11.9/vms/example/xsvm/api/server.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package api
     5  
     6  import (
     7  	"net/http"
     8  
     9  	"github.com/MetalBlockchain/metalgo/database"
    10  	"github.com/MetalBlockchain/metalgo/ids"
    11  	"github.com/MetalBlockchain/metalgo/snow"
    12  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/block"
    13  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/builder"
    14  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/chain"
    15  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/genesis"
    16  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/state"
    17  	"github.com/MetalBlockchain/metalgo/vms/example/xsvm/tx"
    18  	"github.com/MetalBlockchain/metalgo/vms/platformvm/warp"
    19  )
    20  
    21  // Server defines the xsvm API server.
    22  type Server interface {
    23  	Network(r *http.Request, args *struct{}, reply *NetworkReply) error
    24  	Genesis(r *http.Request, args *struct{}, reply *GenesisReply) error
    25  	Nonce(r *http.Request, args *NonceArgs, reply *NonceReply) error
    26  	Balance(r *http.Request, args *BalanceArgs, reply *BalanceReply) error
    27  	Loan(r *http.Request, args *LoanArgs, reply *LoanReply) error
    28  	IssueTx(r *http.Request, args *IssueTxArgs, reply *IssueTxReply) error
    29  	LastAccepted(r *http.Request, args *struct{}, reply *LastAcceptedReply) error
    30  	Block(r *http.Request, args *BlockArgs, reply *BlockReply) error
    31  	Message(r *http.Request, args *MessageArgs, reply *MessageReply) error
    32  }
    33  
    34  func NewServer(
    35  	ctx *snow.Context,
    36  	genesis *genesis.Genesis,
    37  	state database.KeyValueReader,
    38  	chain chain.Chain,
    39  	builder builder.Builder,
    40  ) Server {
    41  	return &server{
    42  		ctx:     ctx,
    43  		genesis: genesis,
    44  		state:   state,
    45  		chain:   chain,
    46  		builder: builder,
    47  	}
    48  }
    49  
    50  type server struct {
    51  	ctx     *snow.Context
    52  	genesis *genesis.Genesis
    53  	state   database.KeyValueReader
    54  	chain   chain.Chain
    55  	builder builder.Builder
    56  }
    57  
    58  type NetworkReply struct {
    59  	NetworkID uint32 `json:"networkID"`
    60  	SubnetID  ids.ID `json:"subnetID"`
    61  	ChainID   ids.ID `json:"chainID"`
    62  }
    63  
    64  func (s *server) Network(_ *http.Request, _ *struct{}, reply *NetworkReply) error {
    65  	reply.NetworkID = s.ctx.NetworkID
    66  	reply.SubnetID = s.ctx.SubnetID
    67  	reply.ChainID = s.ctx.ChainID
    68  	return nil
    69  }
    70  
    71  type GenesisReply struct {
    72  	Genesis *genesis.Genesis `json:"genesis"`
    73  }
    74  
    75  func (s *server) Genesis(_ *http.Request, _ *struct{}, reply *GenesisReply) error {
    76  	reply.Genesis = s.genesis
    77  	return nil
    78  }
    79  
    80  type NonceArgs struct {
    81  	Address ids.ShortID `json:"address"`
    82  }
    83  
    84  type NonceReply struct {
    85  	Nonce uint64 `json:"nonce"`
    86  }
    87  
    88  func (s *server) Nonce(_ *http.Request, args *NonceArgs, reply *NonceReply) error {
    89  	nonce, err := state.GetNonce(s.state, args.Address)
    90  	reply.Nonce = nonce
    91  	return err
    92  }
    93  
    94  type BalanceArgs struct {
    95  	Address ids.ShortID `json:"address"`
    96  	AssetID ids.ID      `json:"assetID"`
    97  }
    98  
    99  type BalanceReply struct {
   100  	Balance uint64 `json:"balance"`
   101  }
   102  
   103  func (s *server) Balance(_ *http.Request, args *BalanceArgs, reply *BalanceReply) error {
   104  	balance, err := state.GetBalance(s.state, args.Address, args.AssetID)
   105  	reply.Balance = balance
   106  	return err
   107  }
   108  
   109  type LoanArgs struct {
   110  	ChainID ids.ID `json:"chainID"`
   111  }
   112  
   113  type LoanReply struct {
   114  	Amount uint64 `json:"amount"`
   115  }
   116  
   117  func (s *server) Loan(_ *http.Request, args *LoanArgs, reply *LoanReply) error {
   118  	amount, err := state.GetLoan(s.state, args.ChainID)
   119  	reply.Amount = amount
   120  	return err
   121  }
   122  
   123  type IssueTxArgs struct {
   124  	Tx []byte `json:"tx"`
   125  }
   126  
   127  type IssueTxReply struct {
   128  	TxID ids.ID `json:"txID"`
   129  }
   130  
   131  func (s *server) IssueTx(r *http.Request, args *IssueTxArgs, reply *IssueTxReply) error {
   132  	newTx, err := tx.Parse(args.Tx)
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	ctx := r.Context()
   138  	s.ctx.Lock.Lock()
   139  	err = s.builder.AddTx(ctx, newTx)
   140  	s.ctx.Lock.Unlock()
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	txID, err := newTx.ID()
   146  	reply.TxID = txID
   147  	return err
   148  }
   149  
   150  type LastAcceptedReply struct {
   151  	BlockID ids.ID           `json:"blockID"`
   152  	Block   *block.Stateless `json:"block"`
   153  }
   154  
   155  func (s *server) LastAccepted(_ *http.Request, _ *struct{}, reply *LastAcceptedReply) error {
   156  	s.ctx.Lock.RLock()
   157  	reply.BlockID = s.chain.LastAccepted()
   158  	s.ctx.Lock.RUnlock()
   159  	blkBytes, err := state.GetBlock(s.state, reply.BlockID)
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	reply.Block, err = block.Parse(blkBytes)
   165  	return err
   166  }
   167  
   168  type BlockArgs struct {
   169  	BlockID ids.ID `json:"blockID"`
   170  }
   171  
   172  type BlockReply struct {
   173  	Block *block.Stateless `json:"block"`
   174  }
   175  
   176  func (s *server) Block(_ *http.Request, args *BlockArgs, reply *BlockReply) error {
   177  	blkBytes, err := state.GetBlock(s.state, args.BlockID)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	reply.Block, err = block.Parse(blkBytes)
   183  	return err
   184  }
   185  
   186  type MessageArgs struct {
   187  	TxID ids.ID `json:"txID"`
   188  }
   189  
   190  type MessageReply struct {
   191  	Message   *warp.UnsignedMessage `json:"message"`
   192  	Signature []byte                `json:"signature"`
   193  }
   194  
   195  func (s *server) Message(_ *http.Request, args *MessageArgs, reply *MessageReply) error {
   196  	message, err := state.GetMessage(s.state, args.TxID)
   197  	if err != nil {
   198  		return err
   199  	}
   200  
   201  	reply.Message = message
   202  	reply.Signature, err = s.ctx.WarpSigner.Sign(message)
   203  	return err
   204  }