Skip to content

Instantly share code, notes, and snippets.

@melardev
Created October 24, 2024 16:23
Show Gist options
  • Select an option

  • Save melardev/73880368497fd05f16428dbb7cbbdc4e to your computer and use it in GitHub Desktop.

Select an option

Save melardev/73880368497fd05f16428dbb7cbbdc4e to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
bin "github.com/gagliardetto/binary"
tokenMetadata "github.com/gagliardetto/metaplex-go/clients/token-metadata"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/gagliardetto/solana-go/rpc/ws"
"log"
"strings"
"testing"
"time"
)
var (
metadataProgramID = solana.MustPublicKeyFromBase58("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s") // METADATA_PROGRAM_ID
pumpFunRaydiumMigrationProgramId = solana.MustPublicKeyFromBase58("39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg")
pumpFunProgramId = solana.MustPublicKeyFromBase58("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
)
func getMetadataPDA(mint solana.PublicKey) (solana.PublicKey, error) {
seeds := [][]byte{
[]byte("metadata"),
metadataProgramID.Bytes(),
mint.Bytes(),
}
pda, _, err := solana.FindProgramAddress(seeds, metadataProgramID)
if err != nil {
return solana.PublicKey{}, fmt.Errorf("failed to find program address: %w", err)
}
return pda, nil
}
func getTokenMetadata(tokenAddr solana.PublicKey) (tokenMetadata.Metadata, error) {
ctx := context.Background()
client := rpc.New(rpc.MainNetBeta_RPC)
metadataPDA, err := getMetadataPDA(tokenAddr)
if err != nil {
return tokenMetadata.Metadata{}, err
}
accountInfo, err := client.GetAccountInfo(ctx, metadataPDA)
if err != nil {
return tokenMetadata.Metadata{}, fmt.Errorf("failed to get account info: %w", err)
}
if accountInfo == nil || accountInfo.Value == nil {
return tokenMetadata.Metadata{}, fmt.Errorf("account not found")
}
dec := bin.NewBorshDecoder(accountInfo.Value.Data.GetBinary())
metadata := tokenMetadata.Metadata{}
// err = dec.Decode(&metadata)
// Or
err = metadata.UnmarshalWithDecoder(dec)
if err != nil {
return tokenMetadata.Metadata{}, fmt.Errorf("failed to unmarshal metadata: %w", err)
}
return metadata, nil
}
func main() {
rpcClient := rpc.New(rpc.MainNetBeta.RPC)
wsClient, err := ws.Connect(context.Background(), rpc.MainNetBeta.WS)
if err != nil {
panic(err)
}
sub, err := wsClient.LogsSubscribeMentions(pumpFunRaydiumMigrationProgramId, rpc.CommitmentConfirmed)
if err != nil {
panic(err)
}
defer sub.Unsubscribe()
var tokensMigrated []int
var totalTokens int32 = 0
var tokenMigrationsCh = make(chan struct{})
// Counter
go func() {
ticker := time.NewTicker(time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
tokensMigrated = append(tokensMigrated, int(totalTokens))
// Rotate every 1000 entries
if len(tokensMigrated) > 1000 {
tokensMigrated = tokensMigrated[1:]
}
// Print total number of tokens created so far
sum := 0
for _, count := range tokensMigrated {
sum += count
}
fmt.Printf("Total tokens migrated, last minute: %d, total: %d\n", totalTokens, sum)
// Reset token count for the next minute
totalTokens = 0
case <-tokenMigrationsCh:
totalTokens++
}
}
}()
for {
msg, err := sub.Recv()
if err != nil {
log.Printf("Error receiving log: %v\n", err)
continue
}
for _, logEntry := range msg.Value.Logs {
if !strings.Contains(logEntry, "Program log: Instruction: Withdraw") {
continue
}
tokenMigrationsCh <- struct{}{} // Signal token creation
fmt.Printf("Migration found at https://solscan.io/tx/%s\n", msg.Value.Signature)
zero := uint64(0)
transactionDetails, err := rpcClient.GetParsedTransaction(
context.TODO(),
msg.Value.Signature,
&rpc.GetParsedTransactionOpts{
Commitment: rpc.CommitmentConfirmed,
MaxSupportedTransactionVersion: &zero,
},
)
if err != nil {
log.Printf("GET_PARSED_TRANSACTIONS_ERROR: %v\n", err)
continue
}
if transactionDetails != nil {
tx := transactionDetails
// accountKeys := tx.Transaction.Message.AccountKeys
instructions := tx.Transaction.Message.Instructions
for _, ix := range instructions {
if ix.ProgramId.String() == pumpFunProgramId.String() {
if len(ix.Accounts) >= 5 {
tokenMintAddress := ix.Accounts[2].String()
// bondingCurveAddress := ix.Accounts[4].String()
metadata, err := getTokenMetadata(solana.MustPublicKeyFromBase58(tokenMintAddress))
if err != nil {
fmt.Printf("Token migrated %s, but error getting token metadata: %v\n",
tokenMintAddress, err)
} else {
name := strings.ReplaceAll(metadata.Data.Name, "\x00", "")
symbol := strings.ReplaceAll(metadata.Data.Symbol, "\x00", "")
fmt.Printf("Token %s %s (%s)\n",
tokenMintAddress, name, symbol)
}
} else {
log.Println("Unexpected instruction format")
}
}
}
}
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment