Skip to content

Commit

Permalink
Merge pull request #134 from map3xyz/phil/map-178-create-shortcut-amo…
Browse files Browse the repository at this point in the history
…unt-pills

feat: add hardcoded shortcut amounts for binance (only binance for now)
  • Loading branch information
plondon authored Feb 12, 2023
2 parents 61e920a + 20d5a9d commit 969ed44
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 218 deletions.
403 changes: 209 additions & 194 deletions src/components/methods/BinancePay/index.tsx

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/components/methods/WalletConnect/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const WalletConnect: React.FC<Props> = ({ amount, disabled }) => {
}
htmlType="submit"
loading={state.account.status === 'loading'}
size="medium"
size="large"
type={'default'}
>
<span className="flex items-center gap-2">
Expand Down
22 changes: 9 additions & 13 deletions src/components/methods/WindowEthereum/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@ import React, {
} from 'react';

import { Context } from '../../../providers/Store';
import { DOWNLOAD_EXTENSION } from '../../../steps/EnterAmount';
import { DOWNLOAD_EXTENSION, SubmitHandler } from '../../../steps/EnterAmount';
import MethodIcon from '../../MethodIcon';

export type ConnectHandler = {
connect: () => void;
};

const WindowEthereum = forwardRef<ConnectHandler, Props>(
({ amount, disabled, setFormError }, connectRef) => {
const WindowEthereum = forwardRef<SubmitHandler, Props>(
({ amount, disabled, setFormError }, submitRef) => {
const [state, dispatch] = useContext(Context);

const connect = async () => {
const submit = async () => {
dispatch({ type: 'SET_PROVIDER_LOADING' });
const providers = window.ethereum?.providers;
const selectedProvider = providers?.find(
Expand Down Expand Up @@ -86,14 +82,14 @@ const WindowEthereum = forwardRef<ConnectHandler, Props>(
}
};

useImperativeHandle(connectRef, () => ({
connect: () => {
connect();
useImperativeHandle(submitRef, () => ({
submit: () => {
submit();
},
}));

useEffect(() => {
connect();
submit();
}, []);

if (!state.method || !state.method?.value) return null;
Expand Down Expand Up @@ -122,7 +118,7 @@ const WindowEthereum = forwardRef<ConnectHandler, Props>(
}
htmlType="submit"
loading={state.account.status === 'loading'}
size="medium"
size="large"
type={'default'}
>
<span className="flex items-center gap-2">
Expand Down
18 changes: 18 additions & 0 deletions src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,22 @@ describe('Map3Sdk', () => {
});
expect(initFn).not.toThrow();
});
it('allows optional shortcutAmounts, slices first 3 amounts if more than 3 are passed.', () => {
const warnSpy = jest.spyOn(console, 'warn');
const initFn = () =>
initMap3Supercharge({
anonKey:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjb25zb2xlIiwib3JnX2lkIjoiYzljNDczMzYtNWM5MS00MDM0LWIyYTgtMGI1NzA5ZTAwMGI1Iiwicm9sZXMiOlsiYW5vbnltb3VzIl0sImlhdCI6MTY3NTg4ODUwOCwiZXhwIjoxNzA3NDI0NTA4fQ.GzuXjFzSVkE3L-LlhtvpXa3aIi48rvHgMY3hw6lS8KU',
options: {
selection: {
shortcutAmounts: [1, 2, 3, 4, 5],
},
},
userId: 'test',
});
expect(initFn).not.toThrow();
expect(warnSpy).toBeCalledWith(
'Warning: shortcutAmounts should not exceed 3 values. Falling back to first 3 values.'
);
});
});
14 changes: 14 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface Map3InitConfig {
fiat?: string;
networkCode?: string;
paymentMethod?: 'binance-pay';
shortcutAmounts?: number[];
};
style?: {
appName?: string;
Expand Down Expand Up @@ -96,6 +97,19 @@ export class Map3 {
config.options.selection.fiat = 'USD';
}

if (
config.options.selection.shortcutAmounts &&
config.options.selection.shortcutAmounts.length > 3
) {
console.warn(
'Warning: shortcutAmounts should not exceed 3 values. Falling back to first 3 values.'
);
config.options.selection.shortcutAmounts = config.options.selection.shortcutAmounts.slice(
0,
3
);
}

if (
config.options.selection.address &&
!config.options.selection.networkCode
Expand Down
1 change: 1 addition & 0 deletions src/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ root.render(
selection: {
assetId: '6b562c23-d79f-4a34-a47f-cc7b28726821',
paymentMethod: 'binance-pay',
shortcutAmounts: [1, 2, 3, 4, 5],
},
style: {
colors: {
Expand Down
5 changes: 4 additions & 1 deletion src/providers/Store/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type State = {
providerChainId?: number;
requiredAmount?: string;
requiredPaymentMethod?: 'binance-pay' | 'show-address';
shortcutAmounts?: number[];
slug?: string;
step: number;
steps: (keyof typeof Steps)[];
Expand Down Expand Up @@ -195,6 +196,7 @@ const initialState: State = {
status: 'idle',
},
providerChainId: undefined,
shortcutAmounts: [],
slug: undefined,
step: Steps.AssetSelection,
steps: [
Expand Down Expand Up @@ -233,7 +235,7 @@ export const Store: React.FC<
PropsWithChildren<Map3InitConfig & { asset?: Asset; network?: Network }>
> = ({ asset, children, network, options, userId }) => {
const { callbacks, selection, style } = options || {};
const { amount, fiat, paymentMethod } = selection || {};
const { amount, fiat, paymentMethod, shortcutAmounts } = selection || {};
const { embed, theme } = style || {};
const {
handleAuthorizeTransaction,
Expand Down Expand Up @@ -483,6 +485,7 @@ export const Store: React.FC<
network,
requiredAmount,
requiredPaymentMethod,
shortcutAmounts,
step,
theme,
userId,
Expand Down
2 changes: 1 addition & 1 deletion src/steps/BinancePay/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ const BinancePay: React.FC<Props> = () => {
href={data.createBinanceOrder.data.checkoutUrl!}
target="_blank"
>
<Button block size="medium" type={'default'}>
<Button block size="large" type={'default'}>
<span className="flex items-center gap-2">
<MethodIcon method={state.method} />{' '}
{t('copy.pay_on_binance_com')}
Expand Down
72 changes: 64 additions & 8 deletions src/steps/EnterAmount/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Badge, CryptoAddress } from '@map3xyz/components';
import { ethers } from 'ethers';
import { motion } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';
import React, { useContext, useEffect, useRef, useState } from 'react';
import { isChrome, isEdge, isFirefox, isOpera } from 'react-device-detect';
import { useTranslation } from 'react-i18next';
Expand All @@ -10,9 +10,7 @@ import LoadingWrapper from '../../components/LoadingWrapper';
import MethodIcon from '../../components/MethodIcon';
import BinancePay from '../../components/methods/BinancePay';
import WalletConnect from '../../components/methods/WalletConnect';
import WindowEthereum, {
ConnectHandler,
} from '../../components/methods/WindowEthereum';
import WindowEthereum from '../../components/methods/WindowEthereum';
import { MIN_CONFIRMATIONS } from '../../constants';
import {
useGetAssetByMappedAssetIdAndNetworkCodeQuery,
Expand All @@ -27,6 +25,10 @@ const INSUFFICIENT_FUNDS = 'This amount exceeds your ';
export const DECIMAL_FALLBACK = 8;
export const DOWNLOAD_EXTENSION = 'Download Extension';

export type SubmitHandler = {
submit: () => void;
};

const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
const { t } = useTranslation();
const [state, dispatch] = useContext(Context);
Expand All @@ -43,7 +45,7 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
const inputRef = useRef<HTMLInputElement>(null);
const formRef = useRef<HTMLFormElement>(null);
const quoteRef = useRef<HTMLSpanElement>(null);
const connectRef = useRef<ConnectHandler>(null);
const submitRef = useRef<SubmitHandler>(null);
const extensionLink =
state.method?.links?.[
isChrome
Expand Down Expand Up @@ -244,6 +246,20 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
});
};

const setFiatAmountAndSubmit = (amount: string) => {
if (!inputRef.current) return;
if (formValue.inputSelected === 'crypto') toggleBase();
inputRef.current.value = amount;
setFormValue({
...formValue,
base: amount,
inputSelected: 'fiat',
});
setTimeout(() => {
submitRef.current?.submit();
}, 100);
};

const handleSubmit = async (e?: React.FormEvent<HTMLFormElement>) => {
try {
e?.preventDefault();
Expand All @@ -256,7 +272,7 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
}

if (state.account.status === 'idle' || state.account.status === 'error') {
connectRef.current?.connect();
submitRef.current?.submit();
return;
}

Expand Down Expand Up @@ -532,14 +548,53 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
onClick={setMax}
role="button"
>
<Badge color="blue">
<Badge color="blue" size="large">
{/* @ts-ignore */}
<span className="whitespace-nowrap">
Max: {state.prebuiltTx.data?.maxLimitFormatted}{' '}
{state.asset.symbol}
</span>
</Badge>
</motion.span>
) : state.method.value === 'binance-pay' && price ? (
<AnimatePresence>
<motion.div
animate="show"
className="mb-1 flex w-full justify-around"
initial="hidden"
variants={{
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
}}
>
{(state.shortcutAmounts || []).map((amount) => (
<motion.span
className="relative"
key={amount}
onClick={() =>
setFiatAmountAndSubmit(amount.toString())
}
role="button"
variants={{
hidden: { opacity: 0, top: '10px' },
show: { opacity: 1, top: '0px' },
}}
>
<Badge color="green" size="large">
{/* @ts-ignore */}
<span className="whitespace-nowrap">
${amount.toFixed(2)}
</span>
</Badge>
</motion.span>
))}
</motion.div>
</AnimatePresence>
) : null}
</span>
{state.method.value === 'isWalletConnect' ? (
Expand All @@ -556,6 +611,7 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
<BinancePay
amount={amount}
isConfirming={isConfirming}
ref={submitRef}
setFormError={setFormError}
setIsConfirming={setIsConfirming}
/>
Expand All @@ -568,7 +624,7 @@ const EnterAmountForm: React.FC<{ price: number }> = ({ price }) => {
state.prebuiltTx.data?.feeError ||
!!formError?.includes(INSUFFICIENT_FUNDS)
}
ref={connectRef}
ref={submitRef}
setFormError={setFormError}
/>
)}
Expand Down

0 comments on commit 969ed44

Please sign in to comment.