Skip to content

Commit

Permalink
Merge branch 'main' into cent-app/update-pinata-gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
sophialittlejohn authored Sep 7, 2023
2 parents d5d7303 + b1f0ec4 commit cc8289e
Show file tree
Hide file tree
Showing 16 changed files with 139 additions and 185 deletions.
2 changes: 1 addition & 1 deletion centrifuge-app/.env-config/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ REACT_APP_WHITELISTED_ACCOUNTS=
REACT_APP_TINLAKE_SUBGRAPH_URL=https://graph.centrifuge.io/tinlake
REACT_APP_REWARDS_TREE_URL=https://storage.googleapis.com/rad-rewards-trees-kovan-staging/latest.json
REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a
REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kAKfp33p1SHRq6d1BMtGndP7Cek6pH6oZKKUoA7wJXRUqf6FY
REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kAJ27w29x7gHM75xajP2yXVLjVBaKmmUTxHwgRuCoAcWaoEiz
7 changes: 3 additions & 4 deletions centrifuge-app/src/components/Menu-deprecated/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { Box, IconInvestments, IconNft, Menu as Panel, MenuItemGroup, Shelf, Sta
import { config } from '../../config'
import { useAddress } from '../../utils/useAddress'
import { useIsAboveBreakpoint } from '../../utils/useIsAboveBreakpoint'
import { usePools } from '../../utils/usePools'
import { usePoolsThatAnyConnectedAddressHasPermissionsFor } from '../../utils/usePermissions'
import { RouterLinkButton } from '../RouterLinkButton'
import { GovernanceMenu } from './GovernanceMenu'
import { IssuerMenu } from './IssuerMenu'
import { PageLink } from './PageLink'
import { PoolLink } from './PoolLink'

export function Menu() {
// const pools = usePoolsThatAnyConnectedAddressHasPermissionsFor() || []
const pools = usePools() || []
const pools = usePoolsThatAnyConnectedAddressHasPermissionsFor() || []
const isXLarge = useIsAboveBreakpoint('XL')
const address = useAddress('substrate')

Expand All @@ -38,7 +37,7 @@ export function Menu() {
<GovernanceMenu />

{(pools.length > 0 || config.poolCreationType === 'immediate') && (
<IssuerMenu defaultOpen={isXLarge} stacked={!isXLarge} poolIds={pools.map(({ id }) => id)}>
<IssuerMenu defaultOpen={isXLarge} stacked={!isXLarge}>
{isXLarge ? (
<Stack as="ul" gap={1}>
{!!pools.length &&
Expand Down
5 changes: 2 additions & 3 deletions centrifuge-app/src/components/Menu/IssuerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import { Toggle } from './Toggle'

type IssuerMenuProps = {
defaultOpen?: boolean
poolIds?: string[]
stacked?: boolean
children?: React.ReactNode
}

export function IssuerMenu({ defaultOpen = false, poolIds = [], stacked, children }: IssuerMenuProps) {
export function IssuerMenu({ defaultOpen = false, stacked, children }: IssuerMenuProps) {
const match = useRouteMatch<{ pid: string }>('/issuer/:pid')
const isActive = match && poolIds.includes(match.params.pid)
const isActive = !!match
const [open, setOpen] = React.useState(defaultOpen)
const { space } = useTheme()
const fullWidth = `calc(100vw - 2 * ${space[1]}px)`
Expand Down
18 changes: 8 additions & 10 deletions centrifuge-app/src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { Box, IconInvestments, IconNft, Menu as Panel, MenuItemGroup, Shelf, Sta
import { config } from '../../config'
import { useAddress } from '../../utils/useAddress'
import { useIsAboveBreakpoint } from '../../utils/useIsAboveBreakpoint'
import { usePools } from '../../utils/usePools'
import { usePoolsThatAnyConnectedAddressHasPermissionsFor } from '../../utils/usePermissions'
import { RouterLinkButton } from '../RouterLinkButton'
import { GovernanceMenu } from './GovernanceMenu'
import { IssuerMenu } from './IssuerMenu'
import { PageLink } from './PageLink'
import { PoolLink } from './PoolLink'

export function Menu() {
// const pools = usePoolsThatAnyConnectedAddressHasPermissionsFor() || []
const pools = usePools() || []
const pools = usePoolsThatAnyConnectedAddressHasPermissionsFor() || []
const isLarge = useIsAboveBreakpoint('L')
const address = useAddress('substrate')

Expand All @@ -38,15 +37,14 @@ export function Menu() {
<GovernanceMenu />

{(pools.length > 0 || config.poolCreationType === 'immediate') && (
<IssuerMenu defaultOpen={isLarge} stacked={!isLarge} poolIds={pools.map(({ id }) => id)}>
<IssuerMenu defaultOpen={isLarge} stacked={!isLarge}>
{isLarge ? (
<Stack as="ul" gap={1}>
{!!pools.length &&
pools.map((pool) => (
<Box key={pool.id} as="li" pl={4}>
<PoolLink pool={pool} />
</Box>
))}
{pools.map((pool) => (
<Box key={pool.id} as="li" pl={4}>
<PoolLink pool={pool} />
</Box>
))}
{address && config.poolCreationType === 'immediate' && (
<Shelf justifyContent="center" as="li" mt={1}>
<CreatePool />
Expand Down
1 change: 0 additions & 1 deletion centrifuge-app/src/components/PoolFilter/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function filterPools(pools: PoolCardProps[], searchParams: URLSearchParam
filtered = filtered.filter(
(pool) => pool.status && (poolStatuses.size ? poolStatuses.has(toKebabCase(pool.status)) : pool.status !== 'Closed')
)
console.log('filtered', filtered)

if (assetClasses.size) {
filtered = filtered.filter((pool) => pool.assetClass && assetClasses.has(toKebabCase(pool.assetClass)))
Expand Down
5 changes: 1 addition & 4 deletions centrifuge-app/src/pages/Pools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ export function PoolsPage() {
function Pools() {
const cent = useCentrifuge()
const { search } = useLocation()
const [listedPools, listedTokens, metadataIsLoading] = useListedPools()
console.log('listedPools', listedPools)
const [listedPools, _listedTokens, metadataIsLoading] = useListedPools()

const centPools = listedPools.filter(({ id }) => !id.startsWith('0x')) as Pool[]
const centPoolsMetaData: PoolMetaDataPartial[] = useMetadataMulti<PoolMetadata>(
Expand All @@ -41,9 +40,7 @@ function Pools() {
const centPoolsMetaDataById = getMetasById(centPools, centPoolsMetaData)

const pools = !!listedPools?.length ? poolsToPoolCardProps(listedPools, centPoolsMetaDataById, cent) : []
console.log('pools', pools)
const filteredPools = !!pools?.length ? filterPools(pools, new URLSearchParams(search)) : []
console.log('flfitleirlerpOPopolp', filteredPools)

if (!listedPools.length) {
return (
Expand Down
2 changes: 1 addition & 1 deletion centrifuge-app/src/utils/tinlake/useTinlakePools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ async function getPools(pools: IpfsPools): Promise<{ pools: TinlakePool[] }> {
const toCurrencyBalance = (val: BigNumber) => new CurrencyBalance(val.toString(), 18)
const toTokenBalance = (val: BigNumber) => new TokenBalance(val.toString(), 18)
const toRate = (val: BigNumber) => new Rate(val.toString())
const toPrice = (val: BigNumber) => new Price(val.toString())
const toPrice = (val: BigNumber) => new Rate(val.toString())

const calls: Call[] = []
pools.active.forEach((pool) => {
Expand Down
58 changes: 29 additions & 29 deletions centrifuge-app/src/utils/usePermissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { combineLatest, filter, map, repeatWhen, switchMap } from 'rxjs'
import { diffPermissions } from '../pages/IssuerPool/Configuration/Admins'
import { useCollections } from './useCollections'
import { useLoan } from './useLoans'
import { usePool, usePoolMetadata } from './usePools'
import { usePool, usePoolMetadata, usePools } from './usePools'

export function usePermissions(address?: string) {
const [result] = useCentrifugeQuery(['permissions', address], (cent) => cent.pools.getUserPermissions([address!]), {
Expand All @@ -29,38 +29,38 @@ export function usePoolPermissions(poolId?: string) {
return result
}

// export function useUserPermissionsMulti(addresses: string[]) {
// const [results] = useCentrifugeQueries(
// addresses.map((address) => ({
// queryKey: ['permissions', address],
// queryCallback: (cent) => cent.pools.getUserPermissions([address!]),
// }))
// )

// return results
// }
export function useUserPermissionsMulti(addresses: string[], options?: { enabled?: boolean }) {
const [result] = useCentrifugeQuery(
['permissions', ...addresses],
(cent) => cent.pools.getUserPermissions([addresses]),
{
enabled: !!addresses.length && options?.enabled !== false,
}
)
return result
}

// // Better name welcomed lol
// export function usePoolsThatAnyConnectedAddressHasPermissionsFor() {
// const {
// substrate: { combinedAccounts },
// } = useWallet()
// const actingAddresses = [...new Set(combinedAccounts?.map((acc) => acc.actingAddress))]
// const permissionResults = useUserPermissionsMulti(actingAddresses)
// Better name welcomed lol
export function usePoolsThatAnyConnectedAddressHasPermissionsFor() {
const {
substrate: { combinedAccounts, proxiesAreLoading },
} = useWallet()
const actingAddresses = [...new Set(combinedAccounts?.map((acc) => acc.actingAddress))]
const permissionsResult = useUserPermissionsMulti(actingAddresses, { enabled: !proxiesAreLoading })

// const poolIds = new Set(
// permissionResults
// .map((permissions) =>
// Object.entries(permissions?.pools || {}).map(([poolId, roles]) => (roles.roles.length ? poolId : []))
// )
// .flat(2)
// )
const poolIds = new Set(
permissionsResult
?.map((permissions) =>
Object.entries(permissions?.pools || {}).map(([poolId, roles]) => (roles.roles.length ? poolId : []))
)
.flat(2)
)

// const pools = usePools(false)
// const filtered = pools?.filter((p) => poolIds.has(p.id))
const pools = usePools(false)
const filtered = pools?.filter((p) => poolIds.has(p.id))

// return filtered
// }
return filtered
}

// Returns whether the connected address can borrow from a pool in principle
export function useCanBorrow(poolId: string) {
Expand Down
136 changes: 86 additions & 50 deletions centrifuge-js/src/modules/pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { CurrencyBalance, Perquintill, Price, Rate, TokenBalance } from '../util
import { Dec } from '../utils/Decimal'

const PerquintillBN = new BN(10).pow(new BN(18))
const PriceBN = new BN(10).pow(new BN(27))
const PriceBN = new BN(10).pow(new BN(18))
const MaxU128 = '340282366920938463463374607431768211455'
const SEC_PER_DAY = 24 * 60 * 60

Expand Down Expand Up @@ -681,6 +681,18 @@ type BorrowerTransaction = {
amount: CurrencyBalance | undefined
}

export type Permissions = {
pools: {
[poolId: string]: PoolRoles
}
currencies: {
[currency: string]: {
roles: CurrencyRole[]
holder: boolean
}
}
}

const formatPoolKey = (keys: StorageKey<[u32]>) => (keys.toHuman() as string[])[0].replace(/\D/g, '')
const formatLoanKey = (keys: StorageKey<[u32, u32]>) => (keys.toHuman() as string[])[1].replace(/\D/g, '')

Expand Down Expand Up @@ -730,7 +742,8 @@ export function getPoolsModule(inst: Centrifuge) {
trancheInput,
currency,
maxReserve.toString(),
pinnedMetadata.ipfsHash
pinnedMetadata.ipfsHash,
[]
)
if (options?.createType === 'propose') {
const proposalTx = api.tx.utility.batchAll([
Expand Down Expand Up @@ -1124,8 +1137,14 @@ export function getPoolsModule(inst: Centrifuge) {
)
}

function getUserPermissions(args: [address: Account]) {
const [address] = args
function getUserPermissions<T extends Account | Account[]>(
args: [address: T]
): T extends Array<Account> ? Observable<Permissions[]> : Observable<Permissions> {
const [maybeArray] = args
const addresses = (Array.isArray(maybeArray) ? (maybeArray as Account[]) : [maybeArray as Account]).map(
(addr) => addressToHex(addr) as string
)
const addressSet = new Set(addresses)
const $api = inst.getApi()

const $events = inst.getEvents().pipe(
Expand All @@ -1135,59 +1154,76 @@ export function getPoolsModule(inst: Centrifuge) {
)
if (!event) return false

const [accountId] = (event.toJSON() as any).event.data
return isSameAddress(address, accountId)
const [accountId] = (event.toHuman() as any).event.data
return addressSet.has(addressToHex(accountId))
})
)

return $api.pipe(
switchMap((api) => api.query.permissions.permission.entries(address)),
map((permissionsData) => {
const roles: {
pools: {
[poolId: string]: PoolRoles
}
currencies: {
[currency: string]: {
roles: CurrencyRole[]
holder: boolean
}
}
} = {
pools: {},
currencies: {},
}

permissionsData.forEach(([keys, value]) => {
const key = (keys.toHuman() as any)[1] as { Pool: string } | { Currency: any }
if ('Pool' in key) {
const poolId = key.Pool.replace(/\D/g, '')
const permissions = value.toJSON() as any
roles.pools[poolId] = {
roles: (
[
'PoolAdmin',
'Borrower',
'PricingAdmin',
'LiquidityAdmin',
'InvestorAdmin',
'LoanAdmin',
'PODReadAccess',
switchMap((api) =>
api.query.permissions.permission.keys().pipe(
switchMap((keys) => {
const userKeys = keys
.map((key) => {
const [account, scope] = key.toHuman() as any as [string, { Pool: string } | { Currency: any }]
return [
addressToHex(account),
'Pool' in scope ? { Pool: scope.Pool.replace(/\D/g, '') } : scope,
] as const
).filter((role) => AdminRoleBits[role] & permissions.poolAdmin.bits),
tranches: {},
}
permissions.trancheInvestor.info
.filter((info: any) => info.permissionedTill * 1000 > Date.now())
.forEach((info: any) => {
roles.pools[poolId].tranches[info.trancheId] = new Date(info.permissionedTill * 1000).toISOString()
})
}
})
return roles
}),
.filter(([account, scope]) => {
return 'Pool' in scope && addressSet.has(account)
})
return api.query.permissions.permission.multi(userKeys).pipe(
map((permissionsData) => {
const permissionsByAddressIndex: Permissions[] = []

function setPoolRoles(user: string, poolId: string, roles: PoolRoles) {
const i = addresses.indexOf(user)
const obj = permissionsByAddressIndex[i] ?? {
pools: {},
currencies: {},
}
obj.pools[poolId] = roles
permissionsByAddressIndex[i] = obj
}
permissionsData.forEach((value, i) => {
const [account, scope] = userKeys[i]
if ('Pool' in scope) {
const poolId = scope.Pool.replace(/\D/g, '')
const permissions = value.toJSON() as any
const roles: PoolRoles = {
roles: (
[
'PoolAdmin',
'Borrower',
'PricingAdmin',
'LiquidityAdmin',
'InvestorAdmin',
'LoanAdmin',
'PODReadAccess',
] as const
).filter((role) => AdminRoleBits[role] & permissions.poolAdmin.bits),
tranches: {},
}
permissions.trancheInvestor.info
.filter((info: any) => info.permissionedTill * 1000 > Date.now())
.forEach((info: any) => {
roles.tranches[info.trancheId] = new Date(info.permissionedTill * 1000).toISOString()
})

setPoolRoles(account, poolId, roles)
}
})
return Array.isArray(maybeArray) ? permissionsByAddressIndex : permissionsByAddressIndex[0]
})
)
})
)
),

repeatWhen(() => $events)
)
) as any
}

function getPoolPermissions(args: [poolId: string]) {
Expand Down
2 changes: 1 addition & 1 deletion centrifuge-js/src/utils/BN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class TokenBalance extends CurrencyBalance {
}

export class Price extends BNSubType {
static decimals = 27
static decimals = 18
static fromFloat(number: Numeric) {
return Price._fromFloat<Price>(number)
}
Expand Down
Loading

0 comments on commit cc8289e

Please sign in to comment.