Skip to content
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

fix: fix counter offer #1263

Merged
merged 9 commits into from
Sep 1, 2024
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
1 change: 1 addition & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ type Listing @entity {
bids: [Bid] @derivedFrom(field: "listing")
status: [ListingStatus] @derivedFrom(field: "listing")
sales: [ListingSale] @derivedFrom(field: "listing")
counterOffers: [CounterOffer] @derivedFrom(field: "listing")

# Extras
highestPrice: BigInt! @index
Expand Down
20 changes: 15 additions & 5 deletions src/mappings/marketplace/events/counter_offer_answered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
CounterOfferResponseType,
CounterOfferResponseCounter,
CounterOfferResponseReject,
ListingType,
} from '../../../model'
import { CommonContext, BlockHeader, EventItem } from '../../types/contexts'
import { Sns } from '../../../common/sns'
Expand Down Expand Up @@ -52,8 +53,8 @@ function getEvent(
id: item.id,
name: MarketplaceCounterOfferAnswered.name,
extrinsic: item.extrinsic?.id ? new Extrinsic({ id: item.extrinsic.id }) : null,
collectionId: listing.makeAssetId.collection.id,
tokenId: listing.makeAssetId.id,
collectionId: listing.takeAssetId.collection.id,
tokenId: listing.takeAssetId.id,
data: new MarketplaceCounterOfferAnswered({
listing: listing.id,
creator: account.id,
Expand All @@ -65,7 +66,7 @@ function getEvent(
event,
new AccountTokenEvent({
id: item.id,
token: new Token({ id: listing.makeAssetId.id }),
token: new Token({ id: listing.takeAssetId.id }),
from: account,
event,
}),
Expand All @@ -81,9 +82,18 @@ export async function counterOfferAnswered(
if (!data) return undefined

const listingId = data.listingId.substring(2)
const listing = await ctx.store.findOneByOrFail<Listing>(Listing, { id: listingId })
const listing = await ctx.store.findOneOrFail(Listing, {
where: { id: listingId },
relations: {
takeAssetId: {
collection: true,
bestListing: true,
},
},
})

const account = await getOrCreateAccount(ctx, data.creator)
assert(listing.state.isTypeOf === 'OfferState', 'Listing is not an offer')
assert(listing.state.listingType === ListingType.Offer, 'Listing is not an offer')
listing.updatedAt = new Date(block.timestamp ?? 0)

if (item.extrinsic) {
Expand Down
45 changes: 30 additions & 15 deletions src/mappings/marketplace/events/counter_offer_placed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import { Sns } from '../../../common/sns'
import { getOrCreateAccount } from '../../util/entities'

function getEventData(event: EventItem) {
if (events.marketplace.counterOfferPlaced.v1010.is(event)) {
return events.marketplace.counterOfferPlaced.v1010.decode(event)
}

if (events.marketplace.counterOfferPlaced.v1011.is(event)) {
return events.marketplace.counterOfferPlaced.v1011.decode(event)
}
Expand All @@ -33,22 +37,22 @@ function getEvent(
id: item.id,
name: MarketplaceCounterOfferPlaced.name,
extrinsic: item.extrinsic?.id ? new Extrinsic({ id: item.extrinsic.id }) : null,
collectionId: listing.makeAssetId.collection.id,
tokenId: listing.makeAssetId.id,
collectionId: listing.takeAssetId.collection.id,
tokenId: listing.takeAssetId.id,
data: new MarketplaceCounterOfferPlaced({
listing: listing.id,
accountId: data.counterOffer.deposit.depositor,
buyerPrice: data.counterOffer.buyerPrice,
depositAmount: data.counterOffer.deposit.amount,
sellerPrice: data.counterOffer.sellerPrice,
accountId: 'deposit' in data.counterOffer ? data.counterOffer.deposit.depositor : data.counterOffer.accountId,
buyerPrice: 'price' in data.counterOffer ? data.counterOffer.price : data.counterOffer.buyerPrice,
depositAmount: 'deposit' in data.counterOffer ? data.counterOffer.deposit.amount : 1n,
sellerPrice: 'sellerPrice' in data.counterOffer ? data.counterOffer.sellerPrice : 1n,
}),
})

return [
event,
new AccountTokenEvent({
id: item.id,
token: new Token({ id: listing.makeAssetId.id }),
token: new Token({ id: listing.takeAssetId.id }),
from: account,
event,
}),
Expand All @@ -64,13 +68,24 @@ export async function counterOfferPlaced(
if (!data) return undefined

const listingId = data.listingId.substring(2)
const listing = await ctx.store.findOne<Listing>(Listing, {
const listing = await ctx.store.findOneOrFail<Listing>(Listing, {
where: { id: listingId },
relations: {
takeAssetId: {
collection: true,
bestListing: true,
},
},
})

const accountId = 'deposit' in data.counterOffer ? data.counterOffer.deposit.depositor : data.counterOffer.accountId
const buyerPrice = 'price' in data.counterOffer ? data.counterOffer.price : data.counterOffer.buyerPrice
const depositAmount = 'deposit' in data.counterOffer ? data.counterOffer.deposit.amount : 1n
const sellerPrice = 'sellerPrice' in data.counterOffer ? data.counterOffer.sellerPrice : 1n

if (!listing) return undefined
listing.updatedAt = new Date(block.timestamp ?? 0)
const account = await getOrCreateAccount(ctx, data.counterOffer.deposit.depositor)
const account = await getOrCreateAccount(ctx, accountId)
assert(listing.state.isTypeOf === 'OfferState', 'Listing is not an offer')

listing.state = new OfferState({
Expand All @@ -81,9 +96,9 @@ export async function counterOfferPlaced(
const offer = new CounterOffer({
id: `${listing.id}-${account.id}`,
listing,
buyerPrice: data.counterOffer.buyerPrice,
amount: data.counterOffer.deposit.amount,
sellerPrice: data.counterOffer.sellerPrice,
buyerPrice,
amount: depositAmount,
sellerPrice,
account,
createdAt: new Date(block.timestamp ?? 0),
})
Expand All @@ -93,9 +108,9 @@ export async function counterOfferPlaced(
id: item.id,
name: item.name,
body: {
buyerPrice: data.counterOffer.buyerPrice?.toString(),
amount: data.counterOffer.deposit.amount.toString(),
sellerPrice: data.counterOffer.sellerPrice.toString(),
buyerPrice: buyerPrice?.toString(),
amount: depositAmount.toString(),
sellerPrice: sellerPrice.toString(),
account: account.id,
listing: listing.id,
extrinsic: item.extrinsic.id,
Expand Down
11 changes: 10 additions & 1 deletion src/mappings/marketplace/events/counter_offer_removed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,16 @@ export async function counterOfferRemoved(
if (!data) return undefined

const listingId = data.listingId.substring(2)
const listing = await ctx.store.findOneByOrFail<Listing>(Listing, { id: listingId })
const listing = await ctx.store.findOneOrFail<Listing>(Listing, {
where: { id: listingId },
relations: {
makeAssetId: {
collection: true,
bestListing: true,
},
},
})

const account = await getOrCreateAccount(ctx, data.creator)
assert(listing.state.isTypeOf === 'OfferState', 'Listing is not an offer')
listing.updatedAt = new Date(block.timestamp ?? 0)
Expand Down
23 changes: 16 additions & 7 deletions src/mappings/marketplace/events/listing_created.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,20 @@ function getEventData(ctx: CommonContext, event: EventItem) {
}

function getEvent(item: EventItem, data: ReturnType<typeof getEventData>): [EventModel, AccountTokenEvent] | undefined {
let collectionId = data.listing.makeAssetId.collectionId.toString()
let tokenId = `${data.listing.makeAssetId.collectionId}-${data.listing.makeAssetId.tokenId}`

if (data.listing.data.__kind === 'Offer') {
collectionId = data.listing.takeAssetId.collectionId.toString()
tokenId = `${data.listing.takeAssetId.collectionId}-${data.listing.takeAssetId.tokenId}`
}

const event = new EventModel({
id: item.id,
name: MarketplaceListingCreated.name,
extrinsic: item.extrinsic?.id ? new Extrinsic({ id: item.extrinsic.id }) : null,
collectionId: data.listing.makeAssetId.collectionId.toString(),
tokenId: `${data.listing.makeAssetId.collectionId}-${data.listing.makeAssetId.tokenId}`,
collectionId,
tokenId,
data: new MarketplaceListingCreated({
listing: data.listingId.substring(2),
}),
Expand All @@ -56,7 +64,7 @@ function getEvent(item: EventItem, data: ReturnType<typeof getEventData>): [Even
event,
new AccountTokenEvent({
id: item.id,
token: new Token({ id: `${data.listing.makeAssetId.collectionId}-${data.listing.makeAssetId.tokenId}` }),
token: new Token({ id: tokenId }),
from: new Account({ id: 'creator' in data.listing ? data.listing.creator : data.listing.seller }),
event,
}),
Expand Down Expand Up @@ -154,11 +162,12 @@ export async function listingCreated(
createdAt: new Date(block.timestamp ?? 0),
})

// update best listing
if ((makeAssetId.bestListing && makeAssetId.bestListing?.highestPrice >= listing.price) || !makeAssetId.bestListing) {
makeAssetId.bestListing = listing
if (data.listing.data.__kind !== 'Offer') {
if ((makeAssetId.bestListing && makeAssetId.bestListing?.highestPrice >= listing.price) || !makeAssetId.bestListing) {
makeAssetId.bestListing = listing
}
makeAssetId.recentListing = listing
}
makeAssetId.recentListing = listing

await Promise.all([ctx.store.insert(listing), ctx.store.insert(listingStatus), ctx.store.save(makeAssetId)])

Expand Down
43 changes: 28 additions & 15 deletions src/mappings/marketplace/events/listing_filled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,20 @@ function getEvent(
data: ReturnType<typeof getEventData>,
listing: Listing
): [EventModel, AccountTokenEvent] | undefined {
let collectionId = listing.makeAssetId.collection.id
let tokenId = listing.makeAssetId.id

if (listing.data.listingType === ListingType.Offer) {
collectionId = listing.takeAssetId.collection.id
tokenId = listing.takeAssetId.id
}

const event = new EventModel({
id: item.id,
name: MarketplaceListingFilled.name,
extrinsic: item.extrinsic?.id ? new Extrinsic({ id: item.extrinsic.id }) : null,
collectionId: listing.makeAssetId.collection.id,
tokenId: listing.makeAssetId.id,
collectionId,
tokenId,
data: new MarketplaceListingFilled({
listing: listing.id,
buyer: data.buyer,
Expand Down Expand Up @@ -76,15 +84,20 @@ export async function listingFilled(
collection: true,
bestListing: true,
},
takeAssetId: {
collection: true,
},
},
})

if (!listing || !listing.makeAssetId) return undefined

listing.state = new FixedPriceState({
listingType: ListingType.FixedPrice,
amountFilled: listing.amount - data.amountRemaining,
})
if (listing.state.listingType === ListingType.FixedPrice) {
listing.state = new FixedPriceState({
listingType: ListingType.FixedPrice,
amountFilled: listing.amount - data.amountRemaining,
})
}

if (data.amountRemaining === 0n) {
const listingStatus = new ListingStatus({
Expand Down Expand Up @@ -113,18 +126,18 @@ export async function listingFilled(

await Promise.all([ctx.store.save(listing), ctx.store.save(sale)])

if (listing.makeAssetId.bestListing?.id === listing.id && data.amountRemaining === 0n) {
const bestListing = await getBestListing(ctx, listing.makeAssetId.id)
listing.makeAssetId.bestListing = null
if (bestListing) {
listing.makeAssetId.bestListing = bestListing
if (listing.data.listingType !== ListingType.Offer) {
if (listing.makeAssetId.bestListing?.id === listing.id && data.amountRemaining === 0n) {
const bestListing = await getBestListing(ctx, listing.makeAssetId.id)
listing.makeAssetId.bestListing = null
if (bestListing) {
listing.makeAssetId.bestListing = bestListing
}
}
await ctx.store.save(listing.makeAssetId)
syncCollectionStats(listing.makeAssetId.collection.id)
}

await ctx.store.save(listing.makeAssetId)

syncCollectionStats(listing.makeAssetId.collection.id)

if (item.extrinsic) {
await Sns.getInstance().send({
id: item.id,
Expand Down
4 changes: 4 additions & 0 deletions src/model/generated/listing.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {ListingState, fromJsonListingState} from "./_listingState"
import {Bid} from "./bid.model"
import {ListingStatus} from "./listingStatus.model"
import {ListingSale} from "./listingSale.model"
import {CounterOffer} from "./counterOffer.model"
import {ListingType} from "./_listingType"

@Entity_()
Expand Down Expand Up @@ -67,6 +68,9 @@ export class Listing {
@OneToMany_(() => ListingSale, e => e.listing)
sales!: ListingSale[]

@OneToMany_(() => CounterOffer, e => e.listing)
counterOffers!: CounterOffer[]

@Index_()
@BigIntColumn_({nullable: false})
highestPrice!: bigint
Expand Down
Loading