NethermindEth / near-sffl

https://nffl.nethermind.io/
MIT License
6 stars 3 forks source link

Remove reinitialization from SafeEthClient #175

Closed Hyodar closed 1 month ago

Hyodar commented 1 month ago

As mentioned in #173, we don't actually need to reinitialize the client for reinitializing the subscription, or it seems anything else. So, we can make SafeEthClient a whole lot less complex.

Besides the unit tests, if you'd like to try the header resubscription in a more interactive manner, use anvil --block-time 1 (you can start/stop as desired) and go run run this:

package main

import (
    "context"
    "fmt"

    "github.com/Layr-Labs/eigensdk-go/logging"
    "github.com/NethermindEth/near-sffl/core/safeclient"
    "github.com/ethereum/go-ethereum/core/types"
)

func main() {
    logger, err := logging.NewZapLogger("development")
    if err != nil {
        panic(err)
    }

    rpcClient, err := safeclient.NewSafeEthClient("ws://localhost:8545", logger)
    if err != nil {
        panic(err)
    }

    ch := make(chan *types.Header)

    sub, err := rpcClient.SubscribeNewHead(context.Background(), ch)
    if err != nil {
        panic(err)
    }

    for {
        select {
        case err := <-sub.Err():
            panic(err)
        case head := <-ch:
            fmt.Println(head.Number.Int64())
        }
    }
}

For logs, run anvil --block-time 1 in the same way, and:

package main

import (
    "fmt"
    "math/big"
    "time"

    "github.com/Layr-Labs/eigensdk-go/logging"
    erc20mock "github.com/NethermindEth/near-sffl/contracts/bindings/ERC20Mock"
    "github.com/NethermindEth/near-sffl/core/safeclient"
    "github.com/ethereum/go-ethereum/accounts/abi/bind"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto"
)

func main() {
    logger, err := logging.NewZapLogger("production")
    if err != nil {
        panic(err)
    }

    ownerPrivateKeyString := "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
    ownerKeyPair, err := crypto.HexToECDSA(ownerPrivateKeyString)
    if err != nil {
        panic(err)
    }

    ownerAuth, err := bind.NewKeyedTransactorWithChainID(ownerKeyPair, big.NewInt(31337))
    if err != nil {
        panic(err)
    }

    rpcClient, err := safeclient.NewSafeEthClient("ws://localhost:8545", logger, safeclient.WithLogResubInterval(5*time.Second))
    if err != nil {
        panic(err)
    }

    _, _, erc20, err := erc20mock.DeployContractERC20Mock(ownerAuth, rpcClient)
    if err != nil {
        panic(err)
    }

    go func() {
        for {
            _, err := erc20.Mint(ownerAuth, common.HexToAddress("0x0000000000000000000000000000000000000001"), big.NewInt(1))
            if err != nil {
                fmt.Println("Error minting token: ", err)

                // redeploys if anvil was disconnected and reset, so we don't have to use an initial anvil state (will be in the same address)
                _, _, newErc20, err := erc20mock.DeployContractERC20Mock(ownerAuth, rpcClient)
                if err != nil {
                    fmt.Println("Error deploying token: ", err)
                } else {
                    erc20 = newErc20
                }
            }

            time.Sleep(2 * time.Second)
        }
    }()

    ch := make(chan *erc20mock.ContractERC20MockTransfer)

    sub, err := erc20.WatchTransfer(nil, ch, []common.Address{}, []common.Address{common.HexToAddress("0x0000000000000000000000000000000000000001")})
    if err != nil {
        panic(err)
    }

    for {
        select {
        case err := <-sub.Err():
            panic(err)
        case log := <-ch:
            fmt.Println(log.Raw.BlockNumber, log.From, log.To, log.Value)
        }
    }
}

Both of these snippets could be used in an integration test with some extra work.

Hyodar commented 1 month ago

Not totally open rn, but already tagging to keep the conversation.

Hyodar commented 1 month ago

Now open