Peel the comparison to the original view Code 09: When the key is created through dashboard, how is the front end data uploaded to the backend?

Source: Internet
Author: User
Tags button type call back

Author: freewind

Compared to the original project warehouse:

GitHub Address: Https://github.com/Bytom/bytom

Gitee Address: Https://gitee.com/BytomBlockc ...

In the previous article, we have a rough look at how the original dashboard is done, but the various details mentioned in the function, and not in-depth study. So from the beginning of this article, we will study each of the functions mentioned in this period of time.

In the previous article, when we first opened dashboard in a browser, because we had not created a key, we were prompted to enter some aliases and passwords, creating a key and corresponding account for us. That's what the following picture corresponds to:

Then this article will study, when we click on the "Register" button, we fill in the front page of the parameters, exactly how to step by step to the back end of the original.

As before, we will subdivide this question and then conquer:

    1. Front End: When we fill out the form, point to the submission, than the original in the front-end is how to send data?
    2. Backend: How does the back end of the original receive the data?

Front End: When we fill out the form and click Submit, which interface does the data send to the backend?

When we click on the "Register" button, in the front page, there will be a certain place to trigger a request to the original node Webapi interface to make the operation. Which Web API are you accessing? What about the data submitted? Let's look at the front-end code first.

Note that the original front-end code is located in another project warehouse Bytom/dashboard. In order to match the code that we used in this series of articles over the original v1.0.1, I found the code for v1.0.0 in dashboard and submitted it to a separate project: freewind/bytom-dashboard-v1.0.0. Note that the project code has not been modified, and its master branches correspond to branches of the official code warehouse v1.0.0 . The reason to get a separate one is because in the article, every time we quote a piece of code, we give you a link on GitHub that makes it easier for readers to jump over to see the full picture and use a separate project.

Since the front-end page is React primarily used, I suspect that in the code there will be a component called register, or a button named register in the form. After searching, we were fortunate to find the Register.jsx component file, which is exactly what we need.

The highly simplified code is as follows:

src/features/app/components/register/register.jsx#l9-l148

Class Register extends React.component {///...//4.       Submitwitherrors (data) {return new Promise ((resolve, reject) = {//5. This.props.registerKey (data). catch ((Err) = Reject ({_error:err.message})})}//... render () {//.    ..      return (//...//3.        <form Classname={styles.form} onsubmit={handlesubmit (this.submitwitherrors)}>//1. <textfield Title={lang = = = ' zh '? ' Account alias ': ' Accounts alias '} Placeholder={lang = = = ' en '?          ' Enter account alias ... ': ' Please enter the accounts alias ... '} Fieldprops={accountalias}/> <textfield Title={lang = = = ' zh '? ' Keys alias ': ' Key alias '} Placeholder={lang = = = ' en '? ' Enter the key alias ... ': ' Please enter the key alias ... '} fieldprops={keyalias}/> <textfield title={l Ang = = = ' zh '? ' Secret key ': ' Key Password '} Placeholder={lang = = = ' en '? ' Enter key password ... ': ' Please enter ' the key password ... '} FIELDPROps={password} type= ' password '/> <textfield Title={lang = = = ' en '? ' Re-enter key password ': ' Repeat your Key password '} Placeholder={lang = = = ' en '?        ' Please re-enter the key password ... ': ' Repeat the key password ... '} fieldprops={repeatpassword} type= ' Password '/>         2. <button type= ' Submit ' classname= ' btn btn-primary ' disabled={submitting}> {lang = = ' en '?  ' Registration ': ' Register '} </button>//.... }}

The above code, a total of 5 places to pay attention to, I used the number marked out. Note that these 5 numbers are not labeled from top to bottom, but in the order in which we are concerned:

    1. The individual input boxes on the form are where we fill in the aliases and passwords. The focus here is on each TextField fieldProps attribute, which corresponds to the data we submit to the background.name
    2. That's the "Register" button. Note that it type is, that is, submit when you click on it, it will trigger form the onSubmit method
    3. Back to form the beginning. Notice the inside of it onSubmit , the call is handleSubmit(this.submitWithErrors) . One of these handleSubmit is from the third-party redux-form used in the form to handle the form submission, and we don't care about it here, just know that we need to pass our handler function to this.submitWithErrors it. In the latter case, we will invoke a Web API that is more than the original node
    4. The 3rd step this.submitWithErrors will eventually go to the function defined here submitWithErrors
    5. submitWithErrorsAn asynchronous request will be initiated, eventually invoking a function passed in by the external registerKey

From here we don't see which API is called, so we have to go on looking for it registerKey . It was soon found in the same document registerKey :

src/features/app/components/register/register.jsx#l176-l180

(dispatch) => ({    registerKey: (token) => dispatch(actions.core.registerKey(token)),    // ...  })

It will then call actions.core.registerKey this function:

Src/features/core/actions.js#l44-l87

const registerKey = (data) => {  return (dispatch) => {    // ...    // 1.1    const keyData = {      'alias': data.keyAlias,      'password': data.password    }    // 1.2    return chainClient().mockHsm.keys.create(keyData)      .then((resp) => {        // ...        // 2.1        const accountData = {          'root_xpubs':[resp.data.xpub],          'quorum':1,          'alias': data.accountAlias}        // 2.2        dispatch({type: 'CREATE_REGISTER_KEY', data})        // 2.3        chainClient().accounts.create(accountData)          .then((resp) => {            // ...            // 2.4            if(resp.status === 'success') {              dispatch({type: 'CREATE_REGISTER_ACCOUNT', resp})            }          })    // ...      })    // ...  }}

As you can see, there are still a lot of things to do in this function. And it wasn't the first time I had expected to call the background interface, but it was called two times (creating the key and creating the account, respectively). The following analysis:

    1. 1.1is for the background to create the key and need to prepare the parameters, one is alias , one is password , they are filled by the user
    2. 1.2is to invoke the interface used to create the key in the background, pass keyData it over, and get the return, and then resp do the subsequent processing
    3. 2.1is to let the background create the account and need to prepare the parameters, respectively root_xpubs , quorum and alias , which root_xpubs is the public key that is returned after the key is created, is quorum not currently known (TODO), alias is the user filled out the account alias
    4. 2.2This sentence has no effect (officially confirmed), because I did not find the code in the code to process CREATE_REGISTER_KEY . You can see this issue#28.
    5. 2.3Call the background to create the account, pass accountData it over, you can get the returnresp
    6. 2.4After the call succeeds, the Redux function is used to dispatch distribute a CREATE_REGISTER_ACCOUNT message. But the message doesn't seem to be much use.

About CREATE_REGISTER_ACCOUNT , I found two correlations in the code:

    1. src/features/core/reducers.js#l229-l234
const accountInit = (state = false, action) => {  if (action.type == 'CREATE_REGISTER_ACCOUNT') {    return true  }  return state}
    1. src/features/app/reducers.js#l10-l115
export const flashMessages = (state = {}, action) => {  switch (action.type) {    // ...    case 'CREATE_REGISTER_ACCOUNT': {      return newSuccess(state, 'CREATE_REGISTER_ACCOUNT')    }    // ...  }}

The first one looks useless, and the second one should be used to display the relevant error message after the operation is complete.

So let's focus on the place where 1.2 the 2.3 two backstage calls.

    1. chainClient().mockHsm.keys.create(keyData)The corresponding is:

Src/sdk/api/mockhsmkeys.js#l3-l31

const mockHsmKeysAPI = (client) => {  return {    create: (params, cb) => {      let body = Object.assign({}, params)      const uri = body.xprv ? '/import-private-key' : '/create-key'      return shared.tryCallback(        client.request(uri, body).then(data => data),        cb      )    },    // ...  }}

You can see that in the create method, if it is not found body.xprv (which is the case in this article), the interface in the background is called /create-key . After a long series of traces, we finally found one.

    1. chainClient().accounts.create(accountData)The corresponding is:

Src/sdk/api/accounts.js#l3-l30

const accountsAPI = (client) => {  return {    create: (params, cb) => shared.create(client, '/create-account', params, {cb, skipArray: true}),    // ...  }}

Soon we'll be here. The interface that is called when the account is created is/create-account

On the front side, we finally finished the analysis. Next, you will go to the original node (i.e. the back end).

Backend: How does the back end of the original receive the data?

If we have an impression of the previous article, we will remember that the HTTP service corresponding to the Web API will be started in the method after startup, and there will be a Node.initAndstartApiServer API.buildHandler() lot of feature points in the method, which will definitely have the interface we call here.

Let's look at the API.buildHandler method:

api/api.go#l164-l244

func (a *API) buildHandler() {    walletEnable := false    m := http.NewServeMux()    if a.wallet != nil {        walletEnable = true        // ...        m.Handle("/create-account", jsonHandler(a.createAccount))        // ...        m.Handle("/create-key", jsonHandler(a.pseudohsmCreateKey))        // ...

Soon, we found:

    1. /create-account: correspondinga.createAccount
    2. /create-key: correspondinga.pseudohsmCreateKey

Let's take a look first a.pseudohsmCreateKey :

Api/hsm.go#l23-l32

func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {    Alias    string `json:"alias"`    Password string `json:"password"`}) Response {    // ...}

As you can see, pseudohsmCreateKey the second parameter, is a struct , it has two fields, respectively, Alias and Password this corresponds exactly to the parameters passed from the front end keyData . So how does the value of this parameter be converted from the JSON data being submitted? The last time we talked about this, it's mostly done by the a.pseudohsmCreateKey outside jsonHandler , which handles the HTTP protocol, and converts the JSON data into the parameters of the go type needed here, which pseudohsmCreateKey can be used directly.

Because in this small problem, the boundary of our problem is how to get the data from the original background, so we can stop the analysis of this method here. It specifically how to create the key, which will be discussed in detail later in the article.

Look again a.createAccount :

Api/accounts.go#l15-l30

// POST /create-accountfunc (a *API) createAccount(ctx context.Context, ins struct {    RootXPubs []chainkd.XPub `json:"root_xpubs"`    Quorum    int            `json:"quorum"`    Alias     string         `json:"alias"`}) Response {    // ...}

As before, the parameters of this method RootXPubs , Quorum and Alias are also submitted by the front end, and are jsonHandler automatically converted by the good.

When we understand how the front-end data interacts in this article, it's easy to generalize to more scenarios. In front of a lot of pages and forms, in many places need to call back-end interface, I believe that according to the idea of this article, should be able to quickly find. If there is a more special situation, we will be a special article to explain later.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.