diff --git a/centrifuge-app/src/components/Tooltips.tsx b/centrifuge-app/src/components/Tooltips.tsx
index 44163a686..2b51b6bf3 100644
--- a/centrifuge-app/src/components/Tooltips.tsx
+++ b/centrifuge-app/src/components/Tooltips.tsx
@@ -318,6 +318,14 @@ export const tooltipText = {
label: 'Additional amount',
body: 'This can be used to repay an additional amount beyond the outstanding principal and interest of the asset. This will lead to an increase in the NAV of the pool.',
},
+ repayFormAvailableBalance: {
+ label: 'Available balance',
+ body: 'Balance of the asset originator account on Centrifuge.',
+ },
+ repayFormAvailableBalanceUnlimited: {
+ label: 'Available balance',
+ body: 'Unlimited because this is a virtual accounting process.',
+ },
}
export type TooltipsProps = {
diff --git a/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx b/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx
index 8f585e0f1..cf3f5f00c 100644
--- a/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx
+++ b/centrifuge-app/src/pages/Loan/ExternalRepayForm.tsx
@@ -5,7 +5,7 @@ import {
useCentrifugeUtils,
wrapProxyCallsForAccount,
} from '@centrifuge/centrifuge-react'
-import { Box, Button, CurrencyInput, InlineFeedback, Shelf, Stack, Text, Tooltip } from '@centrifuge/fabric'
+import { Box, Button, CurrencyInput, InlineFeedback, Shelf, Stack, Text } from '@centrifuge/fabric'
import { BN } from 'bn.js'
import Decimal from 'decimal.js-light'
import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik'
@@ -282,35 +282,28 @@ export function ExternalRepayForm({ loan, destination }: { loan: ExternalLoan; d
)}
- Transaction summary
-
-
- Available balance
-
-
-
- {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)}
-
-
-
-
+ Transaction summary
-
- Sale amount
+
+
+ {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)}
- {formatBalance(totalRepay, displayCurrency, 2)}
-
- {poolFees.renderSummary()}
+
+
+
+ Sale amount
+
+ {formatBalance(totalRepay, displayCurrency, 2)}
+
+
+
+ {poolFees.renderSummary()}
+
{destination === 'reserve' ? (
diff --git a/centrifuge-app/src/pages/Loan/RepayForm.tsx b/centrifuge-app/src/pages/Loan/RepayForm.tsx
index 161aa25ae..ac2f2dbc5 100644
--- a/centrifuge-app/src/pages/Loan/RepayForm.tsx
+++ b/centrifuge-app/src/pages/Loan/RepayForm.tsx
@@ -1,4 +1,12 @@
-import { ActiveLoan, CreatedLoan, CurrencyBalance, ExternalLoan, findBalance, Loan } from '@centrifuge/centrifuge-js'
+import {
+ ActiveLoan,
+ CreatedLoan,
+ CurrencyBalance,
+ ExternalLoan,
+ findBalance,
+ Loan,
+ Rate,
+} from '@centrifuge/centrifuge-js'
import {
useBalances,
useCentrifugeApi,
@@ -6,7 +14,7 @@ import {
useCentrifugeUtils,
wrapProxyCallsForAccount,
} from '@centrifuge/centrifuge-react'
-import { Box, Button, CurrencyInput, InlineFeedback, Select, Shelf, Stack, Text, Tooltip } from '@centrifuge/fabric'
+import { Box, Button, CurrencyInput, InlineFeedback, Select, Shelf, Stack, Text } from '@centrifuge/fabric'
import Decimal from 'decimal.js-light'
import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik'
import * as React from 'react'
@@ -75,6 +83,7 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo
const destinationLoan = loans?.find((l) => l.id === destination) as Loan
const displayCurrency = destination === 'reserve' ? pool.currency.symbol : 'USD'
const utils = useCentrifugeUtils()
+ const [usedMaxInterest, setUsedMaxInterest] = React.useState(false)
const { execute: doRepayTransaction, isLoading: isRepayLoading } = useCentrifugeTransaction(
isCashLoan(loan) ? 'Withdraw funds' : 'Repay asset',
@@ -127,10 +136,37 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo
category: 'correction',
},
onSubmit: (values, actions) => {
- const interest = CurrencyBalance.fromFloat(values.interest || 0, pool.currency.decimals)
+ let interest = CurrencyBalance.fromFloat(values.interest || 0, pool.currency.decimals)
const additionalAmount = CurrencyBalance.fromFloat(values.amountAdditional || 0, pool.currency.decimals)
const principal = CurrencyBalance.fromFloat(values.principal || 0, pool.currency.decimals)
+ if (usedMaxInterest) {
+ const time = Date.now() - loan.fetchedAt.getTime()
+ const outstandingInterest =
+ 'outstandingInterest' in loan
+ ? loan.outstandingInterest
+ : CurrencyBalance.fromFloat(0, pool.currency.decimals)
+ const outstandingPrincipal = new CurrencyBalance(
+ loan.outstandingDebt.sub(outstandingInterest),
+ pool.currency.decimals
+ )
+
+ // TODO: this number is way too small, after repaying we still end up with interest outstanding
+ const mostUpToDateInterest = CurrencyBalance.fromFloat(
+ outstandingPrincipal
+ .toDecimal()
+ .mul(Rate.fractionFromAprPercent(loan.pricing.interestRate.toDecimal().mul(100)).toDecimal())
+ .mul(time / (60 * 60 * 24 * 365))
+ .add(outstandingInterest.toDecimal()),
+ pool.currency.decimals
+ )
+ interest = mostUpToDateInterest
+ console.log(
+ `Repaying with the most up to date outstanding interest: ${mostUpToDateInterest.toDecimal()} instead of ${outstandingInterest.toDecimal()}`,
+ loan.pricing.interestRate.toDecimal().toString()
+ )
+ }
+
doRepayTransaction([principal, interest, additionalAmount], {
account,
forceProxyType: 'Borrow',
@@ -193,7 +229,9 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo
disabled={isRepayLoading}
currency={displayCurrency}
onChange={(value) => form.setFieldValue('principal', value)}
- onSetMax={() => form.setFieldValue('principal', maxPrincipal.gte(0) ? maxPrincipal : 0)}
+ onSetMax={() => {
+ form.setFieldValue('principal', maxPrincipal.gte(0) ? maxPrincipal : 0)
+ }}
secondaryLabel={`${formatBalance(maxPrincipal, displayCurrency)} outstanding`}
/>
)
@@ -217,7 +255,10 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo
disabled={isRepayLoading}
currency={displayCurrency}
onChange={(value) => form.setFieldValue('interest', value)}
- onSetMax={() => form.setFieldValue('interest', maxInterest.gte(0) ? maxInterest : 0)}
+ onSetMax={() => {
+ setUsedMaxInterest(true)
+ form.setFieldValue('interest', maxInterest.gte(0) ? maxInterest : 0)
+ }}
/>
)
}}
@@ -300,34 +341,27 @@ function InternalRepayForm({ loan, destination }: { loan: ActiveLoan | CreatedLo
Transaction summary
-
-
- Available balance
-
-
-
- {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)}
-
-
-
-
-
- {isCashLoan(loan) ? 'Withdrawal amount' : 'Repayment amount'}
+
+
+ {maxAvailable === UNLIMITED ? 'No limit' : formatBalance(maxAvailable, displayCurrency, 2)}
- {formatBalance(totalRepay, displayCurrency, 2)}
-
- {poolFees.renderSummary()}
+
+
+
+ {isCashLoan(loan) ? 'Withdrawal amount' : 'Repayment amount'}
+
+ {formatBalance(totalRepay, displayCurrency, 2)}
+
+
+
+ {poolFees.renderSummary()}
+
{destination === 'reserve' ? (