-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asset finance repay redesign #2282
Merged
Merged
Changes from 98 commits
Commits
Show all changes
110 commits
Select commit
Hold shift + click to select a range
1b0e774
Move transfer debt form so it's showed after the user chooses a source
sophialittlejohn 593b391
Add SourceSelect to repay forms
sophialittlejohn e76d001
Fix decimals
sophialittlejohn d844635
Add fee charging to finance forms (WIP)
sophialittlejohn fef1b07
Add remark txs
sophialittlejohn 3c36d86
Update Repay forms and add fees to repay
sophialittlejohn 096af14
Fix usabilty of fee select
sophialittlejohn 62b8e6b
Fix tx execution
sophialittlejohn cdb7b5f
Update charge fee UI
sophialittlejohn 83d1109
Limit fee charging to borrower (fee must be added with borrower as de…
sophialittlejohn df34f85
Add comment about fees
sophialittlejohn 454c08c
Split up finance and repay drawers & UI improvements
sophialittlejohn e20e04d
Move available financing to loan page
sophialittlejohn 8d3e6be
Add total amount and rename amount to principal in forms
sophialittlejohn 7923fc9
Deploy PR preview to demo
sophialittlejohn 91e1e5f
Purchase/Finance vs Sell/Repay and add totals
sophialittlejohn 88e2b9c
Pass fee tx to remark tx to be executed there
sophialittlejohn 1e53c75
Implement transfer debt directly in finance form
sophialittlejohn e012a3e
Allow multiple fees and check validity of inputs
sophialittlejohn 0a642e6
Disable buttons while form is incomplete
sophialittlejohn dace43f
Better form validation for external assets
sophialittlejohn fed8491
Finish adding transfer debt to all finance/repay forms
sophialittlejohn b11e694
Fix mac price variants from failing on non oracle assets
sophialittlejohn afc110b
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 6b2fd62
Fix inconsistencies
sophialittlejohn ceed6ec
Transfer debt source/desitnation only show cash assets
sophialittlejohn 4e8369e
UI changes proposed by Jeroen
sophialittlejohn 52bde42
Unify finance/repay and transfer debt forms
sophialittlejohn 2833e73
Fix default behavior of add fee
sophialittlejohn 5373183
Add text blurbs
sophialittlejohn 64cba91
Add charge fee summary
sophialittlejohn 0b7abb4
Remove padding on add fees button
sophialittlejohn 585fc87
Handle input/erros in repay form
sophialittlejohn dfb33a1
Update info texts in all forms
sophialittlejohn c648cab
Add error handling and better form control
sophialittlejohn 28d27af
Fix bug in available external finance form
sophialittlejohn 0b26f90
Updates to inline feedback component
sophialittlejohn 6e18da1
Fix fee tx submission
sophialittlejohn 28a61fb
Validate upper limits in repay forms and fix required vs non required…
sophialittlejohn ffb9953
Rename
sophialittlejohn ff02385
Fix bugs in internal finance form
sophialittlejohn 6528b7f
Check charged fees against max charageable
sophialittlejohn 8dfaa11
Remove indiv error messages in favor of general ones on repay form
sophialittlejohn 95333c6
Improve error handling in repay form
sophialittlejohn 6ca0139
Fix wording
sophialittlejohn 3091535
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 5735a24
Fix warning
hieronx a42f18c
Remove repay all and allow repayments of just interest
sophialittlejohn 66c3de7
Merge branch 'asset-finance-repay-redesign' of github.com:centrifuge/…
sophialittlejohn 3aac9d1
Fix type error
sophialittlejohn c13b845
Rename external repay form to sell and use source loan max interest
sophialittlejohn f7a6b57
Rename external finance form to purchase
sophialittlejohn a54cf2b
Prep for cash finance/repayments
sophialittlejohn 316e414
Add support for cash assets
sophialittlejohn 40ac92a
Add cash asset suuport to repay
sophialittlejohn 3ce899a
Clean up and fix form submissions
sophialittlejohn 8fc9755
Fix template rendering
sophialittlejohn c1f3204
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 0f951ef
Fix decimal point error and TransferDebtAmountMismatched error
sophialittlejohn 07a6676
Allow fees to be charged by non AO proxy destinations
sophialittlejohn 7ac2eeb
Cash: rename principal to amount and include withdrawal addresses
sophialittlejohn 32f296d
Fix fee submission
sophialittlejohn f6569d7
Revert charging without AO and remove uncharge fees
sophialittlejohn f33889c
Attempt to fix proxy call on repay
sophialittlejohn 511db30
Fix tx pushed mistake
sophialittlejohn db5e696
Wrap proxy calls and move remarks to module
sophialittlejohn c35aa69
Remove fee percentage from dropdown
sophialittlejohn e6a04bd
Fix showing finance form
sophialittlejohn 8b80f27
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 0b6d944
Always show repay forms so that money can be transfer even without ou…
sophialittlejohn 654b9e0
Fix bug where initial input is missing in fee category
sophialittlejohn 292c31b
Charge fee difference instead of uncharging/recharging
sophialittlejohn 3fea8c4
Fix available in repay forms
sophialittlejohn fc5b2dd
Remove close all transaction
sophialittlejohn 141d169
Use USD for all virtual accounting processes
sophialittlejohn 9ba1db1
Fix null in extension period
sophialittlejohn 8004bb8
Consitently use two commas in error messages
sophialittlejohn 442f04e
Price and quantity updates (max, secondary labels), show buttons appr…
sophialittlejohn 610e1cc
Add custom padding to drawer
sophialittlejohn 6d253d7
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn e99d59e
Remove maturity date in loan list
sophialittlejohn 2482926
Remove decimals from quantity
sophialittlejohn 9ca1adb
Reorder category options in repay
sophialittlejohn 2ae2241
Remove financing date for cash assets
sophialittlejohn 4dc136b
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 58f6909
Merge branch 'main' into asset-finance-repay-redesign
hieronx 9db66b8
Remove low wallet balance warning
sophialittlejohn d214fa7
Add interest rate in pricing values
sophialittlejohn 39ba815
Add tooltip for additional amount input
sophialittlejohn eec0710
Better error messages
sophialittlejohn 52c813f
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 3acd30f
Merge branch 'asset-finance-repay-redesign' of github.com:centrifuge/…
sophialittlejohn b1dd5b2
Improve error messages and remove additional amount from max calcs
sophialittlejohn 17fbc70
Fix repay forms and add errors for balance checking
sophialittlejohn 00dc506
Merge branch 'main' of https://github.com/centrifuge/apps into asset-…
hieronx 763a60c
Asset redesign fixes (#2353)
hieronx 2708d04
Add changes for Jay and add disabled input for principal on external …
sophialittlejohn c9d9a7f
Add tooltips, improve spacing in summary and attempt to charge margin…
sophialittlejohn f3e02eb
Correct interest margin calc
sophialittlejohn 12fb134
Merge branch 'main' of github.com:centrifuge/apps into asset-finance-…
sophialittlejohn 368da6c
Use textencoder instead of Buffer, fix spacing in finance form summar…
sophialittlejohn b42647c
Fix margin buffer and when to use it
sophialittlejohn 32f1b55
convert 5 minute buffer to seconds
sophialittlejohn 499a414
Add reserve info box to finance forms
sophialittlejohn aab291d
Fix layout of external repay
sophialittlejohn 3c41178
Add component for ErrorMessage
sophialittlejohn 525332f
Add principal calc to external finance form
sophialittlejohn d4f6286
Add missing gap
sophialittlejohn bed9658
Merge branch 'main' into asset-finance-repay-redesign
hieronx ec4306a
Merge branch 'main' into asset-finance-repay-redesign
sophialittlejohn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,21 @@ | ||
REACT_APP_COLLATOR_WSS_URL=wss://fullnode.development.cntrfg.com | ||
REACT_APP_DEFAULT_UNLIST_POOLS=false | ||
REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-dev | ||
REACT_APP_COLLATOR_WSS_URL=wss://fullnode-apps.demo.k-f.dev | ||
REACT_APP_DEFAULT_UNLIST_POOLS=true | ||
REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-demo | ||
REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ | ||
REACT_APP_IS_DEMO=false | ||
REACT_APP_NETWORK=centrifuge | ||
REACT_APP_ONBOARDING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/onboarding-api-dev | ||
REACT_APP_PINNING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/pinning-api-dev | ||
REACT_APP_IS_DEMO=true | ||
REACT_APP_ONBOARDING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/onboarding-api-demo | ||
REACT_APP_PINNING_API_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/pinning-api-demo | ||
REACT_APP_POOL_CREATION_TYPE=immediate | ||
REACT_APP_RELAY_WSS_URL=wss://fullnode-relay.development.cntrfg.com | ||
REACT_APP_SUBQUERY_URL=https://api.subquery.network/sq/centrifuge/pools-development | ||
REACT_APP_SUBSCAN_URL=https://centrifuge.subscan.io | ||
REACT_APP_RELAY_WSS_URL=wss://frag-moonbase-relay-rpc-ws.g.moonbase.moonbeam.network | ||
REACT_APP_SUBQUERY_URL=https://api.subquery.network/sq/centrifuge/pools-demo-multichain | ||
REACT_APP_SUBSCAN_URL= | ||
REACT_APP_TINLAKE_NETWORK=goerli | ||
REACT_APP_INFURA_KEY=8cd8e043ee8d4001b97a1c37e08fd9dd | ||
REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 | ||
REACT_APP_WHITELISTED_ACCOUNTS= | ||
REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn | ||
REACT_APP_NETWORK=centrifuge | ||
REACT_APP_REWARDS_TREE_URL=https://storage.googleapis.com/rad-rewards-trees-kovan-staging/latest.json | ||
REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kALwmJutBq95s41U9fWnoApCUgvPqPGTh1GSmFnQh5f9fWo93 | ||
REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a | ||
REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kAJ27w29x7gHM75xajP2yXVLjVBaKmmUTxHwgRuCoAcWaoEiz | ||
REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn | ||
REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn | ||
REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import { CurrencyBalance, Pool, addressToHex } from '@centrifuge/centrifuge-js' | ||
import { | ||
CombinedSubstrateAccount, | ||
formatBalance, | ||
useCentrifuge, | ||
useCentrifugeApi, | ||
wrapProxyCallsForAccount, | ||
} from '@centrifuge/centrifuge-react' | ||
import { Box, CurrencyInput, IconMinusCircle, IconPlusCircle, Select, Shelf, Stack, Text } from '@centrifuge/fabric' | ||
import { Field, FieldArray, FieldProps, useFormikContext } from 'formik' | ||
import React from 'react' | ||
import { combineLatest, of, switchMap } from 'rxjs' | ||
import { Dec } from '../../utils/Decimal' | ||
import { useBorrower } from '../../utils/usePermissions' | ||
import { usePool, usePoolFees, usePoolMetadata } from '../../utils/usePools' | ||
import { FinanceValues } from './ExternalFinanceForm' | ||
import { RepayValues } from './RepayForm' | ||
|
||
export const ChargeFeesFields = ({ | ||
pool, | ||
borrower, | ||
}: { | ||
pool: Pool | ||
borrower: CombinedSubstrateAccount | undefined | ||
}) => { | ||
const form = useFormikContext<FinanceValues>() | ||
const { data: poolMetadata } = usePoolMetadata(pool) | ||
const poolFees = usePoolFees(pool.id) | ||
// fees can only be charged by the destination address | ||
// fees destination must be set to the AO Proxy address | ||
const chargableFees = React.useMemo( | ||
() => | ||
poolFees?.filter( | ||
(fee) => fee.type !== 'fixed' && borrower && addressToHex(fee.destination) === borrower.actingAddress | ||
), | ||
[poolFees, borrower] | ||
) | ||
|
||
const getOptions = React.useCallback(() => { | ||
const chargableOptions = (chargableFees || []).map((f) => { | ||
const feeName = poolMetadata?.pool?.poolFees?.find((feeMeta) => feeMeta.id === f.id)?.name || 'Unknown Fee' | ||
return { | ||
label: `${feeName}`, | ||
value: f.id.toString(), | ||
} | ||
}) | ||
return chargableFees && chargableFees.length > 1 | ||
? [{ label: 'Select fee', value: '' }, ...chargableOptions] | ||
: chargableOptions | ||
}, [chargableFees, poolMetadata]) | ||
|
||
return ( | ||
<Stack gap={2}> | ||
<FieldArray name="fees"> | ||
{({ remove, push }) => { | ||
return ( | ||
<> | ||
<Stack gap={2}> | ||
<Stack gap={2}> | ||
{form.values.fees.map((fee, index) => { | ||
return ( | ||
<Shelf key={`${fee.id}-${index}`} gap={1} alignItems="flex-start"> | ||
<Box flex={1}> | ||
<Select | ||
options={getOptions()} | ||
label="Fee" | ||
onChange={(e) => { | ||
form.setFieldValue(`fees.${index}.id`, e.target.value) | ||
}} | ||
value={form.values.fees[index].id} | ||
/> | ||
</Box> | ||
<Box flex={1}> | ||
<Field | ||
key={`fees.${index}.amount`} | ||
name={`fees.${index}.amount`} | ||
validate={(value: number) => { | ||
let error | ||
if (!value) { | ||
error = 'Enter an amount or remove the fee' | ||
} | ||
return error | ||
}} | ||
> | ||
{({ field, meta }: FieldProps) => { | ||
return ( | ||
<CurrencyInput | ||
{...field} | ||
label="Amount" | ||
errorMessage={meta.touched ? meta.error : undefined} | ||
currency={pool.currency.symbol} | ||
placeholder="0" | ||
onChange={(value) => form.setFieldValue(`fees.${index}.amount`, value)} | ||
/> | ||
) | ||
}} | ||
</Field> | ||
</Box> | ||
<Box | ||
alignSelf="flex-start" | ||
background="none" | ||
border="none" | ||
as="button" | ||
mt={4} | ||
style={{ cursor: 'pointer' }} | ||
onClick={() => remove(index)} | ||
> | ||
<IconMinusCircle size="20px" /> | ||
</Box> | ||
</Shelf> | ||
) | ||
})} | ||
</Stack> | ||
{chargableFees?.length ? ( | ||
<Shelf | ||
gap={1} | ||
alignItems="center" | ||
as="button" | ||
style={{ cursor: 'pointer', background: 'none', border: 'none' }} | ||
onClick={(e) => { | ||
e.preventDefault() | ||
if (chargableFees.length === 1) { | ||
return push({ id: chargableFees[0].id.toString(), amount: '' }) | ||
} | ||
return push({ id: '', amount: '' }) | ||
}} | ||
> | ||
<IconPlusCircle size="20px" color="textButtonTertiary" /> | ||
<Text variant="label1" color="textButtonTertiary"> | ||
Add fee | ||
</Text> | ||
</Shelf> | ||
) : null} | ||
</Stack> | ||
</> | ||
) | ||
}} | ||
</FieldArray> | ||
</Stack> | ||
) | ||
} | ||
|
||
function ChargePoolFeeSummary({ poolId }: { poolId: string }) { | ||
const form = useFormikContext<FinanceValues | RepayValues>() | ||
const pool = usePool(poolId) | ||
const totalFees = form.values.fees.reduce((acc, fee) => acc.add(Dec(fee.amount || 0)), Dec(0)) | ||
|
||
return form.values.fees.length > 0 ? ( | ||
<Stack gap={1}> | ||
<Shelf justifyContent="space-between"> | ||
<Text variant="label2">Fees</Text> | ||
<Text variant="label2">{formatBalance(Dec(totalFees), pool.currency.symbol, 2)}</Text> | ||
</Shelf> | ||
</Stack> | ||
) : null | ||
} | ||
|
||
export function useChargePoolFees(poolId: string, loanId: string) { | ||
const pool = usePool(poolId) | ||
const borrower = useBorrower(poolId, loanId) | ||
const api = useCentrifugeApi() | ||
const cent = useCentrifuge() | ||
return { | ||
render: () => <ChargeFeesFields pool={pool as Pool} borrower={borrower} />, | ||
renderSummary: () => <ChargePoolFeeSummary poolId={poolId} />, | ||
isValid: ({ values }: { values: Pick<FinanceValues | RepayValues, 'fees'> }) => { | ||
return values.fees.every((fee) => !!fee.id && !!fee.amount) | ||
}, | ||
getBatch: ({ values }: { values: Pick<FinanceValues | RepayValues, 'fees'> }) => { | ||
if (!values.fees.length) return of([]) | ||
const fees = values.fees.flatMap((fee) => { | ||
if (!fee.amount) throw new Error('Charge amount not provided') | ||
if (!borrower) throw new Error('No borrower') | ||
const feeAmount = CurrencyBalance.fromFloat(fee.amount, pool.currency.decimals) | ||
let feeTx = api.tx.poolFees.chargeFee(fee.id, feeAmount.toString()) | ||
return cent.remark | ||
.remark([[{ Loan: [poolId, loanId] }], feeTx], { batch: true }) | ||
.pipe(switchMap((tx) => [wrapProxyCallsForAccount(api, tx, borrower, 'Borrow')])) | ||
}) | ||
return combineLatest(fees) | ||
}, | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can just be a
map
(without returning as an array, I guess)