From 54a618559e5aef696bbd006496241c5ba604498f Mon Sep 17 00:00:00 2001 From: Neil Kistner Date: Wed, 2 Feb 2022 06:41:18 -0600 Subject: [PATCH] Slim down marketplace subgraph into essential information only (#3) --- packages/config/src/arbitrum.json | 4 + subgraphs/marketplace/package.json | 17 + subgraphs/marketplace/schema.graphql | 92 ++++ subgraphs/marketplace/src/helpers/ids.ts | 13 + subgraphs/marketplace/src/helpers/index.ts | 4 + subgraphs/marketplace/src/helpers/model.ts | 44 ++ subgraphs/marketplace/src/helpers/token-id.ts | 244 ++++++++++ subgraphs/marketplace/src/helpers/utils.ts | 25 + subgraphs/marketplace/src/mapping.ts | 428 ++++++++++++++++++ .../marketplace/src/mappings/consumables.ts | 18 + .../marketplace/src/mappings/extra-life.ts | 18 + subgraphs/marketplace/src/mappings/keys.ts | 18 + .../src/mappings/legacy-legions-genesis.ts | 18 + .../src/mappings/legacy-legions.ts | 18 + subgraphs/marketplace/src/mappings/legions.ts | 9 + .../marketplace/src/mappings/seed-of-life.ts | 18 + .../marketplace/src/mappings/smol-bodies.ts | 9 + .../src/mappings/smol-brains-land.ts | 9 + .../marketplace/src/mappings/smol-brains.ts | 9 + .../marketplace/src/mappings/smol-cars.ts | 9 + .../marketplace/src/mappings/treasures.ts | 18 + subgraphs/marketplace/template.yaml | 353 +++++++++++++++ 22 files changed, 1395 insertions(+) create mode 100644 subgraphs/marketplace/package.json create mode 100644 subgraphs/marketplace/schema.graphql create mode 100644 subgraphs/marketplace/src/helpers/ids.ts create mode 100644 subgraphs/marketplace/src/helpers/index.ts create mode 100644 subgraphs/marketplace/src/helpers/model.ts create mode 100644 subgraphs/marketplace/src/helpers/token-id.ts create mode 100644 subgraphs/marketplace/src/helpers/utils.ts create mode 100644 subgraphs/marketplace/src/mapping.ts create mode 100644 subgraphs/marketplace/src/mappings/consumables.ts create mode 100644 subgraphs/marketplace/src/mappings/extra-life.ts create mode 100644 subgraphs/marketplace/src/mappings/keys.ts create mode 100644 subgraphs/marketplace/src/mappings/legacy-legions-genesis.ts create mode 100644 subgraphs/marketplace/src/mappings/legacy-legions.ts create mode 100644 subgraphs/marketplace/src/mappings/legions.ts create mode 100644 subgraphs/marketplace/src/mappings/seed-of-life.ts create mode 100644 subgraphs/marketplace/src/mappings/smol-bodies.ts create mode 100644 subgraphs/marketplace/src/mappings/smol-brains-land.ts create mode 100644 subgraphs/marketplace/src/mappings/smol-brains.ts create mode 100644 subgraphs/marketplace/src/mappings/smol-cars.ts create mode 100644 subgraphs/marketplace/src/mappings/treasures.ts create mode 100644 subgraphs/marketplace/template.yaml diff --git a/packages/config/src/arbitrum.json b/packages/config/src/arbitrum.json index ef7dadb0..3cecdc0c 100644 --- a/packages/config/src/arbitrum.json +++ b/packages/config/src/arbitrum.json @@ -32,8 +32,12 @@ "treasure_address": "0xEBba467eCB6b21239178033189CeAE27CA12EaDf", "treasure_start_block": 2416540, + "seed_of_life_address": "0x3956C81A51FeAed98d7A678d53F44b9166c8ed66", + "seed_of_life_start_block": 2416557, "extra_life_address": "0x21e1969884D477afD2Afd4Ad668864a0EebD644c", "extra_life_start_block": 2416557, + "keys_address": "0xf0a35bA261ECE4FC12870e5B7b9E7790202EF9B5", + "keys_start_block": 2416554, "smol_brains_address": "0x6325439389E0797Ab35752B4F43a14C004f22A9c", "smol_brains_start_block": 3163146, "smol_brains_land_address": "0xd666d1CC3102cd03e07794A61E5F4333B4239F53", diff --git a/subgraphs/marketplace/package.json b/subgraphs/marketplace/package.json new file mode 100644 index 00000000..ec31ecf2 --- /dev/null +++ b/subgraphs/marketplace/package.json @@ -0,0 +1,17 @@ +{ + "name": "marketplace", + "version": "1.0.0", + "description": "Subgraph that powers the Treasure Marketplace", + "license": "MIT", + "scripts": { + "build": "graph build subgraph.yaml", + "codegen": "graph codegen subgraph.yaml", + "deploy:dev": "graphx deploy --product hosted-service treasureproject/bridgeworld-dev", + "deploy:prod": "graph deploy --product hosted-service treasureproject/marketplace", + "deploy:staging": "graph deploy --product hosted-service treasureproject/marketplace-next", + "prepare:arbitrum": "mustache ../../node_modules/@treasure/subgraph-config/src/arbitrum.json template.yaml > subgraph.yaml", + "prepare:arbitrum-testnet": "mustache ../../node_modules/@treasure/subgraph-config/src/arbitrum-testnet.json template.yaml > subgraph.yaml", + "prepare:mainnet": "true", + "test": "graph test" + } +} diff --git a/subgraphs/marketplace/schema.graphql b/subgraphs/marketplace/schema.graphql new file mode 100644 index 00000000..fd4d44a2 --- /dev/null +++ b/subgraphs/marketplace/schema.graphql @@ -0,0 +1,92 @@ +enum Status { + Active + Inactive + Sold +} + +enum TokenStandard { + ERC721 + ERC1155 +} + +type Collection @entity { + id: ID! + + contract: String! + floorPrice: BigInt! + listings: [Listing!]! + name: String! + tokens: [Token!]! @derivedFrom(field: "collection") + standard: TokenStandard! + + totalListings: Int! + totalSales: BigInt! + totalVolume: BigInt! +} + +type Listing @entity { + id: ID! + + # "Track originally listed quantity, needed when staking Treasures" + # _listedQuantity: BigInt! + + blockTimestamp: BigInt! + buyer: User + # contract: String! + collection: Collection! + # collectionName: String! + expires: BigInt! + + # "Used to support multiple filters with metadata attributes" + # filters: [String!] + + # nicePrice: String + pricePerItem: BigInt! + quantity: Int! + seller: User! + status: Status! + token: Token! + # tokenName: String + # totalPrice: String + + # Sold listing + transactionLink: String +} + +type Token @entity { + id: ID! + + collection: Collection! + # contract: String! + "For ERC1155s, but is it needed?" + floorPrice: BigInt + listings: [Listing!] @derivedFrom(field: "token") + name: String + owners: [UserToken!]! @derivedFrom(field: "token") + tokenId: BigInt! +} + +type User @entity { + id: ID! + + listings: [Listing!]! @derivedFrom(field: "seller") + purchases: [Listing!]! @derivedFrom(field: "buyer") + tokens: [UserToken!]! @derivedFrom(field: "user") + staked: [StakedToken!]! @derivedFrom(field: "user") +} + +type UserToken @entity { + id: ID! + + quantity: Int! + token: Token! + user: User! +} + +type StakedToken @entity { + id: ID! + + quantity: Int! + token: Token! + user: User! +} diff --git a/subgraphs/marketplace/src/helpers/ids.ts b/subgraphs/marketplace/src/helpers/ids.ts new file mode 100644 index 00000000..035fb255 --- /dev/null +++ b/subgraphs/marketplace/src/helpers/ids.ts @@ -0,0 +1,13 @@ +import { Address, BigInt } from "@graphprotocol/graph-ts"; + +export function getAddressId(address: Address, tokenId: BigInt): string { + return `${address.toHexString()}-${tokenId.toHexString()}`; +} + +export function getUserAddressId( + user: Address, + address: Address, + tokenId: BigInt +): string { + return [user.toHexString(), getAddressId(address, tokenId)].join("-"); +} diff --git a/subgraphs/marketplace/src/helpers/index.ts b/subgraphs/marketplace/src/helpers/index.ts new file mode 100644 index 00000000..eae53b96 --- /dev/null +++ b/subgraphs/marketplace/src/helpers/index.ts @@ -0,0 +1,4 @@ +export * from "./ids"; +export * from "./model"; +export * from "./token-id"; +export * from "./utils"; diff --git a/subgraphs/marketplace/src/helpers/model.ts b/subgraphs/marketplace/src/helpers/model.ts new file mode 100644 index 00000000..3aac67de --- /dev/null +++ b/subgraphs/marketplace/src/helpers/model.ts @@ -0,0 +1,44 @@ +import { Address, log } from "@graphprotocol/graph-ts"; +import { Collection } from "../../generated/schema"; + +function createCollection( + contract: Address, + name: string, + standard: string +): void { + let id = contract.toHexString(); + let collection = Collection.load(id); + + if (!collection) { + collection = new Collection(id); + + collection.contract = id; + collection.listings = []; + collection.name = name; + collection.standard = standard; + + collection.save(); + } +} + +export function createErc721Collection(contract: Address, name: string): void { + createCollection(contract, name, "ERC721"); +} + +export function createErc1155Collection(contract: Address, name: string): void { + createCollection(contract, name, "ERC1155"); +} + +export function getCollection(contract: Address): Collection { + let id = contract.toHexString(); + let collection = Collection.load(id); + + // Should never happen, famous last words + if (!collection) { + collection = new Collection(id); + + log.warning("Unknown collection: {}", [contract.toHexString()]); + } + + return collection; +} diff --git a/subgraphs/marketplace/src/helpers/token-id.ts b/subgraphs/marketplace/src/helpers/token-id.ts new file mode 100644 index 00000000..2581e51b --- /dev/null +++ b/subgraphs/marketplace/src/helpers/token-id.ts @@ -0,0 +1,244 @@ +import { BigInt, log } from "@graphprotocol/graph-ts"; + +export function getName(tokenId: BigInt): string { + let id = tokenId.toI32(); + + switch (id) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + return `All-Class ${id}`; + case 39: + return "Ancient Relic"; + case 40: + case 41: + case 42: + case 43: + case 44: + return `Assassin ${id - 39}`; + case 45: + return "Assassin"; + case 46: + return "Bag of Rare Mushrooms"; + case 47: + return "Bait for Monsters"; + case 48: + return "Beetle-wing"; + case 49: + return "Blue Rupee"; + case 50: + return "Bombmaker"; + case 51: + return "Bottomless Elixir"; + case 52: + return "Cap of Invisibility"; + case 53: + return "Carriage"; + case 54: + return "Castle"; + case 55: + return "Clocksnatcher"; + case 56: + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 65: + case 66: + case 67: + return `Common ${id - 55}`; + case 68: + return "Common Bead"; + case 69: + return "Common Feather"; + case 70: + return "Common Legion"; + case 71: + return "Common Relic"; + case 72: + return "Cow"; + case 73: + return "Diamond"; + case 74: + return "Divine Hourglass"; + case 75: + return "Divine Mask"; + case 76: + return "Donkey"; + case 77: + return "Dragon Tail"; + case 78: + return "Dreamwinder"; + case 79: + return "Emerald"; + case 80: + return "Extra Life"; + case 81: + return "Fallen"; + case 82: + return "Favor from the Gods"; + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + return `Fighter ${id - 82}`; + case 90: + return "Fighter"; + case 91: + return "Framed Butterfly"; + case 92: + return "Gold Coin"; + case 93: + return "Grain"; + case 94: + return "Green Rupee"; + case 95: + return "Grin"; + case 96: + return "Half-Penny"; + case 97: + return "Honeycomb"; + case 98: + return "Immovable Stone"; + case 99: + return "Ivory Breastpin"; + case 100: + return "Jar of Fairies"; + case 102: + return "Keys"; + case 103: + return "Lumber"; + case 104: + return "Military Stipend"; + case 105: + return "Mollusk Shell"; + case 106: + case 107: + case 108: + case 109: + case 110: + case 111: + case 112: + case 113: + return `Numeraire ${id - 105}`; + case 114: + return "Ox"; + case 115: + return "Pearl"; + case 116: + return "Pot of Gold"; + case 117: + return "Quarter-Penny"; + case 118: + case 119: + case 120: + case 121: + case 122: + case 123: + case 124: + case 125: + case 126: + case 127: + case 128: + case 129: + case 130: + return `Range ${id - 117}`; + case 131: + return "Range"; + case 132: + return "Red Feather"; + case 133: + return "Red Rupee"; + case 134: + case 135: + case 136: + case 137: + case 138: + case 139: + case 140: + return `Riverman ${id - 133}`; + case 141: + return "Score of Ivory"; + case 142: + case 143: + return `Seed of Life ${id - 141}`; + case 144: + case 145: + case 146: + case 147: + case 148: + case 149: + return `Siege ${id - 143}`; + case 150: + return "Siege"; + case 151: + return "Silver Coin"; + case 152: + return "Small Bird"; + case 153: + return "Snow White Feather"; + case 154: + case 155: + case 156: + case 157: + case 158: + case 159: + return `Spellcaster ${id - 153}`; + case 160: + return "Spellcaster"; + case 161: + return "Thread of Divine Silk"; + case 162: + return "Unbreakable Pocketwatch"; + case 163: + return "Warlock"; + case 164: + return "Witches Broom"; + default: + // log.warning(`Name not handled: ${id}`, [id]); + + return ""; + } +} diff --git a/subgraphs/marketplace/src/helpers/utils.ts b/subgraphs/marketplace/src/helpers/utils.ts new file mode 100644 index 00000000..f67674c2 --- /dev/null +++ b/subgraphs/marketplace/src/helpers/utils.ts @@ -0,0 +1,25 @@ +import { Address, store } from "@graphprotocol/graph-ts"; + +export function exists(entity: string, id: string): boolean { + return store.get(entity, id) != null; +} + +export function isMint(address: Address): boolean { + return address.equals(Address.zero()); +} + +function removeAtIndex(array: T[], index: i32): T[] { + return index == -1 + ? array + : array.slice(0, index).concat(array.slice(index + 1)); +} + +export function removeFromArray(array: T[], item: T): T[] { + return removeAtIndex(array, array.indexOf(item)); +} + +export function removeIfExists(entity: string, id: string): void { + if (exists(entity, id)) { + store.remove(entity, id); + } +} diff --git a/subgraphs/marketplace/src/mapping.ts b/subgraphs/marketplace/src/mapping.ts new file mode 100644 index 00000000..619af2bc --- /dev/null +++ b/subgraphs/marketplace/src/mapping.ts @@ -0,0 +1,428 @@ +import { Address, BigInt, TypedMap } from "@graphprotocol/graph-ts"; +import { + Listing, + StakedToken, + Token, + User, + UserToken, +} from "../generated/schema"; +import { EXPLORER } from "@treasure/constants"; +import { + ItemCanceled, + ItemListed, + ItemSold, + ItemUpdated, +} from "../generated/TreasureMarketplace/TreasureMarketplace"; +import { + TransferBatch, + TransferSingle, +} from "../generated/TreasureMarketplace/ERC1155"; +import { Transfer } from "../generated/TreasureMarketplace/ERC721"; +import { + exists, + getAddressId, + getCollection, + getName, + getUserAddressId, + removeFromArray, + removeIfExists, +} from "./helpers"; +import { DropGym, JoinGym } from "../generated/Smol Bodies Gym/Gym"; +import { DropSchool, JoinSchool } from "../generated/Smol Brains School/School"; + +const MARKETPLACE_BUYER = Address.fromString( + "0x812cda2181ed7c45a35a691e0c85e231d218e273" +); + +let stakers = new TypedMap(); + +// Smol Bodies +stakers.set( + "0x66299ecc614b7a1920922bba7527819c841174bd", + "0x17dacad7975960833f374622fad08b90ed67d1b5" +); + +// Smol Brains +stakers.set( + "0x602e50ed10a90d324b35930ec0f8e5d3b28cd509", + "0x6325439389e0797ab35752b4f43a14c004f22a9c" +); + +function getListing( + seller: Address, + contract: Address, + tokenId: BigInt +): Listing { + let id = getUserAddressId(seller, contract, tokenId); + let listing = Listing.load(id); + + if (!listing) { + listing = new Listing(id); + + listing.collection = contract.toHexString(); + listing.seller = getUser(seller).id; + listing.status = exists("StakedToken", id) ? "Inactive" : "Active"; + } + + return listing; +} + +function getToken(contract: Address, tokenId: BigInt): Token { + let id = getAddressId(contract, tokenId); + let token = Token.load(id); + + if (!token) { + let collection = getCollection(contract); + + token = new Token(id); + + token.collection = collection.id; + + // TODO: Get dynamic names for Legions? + if (collection.standard == "ERC721") { + token.name = `${collection.name} #${tokenId.toString()}`; + } else { + token.name = getName(tokenId); + } + + token.tokenId = tokenId; + token.save(); + } + + return token; +} + +function getStakedTokenId( + user: Address, + contract: Address, + tokenId: BigInt +): string { + let token = stakers.get(contract.toHexString()); + let id = getUserAddressId( + user, + token ? Address.fromString(token) : contract, + tokenId + ); + + return id; +} + +function getUser(address: Address): User { + let user = User.load(address.toHexString()); + + if (!user) { + user = new User(address.toHexString()); + user.save(); + } + + return user; +} + +function handleStake(user: Address, contract: Address, tokenId: BigInt): void { + let id = getStakedTokenId(user, contract, tokenId); + let stakedToken = StakedToken.load(id); + + if (!stakedToken) { + stakedToken = new StakedToken(id); + + let token = stakers.get(contract.toHexString()); + + // TODO: Is it necessary? Or will it be ok to just use the staked token id + if (token) { + let tokenAddress = Address.fromString(token); + + stakedToken.token = getAddressId(tokenAddress, tokenId); + + // TODO: Handle ERC1155s? + let listing = Listing.load(getUserAddressId(user, tokenAddress, tokenId)); + + if (listing) { + listing.status = "Inactive"; + listing.save(); + + updateCollectionFloorAndTotal(listing.collection); + } + } + + stakedToken.user = user.toHexString(); + } + + // TODO: Support multiple for ERC1155s + stakedToken.quantity = stakedToken.quantity + 1; + stakedToken.save(); +} + +function handleUnstake( + user: Address, + contract: Address, + tokenId: BigInt +): void { + // TODO: Handle ERC1155s with multiple quantities + removeIfExists("StakedToken", getStakedTokenId(user, contract, tokenId)); +} + +/** + * This is a generic function that can handle both ERC1155s and ERC721s + */ +// TODO: Handle staking contracts and bridgeworld staking +function handleTransfer( + contract: Address, + from: Address, + to: Address, + tokenId: BigInt, + quantity: i32 +): void { + let user = getUser(to); + let token = getToken(contract, tokenId); + + let listing = Listing.load(getUserAddressId(from, contract, tokenId)); + + if (listing) { + listing.status = "Inactive"; + listing.save(); + + updateCollectionFloorAndTotal(listing.collection); + } + + let fromUserToken = UserToken.load(`${from.toHexString()}-${token.id}`); + + if (fromUserToken) { + fromUserToken.quantity = fromUserToken.quantity - quantity; + fromUserToken.save(); + + if (fromUserToken.quantity == 0) { + removeIfExists("UserToken", fromUserToken.id); + } + } + + let id = `${user.id}-${token.id}`; + let toUserToken = UserToken.load(id); + + if (!toUserToken) { + toUserToken = new UserToken(id); + + toUserToken.token = token.id; + toUserToken.user = user.id; + } + + toUserToken.quantity = toUserToken.quantity + quantity; + toUserToken.save(); +} + +function updateCollectionFloorAndTotal(id: string): void { + let collection = getCollection(Address.fromString(id)); + let floorPrices = new TypedMap(); + let listings = collection.listings; + let length = listings.length; + + collection.floorPrice = BigInt.zero(); + collection.totalListings = 0; + + for (let index = 0; index < length; index++) { + let id = listings[index]; + let listing = Listing.load(id); + + if (!listing) { + collection.listings = removeFromArray(listings, id); + } else { + if (listing.status == "Active") { + let floorPrice = collection.floorPrice; + let pricePerItem = listing.pricePerItem; + + if (collection.standard == "ERC1155") { + let tokenFloorPrice = floorPrices.get(listing.token); + + if ( + !tokenFloorPrice || + (tokenFloorPrice && tokenFloorPrice.gt(pricePerItem)) + ) { + floorPrices.set(listing.token, pricePerItem); + } + } + + if (floorPrice.isZero() || floorPrice.gt(pricePerItem)) { + collection.floorPrice = pricePerItem; + } + + collection.totalListings += listing.quantity; + } + } + } + + let entries = floorPrices.entries; + + for (let index = 0; index < entries.length; index++) { + let entry = entries[index]; + let token = Token.load(entry.key); + + if (token) { + token.floorPrice = entry.value; + token.save(); + } + } + + collection.save(); +} + +export function handleItemCanceled(event: ItemCanceled): void { + let params = event.params; + let address = params.nftAddress; + let listing = getListing(params.seller, address, params.tokenId); + + removeIfExists("Listing", listing.id); + + updateCollectionFloorAndTotal(listing.collection); +} + +export function handleItemListed(event: ItemListed): void { + let params = event.params; + let pricePerItem = params.pricePerItem; + let quantity = params.quantity; + let tokenAddress = params.nftAddress; + let tokenId = params.tokenId; + let seller = params.seller; + + let listing = getListing(seller, tokenAddress, tokenId); + + listing.blockTimestamp = event.block.timestamp; + listing.expires = params.expirationTime; + listing.pricePerItem = pricePerItem; + listing.quantity = quantity.toI32(); + listing.token = getAddressId(tokenAddress, tokenId); + + listing.save(); + + let collection = getCollection(tokenAddress); + + collection.listings = collection.listings.concat([listing.id]); + collection.save(); + + updateCollectionFloorAndTotal(collection.id); +} + +export function handleItemSold(event: ItemSold): void { + let params = event.params; + let quantity = params.quantity.toI32(); + let seller = params.seller; + let address = params.nftAddress; + let tokenId = params.tokenId; + let buyer = params.buyer.equals(MARKETPLACE_BUYER) + ? event.transaction.from + : params.buyer; + + let listing = getListing(seller, address, tokenId); + + listing.quantity = listing.quantity - quantity; + + if (listing.quantity == 0) { + // Remove sold listing. + removeIfExists("Listing", listing.id); + } else { + listing.save(); + } + + let hash = event.transaction.hash.toHexString(); + let sold = getListing(seller, address, tokenId); + + sold.id = `${sold.id}-${hash}`; + sold.blockTimestamp = event.block.timestamp; + sold.buyer = getUser(buyer).id; + sold.collection = listing.collection; + sold.expires = BigInt.zero(); + sold.pricePerItem = listing.pricePerItem; + sold.quantity = quantity; + sold.status = "Sold"; + sold.transactionLink = `https://${EXPLORER}/tx/${hash}`; + sold.token = listing.token; + + sold.save(); + + let collection = getCollection(address); + + collection.totalSales = collection.totalSales.plus(BigInt.fromI32(1)); + collection.totalVolume = collection.totalVolume.plus( + listing.pricePerItem.times(BigInt.fromI32(quantity)) + ); + + // TODO: Not sure if this is needeed, but put it in for now. + if (listing.quantity == 0) { + collection.listings = removeFromArray(collection.listings, listing.id); + } + + collection.save(); + + updateCollectionFloorAndTotal(collection.id); +} + +export function handleItemUpdated(event: ItemUpdated): void { + let params = event.params; + let listing = getListing(params.seller, params.nftAddress, params.tokenId); + + if (!listing.pricePerItem.equals(params.pricePerItem)) { + listing.blockTimestamp = event.block.timestamp; + } + + listing.expires = params.expirationTime; + listing.status = exists("StakedToken", listing.id) ? "Inactive" : "Active"; + listing.quantity = params.quantity.toI32(); + listing.pricePerItem = params.pricePerItem; + + listing.save(); + + updateCollectionFloorAndTotal(listing.collection); +} + +export function handleTransfer721(event: Transfer): void { + let params = event.params; + + handleTransfer(event.address, params.from, params.to, params.tokenId, 1); +} + +export function handleTransferBatch(event: TransferBatch): void { + let params = event.params; + let ids = params.ids; + let amounts = params.values; + let length = ids.length; + + for (let index = 0; index < length; index++) { + handleTransfer( + event.address, + params.from, + params.to, + ids[index], + amounts[index].toI32() + ); + } +} + +export function handleTransferSingle(event: TransferSingle): void { + let params = event.params; + + handleTransfer( + event.address, + params.from, + params.to, + params.id, + params.value.toI32() + ); +} + +// Smol Bodies + +export function handleDropGym(event: DropGym): void { + handleUnstake(event.transaction.from, event.address, event.params.tokenId); +} + +export function handleJoinGym(event: JoinGym): void { + handleStake(event.transaction.from, event.address, event.params.tokenId); +} + +// Smol Brains + +export function handleDropSchool(event: DropSchool): void { + handleUnstake(event.transaction.from, event.address, event.params.tokenId); +} + +export function handleJoinSchool(event: JoinSchool): void { + handleStake(event.transaction.from, event.address, event.params.tokenId); +} diff --git a/subgraphs/marketplace/src/mappings/consumables.ts b/subgraphs/marketplace/src/mappings/consumables.ts new file mode 100644 index 00000000..5496cefe --- /dev/null +++ b/subgraphs/marketplace/src/mappings/consumables.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Consumables"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Consumables"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/extra-life.ts b/subgraphs/marketplace/src/mappings/extra-life.ts new file mode 100644 index 00000000..6dec1997 --- /dev/null +++ b/subgraphs/marketplace/src/mappings/extra-life.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Extra Life"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Extra Life"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/keys.ts b/subgraphs/marketplace/src/mappings/keys.ts new file mode 100644 index 00000000..0a9156b7 --- /dev/null +++ b/subgraphs/marketplace/src/mappings/keys.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Keys"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Keys"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/legacy-legions-genesis.ts b/subgraphs/marketplace/src/mappings/legacy-legions-genesis.ts new file mode 100644 index 00000000..1860582c --- /dev/null +++ b/subgraphs/marketplace/src/mappings/legacy-legions-genesis.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Legacy Legions Genesis"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Legacy Legions Genesis"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/legacy-legions.ts b/subgraphs/marketplace/src/mappings/legacy-legions.ts new file mode 100644 index 00000000..aaf79055 --- /dev/null +++ b/subgraphs/marketplace/src/mappings/legacy-legions.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Legacy Legions"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Legacy Legions"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/legions.ts b/subgraphs/marketplace/src/mappings/legions.ts new file mode 100644 index 00000000..61befe2c --- /dev/null +++ b/subgraphs/marketplace/src/mappings/legions.ts @@ -0,0 +1,9 @@ +import * as common from "../mapping"; +import { Transfer } from "../../generated/TreasureMarketplace/ERC721"; +import { createErc721Collection } from "../helpers"; + +export function handleTransfer(event: Transfer): void { + createErc721Collection(event.address, "Legions"); + + common.handleTransfer721(event); +} diff --git a/subgraphs/marketplace/src/mappings/seed-of-life.ts b/subgraphs/marketplace/src/mappings/seed-of-life.ts new file mode 100644 index 00000000..9fabecc7 --- /dev/null +++ b/subgraphs/marketplace/src/mappings/seed-of-life.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Seed of Life"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Seed of Life"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/src/mappings/smol-bodies.ts b/subgraphs/marketplace/src/mappings/smol-bodies.ts new file mode 100644 index 00000000..b912e68d --- /dev/null +++ b/subgraphs/marketplace/src/mappings/smol-bodies.ts @@ -0,0 +1,9 @@ +import * as common from "../mapping"; +import { Transfer } from "../../generated/TreasureMarketplace/ERC721"; +import { createErc721Collection } from "../helpers"; + +export function handleTransfer(event: Transfer): void { + createErc721Collection(event.address, "Smol Bodies"); + + common.handleTransfer721(event); +} diff --git a/subgraphs/marketplace/src/mappings/smol-brains-land.ts b/subgraphs/marketplace/src/mappings/smol-brains-land.ts new file mode 100644 index 00000000..8d35719f --- /dev/null +++ b/subgraphs/marketplace/src/mappings/smol-brains-land.ts @@ -0,0 +1,9 @@ +import * as common from "../mapping"; +import { Transfer } from "../../generated/TreasureMarketplace/ERC721"; +import { createErc721Collection } from "../helpers"; + +export function handleTransfer(event: Transfer): void { + createErc721Collection(event.address, "Smol Brains Land"); + + common.handleTransfer721(event); +} diff --git a/subgraphs/marketplace/src/mappings/smol-brains.ts b/subgraphs/marketplace/src/mappings/smol-brains.ts new file mode 100644 index 00000000..256fcfed --- /dev/null +++ b/subgraphs/marketplace/src/mappings/smol-brains.ts @@ -0,0 +1,9 @@ +import * as common from "../mapping"; +import { Transfer } from "../../generated/TreasureMarketplace/ERC721"; +import { createErc721Collection } from "../helpers"; + +export function handleTransfer(event: Transfer): void { + createErc721Collection(event.address, "Smol Brains"); + + common.handleTransfer721(event); +} diff --git a/subgraphs/marketplace/src/mappings/smol-cars.ts b/subgraphs/marketplace/src/mappings/smol-cars.ts new file mode 100644 index 00000000..c89e8103 --- /dev/null +++ b/subgraphs/marketplace/src/mappings/smol-cars.ts @@ -0,0 +1,9 @@ +import * as common from "../mapping"; +import { Transfer } from "../../generated/TreasureMarketplace/ERC721"; +import { createErc721Collection } from "../helpers"; + +export function handleTransfer(event: Transfer): void { + createErc721Collection(event.address, "Smol Cars"); + + common.handleTransfer721(event); +} diff --git a/subgraphs/marketplace/src/mappings/treasures.ts b/subgraphs/marketplace/src/mappings/treasures.ts new file mode 100644 index 00000000..6cd1976e --- /dev/null +++ b/subgraphs/marketplace/src/mappings/treasures.ts @@ -0,0 +1,18 @@ +import * as common from "../mapping"; +import { + TransferBatch, + TransferSingle, +} from "../../generated/TreasureMarketplace/ERC1155"; +import { createErc1155Collection } from "../helpers"; + +export function handleTransferSingle(event: TransferSingle): void { + createErc1155Collection(event.address, "Treasures"); + + common.handleTransferSingle(event); +} + +export function handleTransferBatch(event: TransferBatch): void { + createErc1155Collection(event.address, "Treasures"); + + common.handleTransferBatch(event); +} diff --git a/subgraphs/marketplace/template.yaml b/subgraphs/marketplace/template.yaml new file mode 100644 index 00000000..e09bd6dd --- /dev/null +++ b/subgraphs/marketplace/template.yaml @@ -0,0 +1,353 @@ +specVersion: 0.0.4 +schema: + file: ./schema.graphql +dataSources: + - name: TreasureMarketplace + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ treasure_marketplace_address }}" + abi: TreasureMarketplace + startBlock: {{ treasure_marketplace_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - ItemCanceled + - ItemListed + - ItemSold + - ItemUpdated + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + - name: ERC1155 + file: {{{ abis }}}/1155.json + - name: TreasureMarketplace + file: {{{ abis }}}/TreasureMarketplace.json + eventHandlers: + - event: ItemCanceled(address,address,uint256) + handler: handleItemCanceled + - event: ItemListed(address,address,uint256,uint256,uint256,uint256) + handler: handleItemListed + - event: ItemSold(address,address,address,uint256,uint256,uint256) + handler: handleItemSold + - event: ItemUpdated(address,address,uint256,uint256,uint256,uint256) + handler: handleItemUpdated + file: ./src/mapping.ts + - name: Legacy Legion + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ legacy_legion_address }}" + abi: ERC1155 + startBlock: {{ legacy_legion_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Token + - User + - UserToken + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/legacy-legions.ts + - name: Legacy Legions Genesis + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ legacy_legion_genesis_address }}" + abi: ERC1155 + startBlock: {{ legacy_legion_genesis_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Token + - User + - UserToken + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/legacy-legions-genesis.ts + - name: Treasure + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ treasure_address }}" + abi: ERC1155 + startBlock: {{ treasure_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Token + - User + - UserToken + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/treasures.ts + - name: Seed of Life + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ seed_of_life_address }}" + abi: ERC1155 + startBlock: {{ seed_of_life_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - TransferBatch + - TransferSingle + - URI + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/seed-of-life.ts + - name: Keys + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ keys_address }}" + abi: ERC1155 + startBlock: {{ keys_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - TransferBatch + - TransferSingle + - URI + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/keys.ts + - name: Extra Life + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ extra_life_address }}" + abi: ERC1155 + startBlock: {{ extra_life_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - TransferBatch + - TransferSingle + - URI + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/extra-life.ts + - name: Smol Brains + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_brains_address }}" + abi: ERC721 + startBlock: {{ smol_brains_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + eventHandlers: + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleTransfer + file: ./src/mappings/smol-brains.ts + - name: Smol Brains Land + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_brains_land_address }}" + abi: ERC721 + startBlock: {{ smol_brains_land_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + eventHandlers: + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleTransfer + file: ./src/mappings/smol-brains-land.ts + - name: Smol Brains School + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_brains_school_address }}" + abi: School + startBlock: {{ smol_brains_school_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + abis: + - name: School + file: {{{ abis }}}/SmolBrainsSchool.json + eventHandlers: + - event: DropSchool(uint256) + handler: handleDropSchool + - event: JoinSchool(uint256) + handler: handleJoinSchool + file: ./src/mapping.ts + - name: Smol Cars + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_cars_address }}" + abi: ERC721 + startBlock: {{ smol_cars_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + - SmolCarMint + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + eventHandlers: + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleTransfer + file: ./src/mappings/smol-cars.ts + - name: Smol Bodies + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_bodies_address }}" + abi: ERC721 + startBlock: {{ smol_bodies_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + - SmolBodiesMint + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + eventHandlers: + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleTransfer + file: ./src/mappings/smol-bodies.ts + - name: Smol Bodies Gym + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ smol_bodies_gym_address }}" + abi: Gym + startBlock: {{ smol_bodies_gym_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Transfer + abis: + - name: Gym + file: {{{ abis }}}/SmolBodiesGym.json + eventHandlers: + - event: DropGym(uint256,uint256,uint256) + handler: handleDropGym + - event: JoinGym(uint256) + handler: handleJoinGym + file: ./src/mapping.ts + - name: Legion + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ legion_address }}" + abi: ERC721 + startBlock: {{ legion_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Token + - User + - UserToken + abis: + - name: ERC721 + file: {{{ abis }}}/721.json + eventHandlers: + - event: Transfer(indexed address,indexed address,indexed uint256) + handler: handleTransfer + file: ./src/mappings/legions.ts + - name: Consumable + kind: ethereum/contract + network: {{ network }} + source: + address: "{{ consumable_address }}" + abi: ERC1155 + startBlock: {{ consumable_start_block }} + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - Token + - User + - UserToken + abis: + - name: ERC1155 + file: {{{ abis }}}/1155.json + eventHandlers: + - event: TransferBatch(indexed address,indexed address,indexed address,uint256[],uint256[]) + handler: handleTransferBatch + - event: TransferSingle(indexed address,indexed address,indexed address,uint256,uint256) + handler: handleTransferSingle + file: ./src/mappings/consumables.ts