OSDN Git Service

add the decode raw transaction to the detail transaction page.
authorZhiting Lin <zlin035@uottawa.ca>
Mon, 13 Aug 2018 06:17:22 +0000 (14:17 +0800)
committerZhiting Lin <zlin035@uottawa.ca>
Mon, 13 Aug 2018 06:17:22 +0000 (14:17 +0800)
src/features/transactions/actions.js
src/features/transactions/components/New/AdvancedTransactionForm.jsx
src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.jsx [new file with mode: 0644]
src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.scss [new file with mode: 0644]
src/features/transactions/reducers.js
src/sdk/api/transactions.js

index 89d6745..d4549ec 100644 (file)
@@ -182,7 +182,24 @@ form.submitForm = (formParams) => function (dispatch) {
   }
 }
 
+const decode = (data) => {
+  return (dispatch) => {
+    return  chainClient().transactions.decodeTransaction(data)
+      .then((resp) => {
+        if (resp.status === 'fail') {
+          dispatch({type: 'ERROR', payload: {'message': resp.msg}})
+        } else {
+          dispatch({type: 'DECODE_TRANSACTION', data:resp.data})
+        }
+      })
+      .catch(err => {
+        throw {_error: err}
+      })
+  }
+}
+
 export default {
   ...list,
   ...form,
+  decode,
 }
index fa1e702..7bc5a82 100644 (file)
@@ -2,17 +2,18 @@ import {
   BaseNew,
   FormSection,
   FieldLabel,
-  TextField,
   SubmitIndicator,
   ErrorBanner,
   PasswordField
 } from 'features/shared/components'
+import TransactionDetails from './MultiSignTransactionDetails/TransactionDetails'
 import {DropdownButton, MenuItem} from 'react-bootstrap'
 import {reduxForm} from 'redux-form'
 import ActionItem from './FormActionItem'
 import React from 'react'
 import styles from './New.scss'
 import disableAutocomplete from 'utility/disableAutocomplete'
+import actions from 'actions'
 
 class AdvancedTxForm extends React.Component {
   constructor(props) {
@@ -90,7 +91,8 @@ class AdvancedTxForm extends React.Component {
 
     return (
       <form onSubmit={handleSubmit(this.submitWithValidation)} {...disableAutocomplete}
-            onKeyDown={(e) => { this.props.handleKeyDown(e, handleSubmit(this.submitWithValidation), this.disableSubmit(actions)) }}>
+            // onKeyDown={(e) => { this.props.handleKeyDown(e, handleSubmit(this.submitWithValidation), this.disableSubmit(actions)) }}
+      >
 
         <FormSection title='Actions'>
           {actions.map((action, index) =>
@@ -137,11 +139,13 @@ class AdvancedTxForm extends React.Component {
         {this.state.showAdvanced &&
         <FormSection title={lang === 'zh' ? '高级选项' : 'Advanced Options'}>
           <div>
-            <TextField
-              title={lang === 'zh' ? '带签名交易' : 'To sign transaction'}
-              placeholder={lang === 'zh' ? '在这里复制交易 HEX ...' : 'Paste transaction hex here...'}
+            <TransactionDetails
+              lang={lang}
               fieldProps={signTransaction}
-              autoFocus={true}/>
+              decode={this.props.decode}
+              transaction={this.props.decodedTx}
+              btmAmountUnit={this.props.btmAmountUnit}
+            />
 
             <FieldLabel>{lang === 'zh' ? '交易构建类型' : 'Transaction Build Type'}</FieldLabel>
             <table className={styles.submitTable}>
@@ -232,8 +236,14 @@ const validate = (values, props) => {
 }
 
 export default BaseNew.connect(
-  BaseNew.mapStateToProps('transaction'),
-  BaseNew.mapDispatchToProps('transaction'),
+  (state, ownProps) => ({
+    ...BaseNew.mapStateToProps('transaction')(state, ownProps),
+    decodedTx: state.transaction.decodedTx
+  }),
+  (dispatch) => ({
+    ...BaseNew.mapDispatchToProps('transaction')(dispatch),
+    decode: (transaction) => dispatch( actions.transaction.decode(transaction)),
+  }),
   reduxForm({
     form: 'AdvancedTransactionForm',
     fields: [
diff --git a/src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.jsx b/src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.jsx
new file mode 100644 (file)
index 0000000..e2a25c8
--- /dev/null
@@ -0,0 +1,163 @@
+import React from 'react'
+import pick from 'lodash/pick'
+import { FieldLabel } from 'features/shared/components'
+import disableAutocomplete from 'utility/disableAutocomplete'
+import { btmID } from 'utility/environment'
+import { normalizeGlobalBTMAmount } from 'utility/buildInOutDisplay'
+import { Summary } from '../../'
+import styles from './TransactionDetails.scss'
+
+
+const TEXT_FIELD_PROPS = [
+  'value',
+  'onBlur',
+  'onChange',
+  'onFocus',
+  'name'
+]
+
+class TransactionDetails extends React.Component {
+  constructor(props) {
+    super(props)
+    this.showDetailTransactions = this.showDetailTransactions.bind(this)
+  }
+
+  showDetailTransactions(e, json){
+    e.preventDefault()
+    const rawTransaction = JSON.parse(json).raw_transaction
+    this.props.decode(rawTransaction)
+  }
+
+  render() {
+    const fieldProps = pick(this.props.fieldProps, TEXT_FIELD_PROPS)
+    const {touched, error} = this.props.fieldProps
+
+    const lang = this.props.lang
+
+    const item = this.props.transaction
+    const btmAmountUnit = this.props.btmAmountUnit
+
+    let view = <div></div>
+    if (item.length !== 0) {
+      const fee = normalizeGlobalBTMAmount(btmID, item.fee, btmAmountUnit)
+
+      const inputs = item.inputs
+      const outputs = item.outputs
+
+      view =  (<div  className='form-group'>
+        <FieldLabel>{lang === 'zh' ? '交易内容' : 'Transaction Content'}</FieldLabel>
+
+        <div className={styles.main}>
+          <div className={styles.txID}>
+            <label>{lang === 'zh' ? '详情:' : 'Summary:'}</label>
+            <table key={'txsummary'} className={styles.table}>
+              <tr>
+                <td  className={styles.colLabel}>
+                  {lang === 'zh' ? '交易ID:' : 'Transaction ID:'}
+                </td>
+                <td>
+                  <code>{item.txId}</code>
+                </td>
+              </tr>
+              <tr>
+                <td  className={styles.colLabel}>Gas:</td>
+                <td><code>{fee}</code></td>
+              </tr>
+            </table>
+          </div>
+
+          <div>
+            <label>{lang === 'zh' ? '输入:' : 'Input:'}</label>
+            {inputs.map((input, index) =>
+              <table key={index} className={styles.table}>
+                <tr>
+                  <td className={styles.colLabel}>Type:</td>
+                  <td><code>{input.type}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Address:</td>
+                  <td><code>{input.address}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Amount:</td>
+                  <td><code>{input.amount}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Asset:</td>
+                  <td><code>{input.assetId}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Control Program:</td>
+                  <td><code>{input.controlProgram}</code></td>
+                </tr>
+              </table>
+            )}
+
+            <label>{lang === 'zh' ? '输出:' : 'Output:'}</label>
+            {outputs.map((output, index) =>
+              <table key={index}  className={styles.table}>
+                <tr>
+                  <td className={styles.colLabel}>Type:</td>
+                  <td><code>{output.type}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Address:</td>
+                  <td><code>{output.address}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Amount:</td>
+                  <td><code>{output.amount}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Asset:</td>
+                  <td><code>{output.assetId}</code></td>
+                </tr>
+                <tr>
+                  <td className={styles.colLabel}>Control Program:</td>
+                  <td><code>{output.controlProgram}</code></td>
+                </tr>
+              </table>
+            )}
+          </div>
+
+          {/*<div>*/}
+            {/*<div>*/}
+              {/*<label>Gas</label>*/}
+              {/*<div>*/}
+                {/*<code>{fee}</code>*/}
+              {/*</div>*/}
+            {/*</div>*/}
+          {/*</div>*/}
+        </div>
+
+      </div>)
+    }
+
+
+
+    return(
+      <div className='form-group'>
+        <FieldLabel>{lang === 'zh' ? '带签名交易' : 'To sign transaction'}</FieldLabel>
+        <input className='form-control'
+               type='text'
+               placeholder={lang === 'zh' ? '在这里复制交易 HEX ...' : 'Paste transaction hex here...'}
+               autoFocus={true}
+               {...disableAutocomplete}
+               {...fieldProps} />
+
+        {touched && error && <span className='text-danger'><strong>{error}</strong></span>}
+        {this.props.hint && <span className='help-block'>{this.props.hint}</span>}
+
+        <div>
+          <button className={`btn btn-default ${styles.btn}`}
+                  onClick={(e) => this.showDetailTransactions(e, fieldProps.value)}>
+            展示交易内容
+          </button>
+        </div>
+        {view}
+      </div>
+    )
+  }
+}
+
+export default TransactionDetails
diff --git a/src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.scss b/src/features/transactions/components/New/MultiSignTransactionDetails/TransactionDetails.scss
new file mode 100644 (file)
index 0000000..8ef67a9
--- /dev/null
@@ -0,0 +1,57 @@
+.main {
+  padding: $gutter-size;
+  margin-bottom: $gutter-size;
+  word-break: break-word;
+  background: $background-content-color;
+}
+
+.btn {
+  margin: $gutter-size/2  0px ;
+}
+
+.table{
+  background: $background-color;
+  width: 100%;
+  margin-bottom: $gutter-size;
+
+  code{
+    font-size: $font-size-code;
+  }
+
+  thead {
+    border-bottom: 1px solid $border-color;
+  }
+
+  td, th {
+    padding-top: 6px;
+    padding-bottom: 6px;
+    padding-right: 10px;
+  }
+
+  td {
+    border-bottom: 1px solid $border-light-color;
+  }
+  tr:last-of-type td {
+    border-bottom: none;
+  }
+
+  a {
+    .rawId {
+      color: $highlight-default;
+    }
+
+    &:hover .rawId {
+      text-decoration: underline;
+    }
+  }
+}
+
+.colLabel {
+  color: $text-strong-color;
+  text-align: right;
+  width: 25%;
+}
+
+.txID{
+  margin-bottom: $gutter-size;
+}
index 9af7f6c..97ffd95 100644 (file)
@@ -4,6 +4,13 @@ import { combineReducers } from 'redux'
 const type = 'transaction'
 const maxGeneratedHistory = 50
 
+const decodedTx = (state = [], action) => {
+  if (action.type == 'DECODE_TRANSACTION') {
+    return action.data
+  }
+  return state
+}
+
 export default combineReducers({
   items: reducers.itemsReducer(type),
   queries: reducers.queriesReducer(type),
@@ -13,4 +20,5 @@ export default combineReducers({
     }
     return state
   },
+  decodedTx
 })
index ee24ebc..2a351fb 100644 (file)
@@ -103,6 +103,11 @@ const transactionsAPI = (client) => {
       return shared.createBatch(client, '/build-transaction', builders, {cb})
     },
 
+    decodeTransaction: (raw_transaction, cb) => shared.tryCallback(
+      client.request('/decode-raw-transaction', {'raw_transaction': raw_transaction}).then(resp => checkForError(resp)),
+      cb
+    ),
+
     sign: (template, cb) => finalize(template)
       .then(finalized => client.request('/sign-transaction', finalized ).then(resp => checkForError(resp)),
         cb