Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/apps/src/configs/chains/chain-id.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export enum ChainId {
Kovan,
Goerli,
HarmonyTestnet1,
HarmonyTest0,
HarmonyTest1,
}

export enum WebbEVMChain {
Expand All @@ -24,3 +26,26 @@ export enum WebbEVMChain {
HarmonyTest0 = 1666700000,
HarmonyTest1 = 1666700001,
}

export const evmIdIntoChainId = (evmId: number | string): ChainId => {
switch (Number(evmId) as WebbEVMChain) {
case WebbEVMChain.EthereumMainNet:
return ChainId.EthereumMainNet;
case WebbEVMChain.Ropsten:
return ChainId.Ropsten;
case WebbEVMChain.Rinkeby:
return ChainId.Rinkeby;
case WebbEVMChain.Kovan:
return ChainId.Kovan;
case WebbEVMChain.Goerli:
return ChainId.Goerli;
case WebbEVMChain.Edgeware:
return ChainId.Edgeware;
case WebbEVMChain.Beresheet:
return ChainId.EdgewareTestNet;
case WebbEVMChain.HarmonyTest0:
return ChainId.HarmonyTest0;
case WebbEVMChain.HarmonyTest1:
return ChainId.HarmonyTest1;
}
};
27 changes: 27 additions & 0 deletions packages/apps/src/configs/relayer-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Relayerconfig, WebbRelayerBuilder } from '@webb-dapp/react-environment/webb-context/relayer';
import { ChainId } from '@webb-dapp/apps/configs/chains';

let builder: WebbRelayerBuilder | null = null;
export const relayerConfig: Relayerconfig[] = [
{
address: 'http://localhost:9955',
},
];

export async function getWebbRelayer() {
if (!builder) {
builder = await WebbRelayerBuilder.initBuilder(relayerConfig, (name, basedOn) => {
if (basedOn === 'evm') {
switch (name) {
case 'beresheet':
return ChainId.EdgewareTestNet;
}
}
if (basedOn === 'substrate') {
return null;
}
return null;
});
}
return builder;
}
63 changes: 57 additions & 6 deletions packages/mixer/src/components/Withdraw/Withdraw.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { FormHelperText, InputBase } from '@material-ui/core';
import { Fade, FormHelperText, InputBase, MenuItem, Select } from '@material-ui/core';
import { MixerButton } from '@webb-dapp/mixer/components/MixerButton/MixerButton';
import WithdrawingModal from '@webb-dapp/mixer/components/Withdraw/WithdrawingModal';
import { useWithdraw } from '@webb-dapp/mixer/hooks';
import { WithdrawState } from '@webb-dapp/react-environment';
import { SpaceBox } from '@webb-dapp/ui-components';
import { InputLabel } from '@webb-dapp/ui-components/Inputs/InputLabel/InputLabel';
import { InputSection } from '@webb-dapp/ui-components/Inputs/InputSection/InputSection';
import { NoteInput } from '@webb-dapp/ui-components/Inputs/NoteInput/NoteInput';
import { Modal } from '@webb-dapp/ui-components/Modal/Modal';
import React, { useState } from 'react';
import styled from 'styled-components';
import { WithdrawState } from '@webb-dapp/react-environment';
import { InputSection } from '@webb-dapp/ui-components/Inputs/InputSection/InputSection';

const WithdrawWrapper = styled.div``;
type WithdrawProps = {};
Expand All @@ -18,11 +18,10 @@ export const Withdraw: React.FC<WithdrawProps> = () => {
const [note, setNote] = useState('');
const [recipient, setRecipient] = useState('');

const { canCancel, cancelWithdraw, stage, validationErrors, withdraw } = useWithdraw({
const { canCancel, cancelWithdraw, relayersState, setRelayer, stage, validationErrors, withdraw } = useWithdraw({
recipient,
note,
});

return (
<WithdrawWrapper>
<InputSection>
Expand All @@ -38,7 +37,7 @@ export const Withdraw: React.FC<WithdrawProps> = () => {
onChange={(event) => {
setRecipient(event.target.value as string);
}}
inputProps={{style: {fontSize: 14}}}
inputProps={{ style: { fontSize: 14 } }}
fullWidth
placeholder={`Enter account address`}
/>
Expand All @@ -48,6 +47,58 @@ export const Withdraw: React.FC<WithdrawProps> = () => {
</InputLabel>
</InputSection>

<SpaceBox height={16} />
<InputSection>
<InputLabel label={'Relayer'}>
<Select
fullWidth
value={relayersState.activeRelayer?.address}
onChange={({ target: { value } }) => {
setRelayer(relayersState?.relayers.find((i) => i.address === value) ?? null);
}}
>
{relayersState.relayers.map((relayer) => {
return (
<MenuItem value={relayer.address} key={relayer.address}>
{relayer.address}
</MenuItem>
);
})}
</Select>
<Fade in={Boolean(relayersState.activeRelayer)} unmountOnExit mountOnEnter timeout={300}>
<div
style={{
padding: 10,
}}
>
<table
style={{
width: '100%',
}}
>
<tbody>
<tr>
<td>
<span style={{ whiteSpace: 'nowrap' }}>withdraw fee</span>
</td>
<td>{relayersState.activeRelayer?.fee}</td>
</tr>
<tr>
<td>gas limit</td>
<td>{relayersState.activeRelayer?.gasLimit}</td>
</tr>
<tr>
<td>Account</td>
<td>
<small>{relayersState.activeRelayer?.account}</small>
</td>
</tr>
</tbody>
</table>
</div>
</Fade>
</InputLabel>
</InputSection>
<SpaceBox height={16} />

<MixerButton disabled={!recipient} onClick={withdraw} label={'Withdraw'} />
Expand Down
40 changes: 37 additions & 3 deletions packages/mixer/src/hooks/withdraw/useWithdraw.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useWebContext, WithdrawState } from '@webb-dapp/react-environment/webb-context';
import { ActiveWebbRelayer, WebbRelayer } from '@webb-dapp/react-environment/webb-context/relayer';
import { useCallback, useEffect, useMemo, useState } from 'react';

export type UseWithdrawProps = {
Expand All @@ -13,10 +14,20 @@ export type WithdrawErrors = {
recipient: string;
};
};
type RelayersState = {
relayers: WebbRelayer[];
loading: boolean;
activeRelayer: null | ActiveWebbRelayer;
};
const relayersInitState: RelayersState = {
relayers: [],
activeRelayer: null,
loading: true,
};
export const useWithdraw = (params: UseWithdrawProps) => {
const [stage, setStage] = useState<WithdrawState>(WithdrawState.Ideal);
const { activeApi } = useWebContext();

const [relayersState, setRelayersState] = useState<RelayersState>(relayersInitState);
const [error, setError] = useState<WithdrawErrors>({
error: '',
validationError: {
Expand All @@ -29,9 +40,21 @@ export const useWithdraw = (params: UseWithdrawProps) => {
if (!withdraw?.enabled) return null;
return withdraw.inner;
}, [activeApi]);

// hook events
useEffect(() => {
withdrawApi?.relayers.then((r) => {
setRelayersState((p) => ({
...p,
loading: false,
relayers: r,
}));
});
const sub = withdrawApi?.watcher.subscribe((next) => {
setRelayersState((p) => ({
...p,
activeRelayer: next,
}));
});
const unsubscribe: Record<string, (() => void) | void> = {};
if (!withdrawApi) return;
unsubscribe['stateChange'] = withdrawApi.on('stateChange', (stage: WithdrawState) => {
Expand All @@ -51,7 +74,10 @@ export const useWithdraw = (params: UseWithdrawProps) => {
}));
});

return () => Object.values(unsubscribe).forEach((v) => v && v());
return () => {
sub?.unsubscribe();
Object.values(unsubscribe).forEach((v) => v && v());
};
}, [withdrawApi]);

const withdraw = useCallback(async () => {
Expand All @@ -73,12 +99,20 @@ export const useWithdraw = (params: UseWithdrawProps) => {
}
}, [canCancel, withdrawApi]);

const setRelayer = useCallback(
(nextRelayer: WebbRelayer | null) => {
withdrawApi?.setActiveRelayer(nextRelayer);
},
[withdrawApi]
);
return {
stage,
withdraw,
canCancel,
cancelWithdraw,
error: error.error,
validationErrors: error.validationError,
relayersState,
setRelayer,
};
};
19 changes: 14 additions & 5 deletions packages/react-environment/src/WebbProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
USER_SWITCHED_TO_EXPECT_CHAIN,
} from '@webb-dapp/react-environment/error/interactive-errors/evm-network-conflict';
import { LoggerService } from '@webb-tools/app-util';
import { getWebbRelayer } from '@webb-dapp/apps/configs/relayer-config';

interface WebbProviderProps extends BareProps {
applicationName: string;
Expand Down Expand Up @@ -68,6 +69,7 @@ export const WebbProvider: FC<WebbProviderProps> = ({ applicationName = 'Webb Da
p.forEach((p) => p.cancel());
return [];
});

appEvent.send('changeNetworkSwitcherVisibility', false);
};
}, [activeApi]);
Expand Down Expand Up @@ -197,6 +199,8 @@ export const WebbProvider: FC<WebbProviderProps> = ({ applicationName = 'Webb Da
};
/// Network switcher
const switchChain = async (chain: Chain, _wallet: Wallet) => {
const relayer = await getWebbRelayer();

const wallet = _wallet || activeWallet;
// wallet cleanup
/// if new wallet id isn't the same of the current then the dApp is dealing with api change
Expand All @@ -210,11 +214,16 @@ export const WebbProvider: FC<WebbProviderProps> = ({ applicationName = 'Webb Da
case WalletId.Polkadot:
{
const url = chain.url;
const webbPolkadot = await WebbPolkadot.init('Webb DApp', [url], {
onError: (feedback) => {
registerInteractiveFeedback(setInteractiveFeedbacks, feedback);
const webbPolkadot = await WebbPolkadot.init(
'Webb DApp',
[url],
{
onError: (feedback) => {
registerInteractiveFeedback(setInteractiveFeedbacks, feedback);
},
},
});
relayer
);
await setActiveApiWithAccounts(webbPolkadot, chain.id);
activeApi = webbPolkadot;
setLoading(false);
Expand Down Expand Up @@ -280,7 +289,7 @@ export const WebbProvider: FC<WebbProviderProps> = ({ applicationName = 'Webb Da
}
/// get the current active chain from metamask
const chainId = await web3Provider.network; // storage based on network id
const webbWeb3Provider = await WebbWeb3Provider.init(web3Provider, chainId);
const webbWeb3Provider = await WebbWeb3Provider.init(web3Provider, chainId, relayer);
webbWeb3Provider.on('providerUpdate', async ([chainId]) => {
/// get the nextChain from MetaMask change
const nextChain = Object.values(chains).find((chain) => chain.evmId === chainId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { EventBus } from '@webb-tools/app-util';

import { ApiPromise } from '@polkadot/api';
import { InjectedExtension } from '@polkadot/extension-inject/types';
import { WebbRelayerBuilder } from '@webb-dapp/react-environment/webb-context/relayer';

export class WebbPolkadot extends EventBus<WebbProviderEvents> implements WebbApiProvider<WebbPolkadot> {
readonly methods: WebbMethods<WebbPolkadot>;
Expand All @@ -24,7 +25,11 @@ export class WebbPolkadot extends EventBus<WebbProviderEvents> implements WebbAp
readonly api: ApiPromise;
readonly txBuilder: PolkaTXBuilder;

private constructor(apiPromise: ApiPromise, injectedExtension: InjectedExtension) {
private constructor(
apiPromise: ApiPromise,
injectedExtension: InjectedExtension,
readonly relayingManager: WebbRelayerBuilder
) {
super();
this.provider = new PolkadotProvider(apiPromise, injectedExtension);
this.accounts = this.provider.accounts;
Expand Down Expand Up @@ -78,9 +83,14 @@ export class WebbPolkadot extends EventBus<WebbProviderEvents> implements WebbAp
}
}

static async init(appName: string, endpoints: string[], errorHandler: ApiInitHandler): Promise<WebbPolkadot> {
static async init(
appName: string,
endpoints: string[],
errorHandler: ApiInitHandler,
relayerBuilder: WebbRelayerBuilder
): Promise<WebbPolkadot> {
const [apiPromise, injectedExtension] = await PolkadotProvider.getParams(appName, endpoints, errorHandler.onError);
const instance = new WebbPolkadot(apiPromise, injectedExtension);
const instance = new WebbPolkadot(apiPromise, injectedExtension, relayerBuilder);
instance.insureApiInterface();
/// check metadata update
await instance.awaitMetaDataCheck();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
import { MixerWithdraw, WithdrawState } from '@webb-dapp/react-environment/webb-context';
import {
MixerWithdraw,
OptionalActiveRelayer,
OptionalRelayer,
WithdrawState,
} from '@webb-dapp/react-environment/webb-context';
import { WebbWeb3Provider } from '@webb-dapp/react-environment/api-providers/web3/webb-web3-provider';
import { transactionNotificationConfig } from '@webb-dapp/wallet/providers/polkadot/transaction-notification-config';
import { EvmNote } from '@webb-dapp/contracts/utils/evm-note';
import { evmIdIntoChainId } from '@webb-dapp/apps/configs';
import { WebbRelayer } from '@webb-dapp/react-environment/webb-context/relayer';
import React from 'react';

export class Web3MixerWithdraw extends MixerWithdraw<WebbWeb3Provider> {
cancelWithdraw(): Promise<void> {
return Promise.resolve(undefined);
}

async mapRelayerIntoActive(relayer: OptionalRelayer): Promise<OptionalActiveRelayer> {
if (!relayer) {
return null;
}
const evmId = await this.inner.getChainId();
const chainId = evmIdIntoChainId(evmId);
return WebbRelayer.intoActiveWebRelayer(relayer, {
basedOn: 'evm',
chain: chainId,
});
}

get relayers() {
return this.inner.getChainId().then((evmId) => {
const chainId = evmIdIntoChainId(evmId);
return this.inner.relayingManager.getRelayer({
baseOn: 'evm',
chainId,
});
});
}

get hasRelayer() {
return this.relayers.then((r) => r.length > 0);
}

async withdraw(note: string, recipient: string): Promise<void> {
this.emit('stateChange', WithdrawState.GeneratingZk);
const evmNote = EvmNote.deserialize(note);
Expand Down
Loading