2020-11-13 14:04:10 +00:00
|
|
|
package solana
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
2020-11-18 18:33:03 +00:00
|
|
|
"github.com/Secured-Finance/dione/rpc/types"
|
|
|
|
|
|
|
|
stypes "github.com/Secured-Finance/dione/rpc/solana/types"
|
2020-11-13 14:04:10 +00:00
|
|
|
ws "github.com/dgrr/fastws"
|
|
|
|
"github.com/shengdoushi/base58"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
|
|
)
|
|
|
|
|
|
|
|
var solanaAlphabet = base58.BitcoinAlphabet
|
|
|
|
|
|
|
|
type SolanaClient struct {
|
|
|
|
url string
|
|
|
|
ws string
|
|
|
|
}
|
|
|
|
|
2020-11-13 15:36:01 +00:00
|
|
|
type SubParams struct {
|
|
|
|
Encoding string `json:"encoding"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewSubParam(encoding string) *SubParams {
|
|
|
|
return &SubParams{
|
|
|
|
Encoding: encoding,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 14:04:10 +00:00
|
|
|
// NewSolanaClient creates a new solana client structure.
|
|
|
|
func NewSolanaClient() *SolanaClient {
|
|
|
|
return &SolanaClient{
|
|
|
|
url: "http://devnet.solana.com:8899/",
|
|
|
|
ws: "ws://devnet.solana.com:8900/",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 14:03:39 +00:00
|
|
|
func (c *SolanaClient) GetTransaction(txHash string) ([]byte, error) {
|
2020-11-13 14:04:10 +00:00
|
|
|
req := fasthttp.AcquireRequest()
|
|
|
|
req.SetRequestURI(c.url)
|
|
|
|
req.Header.SetMethod("POST")
|
|
|
|
req.Header.SetContentType("application/json")
|
2020-11-18 18:33:03 +00:00
|
|
|
requestBody := types.NewRPCRequestBody("getConfirmedTransaction")
|
2020-11-15 05:59:46 +00:00
|
|
|
requestBody.Params = append(requestBody.Params, txHash, "json")
|
2020-11-13 14:04:10 +00:00
|
|
|
body, err := json.Marshal(requestBody)
|
|
|
|
if err != nil {
|
2020-12-02 14:03:39 +00:00
|
|
|
return nil, fmt.Errorf("Failed to marshal request body %v", err)
|
2020-11-13 14:04:10 +00:00
|
|
|
}
|
|
|
|
req.AppendBody(body)
|
|
|
|
resp := fasthttp.AcquireResponse()
|
|
|
|
client := &fasthttp.Client{}
|
|
|
|
if err = client.Do(req, resp); err != nil {
|
|
|
|
logrus.Warn("Failed to construct solana node rpc request", err)
|
2020-12-02 14:03:39 +00:00
|
|
|
return nil, err
|
2020-11-13 14:04:10 +00:00
|
|
|
}
|
|
|
|
bodyBytes := resp.Body()
|
|
|
|
logrus.Info(string(bodyBytes))
|
2020-12-02 14:03:39 +00:00
|
|
|
return bodyBytes, nil
|
2020-11-13 14:04:10 +00:00
|
|
|
}
|
|
|
|
|
2020-11-18 18:33:03 +00:00
|
|
|
func (c *SolanaClient) subscribeOnProgram(programID string) {
|
2020-11-13 14:04:10 +00:00
|
|
|
conn, err := ws.Dial(c.ws)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln("Can't establish connection with Solana websocket: ", err)
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
|
2020-11-18 18:33:03 +00:00
|
|
|
requestBody := types.NewRPCRequestBody("programSubscribe")
|
2020-11-13 14:04:10 +00:00
|
|
|
requestBody.Params = append(requestBody.Params, programID)
|
2020-11-13 15:36:01 +00:00
|
|
|
p := NewSubParam("jsonParsed")
|
|
|
|
requestBody.Params = append(requestBody.Params, p)
|
2020-11-13 14:04:10 +00:00
|
|
|
body, err := json.Marshal(requestBody)
|
2020-11-13 15:36:01 +00:00
|
|
|
logrus.Info(string(body))
|
2020-11-13 14:04:10 +00:00
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Couldn't unmarshal parameters to request body %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
subscriptionID, err := conn.Write(body)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Couldn't send a websocket request to Solana node %v", err)
|
|
|
|
}
|
|
|
|
logrus.Info("Websocket established with ProgramID:", programID)
|
|
|
|
logrus.Info("Subscription ID to drop websocket connection:", subscriptionID)
|
|
|
|
|
|
|
|
var msg []byte
|
2020-11-18 18:33:03 +00:00
|
|
|
var parsedSub *stypes.Subscription
|
2020-11-13 14:04:10 +00:00
|
|
|
for {
|
|
|
|
_, msg, err = conn.ReadMessage(msg[:0])
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
json.Unmarshal(msg, &parsedSub)
|
|
|
|
logrus.Info("Subscription: ", parsedSub)
|
|
|
|
// 2) Save data from oracle event in redis cache
|
|
|
|
// 3) Start mining of Solana oracle event
|
|
|
|
}
|
|
|
|
}
|