This repository has been archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 31
/
deposit.js
260 lines (208 loc) · 8.32 KB
/
deposit.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
import { call, put, select } from 'redux-saga/effects'
import { METAMASK_TX_DENIED_ERROR } from '../chain'
import { notifyTransactionConfirmed } from '../lib/notifications/actions'
import { navigateTo } from '../lib/router/actions'
import { TBTCLoaded } from '../wrappers/web3'
import { resumeRedemption } from './redemption'
import BN from "bn.js"
/** @typedef { import("@keep-network/tbtc.js").TBTC } TBTC */
/** @typedef { import("@keep-network/tbtc.js").Deposit } Deposit */
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_RESOLVED = 'DEPOSIT_RESOLVED'
export const DEPOSIT_BTC_ADDRESS = 'DEPOSIT_BTC_ADDRESS'
export const DEPOSIT_STATE_RESTORED = 'DEPOSIT_STATE_RESTORED'
export const DEPOSIT_BTC_AMOUNTS = 'DEPOSIT_BTC_AMOUNTS'
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'
export const DEPOSIT_PROVE_BTC_TX_ERROR = 'DEPOSIT_PROVE_BTC_TX_ERROR'
function* restoreState(nextStepMap, stateKey) {
/** @type {TBTC} */
const tbtc = yield TBTCLoaded
const depositAddress = yield select(state => state[stateKey].depositAddress)
const deposit = yield tbtc.Deposit.withAddress(depositAddress)
yield put({
type: DEPOSIT_RESOLVED,
payload: {
deposit,
}
})
/** @type {BN} */
const depositState = yield call([deposit, deposit.getCurrentState])
let finalCalls = null
let nextStep = nextStepMap[depositState]
switch(depositState) {
case tbtc.Deposit.State.START:
throw new Error("Unexpected state.")
// Funding flow.
case tbtc.Deposit.State.AWAITING_SIGNER_SETUP:
yield put(navigateTo('/deposit/' + depositAddress + '/generate-address'))
break
case tbtc.Deposit.State.AWAITING_WITHDRAWAL_PROOF:
finalCalls = resumeRedemption
nextStep = "/redemption/prove"
// Explicitly fall through.
case tbtc.Deposit.State.AWAITING_WITHDRAWAL_SIGNATURE:
case tbtc.Deposit.State.AWAITING_BTC_FUNDING_PROOF:
case tbtc.Deposit.State.REDEEMED:
case tbtc.Deposit.State.ACTIVE:
const btcAddress = yield call([deposit, deposit.getBitcoinAddress])
yield put({
type: DEPOSIT_BTC_ADDRESS,
payload: {
btcAddress,
}
})
const lotInSatoshis = yield call([deposit, deposit.getSatoshiLotSize])
const signerFeeTbtc = yield call([deposit.contract, deposit.contract.signerFee])
const signerFeeInSatoshis = signerFeeTbtc.div(tbtc.satoshisPerTbtc)
yield put({
type: DEPOSIT_BTC_AMOUNTS,
payload: {
lotInSatoshis,
signerFeeInSatoshis,
}
})
if (finalCalls) {
yield* finalCalls()
}
// FIXME Check to see if Electrum has already seen a tx for payment
// FIXME and fast-forward to /pay/confirming if so.
//
// FIXME Check to see if we have a transaction in the mempool for
// FIXME submitting funding proof, and update state accordingly.
yield put({
type: DEPOSIT_STATE_RESTORED,
})
const inVendingMachine = yield call([deposit, deposit.inVendingMachine])
if (depositState == tbtc.Deposit.State.ACTIVE && ! inVendingMachine) {
yield call([deposit, deposit.mintTBTC])
}
// TODO Fork on active vs await
yield put(navigateTo('/deposit/' + depositAddress + nextStep))
break
// Funding failure states
case tbtc.Deposit.State.FRAUD_AWAITING_BTC_FUNDING_PROOF:
case tbtc.Deposit.State.FAILED_SETUP:
// TODO Update deposit state to reflect situation.
break
default:
throw new Error(`Unexpected state ${depositState.toNumber()}.`)
}
// Here, we need to look at the logs. getDepositBtcAddress submits a
// signed tx to Metamask, so that's not what we need.
//
// Then, we need to dispatch an update to the state.
//yield put({ type: })
}
export function* restoreDepositState() {
/** @type {TBTC} */
const tbtc = yield TBTCLoaded
const DEPOSIT_STEP_MAP = {};
DEPOSIT_STEP_MAP[tbtc.Deposit.State.AWAITING_BTC_FUNDING_PROOF] = "/pay"
DEPOSIT_STEP_MAP[tbtc.Deposit.State.ACTIVE] = "/congratulations"
yield* restoreState(DEPOSIT_STEP_MAP, "deposit")
}
export function* restoreRedemptionState() {
/** @type {TBTC} */
const tbtc = yield TBTCLoaded
const REDEMPTION_STEP_MAP = {};
REDEMPTION_STEP_MAP[tbtc.Deposit.State.AWAITING_BTC_FUNDING_PROOF] = "/pay"
REDEMPTION_STEP_MAP[tbtc.Deposit.State.ACTIVE] = "/redemption"
REDEMPTION_STEP_MAP[tbtc.Deposit.State.AWAITING_WITHDRAWAL_SIGNATURE] = "/redemption/signing"
REDEMPTION_STEP_MAP[tbtc.Deposit.State.AWAITING_WITHDRAWAL_PROOF] = "/redemption/confirming"
REDEMPTION_STEP_MAP[tbtc.Deposit.State.REDEEMED] = "/redemption/congratulations"
yield* restoreState(REDEMPTION_STEP_MAP, "redemption")
}
export function* requestADeposit() {
/** @type {TBTC} */
const tbtc = yield TBTCLoaded
// call Keep to request a deposit
yield put({ type: DEPOSIT_REQUEST_BEGIN })
/** @type {Deposit} */
let deposit
try {
deposit = yield call([tbtc.Deposit, tbtc.Deposit.withSatoshiLotSize], new BN(100000))
} catch (err) {
if (err.message.includes(METAMASK_TX_DENIED_ERROR)) return
throw err
}
yield put({ type: DEPOSIT_REQUEST_METAMASK_SUCCESS })
yield put({
type: DEPOSIT_REQUEST_SUCCESS,
payload: {
depositAddress: deposit.address,
}
})
yield put({
type: DEPOSIT_RESOLVED,
payload: {
deposit,
}
})
const btcAddress = yield deposit.bitcoinAddress
yield put({
type: DEPOSIT_BTC_ADDRESS,
payload: {
btcAddress,
}
})
const lotInSatoshis = yield call([deposit, deposit.getSatoshiLotSize])
const signerFeeTbtc = yield call([deposit.contract, deposit.contract.signerFee])
const signerFeeInSatoshis = signerFeeTbtc.div(tbtc.satoshisPerTbtc)
yield put({
type: DEPOSIT_BTC_AMOUNTS,
payload: {
lotInSatoshis,
signerFeeInSatoshis,
}
})
// goto
yield put(navigateTo('/deposit/' + deposit.address + '/pay'))
}
export function* autoSubmitDepositProof() {
/** @type Deposit */
const deposit = yield select(state => state.deposit.deposit)
const autoSubmission = deposit.autoSubmit()
const fundingTx = yield autoSubmission.fundingTransaction
yield put({
// FIXME This is incorrect, at this point the transaction is _submitted_
// FIXME but it is not yet _mined_, i.e. we only know for a fact that it
// FIXME is in the mempool.
type: BTC_TX_MINED,
payload: {
btcDepositedTxID: fundingTx.transactionID,
fundingOutputIndex: fundingTx.outputPosition
}
})
// wait a certain number of confirmations on this step
yield put({
type: BTC_TX_CONFIRMED_WAIT
})
yield autoSubmission.fundingConfirmations
// when it's finally sufficiently confirmed, dispatch the txid
yield put({
type: BTC_TX_CONFIRMED
// TODO Which transaction?
})
// emit a notification
// FIXME This should be a reducer on BTC_TX_CONFIRMED.
yield put(notifyTransactionConfirmed())
// goto
yield put(navigateTo('/deposit/' + deposit.address + '/prove'))
yield put({ type: DEPOSIT_PROVE_BTC_TX_BEGIN })
const proofTransaction = yield autoSubmission.proofTransaction
yield put({
type: DEPOSIT_PROVE_BTC_TX_SUCCESS,
payload: {
proofTransaction,
}
})
yield call([deposit, deposit.mintTBTC])
// goto
yield put(navigateTo('/deposit/' + deposit.address + '/congratulations'))
}