diff --git a/src/actions/layout.ts b/src/actions/layout.ts index de56394..0b9b28a 100644 --- a/src/actions/layout.ts +++ b/src/actions/layout.ts @@ -10,15 +10,27 @@ export interface LayoutFlipCardAction { flipped: boolean } +export const LAYOUT_TOGGLE_DEBUG = "LAYOUT_TOGGLE_DEBUG"; +export interface LayoutToggleDebugAction { + type: typeof LAYOUT_TOGGLE_DEBUG + open: boolean +} + export type LayoutActions = LayoutToggleSidebarAction | - LayoutFlipCardAction; + LayoutFlipCardAction | + LayoutToggleDebugAction; export const toggleSidebar = (open: boolean): LayoutToggleSidebarAction => ({ type: LAYOUT_TOGGLE_SIDEBAR, open, }); +export const toggleDebug = (open: boolean): LayoutToggleDebugAction => ({ + type: LAYOUT_TOGGLE_DEBUG, + open, +}); + export const flipCard = (flipped: boolean): LayoutFlipCardAction => ({ type: LAYOUT_FLIP_CARD, flipped, diff --git a/src/actions/redeem.ts b/src/actions/redeem.ts index dfd0cd4..31b0bca 100644 --- a/src/actions/redeem.ts +++ b/src/actions/redeem.ts @@ -6,12 +6,7 @@ import { sha3 } from "web3-utils"; import { recoverTypedSignature } from 'eth-sig-util'; import { Web3Type } from "../actions/web3"; import { KECCAK_EMPTY_STRING } from '../utils'; - -const sleep = (ms: number) => { - return new Promise(resolve => { - window.setTimeout(resolve, ms); - }); -} +import { debug } from "./debug"; interface RedeemMessage { receiver: string @@ -22,7 +17,7 @@ interface RedeemMessage { interface SignRedeemResponse { sig: string - address: string + signer: string } export const ERROR_REDEEMING = "ERROR_REDEEMING"; @@ -105,6 +100,11 @@ export const redeem = (bucketAddress: string, recipientAddress: string, cleanCod const bucket = newBucketContract(bucketAddress); const account = state.web3.account; + if (account === undefined) { + //FIXME: show error? + return; + } + const block = await config.web3!.eth.getBlock("latest"); const message = { @@ -182,7 +182,7 @@ async function signRedeem(web3Type: Web3Type, contractAddress: string, signer: s }; if (web3Type === Web3Type.Status) { - return signWithKeycard(signer, data); + return signWithKeycard(data); } else { return signWithWeb3(signer, data); } diff --git a/src/actions/redeemable.ts b/src/actions/redeemable.ts index f6ed7f6..fadc4c9 100644 --- a/src/actions/redeemable.ts +++ b/src/actions/redeemable.ts @@ -1,4 +1,6 @@ import { RootState } from '../reducers'; +import ERC20BucketFactory from '../embarkArtifacts/contracts/ERC20BucketFactory'; +import NFTBucketFactory from '../embarkArtifacts/contracts/NFTBucketFactory'; import ERC20Bucket from '../embarkArtifacts/contracts/ERC20Bucket'; import Bucket from '../embarkArtifacts/contracts/Bucket'; import IERC20Detailed from '../embarkArtifacts/contracts/IERC20Detailed'; @@ -6,6 +8,7 @@ import IERC721Metadata from '../embarkArtifacts/contracts/IERC721Metadata'; import { config } from "../config"; import { Dispatch } from 'redux'; import { ZERO_ADDRESS } from "../utils"; +import { debug } from "./debug"; export const ERROR_REDEEMABLE_NOT_FOUND = "ERROR_REDEEMABLE_NOT_FOUND"; export interface ErrRedeemableNotFound { @@ -176,6 +179,10 @@ export const newERC20BucketContract = (address: string) => { export const loadRedeemable = (bucketAddress: string, recipientAddress: string) => { return async (dispatch: Dispatch, getState: () => RootState) => { + dispatch(debug(`erc20 factory address: ${ERC20BucketFactory.address}`)); + dispatch(debug(`nft factory address: ${NFTBucketFactory.address}`)); + dispatch(debug(`bucket address: ${bucketAddress}`)); + dispatch(debug(`recipient address: ${recipientAddress}`)); dispatch(loadingRedeemable(bucketAddress, recipientAddress)); const bucket = newBucketContract(bucketAddress); bucket.methods.expirationTime().call().then((expirationTime: number) => { @@ -231,9 +238,11 @@ export const loadERC20Token = (bucket: any, data: string, recipient: string) => const symbol = await erc20.methods.symbol().call(); const decimals = parseInt(await erc20.methods.decimals().call()); + dispatch(debug(`erc20 token: ${symbol} ${address}`)); dispatch(tokenLoaded({symbol, decimals})); }).catch((err: string) => { //FIXME: manage error + dispatch(debug(`error loading token: ${err})`)); console.error("ERROR: ", err); }) } @@ -251,6 +260,8 @@ export const loadNFTToken = (bucket: any, data: string, recipient: string) => { dispatch(tokenLoaded({symbol, tokenURI, metadata: undefined})); dispatch(loadingTokenMetadata(address, recipient)) + dispatch(debug(`nft token: ${symbol} ${address}`)); + fetch(tokenURI) .then(response => response.json()) .then(data => { @@ -261,10 +272,12 @@ export const loadNFTToken = (bucket: any, data: string, recipient: string) => { })); }) .catch((err: string) => { + dispatch(debug(`error loading metadata: ${err})`)); //FIXME: manage error console.error("ERROR: ", err); }); }).catch((err: string) => { + dispatch(debug(`error loading token: ${err})`)); //FIXME: manage error console.error("ERROR: ", err); }) diff --git a/src/actions/web3.ts b/src/actions/web3.ts index 9147b19..33ff54c 100644 --- a/src/actions/web3.ts +++ b/src/actions/web3.ts @@ -4,6 +4,7 @@ import { Dispatch, } from 'redux'; import { RootState } from '../reducers'; +import { debug } from "./debug"; export const VALID_NETWORK_NAME = "Ropsten"; export const VALID_NETWORK_ID = 3; @@ -86,6 +87,7 @@ export const initializeWeb3 = () => { return; } + dispatch(debug(`network id: ${id}`)) dispatch(web3NetworkIDLoaded(id)) dispatch(loadAddress()); }); @@ -98,6 +100,7 @@ export const initializeWeb3 = () => { const t: Web3Type = w.ethereum.isStatus ? Web3Type.Status : Web3Type.Generic; dispatch(web3Initialized(t)); config.web3!.eth.net.getId().then((id: number) => { + dispatch(debug(`network id: ${id}`)) dispatch(web3NetworkIDLoaded(id)) dispatch(loadAddress()); }) @@ -114,6 +117,7 @@ export const initializeWeb3 = () => { const loadAddress = () => { return (dispatch: Dispatch, getState: () => RootState) => { config.web3!.eth.getAccounts().then((accounts: string[]) => { + dispatch(debug(`current account: ${accounts[0]}`)); dispatch(accountLoaded(accounts[0])); }); }; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 01d7cfc..44f5c9e 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -9,19 +9,6 @@ import { import { Web3Type } from "../actions/web3"; import "../styles/Layout.scss"; -const web3Type = (t: Web3Type) => { - switch (t) { - case Web3Type.None: - return "not a web3 browser"; - case Web3Type.Generic: - return "generic web3 browser"; - case Web3Type.Remote: - return "remote web3 node"; - case Web3Type.Status: - return "status web3 browser"; - } -} - export default function(ownProps: any) { const props = useSelector((state: RootState) => { return { @@ -40,20 +27,11 @@ export default function(ownProps: any) { }); return
-
-
- Network ID: {props.networkID}
- Factory: {ERC20BucketFactory.address}
- Account: {props.account}
- Web3 Type: {web3Type(props.type)}
-
-
- {props.error &&
{props.error}
} - {!props.initialized &&
+ {!props.error && !props.initialized &&
initializing...
} diff --git a/src/components/Redeemable.tsx b/src/components/Redeemable.tsx index 5c3fb44..6e57b8b 100644 --- a/src/components/Redeemable.tsx +++ b/src/components/Redeemable.tsx @@ -27,12 +27,17 @@ import { ERROR_REDEEMING, ERROR_WRONG_SIGNER, } from '../actions/redeem'; -import { flipCard } from "../actions/layout"; +import { + flipCard, + toggleDebug, +} from "../actions/layout"; import "../styles/Redeemable.scss"; +import "../styles/Debug.scss"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faUndo as flipIcon, faUndo as unflipIcon, + faWrench as debugIcon, } from '@fortawesome/free-solid-svg-icons' @@ -55,7 +60,7 @@ const redeemErrorMessage = (error: RedeemErrors): string => { return `wrong signer. expected signature from ${error.expected}, got signature from ${error.actual}`; case ERROR_REDEEMING: - return `redeem error: ${error.message}`; + return error.message; default: return "something went wrong"; @@ -99,6 +104,8 @@ export default function(ownProps: any) { redeemError: state.redeem.error, redeemTxHash: state.redeem.txHash, cardFlipped: state.layout.cardFlipped, + debugLines: state.debug.lines, + debugOpen: state.layout.debugOpen, } }, shallowEqual); @@ -179,7 +186,8 @@ export default function(ownProps: any) { const backClass = classNames({ side: true, back: true }); - return
+ return
+
{props.redeemError &&
- Error: {redeemErrorMessage(props.redeemError)} + {redeemErrorMessage(props.redeemError)}
} {props.redeemTxHash &&
Done! Tx Hash: {props.redeemTxHash} @@ -241,5 +249,17 @@ export default function(ownProps: any) {
+
+
+ dispatch(toggleDebug(!props.debugOpen)) } + icon={debugIcon} + className="btn" /> + {props.debugOpen &&
    + {props.debugLines.map((text: string, i: number) => (
  • + {text} +
  • ))} +
} +
; } diff --git a/src/reducers/index.ts b/src/reducers/index.ts index 15af169..96e2b43 100644 --- a/src/reducers/index.ts +++ b/src/reducers/index.ts @@ -17,12 +17,17 @@ import { LayoutState, layoutReducer, } from './layout'; +import { + DebugState, + debugReducer, +} from './debug'; export interface RootState { web3: Web3State, redeemable: RedeemableState, redeem: RedeemState, layout: LayoutState, + debug: DebugState, } export default function(history: History) { @@ -32,5 +37,6 @@ export default function(history: History) { redeemable: redeemableReducer, redeem: redeemReducer, layout: layoutReducer, + debug: debugReducer, }); } diff --git a/src/reducers/layout.ts b/src/reducers/layout.ts index d1dc297..ca200a7 100644 --- a/src/reducers/layout.ts +++ b/src/reducers/layout.ts @@ -1,17 +1,20 @@ import { LayoutActions, LAYOUT_TOGGLE_SIDEBAR, + LAYOUT_TOGGLE_DEBUG, LAYOUT_FLIP_CARD, } from "../actions/layout"; export interface LayoutState { sidebarOpen: boolean, cardFlipped: boolean, + debugOpen: boolean, } const initialState: LayoutState = { sidebarOpen: false, cardFlipped: false, + debugOpen: false, } export const layoutReducer = (state: LayoutState = initialState, action: LayoutActions): LayoutState => { @@ -22,6 +25,12 @@ export const layoutReducer = (state: LayoutState = initialState, action: LayoutA sidebarOpen: action.open, }; + case LAYOUT_TOGGLE_DEBUG: + return { + ...state, + debugOpen: action.open, + }; + case LAYOUT_FLIP_CARD: return { ...state, diff --git a/src/styles/Layout.scss b/src/styles/Layout.scss index 05cc3bc..1c83c2b 100644 --- a/src/styles/Layout.scss +++ b/src/styles/Layout.scss @@ -16,53 +16,6 @@ body { font-family: "Roboto", "Helvetica", "Arial", sans-serif; } -.sidebar { - z-index: 9999; - background: #fff; - position: absolute; - top: 0; - left: -100vw; - min-height: 100vh; - width: 100vw; - - &.open { - animation-duration: 0.2s; - animation-name: slidein; - left: 0; - } - - &.closed { - animation-duration: 0.2s; - animation-name: slideout; - left: -100vw; - } - - .inner { - padding: 24px; - word-break: break-all; - } -} - -@keyframes slidein { - from { - left: -100vw; - } - - to { - left: 0; - } -} - -@keyframes slideout { - from { - left: 0; - } - - to { - left: -100vw; - } -} - .main { margin-top: 50px; diff --git a/src/styles/Redeemable.scss b/src/styles/Redeemable.scss index 8ec78a4..4bf39a0 100644 --- a/src/styles/Redeemable.scss +++ b/src/styles/Redeemable.scss @@ -30,10 +30,10 @@ margin: 0 auto; perspective:1000px; + border-radius: 8px; position: relative; background: #fff; box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12); - border-radius: 8px; transform-style: preserve-3d; transition: transform 1.0s; height: 500px; @@ -43,6 +43,7 @@ } .side { + border-radius: 8px; position: absolute; width: 100%; height: 100%;