Sova Labs
  • Introduction
  • FAQ
  • MEV on TON
    • Overview
  • MEV Searcher Guide
    • FAQ
    • Rust SDK
    • Golang SDK
    • Javascript SDK
  • API Overview
  • Blockchain Node
    • Overview
    • First Validator Setup
    • Existing Validator Update
    • Configuration Validator client or LiteServer
    • Rollback to the original TON version
Powered by GitBook
On this page
  • Prerequisite
  • Create a SovaClient Instance for Testnet
  • Authenticate the Client
  • Subscribe for Messages
  • Subscribe by Workchain
  • Subscribe by addresses
  • Subscribe by Workchain shard
  • Subscribe by external out message body opcode
  • Subscribe by internal message body opcode
  • Bundles Submission
  • Bundles Results tracking
  1. MEV Searcher Guide

Golang SDK

PreviousRust SDKNextJavascript SDK

Last updated 2 months ago

Prerequisite

The Golang Sova SDK is available at .

Add the Sova SDK by running:

go get github.com/sova-network/sova-sdk-go@latest

CAUTION: By default, each searcher enforces a limit of 5 requests per second. If you need to have a higher limit, you can send a request to hello@sova.network.

Create a SovaClient Instance for Testnet

package main

import (
	sova_sdk_go "github.com/sova-network/sova-sdk-go"
)

func main() {
	// Create a new client instance for the testnet
	var client = sova_sdk_go.NewTestnetClient()
}

Authenticate the Client

If you need authenticated access, you can sign the challenge provided by the Sova Engine using your ED25519 private key. Replace the dummy private key with your actual 32-byte ED25519 key. If you choose to skip authentication, simply do not call this method.

package main

import (
	"encoding/base64"
	"fmt"
	"time"
	"context"

	sova_sdk_go "github.com/sova-network/sova-sdk-go"
)


func main() {
	client := sova_sdk_go.NewTestnetClient()
	
	// Replace with your actual 32-byte private key.
	privKeyB64 := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
	
	privateKey, err := base64.StdEncoding.DecodeString(privKeyB64)
	if err != nil {
		panic(err)
	}
	
	ctx := context.Background()
	// Authenticate and obtain an access token.
	token, err := client.Authenticate(ctx, privateKey)
	if err != nil {
		fmt.Println(err)
	}
	
	searcher, err := client.Searcher(ctx)
	if err != nil {
		panic(err)
	}
	searcher.SetAccessToken(token)
	
	// Subscription 
	// searcher.SubscribeByWorkchainShard(...)
	
	// Keep the application running to receive messages
	for {
		time.Sleep(1 * time.Second)
	}
}

Subscribe for Messages

Regardless of authentication, you can use the searcher service to subscribe to Mempool messages.

Subscribe by Workchain

    // ...
	mempoolCh := make(chan *types.MempoolPacket, 10)	
	err = searcher.SubscribeByWorkchain(ctx, 0, func(mp *types.MempoolPacket) {
		fmt.Println("reseive wc packet")
		mempoolCh <- mp
	})
	if err != nil {
		panic(err)
	}
    // ...

Subscribe by addresses

// ...
	//"0:hex_adddress1", "0:hex_address2" // 0 - workchain id, hex_address - hex encoded address
	_ = searcher.SubscribeByAddress(ctx, []string{"hex_address", "hex_address"}, func(mp *types.MempoolPacket) {
		fmt.Println("reseive address packet: %v", mp)
	})
// ...

Subscribe by Workchain shard

    // ...
	shard, _ := hex.DecodeString("e000000000000000")
	resultCh := make(chan *types.BundleResult, 1)	
	_ = searcher.SubscribeByWorkchainShard(ctx, 0, shard, func(mp *types.MempoolPacket) {
		fmt.Println("reseive shard packet")
		fmt.Printf("shard: %v\n", shard)
		mempoolCh <- mp
	})
    // ...

Subscribe by external out message body opcode

// TODO

Subscribe by internal message body opcode

    // ...
	resultCh := make(chan *types.BundleResult, 1)	
	shard, _ := hex.DecodeString("e000000000000000")
	_ = searcher.SubscribeByInternalMsgBodyOpcode(ctx, 0, shard, 0xf8a7ea5, func(mp *types.MempoolPacket) {
		fmt.Println("reseive opcode packet")
		fmt.Printf("shard: %v\n", shard)

		mempoolCh <- mp
	})
    // ...

Bundles Submission

	resultCh := make(chan *types.BundleResult, 1)
	err = searcher.SubscribeBundleResult(ctx, func(br *types.BundleResult) {
		fmt.Println("reseive bundle result")
		resultCh <- br
	})
	if err != nil {
		panic(err)
	}

	for {
		select {
		case msg := <-mempoolCh:
			fmt.Printf("got mempool packet: %v\n", len(msg.ExternalMessages))
			extMsg := msg.ExternalMessages[0]
			fmt.Printf("ext msg.GasSpend: %v\n", extMsg.GasSpent)
			fmt.Printf("ext msg.Shard: %v\n", hex.EncodeToString(extMsg.Shard))
			fmt.Printf("ext msg.StdSmcAddress: %v\n", hex.EncodeToString(extMsg.StdSmcAddress))
			
			// Send bundle 
			res, err := searcher.SendBundle(ctx, &types.Bundle{
				Message: []*types.ExternalMessage{
					{
						Data: []byte(msg.ExternalMessages[0].Data),
					},
				},
				ExpirationNs: nil,
			})
			if err != nil {
				panic(err)
			}
			fmt.Printf("got bundle response: %v\n", res)
		}
	}

Bundles Results tracking

// ...
	resultCh := make(chan *types.BundleResult, 1)
	err = searcher.SubscribeBundleResult(ctx, func(br *types.BundleResult) {
		fmt.Println("reseive bundle result")
		resultCh <- br
	})
	if err != nil {
		panic(err)
	}
// ...
	for {
		select {
		case res := <-resultCh:
			fmt.Println("got bundle result")
			fmt.Printf("result: %v\n", res)	
			return
		}
	// ...
	}
https://github.com/sova-network/sova-sdk-go