OSDN Git Service

add the not found chrome extension fallback page.
authorZhiting Lin <zlin035@uottawa.ca>
Sat, 2 Feb 2019 07:16:41 +0000 (15:16 +0800)
committerZhiting Lin <zlin035@uottawa.ca>
Sat, 2 Feb 2019 07:16:41 +0000 (15:16 +0800)
18 files changed:
src/components/App.js
src/components/bytom.js
src/components/constants.js
src/components/layout/account/action.js [new file with mode: 0644]
src/components/layout/account/index.jsx [new file with mode: 0644]
src/components/layout/bytomWrap.jsx [new file with mode: 0644]
src/components/layout/header/NetworkInfo.jsx [new file with mode: 0644]
src/components/layout/header/index.jsx
src/components/layout/header/styles.scss [new file with mode: 0644]
src/components/layout/modal/index.jsx [new file with mode: 0644]
src/components/layout/profit/action.js
src/components/layout/profit/index.jsx
src/components/layout/save/action.js
src/components/layout/save/index.jsx
src/index.html
src/reducers/rotateReducer.js [new file with mode: 0644]
src/store.js [new file with mode: 0644]
src/styles/App.css

index e33ae4d..3f7875e 100644 (file)
@@ -5,6 +5,9 @@ import  Profit  from './layout/profit'
 import Saving from './layout/save'
 import Footer from './layout/footer'
 import Header from './layout/header'
+import Account from './layout/account'
+import bytomWrap from './layout/bytomWrap'
+
 
 import { assetDeposited, assetBill } from "./constants";
 
@@ -46,8 +49,9 @@ const Constants = () =>(
 
 const Main = () => (
   <Switch>
-    <Route exact path='/' component={Saving}></Route>
-    <Route exact path='/profit' component={Profit}></Route>
+    <Route exact path='/' component={bytomWrap(Saving)}/>
+    <Route exact path='/profit' component={bytomWrap(Profit)}/>
+    <Route exact path='/account' component={bytomWrap(Account)}/>
   </Switch>
 );
 
index 4712e9d..5c0d072 100644 (file)
@@ -63,9 +63,76 @@ export function listUTXO(params)
   }).then(response => {
     return response.data.result.data[0];
   })
+}
+
+export function listAddress(params)
+{
+  const url = "/api/api/v1/btm//account/list-addresses"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result.data[0];
+  })
+}
+
+export function listDappUTXO(params)
+{
+  const url = "/dapp/list-utxos"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result.data[0];
+  })
+}
+
+export function updateBase(params)
+{
+  const url = "/dapp/update-base"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result;
+  })
+}
+
+export function updateUtxo(params)
+{
+  const url = "/dapp/update-utxo"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result;
+  })
+}
+
+export function updateBalances(params)
+{
+  const url = "/dapp/update-balance"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result;
+  })
+}
 
-  // window.bytomAPI.sdk.query.listUtxo(params)
-  //   .then( resp =>{
-  //       return resp.data.result.data[0];
-  //   })
-}
\ No newline at end of file
+export function listBalances(params)
+{
+  const url = "/dapp/list-balances"
+  return axios({
+    method: 'post',
+    url,
+    data: params
+  }).then(response => {
+    return response.data.result;
+  })
+}
index 782e010..6d86683 100644 (file)
@@ -1,10 +1,17 @@
-export const depositProgram = "203f98494c8fcce82a1da8054cda521295333a6c7a6ea3b861a27fd766a5cea5731600140014f19df269f9334bdcb496da6b63b275d494470164015001500500c817a8040500e40b540220bbc81814b304cf4e129582b094672b917d28e1109aab4569697d72f102af07c84d4302597a64370200005479cda069c35b790400e1f5059600a05c797ba19a53795579a19a695a790400e1f5059653790400e1f505967800a07800a09a6955797b957c9600a069c35b797c9f9161645b010000005b79c2547951005e79895d79895c79895b7989597989587989537a894ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac890274787e008901c07ec169515b79c2515d79c16952c35c7994c251005d79895c79895b79895a79895979895879895779895679895579890274787e008901c07ec1696332020000005b79c2547951005e79895d79895c79895b7989597989587989537a894ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac890274787e008901c07ec16951c3c2515d79c1696343020000547acd9f69587a587aae7cac747800c0"
-export const profitProgram = "203f98494c8fcce82a1da8054cda521295333a6c7a6ea3b861a27fd766a5cea5731600140014f19df269f9334bdcb496da6b63b275d49447016401500500c817a8040500e40b540220df4638860378a2203466833c935efa19f513ac3aae2cb52d36cee7fa5010b0794ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac747800c0"
+export const depositProgram = "207d4b5c1f33bbd758ddc74e32c044bbd455b67f8ce90ce4add22def142bb2c5d8160014ed6c9062d3174230d53e916d616f132932c635fd02260202f40102f4010600204aa9d101050010a5d4e8200bb838d531a29dc96114cad8b86aa577fc1b22a683745eba53cde03c6850fba84d4302597a64370200005479cda069c35b790400e1f5059600a05c797ba19a53795579a19a695a790400e1f5059653790400e1f505967800a07800a09a6955797b957c9600a069c35b797c9f9161645b010000005b79c2547951005e79895d79895c79895b7989597989587989537a894ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac890274787e008901c07ec169515b79c2515d79c16952c35c7994c251005d79895c79895b79895a79895979895879895779895679895579890274787e008901c07ec1696332020000005b79c2547951005e79895d79895c79895b7989597989587989537a894ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac890274787e008901c07ec16951c3c2515d79c1696343020000547acd9f69587a587aae7cac747800c0"
+export const profitProgram = "207d4b5c1f33bbd758ddc74e32c044bbd455b67f8ce90ce4add22def142bb2c5d8160014ed6c9062d3174230d53e916d616f132932c635fd02260202f4010600204aa9d101050010a5d4e8200d8848b58ba5f5e0143c96af8c83e109fc31cafd1cc5d687fde3f55e68aa89e64ca4587a64980000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c967600a069c3787c9f91616481000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696393000000005b795479515b79c16951c3c2515d79c16963a4000000557acd9f69577a577aae7cac747800c0"
 
-export const assetDeposited = "bbc81814b304cf4e129582b094672b917d28e1109aab4569697d72f102af07c8"
-export const assetBill = "df4638860378a2203466833c935efa19f513ac3aae2cb52d36cee7fa5010b079"
+export const assetDeposited = "0bb838d531a29dc96114cad8b86aa577fc1b22a683745eba53cde03c6850fba8"
+export const assetBill = "0d8848b58ba5f5e0143c96af8c83e109fc31cafd1cc5d687fde3f55e68aa89e6"
 
 export const totalAmountBill = 10000000000
 export const totalAmountCapital = 20000000000
-export const dueBlockHeight = 30
-export const expireBlockHeight = 50
\ No newline at end of file
+export const dueBlockHeight = 500
+export const expireBlockHeight = 550
+
+export const banker = "0014ed6c9062d3174230d53e916d616f132932c635fd"
+
+
+export const btm = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+export const gas = 0.4
+
diff --git a/src/components/layout/account/action.js b/src/components/layout/account/action.js
new file mode 100644 (file)
index 0000000..cb3604b
--- /dev/null
@@ -0,0 +1,36 @@
+import { listAddress } from '../../bytom'
+
+
+import { assetDeposited, assetBill } from "../../constants";
+
+const updateBalances = (guid = '') => {
+  return (dispatch) => {
+    return listAddress({guid})
+      .then((resp)=>{
+        const balances = resp.balances
+        const billBalance = balances.filter(balance => balance.asset === assetBill)
+        const depositBalance = balances.filter(balance => balance.asset === assetDeposited)
+        if(billBalance.length === 1){
+          dispatch({
+            type: "UPDATE_BILL_ASSET_BALANCES",
+            billAssetBalance: billBalance[0].balance
+          })
+        }
+        if(depositBalance.length === 1){
+          dispatch({
+            type: "UPDATE_DEPOSIT_ASSET_BALANCES",
+            depositAssetBalance: depositBalance[0].balance
+          })
+        }
+      })
+      .catch((err) => {
+        throw err
+      })
+  }
+}
+
+let actions = {
+  updateBalances,
+}
+
+export default actions
diff --git a/src/components/layout/account/index.jsx b/src/components/layout/account/index.jsx
new file mode 100644 (file)
index 0000000..590530c
--- /dev/null
@@ -0,0 +1,129 @@
+import React, {
+  Component
+} from 'react'
+import { connect } from "react-redux"
+import jdenticon from "jdenticon"
+import action from "./action";
+import {assetDeposited, assetBill} from "../../constants";
+import { listBalances } from '../../bytom'
+
+class Account extends Component {
+  constructor(props) {
+    super(props)
+    this.state = {
+      record: '',
+      account:''
+    };
+
+    this.listBalance = this.listBalance.bind(this)
+  }
+
+  componentDidMount() {
+    if (
+      window.bytom
+      && window.bytom.defaultAccount
+    ) {
+      const account = window.bytom.defaultAccount
+      this.setState({ account })
+      if(account){
+        this.props.updateBalances(account.guid)
+        this.listBalance(account, assetDeposited)
+      }
+    }
+  }
+
+  listBalance(account, assetId){
+    listBalances({address: account.address, asset:assetId})
+      .then(resp =>{
+        this.setState({
+          record: resp.data
+        })
+      })
+  }
+
+  render () {
+    if(!this.state.account){
+      return <div></div>
+    }
+
+    const account = this.state.account
+    const svg = jdenticon.toSvg(account.alias, 100)
+
+    let record = <div></div>
+    if(this.state.record !== '' && this.state.record.length !== 0){
+      let list = []
+      this.state.record.forEach(
+        (re, i) =>{
+          list.push( <tr key={'record'+i}>
+            <th scope="row">{i}</th>
+            <td>{re.amount}</td>
+            <td>{new Date(re.create_at * 1000).toUTCString()}</td>
+          </tr>)
+        }
+      )
+      record= <table className="table">
+        <thead>
+        <tr>
+          <th scope="col">#</th>
+          <th scope="col">Amount</th>
+          <th scope="col">Time</th>
+        </tr>
+        </thead>
+        <tbody>
+          {list}
+        </tbody>
+      </table>
+    }else{
+      record = <p>No Record Found.</p>
+    }
+
+    return (
+      <div className="container">
+        <div className="row">
+          <div className="col-2">
+            <div className="mr-2" dangerouslySetInnerHTML={{__html:svg}} />
+          </div>
+          <div className="col">
+            <h1 className="text-uppercase">{account.alias}</h1>
+            <div>Address: {account.address}</div>
+            <div>Deposit Asset balance: {this.props.depositAssetBalance || 0}</div>
+            <div>Bill Asset Balance: {this.props.billAssetBalance || 0}</div>
+
+            <hr/>
+            <h4>History</h4>
+            <ul className="nav nav-pills mb-3" id="pills-tab" role="tablist">
+              <li className="nav-item">
+                <a className="nav-link active" id="pills-home-tab" data-toggle="pill"
+                   href="#pills-deposit" onClick={() => this.listBalance(account, assetDeposited)} role="tab" aria-controls="pills-deposit" aria-selected="true">Deposit Asset Record</a>
+              </li>
+              <li className="nav-item">
+                <a className="nav-link" id="pills-profile-tab" data-toggle="pill"
+                   href="#pills-profit" onClick={() => this.listBalance(account, assetBill)} role="tab" aria-controls="pills-profit" aria-selected="false">Bill Asset Record</a>
+              </li>
+            </ul>
+            <div className="tab-content" id="pills-tabContent">
+              <div className="tab-pane fade show active" id="pills-deposit" role="tabpanel" aria-labelledby="pills-deposit-tab">
+                {record}
+              </div>
+              <div className="tab-pane fade" id="pills-profit" role="tabpanel" aria-labelledby="pills-profit-tab">
+                {record}
+              </div>
+            </div>
+          </div>
+        </div>
+
+      </div>
+    )
+  }
+}
+
+const mapStateToProps = state => ({
+  depositAssetBalance: state.depositAssetBalance,
+  billAssetBalance: state.billAssetBalance
+})
+
+const mapDispatchToProps = dispatch => ({
+  updateBalances: (guid) => dispatch(action.updateBalances(guid)),
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(Account)
diff --git a/src/components/layout/bytomWrap.jsx b/src/components/layout/bytomWrap.jsx
new file mode 100644 (file)
index 0000000..3268af0
--- /dev/null
@@ -0,0 +1,64 @@
+import React, { Component } from 'react'
+
+// This is a Higher Order Component (HOC) that wraps up any components that require
+// an unlocked Bytom account instance
+export default function(WrappedComponent) {
+
+  // ...and returns another component...
+  const BytomWrap = class extends Component {
+
+    render () {
+      var contents = <div />
+
+      if (
+        window.bytom
+        && window.bytom.defaultAccount
+      ) {
+        return <WrappedComponent {...this.props} />
+      }
+      else if (( window.bytom )) {
+        return (
+            <div className="columns">
+              <div className="column" />
+              <div className="column is-two-thirds">
+                <h1 className="title">
+                  Hoo-ray! <strong>Bytom-Chrome-Extension</strong> is installed!
+                </h1>
+                <h2 className="subtitle">
+                  However, you need to create a new account. Click the bytom icon in the top-right corner of your browser, then refresh the page.
+                </h2>
+              </div>
+              <div className="column" />
+            </div>
+        )
+      } else {
+        return (
+            <div className="columns">
+              <div className="column" />
+              <div className="column is-two-thirds">
+                <h1 className="title">
+                  Hold up ...
+                </h1>
+                <p className="lead">
+                  To use Dapp Demo you will need to install the Bytom-Chrome-Extension.
+                </p>
+                <p className="lead">
+                  Please install the extension and refresh the page.
+                </p>
+                <br />
+                <br />
+
+              </div>
+              <div className="column" />
+            </div>
+        )
+      }
+
+      return contents
+    }
+
+  }
+
+  return BytomWrap;
+
+}
diff --git a/src/components/layout/header/NetworkInfo.jsx b/src/components/layout/header/NetworkInfo.jsx
new file mode 100644 (file)
index 0000000..f395cb6
--- /dev/null
@@ -0,0 +1,46 @@
+import React, { Component } from 'react'
+import { NavLink } from 'react-router-dom'
+import jdenticon from "jdenticon"
+
+const NetworkInfo = class extends Component {
+
+  constructor (props) {
+    super(props)
+    this.state = {
+      account: ''
+    }
+  }
+
+  componentDidMount() {
+    if (
+      window.bytom
+      && window.bytom.defaultAccount
+    ) {
+      this.setState({ account: window.bytom.defaultAccount })
+    }
+  }
+
+  render() {
+    const account = this.state.account
+
+    if (
+      account
+    ) {
+      const svg = jdenticon.toSvg(account.alias, 40)
+      return (
+        <div className="navbar-nav">
+          <div className="nav-item  d-flex ">
+            <NavLink  exact activeClassName="active" className="d-flex nav-link rounded js-scroll-trigger" to='/account'>
+              <div className="mr-2" dangerouslySetInnerHTML={{__html:svg}} />
+              <div className="mt-auto mb-auto ">{account.alias}</div>
+            </NavLink>
+          </div>
+        </div>
+      )
+    } else {
+      return null
+    }
+  }
+}
+
+export default NetworkInfo
index 7f9d529..7a51011 100644 (file)
@@ -1,5 +1,8 @@
 import React, { Component } from 'react'
 import { NavLink } from 'react-router-dom'
+import NetworkInfo from './NetworkInfo'
+import { UpdateProgramBase as updateSave } from "../save/action";
+import { UpdateProgramBase as updateProfit } from "../profit/action";
 
 const Header = class extends Component {
 
@@ -7,6 +10,13 @@ const Header = class extends Component {
     super(props)
   }
 
+  componentDidMount() {
+    if(window.bytom){
+      updateSave();
+      updateProfit();
+    }
+  }
+
   render () {
     return (
       <nav className="navbar navbar-expand-lg bg-secondary fixed-top text-uppercase" id="mainNav">
@@ -21,7 +31,7 @@ const Header = class extends Component {
           </button>
 
           <div className="collapse navbar-collapse" id="navbarResponsive">
-            <ul className="navbar-nav ml-auto">
+            <ul className="navbar-nav mr-auto">
               <li className="nav-item mx-0 mx-lg-1">
                 <NavLink  exact activeClassName="active" className="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger" to='/'>Saving</NavLink>
               </li>
@@ -29,12 +39,13 @@ const Header = class extends Component {
                 <NavLink  exact activeClassName="active" className="nav-link py-3 px-0 px-lg-3 rounded js-scroll-trigger"  to='/profit'>Profit</NavLink>
               </li>
             </ul>
+            <NetworkInfo/>
           </div>
-        </div>
 
+        </div>
       </nav>
     )
   }
 }
 
-export default Header;
+export default Header
diff --git a/src/components/layout/header/styles.scss b/src/components/layout/header/styles.scss
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/components/layout/modal/index.jsx b/src/components/layout/modal/index.jsx
new file mode 100644 (file)
index 0000000..26b0ece
--- /dev/null
@@ -0,0 +1,30 @@
+import React from 'react'
+
+class Modal extends React.Component {
+  render() {
+    return (
+      <div className="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby={this.props.id}
+           aria-hidden="true">
+        <div className="modal-dialog" role="document">
+          <div className="modal-content">
+            <div className="modal-header">
+              <h5 className="modal-title" id={this.props.id}>{this.title}</h5>
+              <button type="button" className="close" data-dismiss="modal" aria-label="Close">
+                <span aria-hidden="true">&times;</span>
+              </button>
+            </div>
+            <div className="modal-body">
+              {this.props.children}
+            </div>
+            <div className="modal-footer">
+              <button type="button" className="btn btn-secondary" data-dismiss="modal">Close</button>
+              <button type="button" className="btn btn-primary">Save changes</button>
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default Modal
index 6e6f9fe..85d3a6e 100644 (file)
@@ -1,48 +1,78 @@
-import { spendUTXOAction, spendWalletAction, controlProgramAction, controlAddressAction, listUTXO } from '../../bytom'
-import { profitProgram, assetDeposited, assetBill } from "../../constants";
+import {
+  spendUTXOAction, spendWalletAction, controlProgramAction, controlAddressAction,
+  updateBase, updateBalances, updateUtxo, listDappUTXO
+} from '../../bytom'
+import {profitProgram, assetDeposited, assetBill, gas, banker, totalAmountBill, totalAmountCapital} from "../../constants";
 
-export function FixedLimitProfit(amountBill, saver) {
-
-  listUTXO({
-    "filter": {
-      "script": profitProgram,
+export function FixedLimitProfit(account, amountBill, saver) {
+  return new Promise((resolve, reject) => {
+    return listDappUTXO({
+      "program": profitProgram,
       "asset": assetDeposited
-    }
-  }).then(resp => {
-    const capitalAmount = resp.amount
-    const capitalAsset = resp.asset
-    const utxo = resp.hash
-
-    const gas = 40000000
-    const btm = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-
-    const input = []
-    const output = []
+    }).then(resp => {
 
-    const totalAmountBill = 10000000000
-    const totalAmountCapital = 20000000000
+      const capitalAmount = resp.amount
+      const capitalAsset = resp.asset
+      const utxo = resp.hash
 
-    const sAmountBill = amountBill/100000000
-    const sTotalAmountBill = totalAmountBill/100000000
-    const gain = totalAmountCapital*sAmountBill/sTotalAmountBill
+      if(amountBill > capitalAmount) {
+        throw 'input amount must be smaller or equal to ' + capitalAmount + '.'
+      }else{
+        const input = []
+        const output = []
 
-    const banker = "00140014f19df269f9334bdcb496da6b63b275d49447"
+        const sAmountBill = amountBill/100000000
+        const sTotalAmountBill = totalAmountBill/100000000
+        const gain = totalAmountCapital*sAmountBill/sTotalAmountBill
 
-    input.push(spendUTXOAction(utxo, amountBill, saver))
-    input.push(spendWalletAction(amountBill, assetBill))
-    input.push(spendWalletAction(gas, btm))
+        input.push(spendUTXOAction(utxo, amountBill, saver))
+        input.push(spendWalletAction(amountBill, assetBill))
 
-    if(amountBill < capitalAmount){
-      output.push(controlProgramAction(amountBill, assetBill, banker ))
-      output.push(controlAddressAction(gain, capitalAsset, saver))
-      output.push(controlProgramAction((capitalAmount - gain), capitalAsset, profitProgram))
-    }else{
-      output.push(controlProgramAction(amountBill, assetBill, banker ))
-      output.push(controlAddressAction(capitalAmount, capitalAsset, saver))
-    }
-
-    window.bytom.advancedTransfer(input, output)
+        if(amountBill < capitalAmount){
+          output.push(controlProgramAction(amountBill, assetBill, banker ))
+          output.push(controlAddressAction(gain, capitalAsset, saver))
+          output.push(controlProgramAction((capitalAmount - gain), capitalAsset, profitProgram))
+        }else{
+          output.push(controlProgramAction(amountBill, assetBill, banker ))
+          output.push(controlAddressAction(capitalAmount, capitalAsset, saver))
+        }
 
+        window.bytom.advancedTransfer(account, input, output, gas*10000000)
+          .then((resp) => {
+            if(resp.action === 'reject'){
+              reject('user reject the request')
+            }else if(resp.action === 'success'){
+              updateUtxo({"hash": utxo})
+                .then(()=>{
+                  updateBalances({
+                    "address": saver,
+                    "asset": assetDeposited,
+                    "amount": amountBill*totalAmountCapital/totalAmountBill
+                  }).then(()=>{
+                    updateBalances({
+                      "address": account.address,
+                      "asset": assetBill,
+                      "amount": -amountBill
+                    }).then(()=>{
+                      resolve()
+                    })
+                  })
+                })
+            }
+          })
+          .catch(err => {
+            throw err
+          })
+      }
+    }).catch(err => {
+      reject(err)
+    })
   })
+}
 
+export function UpdateProgramBase(){
+  return updateBase({
+    "program": profitProgram,
+    "asset": assetDeposited
+  })
 }
\ No newline at end of file
index 618cdb7..cffd957 100644 (file)
@@ -1,14 +1,17 @@
 import React from 'react'
 import { FixedLimitProfit } from './action'
-import { dueBlockHeight, expireBlockHeight} from "../../constants";
+import {dueBlockHeight, expireBlockHeight, totalAmountBill, totalAmountCapital} from "../../constants";
+import {connect} from "react-redux";
 
-export default class Profit extends React.Component {
+class Profit extends React.Component {
 
   constructor(props) {
     super(props);
     this.state = {
       amount: '',
-      address: ''
+      address: '',
+      msg:'',
+      error:''
     };
 
     this.handleInputChange = this.handleInputChange.bind(this);
@@ -29,9 +32,21 @@ export default class Profit extends React.Component {
     event.preventDefault();
 
     const amount = Number(event.target.amount.value)
+    const account = this.props.account
     const address = event.target.address.value
 
-    FixedLimitProfit(amount, address)
+    FixedLimitProfit(account, amount, address)
+      .then(()=> {
+        this.setState({
+          error:'',
+          msg:`Submit success!!! you spent ${amount} bill asset, and gain ${amount*totalAmountCapital/totalAmountBill} deposit asset.`
+        })
+      }).catch(err => {
+      this.setState({
+        error: err,
+        msg:''
+      })
+    })
   }
 
   render() {
@@ -39,8 +54,8 @@ export default class Profit extends React.Component {
       <div>
         <h2>Profit</h2>
         <div className="mt-3 mb-4">
-          <p className='lead'>Profit should get between the block height {dueBlockHeight} and {expireBlockHeight}.</p>
-          <p className='lead'>Send {this.state.amount} Bill Asset from the selected chrome extension account, and the address {this.state.address} will get the double of what you Deposit Asset.</p>
+          <p className='lead'>Profit should get above the block height {dueBlockHeight}.</p>
+          <p className='lead'>Send {this.state.amount} Bill Asset from your chrome extension account <b className="font-weight-bolder text-uppercase">{this.props.account.alias}</b>, and the address {this.state.address} will gain {this.state.amount*totalAmountCapital/totalAmountBill || ''} Deposit Asset.</p>
         </div>
         <form onSubmit={this.handleSubmit}>
           <div className="form-group">
@@ -63,9 +78,23 @@ export default class Profit extends React.Component {
               value={this.state.address}
               onChange={this.handleInputChange} />
           </div>
-          <button type="submit" className="btn btn-primary">Submit</button>
+          <p>Fee:  0.4 BTM</p>
+          <button type="submit" className="btn btn-primary">Profit to address</button>
+          {this.state.msg && <div className="alert alert-success mt-4" role="alert">
+            {this.state.msg}
+          </div>}
+          {this.state.error && <div className="alert alert-danger mt-4" role="alert">
+            {this.state.error}
+          </div>}
         </form>
       </div>
     )
   }
 }
+
+
+const mapStateToProps = state => ({
+  account: state.account
+})
+
+export default connect(mapStateToProps)(Profit)
index 3755b22..b385e25 100644 (file)
@@ -1,44 +1,75 @@
-import { spendUTXOAction, spendWalletAction, controlProgramAction, controlAddressAction, listUTXO } from '../../bytom'
-import { depositProgram, profitProgram, assetDeposited, assetBill } from "../../constants";
+import {
+  spendUTXOAction, spendWalletAction, controlProgramAction,
+  controlAddressAction, listDappUTXO, updateBase, updateUtxo ,updateBalances
+} from '../../bytom'
+import {
+  depositProgram, profitProgram, assetDeposited, assetBill, gas
+} from "../../constants";
 
-export function FixedLimitDeposit(amount, address) {
-  //
-  // listUTXO({
-  //   "filter": {
-  //     "script": depositProgram,
-  //     "asset": assetBill
-  //   }
-  // }).then(resp => {
-  listUTXO({
-    "filter": {
-      "script":"2022e829107201c6b975b1dc60b928117916285ceb4aa5c6d7b4b8cc48038083e074037caa8700c0",
-      "asset":"df4638860378a2203466833c935efa19f513ac3aae2cb52d36cee7fa5010b079"
-    }
-  }).then(resp => {
-    const billAmount = resp.amount
-    const billAsset = resp.asset
-    const utxo = resp.hash
+export function FixedLimitDeposit(account, amount, address) {
+  return new Promise((resolve, reject) => {
+    return listDappUTXO({
+      "program": depositProgram,
+      "asset": assetBill
+    }).then(resp => {
+      const billAmount = resp.amount
+      const billAsset = resp.asset
+      const utxo = resp.hash
 
+      if(amount > billAmount){
+        throw 'input amount must be smaller or equal to ' + billAmount +'.'
+      }else{
+        const input = []
+        const output = []
 
-    const gas = 40000000
-    const btm = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+        input.push(spendUTXOAction(utxo, amount, address))
+        input.push(spendWalletAction(amount, assetDeposited))
 
-    const input = []
-    const output = []
+        if(amount < billAmount){
+          output.push(controlProgramAction(amount, assetDeposited, profitProgram))
+          output.push(controlAddressAction(amount, billAsset, address))
+          output.push(controlProgramAction((billAmount-amount), billAsset, depositProgram))
+        }else{
+          output.push(controlProgramAction(amount, assetDeposited, profitProgram))
+          output.push(controlAddressAction(billAmount, billAsset, address))
+        }
 
-    input.push(spendUTXOAction(utxo, amount, address))
-    input.push(spendWalletAction(amount, assetDeposited))
-    input.push(spendWalletAction(gas, btm))
-
-    if(amount < billAmount){
-      output.push(controlProgramAction(amount, assetDeposited, profitProgram))
-      output.push(controlAddressAction(amount, billAsset, address))
-      output.push(controlProgramAction((billAmount-amount), billAsset, depositProgram))
-    }else{
-      output.push(controlProgramAction(amount, assetDeposited, profitProgram))
-      output.push(controlAddressAction(billAmount, billAsset, address))
-    }
+        window.bytom.advancedTransfer(account, input, output, gas*10000000)
+          .then((resp) => {
+            if(resp.action === 'reject'){
+              reject('user reject the request')
+            }else if(resp.action === 'success'){
+              updateUtxo({"hash": utxo})
+                .then(()=>{
+                  updateBalances({
+                    address,
+                    "asset": assetDeposited,
+                    "amount": -amount
+                  }).then(()=>{
+                    updateBalances({
+                      address,
+                      "asset": assetBill,
+                      "amount": amount
+                    }).then(()=>{
+                      resolve()
+                    })
+                  })
+                })
+            }
+          })
+          .catch(err => {
+            throw err
+          })
+      }
+    }).catch(err => {
+      reject(err)
+    })
+  })
+}
 
-    window.bytom.advancedTransfer(input, output)
+export function UpdateProgramBase(){
+  return updateBase({
+    "program": depositProgram,
+    "asset": assetBill
   })
-}
\ No newline at end of file
+}
index 16c8262..13d6d9f 100644 (file)
@@ -1,14 +1,17 @@
 import React from 'react'
-import { FixedLimitDeposit } from './action'
-import { dueBlockHeight } from '../../constants'
+import { FixedLimitDeposit} from './action'
+import { dueBlockHeight, gas } from '../../constants'
+import {connect} from "react-redux";
 
-export default class Save extends React.Component {
+class Save extends React.Component {
 
   constructor(props) {
     super(props);
     this.state = {
       amount: '',
-      address: ''
+      address: '',
+      msg:'',
+      error:''
     };
 
     this.handleInputChange = this.handleInputChange.bind(this);
@@ -29,9 +32,21 @@ export default class Save extends React.Component {
     event.preventDefault();
 
     const amount = Number(event.target.amount.value)
-    const address = event.target.address.value
+    const account = this.props.account
+    const address = account.address
 
-    FixedLimitDeposit(amount, address)
+    FixedLimitDeposit(account, amount, address)
+      .then(()=> {
+          this.setState({
+            error:'',
+            msg:`Submit success!!! you spent ${amount} deposite asset,and gain ${amount} bill asset.`
+          })
+        }).catch(err => {
+          this.setState({
+            error:err,
+            msg: ''
+          })
+        })
   }
 
   render() {
@@ -39,8 +54,9 @@ export default class Save extends React.Component {
       <div>
         <h2>Deposit</h2>
         <div className="mt-3 mb-4">
-          <p className='lead'>Deposit should happened under the block height {dueBlockHeight}.</p>
-          <p className='lead' >Spend {this.state.amount} Deposit Asset from your account {this.state.address} and you will get the relevant {this.state.amount} Bill Asset.</p>
+          <p className='lead'>Deposit should happen under the block height {dueBlockHeight}.</p>
+          <p className='lead' >Spend {this.state.amount} Deposit Asset from your current chrome extension account <b className="font-weight-bolder text-uppercase">{this.props.account.alias}</b> and you will get the relevant {this.state.amount} Bill Asset.</p>
+          <p>Please make sure that your account has enough Deposit Asset.</p>
         </div>
         <form onSubmit={this.handleSubmit}>
           <div className="form-group">
@@ -53,19 +69,24 @@ export default class Save extends React.Component {
               value={this.state.amount}
               onChange={this.handleInputChange} />
           </div>
-          <div className="form-group">
-            <label >Address</label>
-            <input
-              type="address"
-              className="form-control"
-              placeholder="Address"
-              name="address"
-              value={this.state.address}
-              onChange={this.handleInputChange} />
-          </div>
-          <button type="submit" className="btn btn-primary">Submit</button>
+          <p>Fee:  {gas} BTM</p>
+          <button type="submit" className="btn btn-primary">Spend Asset</button>
+
+          {this.state.msg && <div className="alert alert-success mt-4" role="alert">
+            {this.state.msg}
+          </div>}
+          {this.state.error && <div className="alert alert-danger mt-4" role="alert">
+            {this.state.error}
+          </div>}
+
         </form>
       </div>
     )
   }
 }
+
+const mapStateToProps = state => ({
+  account: state.account
+})
+
+export default connect(mapStateToProps)(Save)
index 7cab222..914afe8 100644 (file)
@@ -5,7 +5,6 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
-    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
     <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css">
     <link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet" type="text/css">
 
@@ -16,9 +15,6 @@
 <div id="root">
 
 </div>
-<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
-<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
 </body>
 
 </html>
\ No newline at end of file
diff --git a/src/reducers/rotateReducer.js b/src/reducers/rotateReducer.js
new file mode 100644 (file)
index 0000000..0ca09ab
--- /dev/null
@@ -0,0 +1,16 @@
+export default (state, action) => {
+  switch (action.type) {
+    case "UPDATE_BILL_ASSET_BALANCES":
+      return {
+        ...state,
+        billAssetBalance: action.billAssetBalance
+      };
+    case "UPDATE_DEPOSIT_ASSET_BALANCES":
+      return {
+        ...state,
+        depositAssetBalance: action.depositAssetBalance
+      };
+    default:
+      return state
+  }
+}
\ No newline at end of file
diff --git a/src/store.js b/src/store.js
new file mode 100644 (file)
index 0000000..8e9b85b
--- /dev/null
@@ -0,0 +1,17 @@
+import rotateReducer from "./reducers/rotateReducer"
+import { createStore, applyMiddleware, compose } from 'redux'
+import thunkMiddleware from 'redux-thunk'
+
+function configureStore(state = { account: '' , depositAssetBalance:'',billAssetBalance:''}) {
+  return createStore(
+    rotateReducer,
+    state,
+    compose(
+      applyMiddleware(
+        thunkMiddleware,
+      ),
+      window.devToolsExtension ? window.devToolsExtension() : f => f
+    )
+  )
+}
+export default configureStore
\ No newline at end of file
index a4333d4..c4663ea 100644 (file)
@@ -166,6 +166,14 @@ section h2 {
     }
 }
 
+.nav > li.nav-item > a.nav-link.active {
+    color: #fff;
+    background: #18BC9C;
+}
+.nav > li.nav-item > a.nav-link.active:active, .nav > li.nav-item > a.nav-link.active:focus, .nav > li.nav-item > a.nav-link.active:hover {
+    color: #fff;
+    background: #18BC9C;
+}
 header.masthead {
     padding-top: calc(3rem + 72px);
     padding-bottom: 3rem;
@@ -380,3 +388,4 @@ a:focus, a:hover, a:active {
 .form-group label{
     color: #2C3E50;    
 }
+