defmodule Circlex.Emulator.DepositDetector do @moduledoc """ Checks for Deposits """ use GenServer alias Circlex.Emulator.State.{TransferState, WalletState} alias Circlex.Emulator.Actor.TransferActor alias Circlex.Struct.Amount require Logger @chain "ETH" @currency "USD" @usdc_decimals 6 def start_link([filters, state_pid]) do GenServer.start_link(__MODULE__, {filters, state_pid}) end @impl true def init({filters, state_pid}) do Process.put(:state_pid, state_pid) for filter <- filters do Signet.Filter.listen(filter) end {:ok, %{logs: [], events: %{}}} end def logs(pid) do GenServer.call(pid, :logs) end def events(pid) do GenServer.call(pid, :events) end @impl true def handle_info({:event, event, log}, state = %{events: events}) do trx_id = Signet.Util.encode_hex(log.transaction_hash) case event do {"Transfer", %{"from" => from, "to" => to, "amount" => amount}} -> # Okay, now let's see if it matches any known wallet. case WalletState.get_wallet_by_address(@chain, @currency, Signet.Util.encode_hex(to)) do {:ok, wallet} -> {:ok, transfer} = TransferState.new_transfer( %{ type: "blockchain", chain: "ETH", address: Signet.Util.encode_hex(from) }, %{ type: "wallet", id: wallet.wallet_id, address: Signet.Util.encode_hex(to) }, Amount.from_wei(amount, @usdc_decimals), trx_id ) TransferState.add_transfer(transfer) TransferActor.start_link(transfer.id) Logger.info( "Detected new USDC transfer to wallet via trx: #{trx_id}: #{inspect(transfer)}" ) :not_found -> Logger.info("Ignoring irrevelevant USDC transfer via trx: #{trx_id}...") end _ -> nil end {:noreply, %{state | events: Map.put(events, trx_id, event)}} end def handle_info({:log, log}, state = %{logs: logs}) do {:noreply, %{state | logs: [log.transaction_hash | logs]}} end @impl true def handle_call(:logs, _from, state = %{logs: logs}) do {:reply, logs, state} end def handle_call(:events, _from, state = %{events: events}) do {:reply, events, state} end end