Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
Introduce saga/reducer workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
taggartbg authored and Taggart Bowen-Gaddy committed Jul 31, 2019
1 parent 7c22d97 commit eaf1552
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 34 deletions.
24 changes: 24 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export const REQUEST_A_DEPOSIT = 'REQUEST_A_DEPOSIT'
export const WAIT_CONFIRMATION = 'WAIT_CONFIRMATION'
export const SUBMIT_DEPOSIT_PROOF = 'SUBMIT_DEPOSIT_PROOF'

export function requestADeposit({ history }) {
return {
history,
type: REQUEST_A_DEPOSIT
}
}

export function waitConfirmation({ history }) {
return {
history,
type: WAIT_CONFIRMATION
}
}

export function submitProof({ history }) {
return {
history,
type: SUBMIT_DEPOSIT_PROOF
}
}
65 changes: 53 additions & 12 deletions src/components/Pay.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,60 @@
import React from 'react';
import React, { Component } from 'react';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const Pay = ({ confirming, history }) => {
let button;
import { waitConfirmation } from '../actions'

if (confirming) {
button = <button onClick={() => {history.push('/prove')}}>Confirming...</button>
} else {
button = <button onClick={() => {history.push('/pay/confirming')}}>Send BTC "here"</button>
class Pay extends Component {
componentDidMount() {
const { history, waitConfirmation } = this.props

waitConfirmation({ history })
}

render() {
const { address, btcConfirming } = this.props
let renderBody;

if (!btcConfirming) {
renderBody = (
<div className="btc-address">
{address}
</div>
)
} else {
renderBody = (
<div className="confirming">
Confirming...
</div>
)
}

return (
<div className="pay">
{renderBody}
</div>
)
}
}


const mapStateToProps = (state, ownProps) => {
return {
address: state.app.btcAddress,
btcConfirming: !!state.app.btcConfirming
}
}

return (
<div className="pay">
{button}
</div>
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
waitConfirmation
},
dispatch
)
}

export default Pay
export default connect(
mapStateToProps,
mapDispatchToProps
)(Pay)
42 changes: 35 additions & 7 deletions src/components/Prove.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
import React from 'react';
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const Prove = ({ history }) => (
<div className="prove">
<button onClick={() => {history.push('/congratulations')}}>Submit Proof</button>
</div>
)
import { submitProof } from '../actions'

export default Prove
class Prove extends Component {

handleClickProve = (evt) => {
const { submitProof, history } = this.props

submitProof({ history })
}

render() {
return (
<div className="prove">
<button onClick={this.handleClickProve}>Submit Proof</button>
</div>
)
}
}


const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
submitProof
},
dispatch
)
}

export default connect(
() => ({}),
mapDispatchToProps
)(Prove)
42 changes: 35 additions & 7 deletions src/components/Start.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
import React from 'react';
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const Start = ({ history }) => (
<div className="start">
<button onClick={() => {history.push('/pay')}}>Pay</button>
</div>
)
import { requestADeposit } from '../actions'

export default Start
class Start extends Component {

handleClickPay = (evt) => {
const { requestADeposit, history } = this.props

requestADeposit({ history })
}

render() {
return (
<div className="start">
<button onClick={this.handleClickPay}>Pay</button>
</div>
)
}
}


const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
requestADeposit
},
dispatch
)
}

export default connect(
() => ({}),
mapDispatchToProps
)(Start)
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ function AppWrapper() {
<Provider store={store}>
<Router>
<Web3Wrapper>
<Route path="/" exact component={Home} />
<App>
<Route path="/" exact component={Home} />
<Route path="/start" component={Start} />
<Route path="/pay" exact component={Pay} />
<Route path="/pay/confirming" render={(props) => <Pay {...props} confirming={true} />} />
Expand Down
37 changes: 37 additions & 0 deletions src/reducers/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { DEPOSIT_BTC_ADDRESS, DEPOSIT_REQUEST_SUCCESS, DEPOSIT_PROVE_BTC_TX_SUCCESS, BTC_TX_CONFIRMED } from "../sagas";

const intialState = {
btcAddress: null,
depositAddress: null,
btcDepositedTxid: null,
tbtcMintedTxId: null
}

const app = (state = intialState, action) => {
switch(action.type) {
case DEPOSIT_BTC_ADDRESS:
return {
...state,
btcAddress: action.payload.btcAddress
}
case DEPOSIT_REQUEST_SUCCESS:
return {
...state,
depositAddress: action.payload.depositAddress
}
case BTC_TX_CONFIRMED:
return {
...state,
btcDepositedTxid: action.payload.btcDepositedTxid
}
case DEPOSIT_PROVE_BTC_TX_SUCCESS:
return {
...state,
tbtcMintedTxId: action.payload.tbtcMintedTxId
}
default:
return state
}
}

export default app
4 changes: 2 additions & 2 deletions src/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { combineReducers } from 'redux'

// Imports here
import app from './app.js'

const reducers = combineReducers({ todo: 'TODO' })
const reducers = combineReducers({ app })

export default reducers
97 changes: 92 additions & 5 deletions src/sagas/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,96 @@
import { all } from 'redux-saga/effects'
import { call, put, takeLatest } from 'redux-saga/effects'

// Imports here
import { REQUEST_A_DEPOSIT, WAIT_CONFIRMATION, SUBMIT_DEPOSIT_PROOF } from '../actions'

function* sagas() {
yield all([ 'TODO' ])
export const DEPOSIT_REQUEST_BEGIN = 'DEPOSIT_REQUEST_BEGIN'
export const DEPOSIT_REQUEST_METAMASK_SUCCESS = 'DEPOSIT_REQUEST_METAMASK_SUCCESS'
export const DEPOSIT_REQUEST_SUCCESS = 'DEPOSIT_REQUEST_SUCCESS'
export const DEPOSIT_BTC_ADDRESS = 'DEPOSIT_BTC_ADDRESS'

export const BTC_TX_MINED = 'BTC_TX_MINED'
export const BTC_TX_CONFIRMED_WAIT = 'BTC_TX_CONFIRMED_WAIT'
export const BTC_TX_CONFIRMED = 'BTC_TX_CONFIRMED'

export const DEPOSIT_PROVE_BTC_TX_BEGIN = 'DEPOSIT_PROVE_BTC_TX_BEGIN'
export const DEPOSIT_PROVE_BTC_TX_SUCCESS = 'DEPOSIT_PROVE_BTC_TX_SUCCESS'


function* requestADeposit({ history }) {
// call Keep to request a deposit
yield put({ type: DEPOSIT_REQUEST_BEGIN })

// sign the transaction and submit
yield put({ type: DEPOSIT_REQUEST_METAMASK_SUCCESS })

// wait for it to be mined
// get the deposit address
yield put({
type: DEPOSIT_REQUEST_SUCCESS,
payload: {
depositAddress: '0x'+'0'.repeat(40)
}
})

// now call the deposit contract
// and get the btc address
// goto next
yield put({
type: DEPOSIT_BTC_ADDRESS,
payload: {
btcAddress: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'
}
})

// goto
history.push('/pay')
}

function* waitConfirmation({ history }) {
// now show a waiting dialog, with some sort of smart countdown
// wait for the transaction to be received
// wait for the transaction to be confirmed
yield put({
type: BTC_TX_MINED
})

// wait a certain number of confirmations on this step
yield put({
type: BTC_TX_CONFIRMED_WAIT
})

// when it's finally sufficiently confirmed, dispatch the txid
yield put({
type: BTC_TX_CONFIRMED,
payload: {
btcDepositedTxid: 'ed469d3afbe6a4f69b729fc782ed6bf15fb7017d7f4349227d48753c68ac04b3'
}
})

history.push('/prove')
}

function* proveDeposit({ btcTxid, history }) {
// get the transaction details from the bitcoin chain
// run through the proof generation process
// generate a proof

// again, call the web3 contract, submitting the proof
yield put({ type: DEPOSIT_PROVE_BTC_TX_BEGIN })

// wait for the tx to be mined successfully
yield put({
type: DEPOSIT_PROVE_BTC_TX_SUCCESS,
payload: {
tbtcMintedTxId: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'
}
})

// goto next
history.push('/congratulations')
}

export default sagas
export default function* () {
yield takeLatest(REQUEST_A_DEPOSIT, requestADeposit)
yield takeLatest(WAIT_CONFIRMATION, waitConfirmation)
yield takeLatest(SUBMIT_DEPOSIT_PROOF, proveDeposit)
}

0 comments on commit eaf1552

Please sign in to comment.