Skip to content

Notes on Bindings

Victor Farazdagi edited this page Oct 30, 2016 · 18 revisions

Status Bindings Notes

1. Main Account creation

Exported method:

func CreateAccount(password *C.char) *C.char

Internally relies on:

// createAccount creates an internal geth account
// BIP44-compatible keys are generated: CKD#1 is stored as account key, CKD#2 stored as sub-account root
// Public key of CKD#1 is returned, with CKD#2 securely encoded into account key file (to be used for
// sub-account derivations)
func createAccount(password string) (address, pubKey, mnemonic string, err error)

Sample response:

{
  "Address": "0xdeadbeef..",
  "PubKey": "0xdeadbeef..",
  "Mnemonic": "stupid lazy fox jump crazy..",
  "Error": ""
}

2. Sub-account creation

Exported method:

func CreateChildAccount(parentAddress, password *C.char) *C.char

Internally relies on:

// createChildAccount creates sub-account for an account identified by parent address.
// CKD#2 is used as root for master accounts (when parentAddress is "").
// Otherwise (when parentAddress != ""), child is derived directly from parent.
func createChildAccount(parentAddress, password string) (address, pubKey string, err error)

Sample Response:

{
  "Address": "0xdeadbeef..",
  "PubKey": "0xdeadbeef..",
  "Error": ""
}

3. Recover account details

Exported Method:

func RecoverAccount(password, mnemonic *C.char) *C.char

Internally relies on:

// recoverAccount re-creates master key using given details.
// Once master key is re-generated, it is inserted into keystore (if not already there).
func recoverAccount(password, mnemonic string) (address, pubKey string, err error)

Sample Response: (same as on main account creation)

{
  "Address": "0xdeadbeef..",
  "PubKey": "0xdeadbeef..",
  "Mnemonic": "stupid lazy fox jump crazy..",
  "Error": ""
}

4. Login (select active/current account)

Exported Method:

func Login(address, password *C.char) *C.char

Internally:

// selectAccount selects current account, by verifying that address has corresponding account which can be decrypted
// using provided password. Once verification is done, decrypted key is injected into Whisper (as a single identity,
// all previous identities are removed).
func selectAccount(address, password string) error

Sample Response:

{
  "Error": "some issue occurred, login failed.."
}

5. Logout

When called system makes sure that Whisper identity (injected on Login()) is wiped out.

Exported method:

func Logout() *C.char

Sample Response:

{
  "Error": ""
}

666. How to Unlock Account?

Every time somebody unlocks Ethereum account Cthulhu kills kittens (🐱 😸 ), dozens of them. So, don't use this method.

This method is deprecated, and will return error, asking you to rely on Login() instead (if kittens weren't enough for you!)

Output:

{
  "Error": "no need to unlock accounts, login instead"
}

6. Sending Transactions

Every time transaction is sent to geth node (via SendTransaction, which passes through jail package's Send method) it is intercepted and queued. Call is NOT returned immediately and hangs on until either of below happens:

  • CompleteTransaction() received (see below)
  • DiscardTransaction() received (see below)
  • request times out (normally, after 300 seconds)

When request is queued, native application will receive a signal (with transaction id to be used to complete pending/queued transaction).

In order to complete transaction, use the following exported method:

func CompleteTransaction(id, password *C.char) *C.char

where id is transaction id, and password is user's password we will attempt to sign transaction with (if this succeeds, then transaction will be sent to blockchain).

If user wants to cancel transaction (instead of providing password and completing), then the following method should be used:

func DiscardTransaction(id *C.char) *C.char

Note that in order to discard a transaction, only id is required (no need to supply password). Whenever transaction is discarded, SendTransaction() unblocks (and triggers transaction.failed signal to application, with error code 4).

When DiscardTransaction() returns, its response is JSON having the following data:

{
  id: "transaction id passed to DiscardTransaction()",
  error: "error message, if any"
}

🌟 Below are possible error codes that binding can signal back to react-native app:

	SendTransactionNoErrorCode        = "0" // no error, tx executed ok
	SendTransactionDefaultErrorCode   = "1" // some error
	SendTransactionPasswordErrorCode  = "2" // wrong password
	SendTransactionTimeoutErrorCode   = "3" // request times out
	SendTransactionDiscardedErrorCode = "4" // tx discarded manually

7. Node Management

To start node with a given directory:

func StartNode(datadir *C.char) *C.char // starts node with a given data directory

To add peer node:

func AddPeer(url *C.char) *C.char // adds peer, which main node will listen to

8. Jail

Requests from native application do NOT go directly to running node. Instead, they are forwarded via Otto VMs i.e. you use Call() binding which internally executes JavaScript code within jailed JS environment.

That jailed environment is initialized with JS code from jail/web3.go, and is augmented with the code coming via Parse() method (thus allowing native apps specify their custom methods/commands).

Everything MUST start with InitJail():

func InitJail(js *C.char)

which accepts custom JS, to setup custom JS environment. If you haven't initialized jailed environment with InitJail() calls to other exported methods will fail.

Now, once jailed environment is prepared, it is time to start/setup VM:

func Parse(chatId *C.char, js *C.char) *C.char

You need to specify chatId and custom JS. That chatId will uniquely identify crated VM. Then, to execute some JS code on that uniquely identified VM:

func Call(chatId *C.char, path *C.char, params *C.char) *C.char

The path identifies command to run e.g. ["commands", "send"] and params is just command arguments (passed as object i.e. {}).

9. Whisper

To manage observers:

AddWhisperFilter(filterJson *C.char)
RemoveWhisperFilter(id int)
CleanWhisperFilters()
Clone this wiki locally