github.com/gagliardetto/solana-go@v1.11.0/rpc/ws/accountSubscribe.go (about)

     1  // Copyright 2021 github.com/gagliardetto
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ws
    16  
    17  import (
    18  	"github.com/gagliardetto/solana-go"
    19  	"github.com/gagliardetto/solana-go/rpc"
    20  )
    21  
    22  type AccountResult struct {
    23  	Context struct {
    24  		Slot uint64
    25  	} `json:"context"`
    26  	Value struct {
    27  		rpc.Account
    28  	} `json:"value"`
    29  }
    30  
    31  // AccountSubscribe subscribes to an account to receive notifications
    32  // when the lamports or data for a given account public key changes.
    33  func (cl *Client) AccountSubscribe(
    34  	account solana.PublicKey,
    35  	commitment rpc.CommitmentType,
    36  ) (*AccountSubscription, error) {
    37  	return cl.AccountSubscribeWithOpts(
    38  		account,
    39  		commitment,
    40  		"",
    41  	)
    42  }
    43  
    44  // AccountSubscribe subscribes to an account to receive notifications
    45  // when the lamports or data for a given account public key changes.
    46  func (cl *Client) AccountSubscribeWithOpts(
    47  	account solana.PublicKey,
    48  	commitment rpc.CommitmentType,
    49  	encoding solana.EncodingType,
    50  ) (*AccountSubscription, error) {
    51  
    52  	params := []interface{}{account.String()}
    53  	conf := map[string]interface{}{
    54  		"encoding": "base64",
    55  	}
    56  	if commitment != "" {
    57  		conf["commitment"] = commitment
    58  	}
    59  	if encoding != "" {
    60  		conf["encoding"] = encoding
    61  	}
    62  
    63  	genSub, err := cl.subscribe(
    64  		params,
    65  		conf,
    66  		"accountSubscribe",
    67  		"accountUnsubscribe",
    68  		func(msg []byte) (interface{}, error) {
    69  			var res AccountResult
    70  			err := decodeResponseFromMessage(msg, &res)
    71  			return &res, err
    72  		},
    73  	)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return &AccountSubscription{
    78  		sub: genSub,
    79  	}, nil
    80  }
    81  
    82  type AccountSubscription struct {
    83  	sub *Subscription
    84  }
    85  
    86  func (sw *AccountSubscription) Recv() (*AccountResult, error) {
    87  	select {
    88  	case d := <-sw.sub.stream:
    89  		return d.(*AccountResult), nil
    90  	case err := <-sw.sub.err:
    91  		return nil, err
    92  	}
    93  }
    94  
    95  func (sw *AccountSubscription) Err() <-chan error {
    96  	return sw.sub.err
    97  }
    98  
    99  func (sw *AccountSubscription) Response() <-chan *AccountResult {
   100  	typedChan := make(chan *AccountResult, 1)
   101  	go func(ch chan *AccountResult) {
   102  		// TODO: will this subscription yield more than one result?
   103  		d, ok := <-sw.sub.stream
   104  		if !ok {
   105  			return
   106  		}
   107  		ch <- d.(*AccountResult)
   108  	}(typedChan)
   109  	return typedChan
   110  }
   111  
   112  func (sw *AccountSubscription) Unsubscribe() {
   113  	sw.sub.Unsubscribe()
   114  }