Skip to content

Instantly share code, notes, and snippets.

@goodylili
Last active August 21, 2024 14:19
Show Gist options
  • Save goodylili/7a2cb0bf20b5a9192f2d0d1ed3bcb330 to your computer and use it in GitHub Desktop.
Save goodylili/7a2cb0bf20b5a9192f2d0d1ed3bcb330 to your computer and use it in GitHub Desktop.
listen to uniswap pair created events
package main
import (
"context"
"fmt"
"log"
"math/big"
"strings"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
const UniswapV2FactoryABI = `[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"initCodeHash","type":"uint256"}],"name":"PairCreated","type":"event"}]`
const UniswapV2FactoryAddress = "0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6"
func main() {
client, err := ethclient.Dial("https://mainnet.base.org")
if err != nil {
log.Fatalf("Failed to connect to the Ethereum client: %v", err)
}
parsedABI, err := abi.JSON(strings.NewReader(UniswapV2FactoryABI))
if err != nil {
log.Fatalf("Failed to parse ABI: %v", err)
}
pairCreatedEvent := parsedABI.Events["PairCreated"]
filterQuery := ethereum.FilterQuery{
Addresses: []common.Address{common.HexToAddress(UniswapV2FactoryAddress)},
Topics: [][]common.Hash{
{pairCreatedEvent.ID},
},
}
var lastBlock uint64 = 0
for {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
latestBlock, err := client.BlockNumber(ctx)
if err != nil {
log.Printf("Failed to get latest block number: %v", err)
time.Sleep(5 * time.Second)
continue
}
if lastBlock == 0 {
lastBlock = latestBlock - 1
}
filterQuery.FromBlock = new(big.Int).SetUint64(lastBlock + 1)
filterQuery.ToBlock = new(big.Int).SetUint64(latestBlock)
logs, err := client.FilterLogs(ctx, filterQuery)
if err != nil {
log.Printf("Failed to filter logs: %v", err)
time.Sleep(5 * time.Second)
continue
}
for _, vLog := range logs {
fmt.Printf("Raw Log Data: %s\n", vLog.Data) // Debug log data
fmt.Printf("Raw Log Topics: %v\n", vLog.Topics) // Debug log topics
event := struct {
Token0 common.Address
Token1 common.Address
Pair common.Address
InitCodeHash *big.Int
}{}
// Manually extract indexed topics
event.Token0 = common.HexToAddress(vLog.Topics[1].Hex())
event.Token1 = common.HexToAddress(vLog.Topics[2].Hex())
// Unpack non-indexed data
err := parsedABI.UnpackIntoInterface(&event, "PairCreated", vLog.Data)
if err != nil {
log.Printf("Failed to unpack log: %v", err)
continue
}
// Print out the unpacked data for verification
fmt.Printf("Unpacked Data:\n")
fmt.Printf("Token0: %s\n", event.Token0.Hex())
fmt.Printf("Token1: %s\n", event.Token1.Hex())
fmt.Printf("Pair Address: %s\n", event.Pair.Hex())
fmt.Printf("InitCodeHash: %s\n\n", event.InitCodeHash.String())
}
lastBlock = latestBlock
time.Sleep(15 * time.Second)
}
}
package main
import (
"context"
"fmt"
"log"
"math/big"
"strings"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
const UniswapV3FactoryABI = `[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolCreated","type":"event"}]`
const UniswapV3FactoryAddress = "" +
""
func main() {
client, err := ethclient.Dial("https://mainnet.base.org")
if err != nil {
log.Fatalf("Failed to connect to the Base client: %v", err)
}
parsedABI, err := abi.JSON(strings.NewReader(UniswapV3FactoryABI))
if err != nil {
log.Fatalf("Failed to parse ABI: %v", err)
}
filterQuery := ethereum.FilterQuery{
Addresses: []common.Address{common.HexToAddress(UniswapV3FactoryAddress)},
Topics: [][]common.Hash{
{parsedABI.Events["PoolCreated"].ID},
},
}
var lastBlock uint64 = 0
for {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Get the latest block number
latestBlock, err := client.BlockNumber(ctx)
if err != nil {
log.Printf("Failed to get latest block number: %v", err)
time.Sleep(5 * time.Second)
continue
}
if lastBlock == 0 {
lastBlock = latestBlock - 1
}
filterQuery.FromBlock = new(big.Int).SetUint64(lastBlock + 1)
filterQuery.ToBlock = new(big.Int).SetUint64(latestBlock)
logs, err := client.FilterLogs(ctx, filterQuery)
if err != nil {
log.Printf("Failed to filter logs: %v", err)
time.Sleep(5 * time.Second)
continue
}
for _, vLog := range logs {
event := struct {
Token0 common.Address
Token1 common.Address
Fee *big.Int
TickSpacing *big.Int
Pool common.Address
}{}
err := parsedABI.UnpackIntoInterface(&event, "PoolCreated", vLog.Data)
if err != nil {
log.Printf("Failed to unpack log: %v", err)
continue
}
event.Token0 = common.HexToAddress(vLog.Topics[1].Hex())
event.Token1 = common.HexToAddress(vLog.Topics[2].Hex())
fmt.Printf("New pool created:\n")
fmt.Printf("Token0: %s\n", event.Token0.Hex())
fmt.Printf("Token1: %s\n", event.Token1.Hex())
fmt.Printf("Fee: %s\n", event.Fee.String())
fmt.Printf("TickSpacing: %s\n", event.TickSpacing.String())
fmt.Printf("Pool Address: %s\n\n", event.Pool.Hex())
}
lastBlock = latestBlock
time.Sleep(15 * time.Second)
}
}
@theghostmac
Copy link

package main

import (
	"context"
	"fmt"
	"log"
	"math/big"
	"strings"
	"time"

	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
)

const UniswapV3FactoryABI = `[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":true,"internalType":"uint24","name":"fee","type":"uint24"},{"indexed":false,"internalType":"int24","name":"tickSpacing","type":"int24"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolCreated","type":"event"}]`

const UniswapV3FactoryAddress = "0x33128a8fC17869897dcE68Ed026d694621f6FDfD"

func main() {
	client, err := ethclient.Dial("https://mainnet.base.org")
	if err != nil {
		log.Fatalf("Failed to connect to the Base client: %v", err)
	}

	parsedABI, err := abi.JSON(strings.NewReader(UniswapV3FactoryABI))
	if err != nil {
		log.Fatalf("Failed to parse ABI: %v", err)
	}

	filterQuery := ethereum.FilterQuery{
		Addresses: []common.Address{common.HexToAddress(UniswapV3FactoryAddress)},
		Topics: [][]common.Hash{
			{parsedABI.Events["PoolCreated"].ID},
		},
	}

	var lastBlock uint64 = 0
	for {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()

		// Get the latest block number
		latestBlock, err := client.BlockNumber(ctx)
		if err != nil {
			log.Printf("Failed to get latest block number: %v", err)
			time.Sleep(5 * time.Second)
			continue
		}

		if lastBlock == 0 {
			lastBlock = latestBlock - 1
		}

		filterQuery.FromBlock = new(big.Int).SetUint64(lastBlock + 1)
		filterQuery.ToBlock = new(big.Int).SetUint64(latestBlock)

		logs, err := client.FilterLogs(ctx, filterQuery)
		if err != nil {
			log.Printf("Failed to filter logs: %v", err)
			time.Sleep(5 * time.Second)
			continue
		}

		for _, vLog := range logs {
			event := struct {
				Token0      common.Address
				Token1      common.Address
				Fee         *big.Int
				TickSpacing *big.Int
				Pool        common.Address
			}{}
			err := parsedABI.UnpackIntoInterface(&event, "PoolCreated", vLog.Data)
			if err != nil {
				log.Printf("Failed to unpack log: %v", err)
				continue
			}

			event.Token0 = common.HexToAddress(vLog.Topics[1].Hex())
			event.Token1 = common.HexToAddress(vLog.Topics[2].Hex())

			fmt.Printf("New pool created:\n")
			fmt.Printf("Token0: %s\n", event.Token0.Hex())
			fmt.Printf("Token1: %s\n", event.Token1.Hex())
			fmt.Printf("Fee: %s\n", event.Fee.String())
			fmt.Printf("TickSpacing: %s\n", event.TickSpacing.String())
			fmt.Printf("Pool Address: %s\n\n", event.Pool.Hex())
		}

		lastBlock = latestBlock
		time.Sleep(15 * time.Second)
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment