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 }