diff --git a/centrifuge-app/src/components/InvestRedeem/Claim.tsx b/centrifuge-app/src/components/InvestRedeem/Claim.tsx index 56d9fadf0..8a0ee3ffe 100644 --- a/centrifuge-app/src/components/InvestRedeem/Claim.tsx +++ b/centrifuge-app/src/components/InvestRedeem/Claim.tsx @@ -11,6 +11,8 @@ export function Claim({ type, onDismiss }: { type: 'invest' | 'redeem'; onDismis const isPending = !!state.pendingTransaction && ['creating', 'unconfirmed', 'pending'].includes(state.pendingTransaction?.status) const isCollecting = state.pendingAction === 'collect' && isPending + const isPreAction = state.pendingAction === 'preAction' && isPending + return ( {state.collectType === 'invest' ? ( @@ -52,24 +54,30 @@ export function Claim({ type, onDismiss }: { type: 'invest' | 'redeem'; onDismis )} {state.needsToCollectBeforeOrder && Claim tokens before placing another order} - + {state.needsPreAction('collect') ? ( + + ) : ( + + )} {!state.needsToCollectBeforeOrder && ( - )} + {state.canCancelOrder && + !state.collectType && + hasPendingOrder && + (state.needsPreAction('cancelInvest') ? ( + + ) : ( + + ))} diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemCentrifugeProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemCentrifugeProvider.tsx index 237ffeb66..df50d2565 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemCentrifugeProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemCentrifugeProvider.tsx @@ -60,6 +60,7 @@ export function InvestRedeemCentrifugeProvider({ poolId, trancheId, children }: approveTrancheToken: undefined, cancelInvest, cancelRedeem, + preAction: undefined, } const pendingTransaction = pendingAction && txActions[pendingAction]?.lastCreatedTransaction @@ -140,6 +141,7 @@ export function InvestRedeemCentrifugeProvider({ poolId, trancheId, children }: needsToCollectBeforeOrder: false, needsPoolCurrencyApproval: () => false, needsTrancheTokenApproval: () => false, + needsPreAction: () => '', canChangeOrder: true, canCancelOrder: true, pendingAction, @@ -156,6 +158,7 @@ export function InvestRedeemCentrifugeProvider({ poolId, trancheId, children }: cancelInvest: doAction('cancelInvest', () => [poolId, trancheId, new BN(0)], { account, forceProxyType: 'Invest' }), cancelRedeem: doAction('cancelRedeem', () => [poolId, trancheId, new BN(0)], { account, forceProxyType: 'Invest' }), selectPoolCurrency() {}, + preAction() {}, } const hooks = { diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx index 746e8a3e1..fd27f89ee 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx @@ -81,6 +81,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children const collectInvest = useEvmTransaction('Claim', (cent) => cent.liquidityPools.mint) const collectRedeem = useEvmTransaction('Withdraw', (cent) => cent.liquidityPools.withdraw) const approve = useEvmTransaction('Approve', (cent) => cent.liquidityPools.approveForCurrency) + const enableRouter = useEvmTransaction('Approve', (cent) => cent.liquidityPools.enableCentrifugeRouter) const cancelInvest = useEvmTransaction('Cancel order', (cent) => cent.liquidityPools.cancelInvestOrder) const cancelRedeem = useEvmTransaction('Cancel order', (cent) => cent.liquidityPools.cancelRedeemOrder) const collectCancelInvest = useEvmTransaction('Claim', (cent) => cent.liquidityPools.claimCancelDeposit) @@ -104,6 +105,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children approveTrancheToken: approve, cancelInvest, cancelRedeem, + preAction: enableRouter, } const pendingAction = ['investWithPermit', 'decreaseInvest'].includes(pendingActionState!) ? 'invest' @@ -205,6 +207,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children return lpInvest ? lpInvest.lpCurrencyAllowance.toFloat() < amount && !supportsPermits : false }, needsTrancheTokenApproval: () => false, + needsPreAction: (action) => (lpInvest && !lpInvest.isRouterEnabled && action !== 'invest' ? 'Approve' : ''), canChangeOrder, canCancelOrder: !(lpInvest?.pendingCancelDepositRequest || lpInvest?.pendingCancelRedeemRequest), pendingAction, @@ -256,6 +259,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children chainId, ]), approveTrancheToken: () => {}, + preAction: doAction('preAction', () => [lpInvest?.lpAddress, chainId]), cancelInvest: doAction('cancelInvest', () => [lpInvest?.lpAddress, chainId], undefined, { poolId, trancheId }), cancelRedeem: doAction('cancelRedeem', () => [lpInvest?.lpAddress, chainId], undefined, { poolId, trancheId }), selectPoolCurrency(symbol) { diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemTinlakeProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemTinlakeProvider.tsx index 90d5a193b..42e012d44 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemTinlakeProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemTinlakeProvider.tsx @@ -63,6 +63,7 @@ export function InvestRedeemTinlakeProvider({ poolId, trancheId, children }: Pro approveTrancheToken, cancelInvest, cancelRedeem, + preAction: undefined, } const pendingTransaction = pendingAction && txActions[pendingAction]?.lastCreatedTransaction @@ -133,6 +134,7 @@ export function InvestRedeemTinlakeProvider({ poolId, trancheId, children }: Pro needsToCollectBeforeOrder: !collectAmount.isZero(), needsPoolCurrencyApproval: (amount) => Dec(amount).gt(trancheInvestment?.poolCurrencyAllowance ?? 0), needsTrancheTokenApproval: (amount) => Dec(amount).gt(trancheInvestment?.tokenAllowance ?? 0), + needsPreAction: () => '', canChangeOrder: true, canCancelOrder: true, pendingAction, @@ -149,6 +151,7 @@ export function InvestRedeemTinlakeProvider({ poolId, trancheId, children }: Pro cancelInvest: doAction('cancelInvest', () => [seniority, new BN(0)]), cancelRedeem: doAction('cancelRedeem', () => [seniority, new BN(0)]), selectPoolCurrency() {}, + preAction() {}, } const hooks = { diff --git a/centrifuge-app/src/components/InvestRedeem/RedeemForm.tsx b/centrifuge-app/src/components/InvestRedeem/RedeemForm.tsx index fcec29bb2..97b8f6d48 100644 --- a/centrifuge-app/src/components/InvestRedeem/RedeemForm.tsx +++ b/centrifuge-app/src/components/InvestRedeem/RedeemForm.tsx @@ -90,8 +90,15 @@ export function RedeemForm({ autoFocus }: RedeemFormProps) { const isApproving = state.pendingAction === 'approveTrancheToken' && isPending const calculatingOrders = pool.epoch.status !== 'ongoing' + const isPreAction = state.pendingAction === 'preAction' && isPending - const preSubmitAction = state.needsTrancheTokenApproval(inputToNumber(form.values.amount)) + const preSubmitAction = state.needsPreAction('redeem') + ? { + onClick: () => actions.preAction('redeem'), + loading: isPreAction, + label: state.needsPreAction('redeem'), + } + : state.needsTrancheTokenApproval(inputToNumber(form.values.amount)) ? { onClick: () => actions.approveTrancheToken(TokenBalance.fromFloat(form.values.amount, state.trancheCurrency!.decimals)), diff --git a/centrifuge-app/src/components/InvestRedeem/types.ts b/centrifuge-app/src/components/InvestRedeem/types.ts index a0aebddf7..1b881e887 100644 --- a/centrifuge-app/src/components/InvestRedeem/types.ts +++ b/centrifuge-app/src/components/InvestRedeem/types.ts @@ -15,6 +15,7 @@ export type InvestRedeemAction = | 'approveTrancheToken' | 'cancelInvest' | 'cancelRedeem' + | 'preAction' export type InvestRedeemState = { poolId: string @@ -52,6 +53,7 @@ export type InvestRedeemState = { needsToCollectBeforeOrder: boolean needsPoolCurrencyApproval: (amount: number) => boolean needsTrancheTokenApproval: (amount: number) => boolean + needsPreAction: (action: InvestRedeemAction) => string canChangeOrder: boolean canCancelOrder: boolean pendingAction?: InvestRedeemAction | null @@ -71,6 +73,7 @@ export type InvestRedeemActions = { collect(): void approvePoolCurrency(amount: BN): void approveTrancheToken(amount: BN): void + preAction(action: InvestRedeemAction): void cancelInvest(): void cancelRedeem(): void selectPoolCurrency(symbol: string): void diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index d9fd649ba..51bfecebd 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -283,6 +283,13 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return permit as Permit } + function enableCentrifugeRouter(args: [lpAddress: string, chainId: number], options: TransactionRequest = {}) { + const [lpAddress, chainId] = args + const centrifugeRouterAddress = getCentrifugeRouterAddress(chainId) + + return pending(contract(centrifugeRouterAddress, new Interface(ABI.CentrifugeRouter)).enable(lpAddress, options)) + } + function increaseInvestOrder( args: [lpAddress: string, order: BN, chainId: number], options: TransactionRequest = {} @@ -834,6 +841,11 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { call: ['function maxRedeem(address) view returns (uint256)', user], returns: [['maxRedeem', currencyBalanceTransform]], }, + { + target: getCentrifugeRouterAddress(chainId), + call: ['function isEnabled(address, address) view returns (bool)', lp.lpAddress, user], + returns: [['isRouterEnabled']], + }, ] const pool = await multicall<{ @@ -851,6 +863,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { claimableCancelRedeemRequest: TokenBalance pendingCancelDepositRequest: boolean pendingCancelRedeemRequest: boolean + isRouterEnabled: boolean }>(calls, { rpcProvider: options?.rpcProvider ?? inst.config.evmSigner?.provider!, }) @@ -882,5 +895,6 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { getLiquidityPoolInvestment, getRecentLPEvents, getCentrifugeRouterAllowance, + enableCentrifugeRouter, } }