diff --git a/.gitignore b/.gitignore
index 125e6cb..11ce5ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+.idea
+
# dependencies
/node_modules
/.pnp
diff --git a/package.json b/package.json
index 1e24564..e5e802d 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"@apollo/client": "^3.3.11",
"@swingby-protocol/ip-check": "^2.1.0",
"@swingby-protocol/pulsar": "^3.15.3",
- "@swingby-protocol/sdk": "v1.2.0-alpha.3",
+ "@swingby-protocol/sdk": "v1.2.0-alpha.5",
"big.js": "6.0.3",
"bnc-onboard": "^1.38.3",
"graphql": "^15.5.0",
diff --git a/src/components/VerticalWidgetView/index.tsx b/src/components/VerticalWidgetView/index.tsx
index 1345a9c..515e6ee 100644
--- a/src/components/VerticalWidgetView/index.tsx
+++ b/src/components/VerticalWidgetView/index.tsx
@@ -22,6 +22,7 @@ type Props = {
top?: React.ReactNode;
children?: React.ReactNode;
swap?: SwapData | null;
+ fromBTC: boolean;
} & Testable;
export const VerticalWidgetView = ({
@@ -30,6 +31,7 @@ export const VerticalWidgetView = ({
children,
swap,
'data-testid': testId,
+ fromBTC,
}: Props) => {
const {
query: { disableNavigation },
@@ -39,44 +41,48 @@ export const VerticalWidgetView = ({
return (
- {layout !== 'widget-small' && (top || onClickBack) && (
- <>
-
-
+
+
+ {layout !== 'widget-small' && (top || onClickBack) && (
+ <>
+
+
+
+
+ {typeof disableNavigation === 'undefined' && onClickBack && (
+
+ )}
+
+ {swap?.currencyDeposit !== 'BTC' && }
+
+ {top}
+
+
+
+ >
+ )}
+ {layout === 'widget-small' && (top || onClickBack) && (
+
- {typeof disableNavigation === 'undefined' && onClickBack && (
+ {onClickBack && (
)}
- {swap?.currencyDeposit !== 'BTC' && }
+ {fromBTC ? null : }
- {top}
-
-
-
- >
- )}
- {layout === 'widget-small' && (top || onClickBack) && (
-
+ {top && {top}}
+
+ )}
-
- {onClickBack && (
-
- )}
-
-
-
- {top && {top}}
-
- )}
-
- {children && (
-
- {children}
-
- )}
-
+ {children && (
+
+ {children}
+
+ )}
+
+
+
);
diff --git a/src/modules/i18n/files/en.json b/src/modules/i18n/files/en.json
index 246646b..888c2a5 100644
--- a/src/modules/i18n/files/en.json
+++ b/src/modules/i18n/files/en.json
@@ -30,6 +30,8 @@
"widget.status-label-short.COMPLETED": "Sent",
"widget.status-label-short.REFUNDED": "Refunded",
"widget.status-label-short.EXPIRED": "This swap has expired",
+ "widget.status-label-long.TITLE": "To send the funds, you can connect your wallet or scan the QR code",
+ "widget.status-label-long.TITLE-BELLOW": "Or scan the QR code",
"widget.status-label-long.WAITING": "Send exactly {value} to",
"widget.status-label-long.WAITING.note": " ",
"widget.status-label-long.WAITING_CONFIRMATIONS": "Waiting for confirmations…",
diff --git a/src/modules/store/index.tsx b/src/modules/store/index.tsx
index d768da0..1f35822 100644
--- a/src/modules/store/index.tsx
+++ b/src/modules/store/index.tsx
@@ -1 +1 @@
-export { useStore } from './store';
+export { initialStore } from './store';
diff --git a/src/modules/store/store.tsx b/src/modules/store/store.tsx
index 06a6395..e6ec2eb 100644
--- a/src/modules/store/store.tsx
+++ b/src/modules/store/store.tsx
@@ -1,8 +1,9 @@
-import { useMemo } from 'react';
import { DefaultRootState } from 'react-redux';
import { createStore, applyMiddleware, Store } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
+import { isServer } from '../env';
+
import { rootReducer } from './root';
let store: Store | undefined;
@@ -26,14 +27,11 @@ const initializeStore = (preloadedState: Partial | undefined =
}
// For SSG and SSR always create a new store
- if (typeof window === 'undefined') return _store;
+ if (isServer) return _store;
// Create the store once in the client
if (!store) store = _store;
return _store;
};
-export function useStore(initialState: Partial | undefined = undefined) {
- const store = useMemo(() => initializeStore(initialState), [initialState]);
- return store;
-}
+export const initialStore = initializeStore();
diff --git a/src/modules/web3/context.tsx b/src/modules/web3/context.tsx
index 7ec58d8..b6178ee 100644
--- a/src/modules/web3/context.tsx
+++ b/src/modules/web3/context.tsx
@@ -56,6 +56,11 @@ export const OnboardProvider = ({ children }: { children?: React.ReactNode }) =>
return;
}
+ if (onboard) {
+ logger.debug('"onboard" already defined, will skip');
+ return;
+ }
+
const walletSubscription = (wallet: Wallet) => {
if (wallet.name) {
saveLastUsedProvider(wallet.name);
@@ -70,7 +75,7 @@ export const OnboardProvider = ({ children }: { children?: React.ReactNode }) =>
subscriptions: { address: setAddress, wallet: walletSubscription },
}),
);
- }, [context, currentBridge]);
+ }, [context, currentBridge, onboard]);
useEffect(() => {
onboard?.config({ darkMode: theme.pulsar.id !== 'PulsarLight' });
diff --git a/src/modules/web3/useTransferToken.tsx b/src/modules/web3/useTransferToken.tsx
index 667abbb..24ab013 100644
--- a/src/modules/web3/useTransferToken.tsx
+++ b/src/modules/web3/useTransferToken.tsx
@@ -3,7 +3,7 @@ import { CONTRACTS } from '@swingby-protocol/sdk';
import { Big } from 'big.js';
import type { DefaultRootState } from 'react-redux';
import Web3 from 'web3';
-import { TransactionConfig } from 'web3-eth';
+import { TransactionConfig, TransactionReceipt } from 'web3-eth';
import { createToast } from '@swingby-protocol/pulsar';
import { logger } from '../logger';
@@ -18,6 +18,7 @@ export const useTransferToken = () => {
const context = useSdkContext();
const { onboard, wallet, address } = useOnboard();
const [loading, setLoading] = useState(false);
+ const [txHash, setTxHash] = useState(null);
const [error, setError] = useState(null);
const transfer = useCallback(
@@ -84,17 +85,16 @@ export const useTransferToken = () => {
);
}
- return watchTransaction({
+ return await watchTransaction({
coin: swap.currencyDeposit,
tx: web3.eth.sendTransaction({ ...rawTx, gas: estimatedGas }),
- })
- .on('error', (error) => {
+ onReceipt: (receipt: TransactionReceipt) => setLoading(false),
+ onError: (error: Error) => {
setLoading(false);
setError(error);
- })
- .on('receipt', () => {
- setLoading(false);
- });
+ },
+ onTxHash: (transactionHash: string) => setTxHash(transactionHash),
+ });
} catch (err: any) {
setLoading(false);
setError(err);
@@ -110,5 +110,5 @@ export const useTransferToken = () => {
[address, context, onboard, wallet],
);
- return useMemo(() => ({ loading, error, transfer }), [loading, error, transfer]);
+ return useMemo(() => ({ loading, error, transfer, txHash }), [loading, error, transfer, txHash]);
};
diff --git a/src/modules/web3/watchTransaction/index.tsx b/src/modules/web3/watchTransaction/index.tsx
index 013c91d..197c646 100644
--- a/src/modules/web3/watchTransaction/index.tsx
+++ b/src/modules/web3/watchTransaction/index.tsx
@@ -7,13 +7,21 @@ import { logger } from '../../logger';
import { TransferToast } from './TransferToast';
+type WatchTransactionProps = {
+ coin: SkybridgeCoin;
+ tx: PromiEvent;
+ onReceipt: (receipt: TransactionReceipt) => void;
+ onTxHash: (txHash: string) => void;
+ onError: (error: Error) => void;
+};
+
export const watchTransaction = ({
coin,
tx,
-}: {
- coin: SkybridgeCoin;
- tx: PromiEvent;
-}) => {
+ onError,
+ onReceipt,
+ onTxHash,
+}: WatchTransactionProps) => {
let transactionHash: string | null = null;
tx.on('transactionHash', (hash) => {
@@ -24,6 +32,7 @@ export const watchTransaction = ({
type: 'default',
toastId: 'transaction-result',
});
+ onTxHash(transactionHash);
})
.on('confirmation', (confirmations) => {
updateToast({
@@ -45,6 +54,7 @@ export const watchTransaction = ({
type: 'danger',
toastId: 'transaction-result',
});
+ onError(error);
})
.on('receipt', (receipt) => {
createOrUpdateToast({
@@ -58,6 +68,7 @@ export const watchTransaction = ({
type: receipt.status ? 'success' : 'danger',
toastId: 'transaction-result',
});
+ onReceipt(receipt);
});
return tx;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index b54c8a2..3d8b141 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -16,14 +16,12 @@ import { Favicon } from '../components/Favicon';
import { graphQlEndpoint } from '../modules/env';
import { languages } from '../modules/i18n';
import { WidgetLayoutProvider } from '../modules/layout';
-import { useStore } from '../modules/store';
+import { initialStore } from '../modules/store';
import { SdkContextGateKeeper } from '../modules/store/sdkContext';
import { GlobalStyles } from '../modules/styles';
import { OnboardGlobalStyles, OnboardProvider } from '../modules/web3';
-function MyApp({ Component, pageProps, router }: AppProps) {
- const store = useStore();
-
+const App = ({ Component, pageProps, router }: AppProps) => {
const apolloClient = new ApolloClient({
uri: graphQlEndpoint,
cache: new InMemoryCache(),
@@ -54,7 +52,7 @@ function MyApp({ Component, pageProps, router }: AppProps) {
-
+
@@ -78,6 +76,6 @@ function MyApp({ Component, pageProps, router }: AppProps) {
);
-}
+};
-export default MyApp;
+export default App;
diff --git a/src/scenes/SwapDetails/Vertical/index.tsx b/src/scenes/SwapDetails/Vertical/index.tsx
index b4d8913..8e9c140 100644
--- a/src/scenes/SwapDetails/Vertical/index.tsx
+++ b/src/scenes/SwapDetails/Vertical/index.tsx
@@ -20,6 +20,7 @@ import {
ProgressContainer,
RowLink,
StyledQRCode,
+ StyledQRContainer,
TransferButtonsContainer,
} from './styled';
import { Top } from './Top';
@@ -35,7 +36,7 @@ export const Vertical = ({ resource, swap }: VerticalProps) => {
const { locale } = useIntl();
const context = useSdkContext();
const { address } = useOnboard();
- const { transfer, loading: isTransferring } = useTransferToken();
+ const { transfer, loading: isTransferring, txHash } = useTransferToken();
const [hasTransactionSucceeded, setTransactionSucceeded] = useState(false);
const { assertTermsSignature } = useAssertTermsSignature();
@@ -49,13 +50,15 @@ export const Vertical = ({ resource, swap }: VerticalProps) => {
}, [context, swap]);
const inboundLink = useMemo(() => {
- if (!swap || !swap.txDepositId) return undefined;
+ if (!swap) return undefined;
+ if (!txHash && !swap.txDepositId) return undefined;
+
return buildExplorerLink({
context,
coin: swap.currencyDeposit,
- transactionId: swap.txDepositId,
+ transactionId: swap.txDepositId ? swap.txDepositId : (txHash as string),
});
- }, [context, swap]);
+ }, [context, swap, txHash]);
const doTransfer = useCallback(async () => {
try {
@@ -95,10 +98,8 @@ export const Vertical = ({ resource, swap }: VerticalProps) => {
top={}
data-testid={buildTestId('')}
swap={swap}
+ fromBTC={swap.currencyDeposit === 'BTC'}
>
- {address && swap.status === 'WAITING' && (isTransferring || hasTransactionSucceeded) && (
-
- )}
{address &&
supportsWeb3 &&
swap.status === 'WAITING' &&
@@ -114,15 +115,19 @@ export const Vertical = ({ resource, swap }: VerticalProps) => {
swap.status === 'WAITING' &&
!isTransferring &&
!hasTransactionSucceeded && (
-
+
+
+
+
)}
- {swap.status !== 'WAITING' && (
+
+ {txHash && (
{
/>
)}
+
<>
diff --git a/src/scenes/SwapDetails/Vertical/styled.tsx b/src/scenes/SwapDetails/Vertical/styled.tsx
index 344ce91..69bb4c9 100644
--- a/src/scenes/SwapDetails/Vertical/styled.tsx
+++ b/src/scenes/SwapDetails/Vertical/styled.tsx
@@ -66,3 +66,12 @@ export const StyledQRCode = styled(QRCode)`
font-size: ${rem(150)};
}
`;
+
+export const StyledQRContainer = styled.div`
+ background: #888d9375;
+ padding: 20px;
+ border-radius: ${({ theme }) => rem(theme.pulsar.size.box)};
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+`;
diff --git a/yarn.lock b/yarn.lock
index 4402570..cbbd072 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2815,10 +2815,10 @@
qrcode.react "^1.0.0"
react-toastify "^6.2.0"
-"@swingby-protocol/sdk@v1.2.0-alpha.3":
- version "1.2.0-alpha.3"
- resolved "https://registry.yarnpkg.com/@swingby-protocol/sdk/-/sdk-1.2.0-alpha.3.tgz#7bda519312bf7868af37eabf17a7d6b5e1c1296c"
- integrity sha512-Y29wJx+8dtoS1SY1NbbnbmVDJ5JZoeuwJLbRckz9Y+bOqg7EJih3F589tMsvu/HSRjXaPlrsTK6Z8hvC6VXXuA==
+"@swingby-protocol/sdk@v1.2.0-alpha.5":
+ version "1.2.0-alpha.5"
+ resolved "https://registry.yarnpkg.com/@swingby-protocol/sdk/-/sdk-1.2.0-alpha.5.tgz#6a2203d574a477f9ac8751c4f15513a054c3eacf"
+ integrity sha512-BuuATjqXlarK+jhEG3+S7xLXmMQ9mQP/ppi3DfGmykst9Ycid8q3INvOhQ4t3zN7RvPQa79Nt2+epxnaXvnFlg==
dependencies:
"@typescript-eslint/eslint-plugin" "4.18.0"
bech32 "^2.0.0"