diff --git a/.env.example b/.env.example index a0f94e0..96014ec 100644 --- a/.env.example +++ b/.env.example @@ -2,4 +2,5 @@ RPC=https://testnet-rpc.jackalprotocol.com:443 GRPC=jackal-testnet-grpc.polkachu.com:17590 ETH_RPC=ws://127.0.0.1:8545 SEED= -CONTRACT_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 \ No newline at end of file +CONTRACT_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 +JACKAL_CONTRACT=jkl1.... \ No newline at end of file diff --git a/abi.go b/abi.go index 01af01f..2dccc74 100644 --- a/abi.go +++ b/abi.go @@ -75,7 +75,7 @@ func init() { } } -func handleLog(vLog *types.Log, w *wallet.Wallet, q *uploader.Queue) { +func handleLog(vLog *types.Log, w *wallet.Wallet, q *uploader.Queue, jackalContract string) { event := struct { Sender common.Address Merkle string @@ -143,11 +143,13 @@ func handleLog(vLog *types.Log, w *wallet.Wallet, q *uploader.Queue) { msg := &wasm.MsgExecuteContract{ Sender: w.AccAddress(), - Contract: "CONTRACT_ADDRESS", + Contract: jackalContract, Msg: factoryMsg.Encode(), Funds: sdk.NewCoins(c), } + log.Printf("execute msg: %v", msg) + if err := msg.ValidateBasic(); err != nil { log.Fatalf("Failed to validate message: %v", err) return diff --git a/main.go b/main.go index bb016b0..585e709 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,8 @@ import ( "fmt" "log" "os" + "os/signal" + "syscall" "time" "github.com/JackalLabs/mulberry/jackal/uploader" @@ -36,18 +38,14 @@ func main() { return } + jackalContract := os.Getenv("JACKAL_CONTRACT") + log.Printf("Address: %s\n", w.AccAddress()) q := uploader.NewQueue(w) q.Listen() - client, err := ethclient.Dial(os.Getenv("ETH_RPC")) - if err != nil { - log.Fatalf("Failed to connect to the Ethereum client: %v", err) - } - defer client.Close() - // Specify the contract address contractAddress := common.HexToAddress(os.Getenv("CONTRACT_ADDRESS")) query := ethereum.FilterQuery{ @@ -55,43 +53,82 @@ func main() { } // Subscribe to the logs - logs := make(chan types.Log) - sub, err := client.SubscribeFilterLogs(context.Background(), query, logs) - if err != nil { - log.Fatalf("Failed to subscribe to the logs: %v", err) - } + var sub ethereum.Subscription + var logs chan types.Log + + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) - log.Println("Ready to listen!") for { - select { - case err := <-sub.Err(): - log.Fatalf("Subscription error: %v", err) - case vLog := <-logs: - log.Printf("Log received: \n") - log.Printf("Address: %s\n", vLog.Address.Hex()) - - // Ensure transaction is confirmed - receipt, err := waitForReceipt(client, vLog.TxHash) - if err != nil { - fmt.Printf("Failed to get transaction receipt: %v\n", err) - continue - } - if receipt != nil { - // Process logs if receipt is available - for _, log := range receipt.Logs { - if log.Address.Hex() == contractAddress.Hex() { - handleLog(log, w, q) + client, err := ethclient.Dial(os.Getenv("ETH_RPC")) + if err != nil { + log.Printf("Failed to connect to the Ethereum client, retrying in 5 seconds: %v", err) + time.Sleep(5 * time.Second) + continue + } + + sub, logs, err = subscribeLogs(client, query) + if err != nil { + log.Printf("Failed to subscribe, retrying in 5 seconds: %v", err) + client.Close() + time.Sleep(5 * time.Second) + continue + } + + log.Println("Ready to listen!") + + // Listening loop + func() { + defer func() { + // Unsubscribe and close client on exit + if sub != nil { + sub.Unsubscribe() + } + client.Close() + }() + + for { + select { + case <-sigs: + log.Println("Exiting...") + return + case err := <-sub.Err(): + log.Printf("Subscription error, reconnecting: %v", err) + return // Break out of the loop to retry + case vLog := <-logs: + log.Printf("Log received: %s", vLog.Address.Hex()) + + // Ensure transaction is confirmed + receipt, err := waitForReceipt(client, vLog.TxHash) + if err != nil { + fmt.Printf("Failed to get transaction receipt: %v\n", err) + continue + } + + if receipt != nil { + // Process logs if receipt is available + for _, l := range receipt.Logs { + if l.Address.Hex() == contractAddress.Hex() { + handleLog(l, w, q, jackalContract) + } + } + } else { + fmt.Println("No receipt found for the transaction.") } } - } else { - fmt.Println("No receipt found for the transaction.") } + }() - } } } +func subscribeLogs(client *ethclient.Client, query ethereum.FilterQuery) (ethereum.Subscription, chan types.Log, error) { + logs := make(chan types.Log) + sub, err := client.SubscribeFilterLogs(context.Background(), query, logs) + return sub, logs, err +} + // waitForReceipt polls for the transaction receipt until it's available func waitForReceipt(client *ethclient.Client, txHash common.Hash) (*types.Receipt, error) { for {