-
Notifications
You must be signed in to change notification settings - Fork 74
Conversation
b7308ee
to
b94edd5
Compare
399a529
to
5d50b03
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried running this on my local machine. Works like magic!
iex> EthBlockchain.Transaction.send({"0x33dbe8d0cddd178bc2aad4b194855d2b912dbfe1", "0x3230f3a6bc7c5fbec52eb533e762722bb339a140", 123, "0x90fa40efd96489b98a73d15aa226c2d64099a3d3"})
[debug] QUERY OK source="keychain" db=3.2ms queue=0.1ms
SELECT k0."encrypted_private_key" FROM "keychain" AS k0 WHERE (k0."wallet_id" = $1) ["0x33dbe8d0cddd178bc2aad4b194855d2b912dbfe1"]
{:ok, "0x5e22da6ead930b248b46034020f0b1ac9754527f8571a2e43479f970ece3ca4a"}
> omgtoken.balanceOf(eth.accounts[0])
99999999999999999877
> omgtoken.balanceOf(eth.accounts[1])
123
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly nitpicking, otherwise looks ok to me.
Also, do we want to reject 0x000...000
from being inserted? (Or was this already a thing? I can’t remember)
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", | ||
"gasLimit": "0xffffffff", | ||
"config": { | ||
"chainId": 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should change chainId to something else other than 1
. This ID collides with mainnet. We used to use 90325 for our internal ETH testnet a while ago (it reads 0 = O, 3 = Mi, 2 = Se(cond), 5 = Go).
fi | ||
|
||
echo "Starting geth console..." | ||
geth --identity "local-geth" --rpc --rpccorsdomain "*" --datadir "${DATA_DIR}" --nodiscover --rpcapi "db,eth,net,web3" --nat "any" console |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be better to run this with --dev
if we’re running private local chain.
|
||
import Utils.Helpers.Encoding | ||
|
||
def balance_of(address) when byte_size(address) == 42 do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use something like balance_of(0x <> _ = address)
instead?
@@ -77,6 +77,14 @@ defmodule EthBlockchain.Adapter do | |||
GenServer.stop(pid) | |||
end | |||
|
|||
@spec adapter_or_default(atom() | nil) :: atom() | |||
def adapter_or_default(adapter \\ nil) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function seems specific to adapter
and adapter_or_default/0
doesn’t seems to get used, should you change this to call(nil, func_spec, pid)
that did resolve adapter from default adapter instead?
gas_price = Application.get_env(:eth_blockchain, :default_gas_price) | ||
|
||
send( | ||
{from_address, to_address, amount, "0x0000000000000000000000000000000000000000", gas_price}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might help readability if we put this to @eth_address
😅
def send({from_address, to_address, amount, contract_address}, adapter, pid) | ||
when is_binary(contract_address) do | ||
gas_price = Application.get_env(:eth_blockchain, :default_gas_price) | ||
send({from_address, to_address, amount, contract_address, gas_price}, adapter, pid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be able to simplify default gas price retrieving with (for both eth/contract):
def send({_, _, _, _} = t, adapter, pid) do
gas_price = Application.get_env(:eth_blockchain, :default_gas_price)
t2 = Tuple.append(t, gas_price)
send(t2, adapter, pid)
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, it might be easier if we use map instead of tuple.
s | ||
] = rlp | ||
|
||
{init, data} = if to == <<>>, do: {init_or_data, <<>>}, else: {<<>>, init_or_data} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨👮 THIS IS if
POLICE 👮♀ 🚔
YOU MUST SHOW YOUR ERLANG LICENSE
Please use case 😢
{init, data} =
case to do
<<>> -> {init_or_data, <<>>}
_ -> {<<>>, init_or_data}
end
@@ -11,7 +11,7 @@ config :eth_blockchain, | |||
default_gas_price: 20_000_000_000, | |||
default_eth_transaction_gas_limit: 21_000, | |||
default_contract_transaction_gas_limit: 90_000, | |||
chain_id: 90325 | |||
chain_id: 90_325 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a code comment noting where 90_325
number came from?
@@ -55,4 +65,6 @@ defmodule EthBlockchain.Balance do | |||
error | |||
end | |||
end | |||
|
|||
defp do_get(_, _, _), do: {:error, :invalid_parameters} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid parameter checking should be done closer to where the data enters the system, i.e. controller and gates. Data should be safe by the time it reaches this module and throws an exception about unmatched function.
cc: @sirn for a second opinion?
assert Enum.member?(balances, {"0x0000000000000000000000000000000000000002", 123}) | ||
end | ||
|
||
test_with_auths "returns an error when given a non-existing address" do | ||
response = | ||
request("/blockchain_wallet.get_balances", %{ | ||
"address" => "0x00000000000000000000000000000000000000000" | ||
"address" => EthBlockchain.eth_address() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This attribute is for a non-existing wallet address, so I think it's better to be a random address than EthBlockchain.eth_address()
e355f57
to
c61c682
Compare
Issue/Task Number: 699
Closes #699
Overview
This PR adds 2 new blockchain actions to allow sending Eth or Tokens from a hot wallet.
Changes
EthBlockchain.Transaction.send(%{from: "0xsender", to: "0xreceiver", amount: amount})
EthBlockchain.Transaction.send(%{from:" 0xsender", to: "0xreceiver", amount: amount, contract_address: "0xcontract_address"})
Keychain
app.Implementation Details
We use the
send_raw_transaction
method from geth to submit an offline signed and encoded transaction to the network.The transaction is generated in the
EthBlockchain
app, then signed in theKeychain
app, so the private key doesn't leave theKeychain
app.A few settings have been added to set default value to some parameters:
This settings are arbitrarily set and may/should/will need to be updated in the future.
There is a limitation to this implementation where you need to wait until a transaction gets included in a block before making a new one from the same account. (due to the nonce that needs to be incremented and equal to the current number of mined transaction for the account).
Usage
There is a new folder at the root of the project named
local_geth_testnet
that contains a README file to setup a local geth testnet with some initial data.Follow this guide then you will be able to test the following by replacing the different addresses with the one obtained:
Send ETH:
EthBlockchain.Transaction.send(%{from: "0xprimary_address", to: "0xrecipient_address", amount: 123})
Send OMG:
EthBlockchain.Transaction.send({from: "0xprimary_address", to: "0xrecipient_address", amount: 123, contract_address: "0xcontract_address"})
You can also check the balance of an address with:
EthBlockchain.Balance.get(%{address: "0xprimary_address", contract_addresses: ["0x0000000000000000000000000000000000000000", "0xcontract_address"]})
which will output the balance of ETH and OMG for the specified address.