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";
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>
);
}).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;
+ })
+}
-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
+
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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;
+
+}
--- /dev/null
+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
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 {
super(props)
}
+ componentDidMount() {
+ if(window.bytom){
+ updateSave();
+ updateProfit();
+ }
+ }
+
render () {
return (
<nav className="navbar navbar-expand-lg bg-secondary fixed-top text-uppercase" id="mainNav">
</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>
<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
--- /dev/null
+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">×</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
-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
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);
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() {
<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">
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)
-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
+}
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);
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() {
<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">
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)
<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">
<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
--- /dev/null
+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
--- /dev/null
+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
}
}
+.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;
.form-group label{
color: #2C3E50;
}
+