-
Notifications
You must be signed in to change notification settings - Fork 15
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
feat: add parcel list modal #398
Merged
Merged
Changes from 2 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
5130196
feat: add parcel list modal
tnrdd 3a82bcd
fix: remove skip variable in random query
tnrdd 5ff5275
fix: handle parcels update on user action
tnrdd cf4abe2
fix: ensure max list size is respected in foreclosure and needs actio…
tnrdd 823d854
fix: use ethers JsonRpcBatchProvider
tnrdd 7136d2c
perf: limit ceramic calls in foreclosure and needs transfer queries
tnrdd 1cc2e5e
refactor: remove unnecessary splice
tnrdd a667f4d
feat: always hit the network for random queries
tnrdd 71f0c24
fix: uses promises array to settle all getParcelContent calls
tnrdd 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
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,209 @@ | ||
import { useState, useEffect } from "react"; | ||
import { BigNumber } from "ethers"; | ||
import { gql, useQuery } from "@apollo/client"; | ||
import { Container } from "react-bootstrap"; | ||
import { Framework } from "@superfluid-finance/sdk-core"; | ||
import type { Point } from "@turf/turf"; | ||
import * as turf from "@turf/turf"; | ||
import { GeoWebContent } from "@geo-web/content"; | ||
import { Contracts } from "@geo-web/sdk/dist/contract/types"; | ||
import { PCOLicenseDiamondFactory } from "@geo-web/sdk/dist/contract/index"; | ||
import { MAX_LIST_SIZE, Parcel, ParcelsQuery } from "./ParcelList"; | ||
import ParcelTable from "./ParcelTable"; | ||
import { STATE } from "../Map"; | ||
import { getParcelContent } from "../../lib/utils"; | ||
|
||
interface ForeclosureProps { | ||
sfFramework: Framework; | ||
geoWebContent: GeoWebContent; | ||
registryContract: Contracts["registryDiamondContract"]; | ||
setSelectedParcelId: React.Dispatch<React.SetStateAction<string>>; | ||
setInteractionState: React.Dispatch<React.SetStateAction<STATE>>; | ||
handleCloseModal: () => void; | ||
setParcelNavigationCenter: React.Dispatch<React.SetStateAction<Point | null>>; | ||
shouldRefetch: boolean; | ||
setShouldRefetch: React.Dispatch<React.SetStateAction<boolean>>; | ||
} | ||
|
||
type Bid = Parcel & { | ||
timestamp: number; | ||
licenseOwner: string; | ||
}; | ||
|
||
const foreclosureQuery = gql` | ||
query Foreclosure($skip: Int) { | ||
geoWebParcels( | ||
first: 1000 | ||
orderBy: currentBid__timestamp | ||
orderDirection: desc | ||
skip: $skip | ||
) { | ||
id | ||
createdAtBlock | ||
bboxN | ||
bboxS | ||
bboxE | ||
bboxW | ||
licenseOwner | ||
licenseDiamond | ||
currentBid { | ||
forSalePrice | ||
contributionRate | ||
timestamp | ||
} | ||
} | ||
} | ||
`; | ||
|
||
function Foreclosure(props: ForeclosureProps) { | ||
const { | ||
sfFramework, | ||
geoWebContent, | ||
registryContract, | ||
setSelectedParcelId, | ||
setInteractionState, | ||
handleCloseModal, | ||
setParcelNavigationCenter, | ||
shouldRefetch, | ||
setShouldRefetch, | ||
} = props; | ||
|
||
const [parcels, setParcels] = useState<Bid[] | null>(null); | ||
|
||
const { data, refetch, networkStatus } = useQuery<ParcelsQuery>( | ||
foreclosureQuery, | ||
{ | ||
variables: { | ||
skip: 0 * MAX_LIST_SIZE, | ||
}, | ||
notifyOnNetworkStatusChange: true, | ||
} | ||
); | ||
|
||
useEffect(() => { | ||
if (!data) { | ||
return; | ||
} | ||
|
||
if (data.geoWebParcels.length === 0) { | ||
setParcels([]); | ||
return; | ||
} | ||
|
||
let isMounted = true; | ||
|
||
(async () => { | ||
const _parcels: Bid[] = []; | ||
const promises = []; | ||
|
||
for (const parcel of data.geoWebParcels) { | ||
const licenseDiamondAddress = parcel.licenseDiamond; | ||
const licenseDiamondContract = PCOLicenseDiamondFactory.connect( | ||
licenseDiamondAddress, | ||
sfFramework.settings.provider | ||
); | ||
|
||
const promiseChain = (async () => { | ||
if (_parcels.length === MAX_LIST_SIZE) { | ||
return; | ||
} | ||
|
||
const isPayerBidActive = | ||
await licenseDiamondContract.isPayerBidActive(); | ||
|
||
if (!isPayerBidActive) { | ||
const parcelId = parcel.id; | ||
const createdAtBlock = parcel.createdAtBlock; | ||
const currentBid = parcel.currentBid; | ||
const forSalePrice = BigNumber.from(currentBid.forSalePrice); | ||
const timestamp = currentBid.timestamp; | ||
const poly = turf.bboxPolygon([ | ||
parcel.bboxW, | ||
parcel.bboxS, | ||
parcel.bboxE, | ||
parcel.bboxN, | ||
]); | ||
const center = turf.center(poly); | ||
const parcelContent = await getParcelContent( | ||
registryContract.address.toLowerCase(), | ||
geoWebContent, | ||
parcel.id, | ||
parcel.licenseOwner | ||
); | ||
const name = | ||
parcelContent && parcelContent.name | ||
? parcelContent.name | ||
: `Parcel ${parcel.id}`; | ||
|
||
_parcels.push({ | ||
parcelId: parcelId, | ||
status: "In Foreclosure", | ||
createdAtBlock: createdAtBlock, | ||
name: name, | ||
timestamp: timestamp, | ||
price: forSalePrice, | ||
center: center.geometry, | ||
licenseOwner: parcel.licenseOwner, | ||
}); | ||
} | ||
})(); | ||
promises.push(promiseChain); | ||
} | ||
|
||
await Promise.allSettled(promises); | ||
|
||
if (isMounted) { | ||
const sorted = sortParcels(_parcels); | ||
|
||
setParcels(sorted); | ||
} | ||
})(); | ||
|
||
return () => { | ||
isMounted = false; | ||
}; | ||
}, [data]); | ||
|
||
useEffect(() => { | ||
if (!shouldRefetch) { | ||
return; | ||
} | ||
|
||
refetch({ | ||
skip: 0, | ||
}); | ||
|
||
setShouldRefetch(false); | ||
}, [shouldRefetch]); | ||
|
||
const sortParcels = (parcels: Bid[]): Bid[] => { | ||
const sorted = [...parcels].sort((a, b) => { | ||
let result = 0; | ||
|
||
result = a.timestamp > b.timestamp ? -1 : 1; | ||
|
||
return result; | ||
}); | ||
|
||
return sorted; | ||
}; | ||
|
||
const handleAction = (parcel: Parcel): void => { | ||
handleCloseModal(); | ||
setInteractionState(STATE.PARCEL_SELECTED); | ||
setSelectedParcelId(parcel.parcelId); | ||
setParcelNavigationCenter(parcel.center); | ||
}; | ||
|
||
return ( | ||
<Container> | ||
<ParcelTable | ||
parcels={parcels} | ||
networkStatus={networkStatus} | ||
handleAction={handleAction} | ||
/> | ||
</Container> | ||
); | ||
} | ||
|
||
export default Foreclosure; |
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.
Do we need to get 1000 parcels here? Or can we limit it to
MAX_LIST_SIZE
?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.
Here and in
NeedsTransfer
querying for only 25 parcels wouldn't result in 25 parcels foreclosed or that needs transfer because we don't have a way to query the subgraph directly for that, but e.g. need to callisPayerBidActive
on each to tell if a parcel is foreclosed.So we just get a pool of parcels to check and loop over them, performance should be alright even when there are 1000 parcels because it is done asynchronously.
A way to reduce the number of calls to the Ethereum node is to use
ethers
JsonRpcBatchProvider, in this comment the author was wondering if 1 million calls is too much so 1000 shouldn't be a problem.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.
Great find on the
JsonRpcBatchProvider
. We should try to limit RPC calls as much as possible. Looks like this is working well with Infura.I also see Ceramic multiqueries working well and also the Ceramic caching.
This does now result in many IPFS lookups via our delegate node. This should be fine, as they are only calls for content routing and do not return or fetch actual content. However, there are many 404s to
/block/stat
. I will look into how to remove these calls, as they are unnecessary.findprovs
is what is needed.