github.com/gagliardetto/solana-go@v1.11.0/rpc/ws/signatureSubscribe.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  	"fmt"
    19  	"time"
    20  
    21  	"github.com/gagliardetto/solana-go"
    22  	"github.com/gagliardetto/solana-go/rpc"
    23  )
    24  
    25  type SignatureResult struct {
    26  	Context struct {
    27  		Slot uint64
    28  	} `json:"context"`
    29  	Value struct {
    30  		Err interface{} `json:"err"`
    31  	} `json:"value"`
    32  }
    33  
    34  // SignatureSubscribe subscribes to a transaction signature to receive
    35  // notification when the transaction is confirmed On signatureNotification,
    36  // the subscription is automatically cancelled
    37  func (cl *Client) SignatureSubscribe(
    38  	signature solana.Signature, // Transaction Signature.
    39  	commitment rpc.CommitmentType, // (optional)
    40  ) (*SignatureSubscription, error) {
    41  	params := []interface{}{signature.String()}
    42  	conf := map[string]interface{}{}
    43  	if commitment != "" {
    44  		conf["commitment"] = commitment
    45  	}
    46  
    47  	genSub, err := cl.subscribe(
    48  		params,
    49  		conf,
    50  		"signatureSubscribe",
    51  		"signatureUnsubscribe",
    52  		func(msg []byte) (interface{}, error) {
    53  			var res SignatureResult
    54  			err := decodeResponseFromMessage(msg, &res)
    55  			return &res, err
    56  		},
    57  	)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	return &SignatureSubscription{
    62  		sub: genSub,
    63  	}, nil
    64  }
    65  
    66  type SignatureSubscription struct {
    67  	sub *Subscription
    68  }
    69  
    70  func (sw *SignatureSubscription) Recv() (*SignatureResult, error) {
    71  	select {
    72  	case d := <-sw.sub.stream:
    73  		return d.(*SignatureResult), nil
    74  	case err := <-sw.sub.err:
    75  		return nil, err
    76  	}
    77  }
    78  
    79  func (sw *SignatureSubscription) Err() <-chan error {
    80  	return sw.sub.err
    81  }
    82  
    83  func (sw *SignatureSubscription) Response() <-chan *SignatureResult {
    84  	typedChan := make(chan *SignatureResult, 1)
    85  	go func(ch chan *SignatureResult) {
    86  		// TODO: will this subscription yield more than one result?
    87  		d, ok := <-sw.sub.stream
    88  		if !ok {
    89  			return
    90  		}
    91  		ch <- d.(*SignatureResult)
    92  	}(typedChan)
    93  	return typedChan
    94  }
    95  
    96  var ErrTimeout = fmt.Errorf("timeout waiting for confirmation")
    97  
    98  func (sw *SignatureSubscription) RecvWithTimeout(timeout time.Duration) (*SignatureResult, error) {
    99  	select {
   100  	case <-time.After(timeout):
   101  		return nil, ErrTimeout
   102  	case d := <-sw.sub.stream:
   103  		return d.(*SignatureResult), nil
   104  	case err := <-sw.sub.err:
   105  		return nil, err
   106  	}
   107  }
   108  
   109  func (sw *SignatureSubscription) Unsubscribe() {
   110  	sw.sub.Unsubscribe()
   111  }