diff --git a/solidity/dashboard/src/App.js b/solidity/dashboard/src/App.js index 4911732b59..0f2fd8854a 100644 --- a/solidity/dashboard/src/App.js +++ b/solidity/dashboard/src/App.js @@ -13,15 +13,15 @@ import Footer from "./components/Footer" const App = () => ( - - - - + + + + - - - - + + + + ) diff --git a/solidity/dashboard/src/actions/messages.js b/solidity/dashboard/src/actions/messages.js index 8bfa1fca66..c06dca8e46 100644 --- a/solidity/dashboard/src/actions/messages.js +++ b/solidity/dashboard/src/actions/messages.js @@ -20,6 +20,7 @@ export class Message { content type sticky + classes } export const showMessage = (options) => { diff --git a/solidity/dashboard/src/components/Message.jsx b/solidity/dashboard/src/components/Message.jsx index 82ec3cfc53..be289f6296 100644 --- a/solidity/dashboard/src/components/Message.jsx +++ b/solidity/dashboard/src/components/Message.jsx @@ -4,16 +4,25 @@ import Banner from "./Banner" import { showMessage, closeMessage } from "../actions/messages" import { connect } from "react-redux" import { ViewInBlockExplorer } from "./ViewInBlockExplorer" -import * as Icons from "./Icons" +import LiquidityRewardsEarnedMessage from "./messages/LiquidityRewardsEarnedMessage" +import LPTokensInWalletMessage from "./messages/LPTokensInWalletMessage" +import WalletMessage from "./messages/WalletMessage" +import PendingActionMessage from "./messages/PendingActionMessage" +import SuccessMessage from "./messages/SuccessMessage" +import ErrorMessage from "./messages/ErrorMessage" +import DelegationAlreadyCopiedMessage from "./messages/DelegationAlreadyCopiedMessage" export const MessagesContext = React.createContext({}) export const messageType = { - SUCCESS: { icon: Icons.Success, iconClassName: "success-icon green" }, - ERROR: { icon: Icons.Warning }, - PENDING_ACTION: { icon: Icons.Time }, - INFO: { icon: Icons.Question }, - WALLET: { icon: Icons.Wallet, iconClassName: "wallet-icon grey-50" }, + SUCCESS: SuccessMessage, + ERROR: ErrorMessage, + PENDING_ACTION: PendingActionMessage, + INFO: LiquidityRewardsEarnedMessage, + WALLET: WalletMessage, + NEW_LP_TOKENS_IN_WALLET: LPTokensInWalletMessage, + LIQUIDITY_REWARDS_EARNED: LiquidityRewardsEarnedMessage, + DELEGATION_ALREADY_COPIED: DelegationAlreadyCopiedMessage, } const messageTransitionTimeoutInMs = 500 @@ -23,8 +32,19 @@ class MessagesComponent extends React.Component { this.props.showMessage(options) } - onMessageClose = (message) => { - this.props.closeMessage(message.id) + onMessageClose = (messageId) => { + this.props.closeMessage(messageId) + } + + renderSpecificMessageType = (message) => { + const SpecificComponent = message.messageType + return ( + + ) } render() { @@ -43,11 +63,7 @@ class MessagesComponent extends React.Component { key={message.id} classNames="banner" > - + {this.renderSpecificMessageType(message)} ))} @@ -74,40 +90,49 @@ export const Messages = connect( const closeMessageTimeoutInMs = 3250 -const Message = ({ message, onMessageClose }) => { +export const Message = ({ + icon, + sticky, + title, + content, + classes, + withTransactionHash, + txHash, + messageId, + onMessageClose, +}) => { useEffect(() => { - if (!message.sticky) { + if (!sticky) { const timeout = setTimeout( - () => onMessageClose(message), + () => onMessageClose(messageId), closeMessageTimeoutInMs ) return () => clearTimeout(timeout) } - }, [message, onMessageClose]) + }, [sticky, messageId, onMessageClose]) return (
- +
- {message.title} - {message.content && ( - {message.content} + {title} + {content && ( + + {content} + )} - {message.withTransactionHash && ( + {withTransactionHash && ( )}
- onMessageClose(message)} /> + onMessageClose(messageId)} />
) diff --git a/solidity/dashboard/src/components/SelectedWalletModal.jsx b/solidity/dashboard/src/components/SelectedWalletModal.jsx index 10d5919752..1058fcb6c2 100644 --- a/solidity/dashboard/src/components/SelectedWalletModal.jsx +++ b/solidity/dashboard/src/components/SelectedWalletModal.jsx @@ -73,9 +73,11 @@ const SelectedWalletModal = ({ handleError(error) } showMessage({ - type: messageType.ERROR, - title: error.message, - sticky: true, + messageType: messageType.ERROR, + messageProps: { + content: error.message, + sticky: true, + }, }) }) } @@ -106,7 +108,13 @@ const SelectedWalletModal = ({ closeModal() } catch (error) { handleError(error) - showMessage({ type: messageType.ERROR, title: error.message }) + showMessage({ + messageType: messageType.ERROR, + messageProps: { + content: error.message, + sticky: true, + }, + }) } } diff --git a/solidity/dashboard/src/components/messages/DelegationAlreadyCopiedMessage.jsx b/solidity/dashboard/src/components/messages/DelegationAlreadyCopiedMessage.jsx new file mode 100644 index 0000000000..fb7a0b410c --- /dev/null +++ b/solidity/dashboard/src/components/messages/DelegationAlreadyCopiedMessage.jsx @@ -0,0 +1,32 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +const DelegationAlreadyCopiedMessage = ({ + sticky, + withTransactionHash, + txHash, + messageId, + onMessageClose, +}) => { + const icon = Icons.Success + const title = `Delegation already copied` + const classes = { + iconClassName: "success-icon green", + } + + return ( + + ) +} + +export default React.memo(DelegationAlreadyCopiedMessage) diff --git a/solidity/dashboard/src/components/messages/ErrorMessage.jsx b/solidity/dashboard/src/components/messages/ErrorMessage.jsx new file mode 100644 index 0000000000..293e5856e7 --- /dev/null +++ b/solidity/dashboard/src/components/messages/ErrorMessage.jsx @@ -0,0 +1,21 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +const ErrorMessage = ({ sticky, content, messageId, onMessageClose }) => { + const icon = Icons.Warning + const title = `Error` + + return ( + + ) +} + +export default React.memo(ErrorMessage) diff --git a/solidity/dashboard/src/components/messages/InfoMessage.jsx b/solidity/dashboard/src/components/messages/InfoMessage.jsx new file mode 100644 index 0000000000..11c07e4289 --- /dev/null +++ b/solidity/dashboard/src/components/messages/InfoMessage.jsx @@ -0,0 +1,22 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +// TODO: use info message somewhere or delete this component completely +const InfoMessage = ({ sticky, content, messageId, onMessageClose }) => { + const icon = Icons.MoreInfo + const title = `Info` + + return ( + + ) +} + +export default React.memo(InfoMessage) diff --git a/solidity/dashboard/src/components/messages/LPTokensInWalletMessage.jsx b/solidity/dashboard/src/components/messages/LPTokensInWalletMessage.jsx new file mode 100644 index 0000000000..305ab8825a --- /dev/null +++ b/solidity/dashboard/src/components/messages/LPTokensInWalletMessage.jsx @@ -0,0 +1,33 @@ +import React from "react" +import * as Icons from "../Icons" +import { Message } from "../Message" +import { Link } from "react-router-dom" + +const LPTokensInWalletMessage = ({ + liquidityRewardPairName, + sticky, + messageId, + onMessageClose, +}) => { + const icon = Icons.Wallet + const title = `[${liquidityRewardPairName}] Your wallet has LP Tokens!` + const content = Deposit them and earn rewards + const classes = { + bannerDescription: "m-0", + iconClassName: "wallet-icon grey-50", + } + + return ( + + ) +} + +export default React.memo(LPTokensInWalletMessage) diff --git a/solidity/dashboard/src/components/messages/LiquidityRewardsEarnedMessage.jsx b/solidity/dashboard/src/components/messages/LiquidityRewardsEarnedMessage.jsx new file mode 100644 index 0000000000..cbbd99b280 --- /dev/null +++ b/solidity/dashboard/src/components/messages/LiquidityRewardsEarnedMessage.jsx @@ -0,0 +1,33 @@ +import React from "react" +import { Message } from "../Message" +import * as Icons from "../Icons" +import { Link } from "react-router-dom" + +const LiquidityRewardsEarnedMessage = ({ + liquidityRewardPairName, + sticky, + messageId, + onMessageClose, +}) => { + const icon = Icons.Rewards + const title = `[${liquidityRewardPairName}] You've earned rewards!` + const content = View your balance + const classes = { + bannerDescription: "m-0", + iconClassName: "reward-icon brand-violet", + } + + return ( + + ) +} + +export default React.memo(LiquidityRewardsEarnedMessage) diff --git a/solidity/dashboard/src/components/messages/PendingActionMessage.jsx b/solidity/dashboard/src/components/messages/PendingActionMessage.jsx new file mode 100644 index 0000000000..1c936b913e --- /dev/null +++ b/solidity/dashboard/src/components/messages/PendingActionMessage.jsx @@ -0,0 +1,28 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +const PendingActionMessage = ({ + sticky, + withTransactionHash, + txHash, + messageId, + onMessageClose, +}) => { + const icon = Icons.Time + const title = `Pending transaction` + + return ( + + ) +} + +export default React.memo(PendingActionMessage) diff --git a/solidity/dashboard/src/components/messages/SuccessMessage.jsx b/solidity/dashboard/src/components/messages/SuccessMessage.jsx new file mode 100644 index 0000000000..9cbda2cb02 --- /dev/null +++ b/solidity/dashboard/src/components/messages/SuccessMessage.jsx @@ -0,0 +1,32 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +const SuccessMessage = ({ + sticky, + withTransactionHash, + txHash, + messageId, + onMessageClose, +}) => { + const icon = Icons.Success + const title = `Success!` + const classes = { + iconClassName: "success-icon green", + } + + return ( + + ) +} + +export default React.memo(SuccessMessage) diff --git a/solidity/dashboard/src/components/messages/WalletMessage.jsx b/solidity/dashboard/src/components/messages/WalletMessage.jsx new file mode 100644 index 0000000000..0bdd644bb1 --- /dev/null +++ b/solidity/dashboard/src/components/messages/WalletMessage.jsx @@ -0,0 +1,24 @@ +import * as Icons from "../Icons" +import { Message } from "../Message" +import React from "react" + +const WalletMessage = ({ sticky, messageId, onMessageClose }) => { + const icon = Icons.Wallet + const title = `Waiting for the transaction confirmation...` + const classes = { + iconClassName: "wallet-icon grey-50", + } + + return ( + + ) +} + +export default React.memo(WalletMessage) diff --git a/solidity/dashboard/src/contracts.js b/solidity/dashboard/src/contracts.js index cce521d929..27058a19a5 100644 --- a/solidity/dashboard/src/contracts.js +++ b/solidity/dashboard/src/contracts.js @@ -170,15 +170,11 @@ export let Web3Loaded = Web3Deferred.promise export let ContractsLoaded = ContractsDeferred.promise export const resolveWeb3Deferred = (web3) => { - Web3Deferred = new Deferred() Web3Deferred.resolve(web3) - Web3Loaded = Web3Deferred.promise } export const resovleContractsDeferred = (contracts) => { - ContractsDeferred = new Deferred() ContractsDeferred.resolve(contracts) - ContractsLoaded = ContractsDeferred.promise } export async function getContracts(web3) { diff --git a/solidity/dashboard/src/css/banner.less b/solidity/dashboard/src/css/banner.less index 57024422f5..4477136cda 100644 --- a/solidity/dashboard/src/css/banner.less +++ b/solidity/dashboard/src/css/banner.less @@ -17,6 +17,10 @@ line-height: 1rem; color: @color-grey-60; margin-bottom: 0.75rem; + + &.m-0 { + margin: 0!important; + } } &__action { diff --git a/solidity/dashboard/src/css/commons.less b/solidity/dashboard/src/css/commons.less index 3e900c20d0..bd302a1221 100644 --- a/solidity/dashboard/src/css/commons.less +++ b/solidity/dashboard/src/css/commons.less @@ -316,6 +316,14 @@ svg.wallet-icon { } } +svg.reward-icon { + &.brand-violet { + path { + fill: @color-brand-violet; + } + } +} + svg.time-icon, svg.success-icon, svg.keep-outline, svg.tbtc-icon, svg.reward-icon { &--black { path { diff --git a/solidity/dashboard/src/pages/liquidity/LiquidityPage.jsx b/solidity/dashboard/src/pages/liquidity/LiquidityPage.jsx index 73ed5ace36..fa3884f643 100644 --- a/solidity/dashboard/src/pages/liquidity/LiquidityPage.jsx +++ b/solidity/dashboard/src/pages/liquidity/LiquidityPage.jsx @@ -32,11 +32,13 @@ const LiquidityPage = ({ headerTitle }) => { const address = useWeb3Address() useEffect(() => { - dispatch({ - type: "liquidity_rewards/fetch_data_request", - payload: { address }, - }) - }, [dispatch, address]) + if (isConnected) { + dispatch({ + type: "liquidity_rewards/fetch_data_request", + payload: { address }, + }) + } + }, [dispatch, address, isConnected]) useEffect(() => { dispatch({ diff --git a/solidity/dashboard/src/reducers/liquidity-rewards.js b/solidity/dashboard/src/reducers/liquidity-rewards.js index fdd6c9e020..8f7fe347fe 100644 --- a/solidity/dashboard/src/reducers/liquidity-rewards.js +++ b/solidity/dashboard/src/reducers/liquidity-rewards.js @@ -7,6 +7,7 @@ const liquidityPairInitialData = { reward: 0, wrappedTokenBalance: 0, lpBalance: 0, + lastNotificationRewardAmount: "0", isFetching: false, error: null, } @@ -109,6 +110,14 @@ const liquidityRewardsReducer = (state = initialState, action) => { apy: restPayload.apy, }, } + case `liquidity_rewards/${liquidityRewardPairName}_wrapped_token_balance_updated`: + return { + ...state, + [liquidityRewardPairName]: { + ...state[liquidityRewardPairName], + wrappedTokenBalance: restPayload.wrappedTokenBalance.toString(), + }, + } case `liquidity_rewards/${liquidityRewardPairName}_fetch_apy_start`: return { ...state, @@ -134,6 +143,23 @@ const liquidityRewardsReducer = (state = initialState, action) => { isAPYFetching: false, }, } + case `liquidity_rewards/${liquidityRewardPairName}_reward_updated`: + return { + ...state, + [liquidityRewardPairName]: { + ...state[liquidityRewardPairName], + reward: restPayload.reward, + }, + } + case `liquidity_rewards/${liquidityRewardPairName}_last_notification_reward_amount_updated`: + return { + ...state, + [liquidityRewardPairName]: { + ...state[liquidityRewardPairName], + lastNotificationRewardAmount: + restPayload.lastNotificationRewardAmount, + }, + } default: return state } diff --git a/solidity/dashboard/src/sagas/copy-stake.js b/solidity/dashboard/src/sagas/copy-stake.js index 9589365bc5..647525301a 100644 --- a/solidity/dashboard/src/sagas/copy-stake.js +++ b/solidity/dashboard/src/sagas/copy-stake.js @@ -55,10 +55,11 @@ function* copyStake(action) { } catch (error) { yield put( showMessage({ - type: messageType.ERROR, - title: "Error", - subtitle: error.message, - sticky: true, + messageType: messageType.ERROR, + messageProps: { + content: error.message, + sticky: true, + }, }) ) yield put({ type: "copy-stake/copy-stake_failure", payload: error }) @@ -90,11 +91,12 @@ function* safeCopyStake(operator) { yield put( showCreatedMessage({ id: txHash, - title: "Your delegation has been already copied.", - content: txHash, - type: messageType.SUCCESS, - sticky: true, - withTransactionHash: true, + messageType: messageType.DELEGATION_ALREADY_COPIED, + messageProps: { + content: txHash, + withTransactionHash: true, + sticky: true, + }, }) ) } diff --git a/solidity/dashboard/src/sagas/liquidity-rewards.js b/solidity/dashboard/src/sagas/liquidity-rewards.js index 5f0a4a7e7a..41fcd0ba01 100644 --- a/solidity/dashboard/src/sagas/liquidity-rewards.js +++ b/solidity/dashboard/src/sagas/liquidity-rewards.js @@ -1,5 +1,18 @@ -import { takeLatest, takeEvery, fork, call, put } from "redux-saga/effects" -import { submitButtonHelper, logError, getLPRewardsWrapper } from "./utils" +import { + takeLatest, + takeEvery, + fork, + call, + put, + select, + delay, +} from "redux-saga/effects" +import { + submitButtonHelper, + logError, + getLPRewardsWrapper, + getWeb3Context, +} from "./utils" import { sendTransaction } from "./web3" import { LiquidityRewardsFactory } from "../services/liquidity-rewards" import { gt, percentageOf, eq } from "../utils/arithmetics.utils" @@ -7,6 +20,10 @@ import { LIQUIDITY_REWARD_PAIRS } from "../constants/constants" import { getWsUrl } from "../connectors/utils" import { initializeWeb3, createLPRewardsContract } from "../contracts" /** @typedef { import("../services/liquidity-rewards").LiquidityRewards} LiquidityRewards */ +import BigNumber from "bignumber.js" +import { showMessage } from "../actions/messages" +import { messageType } from "../components/Message" +import moment from "moment" function* fetchAllLiquidtyRewardsData(action) { const { address } = action.payload @@ -90,6 +107,76 @@ export function* watchFetchLiquidityRewardsData() { ) } +export function* watchLiquidityRewardNotifications() { + const { + eth: { defaultAccount }, + } = yield getWeb3Context() + + // for the first iteration update the lastNotificationRewardAmount variable in redux without showing message + let displayMessage = false + while (true) { + for (const pairName of Object.keys(LIQUIDITY_REWARD_PAIRS)) { + yield fork( + processLiquidityRewardEarnedNotification, + pairName, + defaultAccount, + displayMessage + ) + } + displayMessage = true + yield delay(moment.duration(7, "minutes").asMilliseconds()) // every 7 minutes + } +} + +function* processLiquidityRewardEarnedNotification( + liquidityRewardPairName, + address, + displayMessage +) { + const liquidityRewardPair = LIQUIDITY_REWARD_PAIRS[liquidityRewardPairName] + + /** @type LiquidityRewards */ + const LiquidityRewards = yield getLPRewardsWrapper(liquidityRewardPair) + const { liquidityRewards } = yield select() + const lastNotificationRewardAmount = new BigNumber( + liquidityRewards[liquidityRewardPairName].lastNotificationRewardAmount + ) + const currentReward = yield call( + [LiquidityRewards, LiquidityRewards.rewardBalance], + address + ) + // show the notification if the rewardBalance from LPRewardsContract is greater + // than the reward amount that was last time the notification was displayed + if (gt(currentReward, lastNotificationRewardAmount) && displayMessage) { + yield put( + showMessage({ + messageType: messageType.LIQUIDITY_REWARDS_EARNED, + messageProps: { + liquidityRewardPairName: liquidityRewardPairName, + sticky: true, + }, + }) + ) + + yield put({ + type: `liquidity_rewards/${liquidityRewardPairName}_reward_updated`, + payload: { + liquidityRewardPairName, + reward: currentReward, + }, + }) + } + + // save last notification reward amount for future comparisons + yield put({ + type: `liquidity_rewards/${liquidityRewardPairName}_last_notification_reward_amount_updated`, + payload: { + liquidityRewardPairName, + lastNotificationRewardAmount: currentReward, + }, + }) +} + function* stakeTokens(action) { const { contractName, address, amount, pool } = action.payload diff --git a/solidity/dashboard/src/sagas/subscriptions.js b/solidity/dashboard/src/sagas/subscriptions.js index af70a77d8e..87cd7d19ff 100644 --- a/solidity/dashboard/src/sagas/subscriptions.js +++ b/solidity/dashboard/src/sagas/subscriptions.js @@ -12,6 +12,8 @@ import { isSameEthAddress } from "../utils/general.utils" import { getEventsFromTransaction, ZERO_ADDRESS } from "../utils/ethereum.utils" import { LIQUIDITY_REWARD_PAIRS } from "../constants/constants" /** @typedef { import("../services/liquidity-rewards").LiquidityRewards} LiquidityRewards */ +import { showMessage } from "../actions/messages" +import { messageType } from "../components/Message" export function* subscribeToKeepTokenTransferEvent() { yield take("keep-token/balance_request_success") @@ -758,6 +760,10 @@ function* observeWrappedTokenMintAndBurnTx(liquidityRewardPair) { /** @type LiquidityRewards */ const LiquidityRewards = yield getLPRewardsWrapper(liquidityRewardPair) + const { + eth: { defaultAccount }, + } = yield getWeb3Context() + const contractEventCahnnel = yield call( createSubcribeToContractEventChannel, LiquidityRewards.wrappedToken, @@ -767,6 +773,7 @@ function* observeWrappedTokenMintAndBurnTx(liquidityRewardPair) { while (true) { try { const { + transactionHash, returnValues: { from, to }, } = yield take(contractEventCahnnel) @@ -777,6 +784,49 @@ function* observeWrappedTokenMintAndBurnTx(liquidityRewardPair) { if (from === ZERO_ADDRESS || to === ZERO_ADDRESS) { yield* updateAPY(LiquidityRewards, liquidityRewardPair.name) } + + // If the 'to' address is equal to the address of the connected wallet + // then it means that LP tokens are transferred to this address so we are + // displaying the proper notification + if ( + isSameEthAddress(to, defaultAccount) && + liquidityRewardPair.label !== LIQUIDITY_REWARD_PAIRS.KEEP_ONLY.label + ) { + yield put( + showMessage({ + messageType: messageType.NEW_LP_TOKENS_IN_WALLET, + messageProps: { + liquidityRewardPairName: liquidityRewardPair.label, + sticky: true, + }, + }) + ) + + const eventsToCheck = [ + [ + LiquidityRewards.LPRewardsContract, + LiquidityRewards.depositWithdrawnEventName, + ], + ] + + const emittedEvents = yield call( + getEventsFromTransaction, + eventsToCheck, + transactionHash + ) + + // Fetch wrappedTokenBalance value only when depositWithdrawnEventName event was not previously emitted (so + // in other words when user did not withdraw all on the dApp, but still got some lp tokens transferred + // to his wallet). If the user clicks withdraw all the wrappedTokenBalance will be updated on the redux + // side (`liquidity_rewards/${liquidityRewardPairName}_withdrawn` case) so we don't need to update it here. + if (!emittedEvents[LiquidityRewards.depositWithdrawnEventName]) { + yield* updateWrappedTokenBalance( + LiquidityRewards, + liquidityRewardPair.name, + defaultAccount + ) + } + } } catch (error) { console.error(`Failed subscribing to Transfer event`, error) contractEventCahnnel.close() @@ -807,17 +857,37 @@ function* updateAPY( }) } +function* updateWrappedTokenBalance( + LiquidityRewards, + liquidityRewardPairName, + address +) { + // Fetching balance of liquidity token for a given uniswap pair. + const wrappedTokenBalance = yield call( + [LiquidityRewards, LiquidityRewards.wrappedTokenBalance], + address + ) + + yield put({ + type: `liquidity_rewards/${liquidityRewardPairName}_wrapped_token_balance_updated`, + payload: { + wrappedTokenBalance, + liquidityRewardPairName, + }, + }) +} + export function* subscribeToLiquidityRewardsEvents() { for (const [pairName, value] of Object.entries(LIQUIDITY_REWARD_PAIRS)) { yield fork( function* (liquidityRewardPair) { + yield fork(observeWrappedTokenMintAndBurnTx, liquidityRewardPair) yield take( `liquidity_rewards/${liquidityRewardPair.name}_fetch_data_success` ) yield fork(observeLiquidityTokenStakedEvent, liquidityRewardPair) yield fork(observeLiquidityTokenWithdrawnEvent, liquidityRewardPair) yield fork(observeLiquidityRewardPaidEvent, liquidityRewardPair) - yield fork(observeWrappedTokenMintAndBurnTx, liquidityRewardPair) }, { name: pairName, diff --git a/solidity/dashboard/src/sagas/web3.js b/solidity/dashboard/src/sagas/web3.js index 4b2b47cbfd..db1671c12c 100644 --- a/solidity/dashboard/src/sagas/web3.js +++ b/solidity/dashboard/src/sagas/web3.js @@ -2,7 +2,6 @@ import { eventChannel, END, buffers } from "redux-saga" import { take, takeEvery, put, call } from "redux-saga/effects" import { getContractsContext, submitButtonHelper } from "./utils" import { - Message, showCreatedMessage, showMessage, closeMessage, @@ -15,32 +14,37 @@ function createTransactionEventChannel( args = [], options = {} ) { - const infoMessage = Message.create({ - title: "Waiting for the transaction confirmation...", - type: messageType.WALLET, - sticky: true, + const showWalletMessage = showMessage({ + messageType: messageType.WALLET, + messageProps: { + sticky: true, + }, }) const emitter = contract.methods[method](...args).send(options) let txHashCache + let showPendingActionMessage + let showSuccessMessage + let showErrorMessage + return eventChannel((emit) => { - emit(showCreatedMessage(infoMessage)) + emit(showWalletMessage) emitter .once("transactionHash", (txHash) => { - emit(closeMessage(infoMessage.id)) + emit(closeMessage(showWalletMessage.payload.id)) txHashCache = txHash - emit( - showCreatedMessage({ - id: txHash, - title: "Pending transaction", - sticky: true, - type: messageType.PENDING_ACTION, + showPendingActionMessage = showCreatedMessage({ + id: txHash, + messageType: messageType.PENDING_ACTION, + messageProps: { + txHash: txHash, withTransactionHash: true, - txHash, - }) - ) + sticky: true, + }, + }) + emit(showPendingActionMessage) }) .once("receipt", (receipt) => { let id @@ -49,30 +53,30 @@ function createTransactionEventChannel( } else { id = txHashCache } - emit(closeMessage(infoMessage.id)) + emit(closeMessage(showWalletMessage.payload.id)) emit(closeMessage(id)) - emit( - showMessage({ - title: "Success!", - sticky: true, - type: messageType.SUCCESS, - withTransactionHash: true, + showSuccessMessage = showMessage({ + messageType: messageType.SUCCESS, + messageProps: { txHash: id, - }) - ) + withTransactionHash: true, + sticky: true, + }, + }) + emit(showSuccessMessage) emit(END) }) .once("error", (error, receipt) => { - emit(closeMessage(infoMessage.id)) + emit(closeMessage(showWalletMessage.payload.id)) emit(closeMessage(txHashCache)) - emit( - showMessage({ - title: "Error", + showErrorMessage = showMessage({ + messageType: messageType.ERROR, + messageProps: { content: error.message, - type: messageType.ERROR, sticky: true, - }) - ) + }, + }) + emit(showErrorMessage) emit(new Error()) })