Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
333 changes: 330 additions & 3 deletions src/DataLoaders/GenTokens.test.ts

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions src/DataLoaders/GenTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { objktQueryFilter } from "../Query/Filters/Objkt"
import {
collectionOfferQueryFilter,
offerQueryFilter,
sortOffersAndCollectionOffers,
} from "../Query/Filters/Offer"
import { GenerativeTokenVersion } from "../types/GenerativeToken"
import { AnyOffer, offerTypeGuard } from "../types/AnyOffer"
Expand Down Expand Up @@ -333,7 +334,7 @@ const batchGenTokOffers = async (inputs: any) => {
const sort = inputs[0]?.sort

const query = Offer.createQueryBuilder("offer")
.select()
.select("offer")
.leftJoinAndSelect("offer.objkt", "objkt")
.leftJoinAndSelect("objkt.issuer", "issuer", "issuer.id IN(:...ids)")
.where("issuer.id IN(:...ids)", { ids })
Expand Down Expand Up @@ -388,7 +389,7 @@ const batchGenTokOffersAndCollectionOffers = async (inputs: any) => {
.leftJoinAndSelect("objkt.issuer", "issuer", "issuer.id IN(:...ids)")
.where("issuer.id IN(:...ids)", { ids })

// get received collection offers
// get collection offers
const collectionOffersQuery = CollectionOffer.createQueryBuilder(
"collection_offer"
)
Expand All @@ -405,14 +406,10 @@ const batchGenTokOffersAndCollectionOffers = async (inputs: any) => {
collectionOffersQuery.getMany(),
])

// extract the sort property and direction
const sortProperty = Object.keys(sort)[0]
const sortDirection = sort[sortProperty]

// combine and sort the results
const offers = [...individualOffers, ...collectionOffers].sort(
sortByProperty(sortProperty, sortDirection)
)
// combine the results
const offers = sort
? sortOffersAndCollectionOffers(individualOffers, collectionOffers, sort)
: [...individualOffers, ...collectionOffers]

return ids.map(id =>
offers.filter((offer: AnyOffer) =>
Expand Down
130 changes: 127 additions & 3 deletions src/DataLoaders/User.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ import { Connection, EntityManager } from "typeorm"

import {
actionFactory,
collectionOfferFactory,
generativeTokenFactory,
marketStatsFactory,
mintTicketFactory,
objktFactory,
offerFactory,
userFactory,
} from "../tests/factories"
import { GenerativeTokenVersion } from "../types/GenerativeToken"
import { createConnection } from "../createConnection"
import { createMarketStatsGenTokLoader } from "./MarketStats"
import {
createUsersGenerativeTokensLoader,
createUsersMintTicketsLoader,
createUsersOffersAndCollectionOffersReceivedLoader,
createUsersOffersAndCollectionOffersSentLoader,
createUsersSalesLoader,
} from "./User"
import { TokenActionType } from "../Entity/Action"
Expand All @@ -31,11 +34,14 @@ afterAll(() => {
})

const cleanup = async () => {
await manager.query("DELETE FROM collection_offer")
await manager.query("DELETE FROM offer")
await manager.query("DELETE FROM objkt")
await manager.query("DELETE FROM mint_ticket")
await manager.query("DELETE FROM generative_token")
}

afterEach(cleanup)
// afterEach(cleanup)

describe("User dataloaders", () => {
let dataloader
Expand Down Expand Up @@ -173,4 +179,122 @@ describe("User dataloaders", () => {
)
})
})

describe("createUsersOffersAndCollectionOffersSentLoader", () => {
beforeAll(async () => {
dataloader = createUsersOffersAndCollectionOffersSentLoader()

// create some users
const user = await userFactory("tz1")
const user2 = await userFactory("tz2")

// create some tokens
await generativeTokenFactory(0, GenerativeTokenVersion.PRE_V3)
await generativeTokenFactory(1, GenerativeTokenVersion.V3)

// create some objkts
await objktFactory(0, GenerativeTokenVersion.PRE_V3, {
tokenId: 0,
buyerId: user.id,
})
await objktFactory(1, GenerativeTokenVersion.V3, {
tokenId: 1,
buyerId: user2.id,
})

// create some offers
await offerFactory(0, 0, GenerativeTokenVersion.PRE_V3, {
buyerId: user.id,
})
await offerFactory(1, 1, GenerativeTokenVersion.V3, {
buyerId: user2.id,
})

// create some collection offers
await collectionOfferFactory(2, { tokenId: 0, buyerId: user.id })
await collectionOfferFactory(3, { tokenId: 1, buyerId: user2.id })
})

it("returns the correct offers and collection offers", async () => {
const result = await dataloader.loadMany([{ id: "tz1" }, { id: "tz2" }])
expect(result).toHaveLength(2)
expect(result).toMatchObject([
[
{
id: 0,
},
{
id: 2,
},
],
[
{
id: 1,
},
{
id: 3,
},
],
])
})
})

describe.only("createUsersOffersAndCollectionOffersReceivedLoader", () => {
beforeAll(async () => {
dataloader = createUsersOffersAndCollectionOffersReceivedLoader()

// create some users
const user = await userFactory("tz1")
const user2 = await userFactory("tz2")

// create some tokens
await generativeTokenFactory(0, GenerativeTokenVersion.PRE_V3)
await generativeTokenFactory(1, GenerativeTokenVersion.V3)

// create some objkts
await objktFactory(0, GenerativeTokenVersion.PRE_V3, {
tokenId: 0,
ownerId: user.id,
})
await objktFactory(1, GenerativeTokenVersion.V3, {
tokenId: 1,
ownerId: user2.id,
})

// create some offers
await offerFactory(0, 0, GenerativeTokenVersion.PRE_V3, {
buyerId: user2.id,
})
await offerFactory(1, 1, GenerativeTokenVersion.V3, {
buyerId: user.id,
})

// create some collection offers
await collectionOfferFactory(2, { tokenId: 0, buyerId: user2.id })
await collectionOfferFactory(3, { tokenId: 1, buyerId: user.id })
})

it("returns the correct offers and collection offers", async () => {
const result = await dataloader.loadMany([{ id: "tz1" }, { id: "tz2" }])
expect(result).toHaveLength(2)
expect(result).toMatchObject([
[
{
id: 0,
},
{
id: 2,
},
],
[
{
id: 1,
},
{
id: 3,
},
],
])
})
})
})
29 changes: 13 additions & 16 deletions src/DataLoaders/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Action, TokenActionType } from "../Entity/Action"
import {
collectionOfferQueryFilter,
offerQueryFilter,
sortOffersAndCollectionOffers,
} from "../Query/Filters/Offer"
import { Article } from "../Entity/Article"
import { articleQueryFilter } from "../Query/Filters/Article"
Expand Down Expand Up @@ -192,14 +193,10 @@ const batchUserOffersAndCollectionOffersSent = async (inputs: any) => {
sentCollectionOffersQuery.getMany(),
])

// extract the sort property and direction
const sortProperty = Object.keys(sort)[0]
const sortDirection = sort[sortProperty]

// combine and sort the results
const offers = [...sentOffers, ...sentCollectionOffers].sort(
sortByProperty(sortProperty, sortDirection)
)
// combine the results
const offers = sort
? sortOffersAndCollectionOffers(sentOffers, sentCollectionOffers, sort)
: [...sentOffers, ...sentCollectionOffers]

return ids.map(id => offers.filter(offer => offer.buyerId === id))
}
Expand Down Expand Up @@ -241,14 +238,14 @@ const batchUserOffersAndCollectionOffersReceived = async (inputs: any) => {
receivedCollectionOffersQuery.getMany(),
])

// extract the sort property and direction
const sortProperty = Object.keys(sort)[0]
const sortDirection = sort[sortProperty]

// combine and sort the results
const offers = [...receivedOffers, ...receivedCollectionOffers].sort(
sortByProperty(sortProperty, sortDirection)
)
// combine the results
const offers = sort
? sortOffersAndCollectionOffers(
receivedOffers,
receivedCollectionOffers,
sort
)
: [...receivedOffers, ...receivedCollectionOffers]

return ids.map(id =>
offers.filter(
Expand Down
61 changes: 61 additions & 0 deletions src/Query/Filters/Offer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Brackets } from "typeorm"
import { OffersSortInput } from "../../Resolver/Arguments/Sort"
import { TQueryFilter } from "./QueryFilter"
import { AnyOffer, offerTypeGuard } from "../../types/AnyOffer"
import { sortByProperty } from "../../Utils/Sort"

type OfferFilters = Record<string, any>

Expand Down Expand Up @@ -30,6 +32,27 @@ const anyOfferQueryFilter =
// add the sort arguments
if (sort) {
for (const field in sort) {
if (field === "floorDifference") {
// use fd_ as a prefix to avoid conflicts with existing table aliases
if (table === "offer") {
query.leftJoinAndSelect("offer.objkt", "fd_objkt")
query.leftJoinAndSelect("fd_objkt.issuer", "fd_token")
query.leftJoinAndSelect("fd_token.marketStats", "fd_stats")
query.addSelect(
"(offer.price / fd_stats.floor) * 100",
"floorDifference"
)
query.addOrderBy(`"floorDifference"`, sort[field])
} else {
query.leftJoinAndSelect("collection_offer.token", "fd_token")
query.leftJoinAndSelect("fd_token.marketStats", "fd_stats")
query.addOrderBy(
`(collection_offer.price / fd_stats.floor) * 100`,
sort[field]
)
}
continue
}
query.addOrderBy(`${table}.${field}`, sort[field])
}
}
Expand All @@ -47,3 +70,41 @@ export const collectionOfferQueryFilter: TQueryFilter<
OfferFilters,
OffersSortInput
> = anyOfferQueryFilter("collection_offer")

export const sortOffersAndCollectionOffers = (
offersA: AnyOffer[],
offersB: AnyOffer[],
sort: OffersSortInput
) => {
const sortProperty = Object.keys(sort)[0]
const sortDirection = sort[sortProperty]

// workaround for the floorDifference computed column
if (sortProperty === "floorDifference") {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to have a manual workaround for floorDifference as I can't get typeorm to return it from the query 😕

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's validate for the time being and extract it as a github issue to tackle on eventually

return [...offersA, ...offersB].sort((a, b) => {
const aFloor =
(offerTypeGuard(a)
? a.objkt.issuer?.marketStats.floor
: a.token.marketStats.floor) || 0
const bFloor =
(offerTypeGuard(b)
? b.objkt.issuer?.marketStats.floor
: b.token.marketStats.floor) || 0

const aFloorDifference = (a.price / aFloor) * 100
const bFloorDifference = (b.price / bFloor) * 100

const displayA = offerTypeGuard(a) ? a.objkt.name : a.token.name
const displayB = offerTypeGuard(b) ? b.objkt.name : b.token.name

return sortDirection === "ASC"
? aFloorDifference - bFloorDifference
: bFloorDifference - aFloorDifference
})
}

// sort the results
return [...offersA, ...offersB].sort(
sortByProperty(sortProperty, sortDirection)
)
}
4 changes: 4 additions & 0 deletions src/Resolver/Arguments/Sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class OffersSortInput {
@IsIn(["ASC", "DESC"])
price?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
floorDifference?: "ASC" | "DESC"

@Field(type => String, { nullable: true })
@IsIn(["ASC", "DESC"])
createdAt?: "ASC" | "DESC"
Expand Down
Loading