From 0ca07c64a2bee84e3497866661a456675ad8a4d1 Mon Sep 17 00:00:00 2001 From: Ben Goldberg Date: Tue, 12 Nov 2024 12:01:23 -0500 Subject: [PATCH] modify raps to support claim as x --- src/raps/actions/claimClaimable.ts | 8 +++ src/raps/claimClaimable.ts | 89 ++++++++++++++++++++++++++++++ src/raps/execute.ts | 10 +++- src/raps/references.ts | 24 ++++++-- 4 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 src/raps/actions/claimClaimable.ts create mode 100644 src/raps/claimClaimable.ts diff --git a/src/raps/actions/claimClaimable.ts b/src/raps/actions/claimClaimable.ts new file mode 100644 index 00000000000..59a88f43e9c --- /dev/null +++ b/src/raps/actions/claimClaimable.ts @@ -0,0 +1,8 @@ +import { ActionProps, RapActionResult } from '../references'; +import { executeClaim } from '@/screens/claimables/transaction/claim'; + +export async function claimClaimable({ wallet, parameters }: ActionProps<'claimClaimable'>): Promise { + const { claimTx, asset } = parameters; + + return executeClaim({ asset, claimTx, wallet }); +} diff --git a/src/raps/claimClaimable.ts b/src/raps/claimClaimable.ts new file mode 100644 index 00000000000..6e279564c3b --- /dev/null +++ b/src/raps/claimClaimable.ts @@ -0,0 +1,89 @@ +import { Address } from 'viem'; +import { createNewAction, createNewRap } from './common'; +import { RapAction, RapSwapActionParameters } from './references'; +import { RainbowError } from '@/logger'; +import { CrosschainQuote } from '@rainbow-me/swaps'; +import { assetNeedsUnlocking } from './actions'; + +export async function createClaimClaimableRap(parameters: RapSwapActionParameters<'claimClaimable'>) { + let actions: RapAction<'claimClaimable' | 'crosschainSwap' | 'unlock' | 'swap'>[] = []; + + const { sellAmount, assetToBuy, quote, chainId, toChainId, assetToSell, meta, gasFeeParamsBySpeed, gasParams, additionalParams } = + parameters; + + if (!additionalParams?.claimTx) throw new RainbowError('[raps/claimClaimable]: claimTx is undefined'); + + const claim = createNewAction('claimClaimable', { + claimTx: additionalParams.claimTx, + asset: assetToSell, + }); + actions = actions.concat(claim); + + const { + from: accountAddress, + allowanceTarget, + allowanceNeeded, + } = quote as { + from: Address; + allowanceTarget: Address; + allowanceNeeded: boolean; + }; + + let swapAssetNeedsUnlocking = false; + + if (allowanceNeeded) { + swapAssetNeedsUnlocking = await assetNeedsUnlocking({ + owner: accountAddress, + amount: sellAmount, + assetToUnlock: assetToSell, + spender: allowanceTarget, + chainId, + }); + } + + if (swapAssetNeedsUnlocking) { + if (!quote.to) throw new RainbowError('[raps/claimClaimable]: quote.to is undefined'); + + const unlock = createNewAction('unlock', { + fromAddress: accountAddress, + assetToUnlock: assetToSell, + chainId, + contractAddress: quote.to as Address, + }); + actions = actions.concat(unlock); + } + + if (chainId === toChainId) { + // create a swap rap + const swap = createNewAction('swap', { + chainId: chainId, + requiresApprove: swapAssetNeedsUnlocking, + quote: quote as CrosschainQuote, + meta: meta, + assetToSell, + sellAmount, + assetToBuy, + gasParams, + gasFeeParamsBySpeed, + }); + actions = actions.concat(swap); + } else { + // create a crosschain swap rap + const crosschainSwap = createNewAction('crosschainSwap', { + chainId: chainId, + requiresApprove: swapAssetNeedsUnlocking, + quote: quote as CrosschainQuote, + meta: meta, + assetToSell, + sellAmount, + assetToBuy, + gasParams, + gasFeeParamsBySpeed, + }); + actions = actions.concat(crosschainSwap); + } + + // create the overall rap + const newRap = createNewRap(actions); + return newRap; +} diff --git a/src/raps/execute.ts b/src/raps/execute.ts index 3ee2c9ec9b4..fc7151b2b6e 100644 --- a/src/raps/execute.ts +++ b/src/raps/execute.ts @@ -24,6 +24,8 @@ import { createUnlockAndSwapRap } from './unlockAndSwap'; import { GasFeeParamsBySpeed, LegacyGasFeeParamsBySpeed, LegacyTransactionGasParamAmounts, TransactionGasParamAmounts } from '@/entities'; import { Screens, TimeToSignOperation, performanceTracking } from '@/state/performance/performance'; import { swapsStore } from '@/state/swaps/swapsStore'; +import { createClaimClaimableRap } from './claimClaimable'; +import { claimClaimable } from './actions/claimClaimable'; export function createSwapRapByType( type: T, @@ -36,6 +38,8 @@ export function createSwapRapByType( return createUnlockAndCrosschainSwapRap(swapParameters as RapSwapActionParameters<'crosschainSwap'>); case 'swap': return createUnlockAndSwapRap(swapParameters as RapSwapActionParameters<'swap'>); + case 'claimClaimable': + return createClaimClaimableRap(swapParameters as RapSwapActionParameters<'claimClaimable'>); default: return Promise.resolve({ actions: [] }); } @@ -53,6 +57,8 @@ function typeAction(type: T, props: ActionProps) { return () => claimBridge(props as ActionProps<'claimBridge'>); case 'crosschainSwap': return () => crosschainSwap(props as ActionProps<'crosschainSwap'>); + case 'claimClaimable': + return () => claimClaimable(props as ActionProps<'claimClaimable'>); default: // eslint-disable-next-line react/display-name return () => null; @@ -128,11 +134,11 @@ const waitForNodeAck = async (hash: string, provider: Signer['provider']): Promi export const walletExecuteRap = async ( wallet: Signer, type: RapTypes, - parameters: RapSwapActionParameters<'swap' | 'crosschainSwap' | 'claimBridge'> + parameters: RapSwapActionParameters<'swap' | 'crosschainSwap' | 'claimBridge' | 'claimClaimable'> ): Promise<{ nonce: number | undefined; errorMessage: string | null }> => { // NOTE: We don't care to track claimBridge raps const rap = - type === 'claimBridge' + type === 'claimBridge' || type == 'claimClaimable' ? await createSwapRapByType(type, parameters) : await performanceTracking.getState().executeFn({ fn: createSwapRapByType, diff --git a/src/raps/references.ts b/src/raps/references.ts index 259b8fe330c..3ebd948c875 100644 --- a/src/raps/references.ts +++ b/src/raps/references.ts @@ -5,6 +5,7 @@ import { Address } from 'viem'; import { ParsedAsset } from '@/__swaps__/types/assets'; import { GasFeeParamsBySpeed, LegacyGasFeeParamsBySpeed, LegacyTransactionGasParamAmounts, TransactionGasParamAmounts } from '@/entities'; import { ChainId } from '@/chains/types'; +import { TransactionClaimableTxPayload } from '@/screens/claimables/transaction/types'; export enum SwapModalField { input = 'inputAmount', @@ -39,9 +40,17 @@ export type QuoteTypeMap = { swap: Quote; crosschainSwap: CrosschainQuote; claimBridge: undefined; + claimClaimable: Quote | CrosschainQuote; }; -export interface RapSwapActionParameters { +type AdditionalParamsMap = { + swap: undefined; + crosschainSwap: undefined; + claimBridge: undefined; + claimClaimable: { claimTx: TransactionClaimableTxPayload }; +}; + +export interface RapSwapActionParameters { amount?: string | null; sellAmount: string; buyAmount?: string; @@ -58,6 +67,7 @@ export interface RapSwapActionParameters | RapSwapActionParameters<'crosschainSwap'> | RapClaimActionParameters - | RapUnlockActionParameters; + | RapUnlockActionParameters + | RapClaimClaimableActionParameters; export interface RapActionTransaction { hash: string | null; @@ -95,6 +108,7 @@ export type RapActionParameterMap = { unlock: RapUnlockActionParameters; claim: RapClaimActionParameters; claimBridge: RapClaimActionParameters; + claimClaimable: RapClaimClaimableActionParameters; }; export interface RapAction { @@ -104,7 +118,7 @@ export interface RapAction { } export interface Rap { - actions: RapAction<'swap' | 'crosschainSwap' | 'unlock' | 'claim' | 'claimBridge'>[]; + actions: RapAction<'swap' | 'crosschainSwap' | 'unlock' | 'claim' | 'claimBridge' | 'claimClaimable'>[]; } export enum rapActions { @@ -113,6 +127,7 @@ export enum rapActions { unlock = 'unlock', claim = 'claim', claimBridge = 'claimBridge', + claimClaimable = 'claimClaimable', } export type RapActionTypes = keyof typeof rapActions; @@ -121,6 +136,7 @@ export enum rapTypes { swap = 'swap', crosschainSwap = 'crosschainSwap', claimBridge = 'claimBridge', + claimClaimable = 'claimClaimable', } export type RapTypes = keyof typeof rapTypes; @@ -147,6 +163,6 @@ export interface ActionProps { } export interface WalletExecuteRapProps { - rapActionParameters: RapSwapActionParameters<'swap' | 'crosschainSwap' | 'claimBridge'>; + rapActionParameters: RapSwapActionParameters<'swap' | 'crosschainSwap' | 'claimBridge' | 'claimClaimable'>; type: RapTypes; }