package main import ( "context" "fmt" "strings" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" ) const membershipABI = `[{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"mintMembership","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountPaid","type":"uint256"},{"indexed":false,"internalType":"address","name":"currency","type":"address"}],"name":"MembershipMinted","type":"event"}]` func encodeMintMembershipCalldata(recipient string) (string, error) { parsed, err := abi.JSON(strings.NewReader(membershipABI)) if err != nil { return "", fmt.Errorf("parse membership abi: %w", err) } address := common.HexToAddress(recipient) data, err := parsed.Pack("mintMembership", address) if err != nil { return "", fmt.Errorf("pack mint calldata: %w", err) } return "0x" + common.Bytes2Hex(data), nil } func verifyMintedOnChain(ctx context.Context, cfg Config, txHash string, expectedWallet string) error { if strings.TrimSpace(cfg.ChainRPCURL) == "" { return nil } client, err := ethclient.DialContext(ctx, cfg.ChainRPCURL) if err != nil { return fmt.Errorf("dial chain rpc: %w", err) } defer client.Close() hash := common.HexToHash(txHash) receipt, err := client.TransactionReceipt(ctx, hash) if err != nil { return fmt.Errorf("read tx receipt: %w", err) } if receipt == nil { return fmt.Errorf("tx receipt not found") } if receipt.Status != types.ReceiptStatusSuccessful { return fmt.Errorf("tx failed status=%d", receipt.Status) } parsed, err := abi.JSON(strings.NewReader(membershipABI)) if err != nil { return fmt.Errorf("parse membership abi: %w", err) } mintedEvent := parsed.Events["MembershipMinted"] expectedWallet = strings.ToLower(common.HexToAddress(expectedWallet).Hex()) for _, lg := range receipt.Logs { if strings.ToLower(lg.Address.Hex()) != strings.ToLower(common.HexToAddress(cfg.MembershipContract).Hex()) { continue } if len(lg.Topics) == 0 || lg.Topics[0] != mintedEvent.ID { continue } if len(lg.Topics) < 2 { continue } wallet := common.HexToAddress(lg.Topics[1].Hex()).Hex() if strings.ToLower(wallet) == expectedWallet { return nil } } return fmt.Errorf("membership mint event not found for wallet") }