Skip to content

Commit

Permalink
feat: implement Keysign swap payload handling and enhance swap quote …
Browse files Browse the repository at this point in the history
…provider integration

- Added `toKeysignSwapPayload` function to validate and transform swap payloads.
- Introduced `oneInchName` constant for better swap provider name management.
- Updated `getSwapQuoteProviderName` to utilize the new `oneInchName` constant.
- Enhanced `KeysignSwapTxInfo` component to display detailed swap transaction information, including asset allowances and amounts.
- Added new translations for 'From Asset', 'To Asset', 'Allowance spender', and 'Allowance amount' in English locale.
  • Loading branch information
rcoderdev committed Jan 10, 2025
1 parent 41b9fb2 commit f26339b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 5 deletions.
9 changes: 9 additions & 0 deletions frontend/src/chain/keysign/KeysignSwapPayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@ export type KeysignSwapPayload = Exclude<
KeysignPayload['swapPayload'],
{ case: undefined; value?: undefined }
>;

export const toKeysignSwapPayload = (
swapPayload: KeysignPayload['swapPayload']
): KeysignSwapPayload => {
if (swapPayload.case === undefined) {
throw new Error('Swap payload case is undefined');
}
return swapPayload;
};
1 change: 1 addition & 0 deletions frontend/src/chain/swap/oneInch/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const oneInchName = '1inch';
3 changes: 2 additions & 1 deletion frontend/src/chain/swap/quote/getSwapQuoteProviderName.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { matchRecordUnion } from '../../../lib/utils/matchRecordUnion';
import { oneInchName } from '../oneInch/config';
import { SwapQuote } from './SwapQuote';

export const getSwapQuoteProviderName = (quote: SwapQuote) => {
return matchRecordUnion(quote, {
native: ({ swapChain }) => swapChain,
oneInch: () => '1inch',
oneInch: () => oneInchName,
});
};
4 changes: 4 additions & 0 deletions frontend/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,4 +624,8 @@ export const en = {
scan_with_devices: 'Scan with devices to join the vault generation',
scan_with_devices_to_sign:
'Scan with devices to participate in signing the transaction',
from_asset: 'From Asset',
to_asset: 'To Asset',
allowance_spender: 'Allowance spender',
allowance_amount: 'Allowance amount',
};
7 changes: 4 additions & 3 deletions frontend/src/lib/utils/matchDiscriminatedUnion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ export function matchDiscriminatedUnion<
D extends string,
V extends string,
U extends { [P in D]: string } & { [Q in V]: unknown },
R,
K extends U[D] = U[D],
R = never,
>(
unionValue: U,
discriminantKey: D,
valueKey: V,
handlers: {
[K in U[D]]: (val: Extract<U, { [P in D]: K }>[V]) => R;
[P in K]: (val: Extract<U, { [Q in D]: P }>[V]) => R;
}
): R {
const discriminantValue = unionValue[discriminantKey] as U[D];
const discriminantValue = unionValue[discriminantKey] as K;
const handler = handlers[discriminantValue];
const value = (
unionValue as Extract<U, { [P in D]: typeof discriminantValue }>
Expand Down
58 changes: 57 additions & 1 deletion frontend/src/vault/swap/keysign/KeysignSwapTxInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { useTranslation } from 'react-i18next';

import { toKeysignSwapPayload } from '../../../chain/keysign/KeysignSwapPayload';
import { oneInchName } from '../../../chain/swap/oneInch/config';
import { TxOverviewPrimaryRow } from '../../../chain/tx/components/TxOverviewPrimaryRow';
import { fromChainAmount } from '../../../chain/utils/fromChainAmount';
import { withoutUndefined } from '../../../lib/utils/array/withoutUndefined';
import { formatAmount } from '../../../lib/utils/formatAmount';
import { getDiscriminatedUnionValue } from '../../../lib/utils/getDiscriminatedUnionValue';
import { matchDiscriminatedUnion } from '../../../lib/utils/matchDiscriminatedUnion';
import { assertField } from '../../../lib/utils/record/assertField';
import { Chain } from '../../../model/chain';
import { useKeysignPayload } from '../../keysign/shared/state/keysignPayload';

export const KeysignSwapTxInfo = () => {
const { erc20ApprovePayload } = useKeysignPayload();
const payload = useKeysignPayload();

const { erc20ApprovePayload, toAmount: fromAmount } = payload;

const fromCoin = assertField(payload, 'coin');

const { t } = useTranslation();

Expand All @@ -14,9 +26,53 @@ export const KeysignSwapTxInfo = () => {
t('swap'),
]).join(` ${t('and')} `);

const swapPayload = toKeysignSwapPayload(payload.swapPayload);

const swapPayloadValue = getDiscriminatedUnionValue(
swapPayload,
'case',
'value',
swapPayload.case
);

const toCoin = assertField(swapPayloadValue, 'toCoin');
const toAmount = Number(swapPayloadValue.toAmountDecimal);

const provider = matchDiscriminatedUnion(swapPayload, 'case', 'value', {
thorchainSwapPayload: () => Chain.THORChain,
mayachainSwapPayload: () => Chain.MayaChain,
oneinchSwapPayload: () => oneInchName,
});

return (
<>
<TxOverviewPrimaryRow title={t('action')}>{action}</TxOverviewPrimaryRow>
<TxOverviewPrimaryRow title={t('provider')}>
{provider}
</TxOverviewPrimaryRow>
<TxOverviewPrimaryRow title={t('from_asset')}>
{formatAmount(
fromChainAmount(fromAmount, fromCoin.decimals),
fromCoin.ticker
)}
</TxOverviewPrimaryRow>
<TxOverviewPrimaryRow title={t('to_asset')}>
{formatAmount(toAmount, toCoin.ticker)}
</TxOverviewPrimaryRow>

{erc20ApprovePayload && (
<>
<TxOverviewPrimaryRow title={t('allowance_spender')}>
{erc20ApprovePayload.spender}
</TxOverviewPrimaryRow>
<TxOverviewPrimaryRow title={t('allowance_amount')}>
{formatAmount(
fromChainAmount(erc20ApprovePayload.amount, fromCoin.decimals),
fromCoin.ticker
)}
</TxOverviewPrimaryRow>
</>
)}
</>
);
};

0 comments on commit f26339b

Please sign in to comment.