From 74a7ae1a6e3d12f921cd9ca138d9de553197bc91 Mon Sep 17 00:00:00 2001
From: LiAohua <liaohua@LiAohuadeMacBook-Pro.local>
Date: Wed, 3 Jan 2024 08:12:18 +0800
Subject: [PATCH] update

---
 .swp                          | Bin 12288 -> 0 bytes
 lib/components/transaction.ex | 109 ++++++++++++++++++++++++++++++++++
 lib/components/verifier.ex    |   3 +-
 lib/utils/type_translator.ex  |   7 +++
 mix.exs                       |   3 +
 5 files changed, 121 insertions(+), 1 deletion(-)
 delete mode 100644 .swp
 create mode 100644 lib/components/transaction.ex

diff --git a/.swp b/.swp
deleted file mode 100644
index a60f871474e292634716f120cf4095f3aa001cb4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 12288
zcmeI%%SyvQ6oBEWu3Rbl0#(;7lQeD8r6{P2c%v0}VUn4W(rQ~1(#ytIaq9#5J|;EY
zNY|FYe_-Y?hk-Nm!7M^T`F!iwyG<$bI4Y*!cu9qLpG2eOdfHUC=ci(yHol4)ufw-t
zb3BREc>7kW2q3UCfrEa_w$@Mm{Oq)Ta@^n9Nob4!0tg_000IagfB*vjFOW`a;v;Xn
zSGL|SbL~$qmm~xbKmY**5I_I{1Q0*~0R#}Jpn%dsEDnYE%t!J6fAjtSov*((^$OmL
zBO`zS0tg_000IagfB*srAW$U%OXiUzvADi6t6-Up<UG5~!ocxwX44CuhH=tx<_~Ug
t-<v(gcYe=lOCcB9lA&>3rCr;NOv{eEwkNyFR>m6)9PM>X7|D*O#Sb1zG=Bg9

diff --git a/lib/components/transaction.ex b/lib/components/transaction.ex
new file mode 100644
index 0000000..b1652b0
--- /dev/null
+++ b/lib/components/transaction.ex
@@ -0,0 +1,109 @@
+defmodule Components.Transaction do
+  alias Ethereumex.HttpClient
+  defstruct from: <<>>, to: <<>>, gas_price: 0, gas_limit: 0, value: 0, init: <<>>, data: <<>>
+
+  @base_recovery_id_eip_155 35
+    
+  def send(chain_id, priv_key, tx, nonce, others) do
+    items = prepare_items(tx, nonce, others)
+
+    # Refer to EIP-155, we SHOULD hash nine rlp encoded elements:
+    # (nonce, gasprice, startgas, to, value, data, chainid, 0, 0)
+    hashed_tx = hash(items ++ [encode_unsigned(chain_id), <<>>, <<>>])
+    {v, r, s} = sign(hashed_tx, priv_key, chain_id)
+    signature = [
+           encode_unsigned(v),
+           encode_unsigned(r),
+           encode_unsigned(s)
+         ]
+
+    raw_tx =
+      (items ++ signature)
+      |> ExRLP.encode(encoding: :hex)
+    HttpClient.eth_send_raw_transaction("0x" <> raw_tx, others)
+  end
+
+  def send(chain_id, priv_key, tx, others) do
+    items = prepare_items(tx, others)
+
+    # Refer to EIP-155, we SHOULD hash nine rlp encoded elements:
+    # (nonce, gasprice, startgas, to, value, data, chainid, 0, 0)
+    hashed_tx = hash(items ++ [encode_unsigned(chain_id), <<>>, <<>>])
+    {v, r, s} = sign(hashed_tx, priv_key, chain_id)
+    signature = [
+           encode_unsigned(v),
+           encode_unsigned(r),
+           encode_unsigned(s)
+         ]
+
+    raw_tx =
+      (items ++ signature)
+      |> ExRLP.encode(encoding: :hex)
+    HttpClient.eth_send_raw_transaction("0x" <> raw_tx, others)
+  end
+
+  def get_gas(contract_address, behaviour, payloads, others) do
+    transaction = %{
+      "to" => contract_address,
+      "data" => TypeTranslator.get_data(behaviour, payloads)
+    }
+
+    {:ok, gas_limit} = HttpClient.eth_estimate_gas(transaction, others)
+    {:ok, gas_price} = HttpClient.eth_gas_price(others)
+
+    {
+      TypeTranslator.hex_to_int(gas_limit),
+      TypeTranslator.hex_to_int(gas_price)
+    }
+  end
+
+  defp prepare_items(tx, nonce, _others) do
+
+    [
+      encode_unsigned(nonce),
+      encode_unsigned(tx.gas_price),
+      encode_unsigned(tx.gas_limit),
+      tx.to |> String.replace("0x", "") |> Base.decode16!(case: :mixed),
+      encode_unsigned(tx.value || 0),
+      if(tx.to == <<>>, do: <<>>, else: tx.data)
+    ]
+  end
+
+  defp prepare_items(tx, others) do
+    nonce = get_nonce(tx.from, others)
+
+    [
+      encode_unsigned(nonce),
+      encode_unsigned(tx.gas_price),
+      encode_unsigned(tx.gas_limit),
+      tx.to |> String.replace("0x", "") |> Base.decode16!(case: :mixed),
+      encode_unsigned(tx.value || 0),
+      if(tx.to == <<>>, do: <<>>, else: tx.data)
+    ]
+  end
+
+  defp hash(items) do
+    items
+    |> ExRLP.encode(encoding: :binary)
+    |> ExKeccak.hash_256()
+  end
+
+  defp sign(hashed_tx, priv_key, chain_id) do
+    {:ok, {<<r::size(256), s::size(256)>>, recovery_id}} =
+      ExSecp256k1.sign_compact(hashed_tx, priv_key)
+
+    # Refer to EIP-155
+    recovery_id = chain_id * 2 + @base_recovery_id_eip_155 + recovery_id
+
+    {recovery_id, r, s}
+  end
+
+  def get_nonce(wallet_address, others) do
+    {:ok, hex} = HttpClient.eth_get_transaction_count(wallet_address, "latest", others)
+
+    TypeTranslator.hex_to_int(hex)
+  end
+
+  defp encode_unsigned(0), do: <<>>
+  defp encode_unsigned(number), do: :binary.encode_unsigned(number)
+end
\ No newline at end of file
diff --git a/lib/components/verifier.ex b/lib/components/verifier.ex
index c91ec89..1644e0d 100644
--- a/lib/components/verifier.ex
+++ b/lib/components/verifier.ex
@@ -103,6 +103,7 @@ defmodule Components.Verifier do
 
   defp verify_signature(hash, signature) do
     {r, s, v} = destructure_sig(signature)
-    :libsecp256k1.ecdsa_recover_compact(hash, r <> s, :uncompressed, v)
+    # :libsecp256k1.ecdsa_recover_compact(hash, r <> s, :uncompressed, v)
+    ExSecp256k1.recover_compact(hash, r <> s, v)
   end
 end
diff --git a/lib/utils/type_translator.ex b/lib/utils/type_translator.ex
index d24e79c..1ed575b 100644
--- a/lib/utils/type_translator.ex
+++ b/lib/utils/type_translator.ex
@@ -1,4 +1,11 @@
 defmodule TypeTranslator do
+    @doc """
+      TODO: impl the cases.
+      iex(34)> ABI.encode("buy(uint256,uint256)", [13721, 10000000000000000])
+      iex(33)> ABI.decode("buy(uint256,uint256)", "d6febde80000000000000000000000000000000000000000000000000000000000003599000000000000000000000000000000000000000000000000002386f26fc10000" |> Base.decode16!(case: :lower))
+[97245039436039886927109785377494219820477888259653562449568703439859083116544,
+ 369917428219973928622626114008996352472975258621679195013222636231821042]
+    """
 
     def str_to_module(class, mod_name) do
       "Elixir.TaiShangWorldGenerator.#{class}.#{mod_name}"
diff --git a/mix.exs b/mix.exs
index 7e78b29..8f37ecf 100644
--- a/mix.exs
+++ b/mix.exs
@@ -111,6 +111,9 @@ defmodule TaiShangMicroFaasSystem.MixProject do
       # graphql client
       {:neuron, "~> 5.1.0"},
 
+      # decimal
+      {:decimal, "~> 2.0"}
+
     ]
   end