Skip to content

Commit

Permalink
fix: estates race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
juanmahidalgo committed Dec 17, 2024
1 parent 2a3310d commit 24ebdab
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 44 deletions.
2 changes: 0 additions & 2 deletions db/migrations/1720613055375-Data.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module.exports = class Data1720613055375 {
await db.query(`CREATE INDEX "IDX_45072545bb44e246e0496110f9" ON "metadata" ("wearable_id") `)
await db.query(`CREATE INDEX "IDX_cee9cecc2205cd07a21813203d" ON "metadata" ("emote_id") `)
await db.query(`CREATE TABLE "item" ("id" character varying NOT NULL, "blockchain_id" numeric NOT NULL, "creator" text NOT NULL, "item_type" character varying(17) NOT NULL, "total_supply" numeric NOT NULL, "max_supply" numeric NOT NULL, "rarity" text NOT NULL, "creation_fee" numeric NOT NULL, "available" numeric NOT NULL, "price" numeric NOT NULL, "beneficiary" text NOT NULL, "content_hash" text, "uri" text NOT NULL, "image" text, "minters" text array NOT NULL, "managers" text array NOT NULL, "raw_metadata" text NOT NULL, "urn" text NOT NULL, "created_at" numeric NOT NULL, "updated_at" numeric NOT NULL, "reviewed_at" numeric NOT NULL, "sold_at" numeric, "first_listed_at" numeric, "sales" integer NOT NULL, "volume" numeric NOT NULL, "search_text" text, "search_item_type" text, "search_is_collection_approved" boolean, "search_is_store_minter" boolean NOT NULL, "search_is_wearable_head" boolean, "search_is_wearable_accessory" boolean, "search_wearable_category" character varying(11), "search_wearable_rarity" text, "search_wearable_body_shapes" character varying(10) array, "search_emote_category" character varying(13), "search_emote_loop" boolean, "search_emote_rarity" text, "search_emote_body_shapes" character varying(10) array, "search_emote_has_sound" boolean, "search_emote_has_geometry" boolean, "unique_collectors" text array NOT NULL, "unique_collectors_total" integer NOT NULL, "collection_id" character varying, "metadata_id" character varying, CONSTRAINT "PK_d3c0c71f23e7adcf952a1d13423" PRIMARY KEY ("id"))`)
await db.query(`CREATE INDEX "IDX_0afcbaf43e44997480d93b5756" ON "item" ("collection_id") `)
await db.query(`CREATE INDEX "IDX_6d5bb320c601281cd3a213979e" ON "item" ("metadata_id") `)
await db.query(`CREATE TABLE "collection" ("id" character varying NOT NULL, "owner" text NOT NULL, "creator" text NOT NULL, "name" text NOT NULL, "symbol" text NOT NULL, "is_completed" boolean, "is_approved" boolean, "is_editable" boolean, "minters" text array NOT NULL, "managers" text array NOT NULL, "urn" text NOT NULL, "items_count" integer NOT NULL, "created_at" numeric NOT NULL, "updated_at" numeric NOT NULL, "reviewed_at" numeric NOT NULL, "first_listed_at" numeric, "search_is_store_minter" boolean NOT NULL, "search_text" text NOT NULL, "base_uri" text NOT NULL, "chain_id" numeric NOT NULL, CONSTRAINT "PK_ad3f485bbc99d875491f44d7c85" PRIMARY KEY ("id"))`)
await db.query(`CREATE TABLE "rarity" ("id" character varying NOT NULL, "name" text NOT NULL, "max_supply" numeric NOT NULL, "price" numeric NOT NULL, "currency" character varying(4) NOT NULL, CONSTRAINT "PK_abfb3052bad892c356e54679f8f" PRIMARY KEY ("id"))`)
Expand Down Expand Up @@ -96,7 +95,6 @@ module.exports = class Data1720613055375 {
await db.query(`DROP INDEX "public"."IDX_45072545bb44e246e0496110f9"`)
await db.query(`DROP INDEX "public"."IDX_cee9cecc2205cd07a21813203d"`)
await db.query(`DROP TABLE "item"`)
await db.query(`DROP INDEX "public"."IDX_0afcbaf43e44997480d93b5756"`)
await db.query(`DROP INDEX "public"."IDX_6d5bb320c601281cd3a213979e"`)
await db.query(`DROP TABLE "collection"`)
await db.query(`DROP TABLE "rarity"`)
Expand Down
2 changes: 0 additions & 2 deletions db/migrations/1722000501171-Data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ module.exports = class Data1722000501171 {
async up(db) {
await db.query(`ALTER TABLE "mint" ADD "network" character varying(8) NOT NULL`)
await db.query(`CREATE INDEX "IDX_7e215df412b248db3731737290" ON "nft" ("token_id") `)
await db.query(`CREATE INDEX "IDX_1b42beeb0f000d3a887f243725" ON "nft" ("contract_address") `)
}

async down(db) {
await db.query(`ALTER TABLE "mint" DROP COLUMN "network"`)
await db.query(`DROP INDEX "public"."IDX_7e215df412b248db3731737290"`)
await db.query(`DROP INDEX "public"."IDX_1b42beeb0f000d3a887f243725"`)
}
}
21 changes: 21 additions & 0 deletions db/migrations/1734457709893-Data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = class Data1734457709893 {
name = "Data1734457709893";

async up(db) {
await db.query(
`CREATE INDEX "IDX_1f3ec6150afbb8a3fd75fae814" ON "estate" ("size") `
);
await db.query(
`CREATE INDEX "IDX_9ddbd0267ddb9c59621775f94e" ON "item" ("collection_id", "blockchain_id") `
);
await db.query(
`CREATE INDEX "IDX_0fca1a8c5d9399d9a9a52e26f7" ON "nft" ("contract_address", "token_id") `
);
}

async down(db) {
await db.query(`DROP INDEX "public"."IDX_1f3ec6150afbb8a3fd75fae814"`);
await db.query(`DROP INDEX "public"."IDX_9ddbd0267ddb9c59621775f94e"`);
await db.query(`DROP INDEX "public"."IDX_0fca1a8c5d9399d9a9a52e26f7"`);
}
};
9 changes: 5 additions & 4 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,19 @@ type Data @entity {
type NFT
@entity
@index(fields: ["item", "owner"])
@index(fields: ["contractAddress", "tokenId"])
@index(fields: ["searchOrderStatus", "searchOrderExpiresAt", "network"])
@index(fields: ["searchOrderStatus", "searchOrderExpiresAt", "category"]) {
id: ID!
tokenId: BigInt! @index
contractAddress: String! @index
category: Category! @index
owner: Account!
owner: Account! @index
tokenURI: String

orders: [Order!] @derivedFrom(field: "nft") # History of all orders. Should only ever be ONE open order. all others must be cancelled or sold
bids: [Bid!] @derivedFrom(field: "nft") # History of all bids.
activeOrder: Order
activeOrder: Order @index

name: String
image: String
Expand Down Expand Up @@ -249,7 +250,7 @@ type Estate @entity {
parcels: [Parcel!]! @derivedFrom(field: "estate")
parcelDistances: [Int!]
adjacentToRoadCount: Int
size: Int
size: Int @index
data: Data
rawData: String
nft: NFT @derivedFrom(field: "estate")
Expand Down Expand Up @@ -422,7 +423,7 @@ type Collection @entity {
network: Network!
}

type Item @entity {
type Item @entity @index(fields: ["collection", "blockchainId"]) {
id: ID! # ${Collection address}_${item Id}
collection: Collection!
blockchainId: BigInt!
Expand Down
2 changes: 1 addition & 1 deletion src/common/utils/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function getNetwork(network: Network): string {
const chainName =
network === Network.ETHEREUM
? chainId === ChainId.ETHEREUM_MAINNET.toString()
? "mainnet"
? "ethereum"
: "sepolia"
: chainId === ChainId.MATIC_MAINNET.toString()
? "matic"
Expand Down
4 changes: 2 additions & 2 deletions src/eth/handlers/estate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ export function handleRemoveLand(
// @TODO check why && estate.size is needed, try to put at mandatory and start in -1
estate.size -= 1;
} else {
console.log('ERROR: estate: ', estate);
console.log('ERROR: estate.size: ', estate?.size);
console.log("ERROR: estate: ", estate);
console.log("ERROR: estate.size: ", estate?.size);
}

const estateNFT = nfts.get(id);
Expand Down
13 changes: 11 additions & 2 deletions src/eth/handlers/nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,18 @@ export function handleTransfer(
nft.searchAdjacentToRoad = false;
nft.searchEstateSize = estate.size;
} else {
if (estate) estate.owner = nft.owner;
// console.log("DETECTED A TRANSFER OF THE ESTATE: ", id);
if (estate) {
estate.owner = nft.owner;
} else {
console.log(
`ERROR: Estate with tokenId ${nft.tokenId} not found on handleTransfer. Ownership not updated correclty`
);
}
}
if (estate) {
estates.set(id, estate);
}
if (estate) estates.set(id, estate);
} else if (category == Category.wearable) {
let wearable: Wearable | undefined = undefined;
if (isMint(from)) {
Expand Down
55 changes: 37 additions & 18 deletions src/eth/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ processor.run(
collectionIds,
itemIds,
accountIds,
estateEvents,
estateTokenIds,
landTokenIds,
ensTokenIds,
Expand Down Expand Up @@ -259,10 +258,11 @@ processor.run(
break;
}
case estateRegistryABI.events.CreateEstate.topic: {
estateEvents.push({
markteplaceEvents.push({
topic,
event: estateRegistryABI.events.CreateEstate.decode(log),
block,
log,
});
break;
}
Expand All @@ -271,10 +271,11 @@ processor.run(
if (log.address === addresses.EstateRegistry) {
const event = estateRegistryABI.events.Update.decode(log);
estateTokenIds.add(event._assetId);
estateEvents.push({
markteplaceEvents.push({
topic,
event,
block,
log,
});
} else if (log.address === addresses.LANDRegistry) {
const event = landRegistryABI.events.Update.decode(log);
Expand All @@ -290,20 +291,22 @@ processor.run(
case estateRegistryABI.events.AddLand.topic: {
const event = estateRegistryABI.events.AddLand.decode(log);
estateTokenIds.add(event._estateId);
estateEvents.push({
markteplaceEvents.push({
topic: estateRegistryABI.events.AddLand.topic,
event,
block,
log,
});
break;
}
case estateRegistryABI.events.RemoveLand.topic: {
const event = estateRegistryABI.events.RemoveLand.decode(log);
estateTokenIds.add(event._estateId);
estateEvents.push({
markteplaceEvents.push({
topic: estateRegistryABI.events.RemoveLand.topic,
event,
block,
log,
});

break;
Expand Down Expand Up @@ -801,31 +804,47 @@ processor.run(
wearables,
metadatas
);
}
}

for (const { block, event, topic } of estateEvents) {
if (
} else if (
topic === estateRegistryABI.events.CreateEstate.topic &&
isCreateEstateEvent(event)
isCreateEstateEvent(event as estateRegistryABI.CreateEstateEventArgs)
) {
handleCreateEstate(block, event, nfts, estates, accounts, datas);
handleCreateEstate(
block,
event as estateRegistryABI.CreateEstateEventArgs,
nfts,
estates,
accounts,
datas
);
} else if (
topic === estateRegistryABI.events.Update.topic &&
isUpdateEvent(event)
isUpdateEvent(event as estateRegistryABI.UpdateEventArgs)
) {
handleEstateUpdate(event, block, estates, nfts, datas);
handleEstateUpdate(
event as estateRegistryABI.UpdateEventArgs,
block,
estates,
nfts,
datas
);
} else if (
topic === estateRegistryABI.events.AddLand.topic &&
isAddLandEvent(event)
isAddLandEvent(event as estateRegistryABI.AddLandEventArgs)
) {
handleAddLand(event, estates, nfts, parcels, accounts, landCoordinates);
handleAddLand(
event as estateRegistryABI.AddLandEventArgs,
estates,
nfts,
parcels,
accounts,
landCoordinates
);
} else if (
topic === estateRegistryABI.events.RemoveLand.topic &&
isRemoveLandEvent(event)
isRemoveLandEvent(event as estateRegistryABI.RemoveLandEventArgs)
) {
handleRemoveLand(
event,
event as estateRegistryABI.RemoveLandEventArgs,
estates,
nfts,
parcels,
Expand Down
15 changes: 5 additions & 10 deletions src/eth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ export type EthereumInMemoryState = {
string,
{ event: erc721abi.TransferEventArgs_2; block: BlockData }[]
>;
estateEvents: {
topic: string;
event:
| estateRegistryABI.CreateEstateEventArgs
| estateRegistryABI.UpdateEventArgs
| estateRegistryABI.AddLandEventArgs
| estateRegistryABI.RemoveLandEventArgs;
block: BlockData;
}[];
parcelEvents: {
topic: string;
event: landRegistryABI.UpdateEventArgs;
Expand All @@ -58,7 +49,11 @@ export type EthereumInMemoryState = {
| erc721abi.TransferEventArgs_2
| erc721abi.OwnershipTransferredEventArgs
| erc721abi.AddWearableEventArgs
| MarketplaceV3ABI.TradedEventArgs;
| MarketplaceV3ABI.TradedEventArgs
| estateRegistryABI.CreateEstateEventArgs
| estateRegistryABI.UpdateEventArgs
| estateRegistryABI.AddLandEventArgs
| estateRegistryABI.RemoveLandEventArgs;
block: BlockData;
log: Log & { transactionHash: string };
marketplaceOwnerCutPerMillion?: bigint | null;
Expand Down
1 change: 1 addition & 0 deletions src/model/generated/estate.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class Estate {
@IntColumn_({nullable: true})
adjacentToRoadCount!: number | undefined | null

@Index_()
@IntColumn_({nullable: true})
size!: number | undefined | null

Expand Down
4 changes: 2 additions & 2 deletions src/model/generated/item.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, ManyToOne as ManyToOne_, Index as Index_, BigIntColumn as BigIntColumn_, StringColumn as StringColumn_, OneToMany as OneToMany_, IntColumn as IntColumn_, BooleanColumn as BooleanColumn_} from "@subsquid/typeorm-store"
import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_, ManyToOne as ManyToOne_, BigIntColumn as BigIntColumn_, StringColumn as StringColumn_, OneToMany as OneToMany_, IntColumn as IntColumn_, BooleanColumn as BooleanColumn_} from "@subsquid/typeorm-store"
import {Collection} from "./collection.model"
import {ItemType} from "./_itemType"
import {Metadata} from "./metadata.model"
Expand All @@ -8,6 +8,7 @@ import {WearableBodyShape} from "./_wearableBodyShape"
import {EmoteCategory} from "./_emoteCategory"
import {Network} from "./_network"

@Index_(["collection", "blockchainId"], {unique: false})
@Entity_()
export class Item {
constructor(props?: Partial<Item>) {
Expand All @@ -17,7 +18,6 @@ export class Item {
@PrimaryColumn_()
id!: string

@Index_()
@ManyToOne_(() => Collection, {nullable: true})
collection!: Collection

Expand Down
2 changes: 1 addition & 1 deletion src/model/generated/nft.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {EmoteCategory} from "./_emoteCategory"
import {Network} from "./_network"

@Index_(["item", "owner"], {unique: false})
@Index_(["contractAddress", "tokenId"], {unique: false})
@Index_(["searchOrderStatus", "searchOrderExpiresAt", "network"], {unique: false})
@Index_(["searchOrderStatus", "searchOrderExpiresAt", "category"], {unique: false})
@Entity_()
Expand All @@ -33,7 +34,6 @@ export class NFT {
@BigIntColumn_({nullable: false})
tokenId!: bigint

@Index_()
@StringColumn_({nullable: false})
contractAddress!: string

Expand Down

0 comments on commit 24ebdab

Please sign in to comment.