From 27eac98d6793d4b0c73266fce3555a58cc8618b9 Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:42:28 +0100 Subject: [PATCH 1/8] fix: add parcel installations/tiles balances --- schema.graphql | 2 + src/helper/realm.ts | 113 ++++++++++++++++++++++++++++++++++++------ src/mappings/realm.ts | 2 + 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/schema.graphql b/schema.graphql index b0b117b..3424da9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4,6 +4,8 @@ type Parcel @entity { id: ID! equippedInstallations: [InstallationType!]! equippedTiles: [TileType!]! + equippedInstallationsBalance: [BigInt!]! + equippedTilesBalance: [BigInt!]! lastChanneledAlchemica: BigInt lastClaimedAlchemica: BigInt owner: Bytes diff --git a/src/helper/realm.ts b/src/helper/realm.ts index b16d0a9..458afde 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -9,7 +9,12 @@ import { Parcel, ParcelAccessRight, } from "../../generated/schema"; -import { BIGINT_ZERO, REALM_DIAMOND, StatCategory } from "./constants"; +import { + BIGINT_ONE, + BIGINT_ZERO, + REALM_DIAMOND, + StatCategory, +} from "./constants"; import { getStat } from "./stats"; export const getOrCreateParcel = (realmId: BigInt): Parcel => { @@ -19,6 +24,8 @@ export const getOrCreateParcel = (realmId: BigInt): Parcel => { parcel = new Parcel(id); parcel.equippedInstallations = new Array(); parcel.equippedTiles = new Array(); + parcel.equippedInstallationsBalance = new Array(); + parcel.equippedTilesBalance = new Array(); parcel.remainingAlchemica = [ BIGINT_ZERO, BIGINT_ZERO, @@ -141,9 +148,25 @@ export const createParcelInstallation = ( installationId: BigInt ): Parcel => { let installations = parcel.equippedInstallations; + let installationsBalance = parcel.equippedInstallationsBalance; let id = installationId.toString(); - installations.push(id); + + // Find if this installation type already exists + let existingIndex = installations.indexOf(id); + + if (existingIndex === -1) { + // First installation of this type - add to arrays + installations.push(id); + installationsBalance.push(BIGINT_ONE); + } else { + // Installation type exists - increment balance + installationsBalance[existingIndex] = installationsBalance[ + existingIndex + ].plus(BIGINT_ONE); + } + parcel.equippedInstallations = installations; + parcel.equippedInstallationsBalance = installationsBalance; return parcel; }; @@ -152,37 +175,97 @@ export const removeParcelInstallation = ( installationId: BigInt ): Parcel => { let installations = parcel.equippedInstallations; - let newInstallations = new Array(); + let installationsBalance = parcel.equippedInstallationsBalance; let id = installationId.toString(); - for (let i = 0; i < installations.length; i++) { - let item = installations[i]; - if (item != id) { - newInstallations.push(item); + + // Find the installation type + let existingIndex = installations.indexOf(id); + + if (existingIndex !== -1) { + // Decrement balance + installationsBalance[existingIndex] = installationsBalance[ + existingIndex + ].minus(BIGINT_ONE); + + // If balance reaches zero, remove from both arrays + if (installationsBalance[existingIndex].equals(BIGINT_ZERO)) { + let newInstallations = new Array(); + let newInstallationsBalance = new Array(); + + for (let i = 0; i < installations.length; i++) { + if (i !== existingIndex) { + newInstallations.push(installations[i]); + newInstallationsBalance.push(installationsBalance[i]); + } + } + + parcel.equippedInstallations = newInstallations; + parcel.equippedInstallationsBalance = newInstallationsBalance; + } else { + parcel.equippedInstallationsBalance = installationsBalance; } } - parcel.equippedInstallations = newInstallations; + return parcel; }; export const createParcelTile = (parcel: Parcel, tileId: BigInt): Parcel => { let tiles = parcel.equippedTiles; + let tilesBalance = parcel.equippedTilesBalance; let id = tileId.toString(); - tiles.push(id); + + // Find if this tile type already exists + let existingIndex = tiles.indexOf(id); + + if (existingIndex === -1) { + // First tile of this type - add to arrays + tiles.push(id); + tilesBalance.push(BIGINT_ONE); + } else { + // Tile type exists - increment balance + tilesBalance[existingIndex] = tilesBalance[existingIndex].plus( + BIGINT_ONE + ); + } + parcel.equippedTiles = tiles; + parcel.equippedTilesBalance = tilesBalance; return parcel; }; export const removeParcelTile = (parcel: Parcel, tileId: BigInt): Parcel => { let tiles = parcel.equippedTiles; - let newTiles = new Array(); + let tilesBalance = parcel.equippedTilesBalance; let id = tileId.toString(); - for (let i = 0; i < tiles.length; i++) { - let item = tiles[i]; - if (item != id) { - newTiles.push(item); + + // Find the tile type + let existingIndex = tiles.indexOf(id); + + if (existingIndex !== -1) { + // Decrement balance + tilesBalance[existingIndex] = tilesBalance[existingIndex].minus( + BIGINT_ONE + ); + + // If balance reaches zero, remove from both arrays + if (tilesBalance[existingIndex].equals(BIGINT_ZERO)) { + let newTiles = new Array(); + let newTilesBalance = new Array(); + + for (let i = 0; i < tiles.length; i++) { + if (i !== existingIndex) { + newTiles.push(tiles[i]); + newTilesBalance.push(tilesBalance[i]); + } + } + + parcel.equippedTiles = newTiles; + parcel.equippedTilesBalance = newTilesBalance; + } else { + parcel.equippedTilesBalance = tilesBalance; } } - parcel.equippedTiles = newTiles; + return parcel; }; diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index 64d02dd..6fb4f27 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -551,6 +551,8 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Clear the equipped arrays to start fresh parcel.equippedInstallations = new Array(); parcel.equippedTiles = new Array(); + parcel.equippedInstallationsBalance = new Array(); + parcel.equippedTilesBalance = new Array(); // STEP 3: Equip installations from the new event for (let j = 0; j < parcelData.installations.length; j++) { From 206c09afc15d7f0d9054eb216ff577316632fa67 Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:02:31 +0100 Subject: [PATCH 2/8] fix: resync migrate --- src/mappings/realm.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index 6fb4f27..c8c73b9 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -532,29 +532,13 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Get or create the parcel let parcel = getOrCreateParcel(realmId); - // STEP 1: Unequip all previously equipped installations - let previousInstallations = parcel.equippedInstallations; - for (let p = 0; p < previousInstallations.length; p++) { - let installationTypeId = BigInt.fromString( - previousInstallations[p] - ); - parcel = removeParcelInstallation(parcel, installationTypeId); - } - - // STEP 2: Unequip all previously equipped tiles - let previousTiles = parcel.equippedTiles; - for (let q = 0; q < previousTiles.length; q++) { - let tileTypeId = BigInt.fromString(previousTiles[q]); - parcel = removeParcelTile(parcel, tileTypeId); - } - - // Clear the equipped arrays to start fresh + // STEP 1: Clear the equipped arrays to start fresh (skip removal since we're rebuilding from scratch) parcel.equippedInstallations = new Array(); parcel.equippedTiles = new Array(); parcel.equippedInstallationsBalance = new Array(); parcel.equippedTilesBalance = new Array(); - // STEP 3: Equip installations from the new event + // STEP 2: Equip installations from the new event for (let j = 0; j < parcelData.installations.length; j++) { const installationData = parcelData.installations[j]; @@ -582,7 +566,7 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { installationType.save(); } - // STEP 4: Equip tiles from the new event + // STEP 3: Equip tiles from the new event for (let k = 0; k < parcelData.tiles.length; k++) { const tileData = parcelData.tiles[k]; From 9b08cf07f1d5e1be9d48f9ebc99cafa57ea4c8dc Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:34:41 +0100 Subject: [PATCH 3/8] fix: update parcel info --- src/helper/realm.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/helper/realm.ts b/src/helper/realm.ts index 458afde..dccf1c3 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -74,8 +74,9 @@ export function updateParcelInfo( parcel.remainingAlchemica = parcelMetadata.alchemicaRemaining; - // Extract installation IDs from the structured array, handling balance + // Extract installation IDs and balances from the structured array let installationIds = new Array(); + let installationBalances = new Array(); for ( let i = 0; i < parcelMetadata.equippedInstallations.length; @@ -83,28 +84,27 @@ export function updateParcelInfo( ) { let item = parcelMetadata.equippedInstallations[i]; let installationId = item.installationId.toString(); - let balance = item.balance.toI32(); + let balance = item.balance; - // Add the same installationId multiple times if balance > 1 - for (let j = 0; j < balance; j++) { - installationIds.push(installationId); - } + installationIds.push(installationId); + installationBalances.push(balance); } parcel.equippedInstallations = installationIds; + parcel.equippedInstallationsBalance = installationBalances; - // Extract tile IDs from the structured array, handling balance + // Extract tile IDs and balances from the structured array let tileIds = new Array(); + let tileBalances = new Array(); for (let i = 0; i < parcelMetadata.equippedTiles.length; i++) { let item = parcelMetadata.equippedTiles[i]; let tileId = item.tileId.toString(); - let balance = item.balance.toI32(); + let balance = item.balance; - // Add the same tileId multiple times if balance > 1 - for (let j = 0; j < balance; j++) { - tileIds.push(tileId); - } + tileIds.push(tileId); + tileBalances.push(balance); } parcel.equippedTiles = tileIds; + parcel.equippedTilesBalance = tileBalances; parcel.lastChanneledAlchemica = parcelMetadata.lastChanneledAlchemica; From 71edc41380639ee04586beca172a8db07bb2c8ef Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Wed, 17 Sep 2025 14:06:52 +0100 Subject: [PATCH 4/8] fix: use just total balance --- schema.graphql | 4 +- src/helper/realm.ts | 102 ++++++++++++++++++++---------------------- src/mappings/realm.ts | 5 ++- 3 files changed, 53 insertions(+), 58 deletions(-) diff --git a/schema.graphql b/schema.graphql index 3424da9..8806a67 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4,8 +4,8 @@ type Parcel @entity { id: ID! equippedInstallations: [InstallationType!]! equippedTiles: [TileType!]! - equippedInstallationsBalance: [BigInt!]! - equippedTilesBalance: [BigInt!]! + equippedInstallationsBalance: BigInt! + equippedTilesBalance: BigInt! lastChanneledAlchemica: BigInt lastClaimedAlchemica: BigInt owner: Bytes diff --git a/src/helper/realm.ts b/src/helper/realm.ts index dccf1c3..5823174 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -24,8 +24,8 @@ export const getOrCreateParcel = (realmId: BigInt): Parcel => { parcel = new Parcel(id); parcel.equippedInstallations = new Array(); parcel.equippedTiles = new Array(); - parcel.equippedInstallationsBalance = new Array(); - parcel.equippedTilesBalance = new Array(); + parcel.equippedInstallationsBalance = BIGINT_ZERO; + parcel.equippedTilesBalance = BIGINT_ZERO; parcel.remainingAlchemica = [ BIGINT_ZERO, BIGINT_ZERO, @@ -74,9 +74,9 @@ export function updateParcelInfo( parcel.remainingAlchemica = parcelMetadata.alchemicaRemaining; - // Extract installation IDs and balances from the structured array + // Extract installation IDs and calculate total balance let installationIds = new Array(); - let installationBalances = new Array(); + let totalInstallationsBalance = BIGINT_ZERO; for ( let i = 0; i < parcelMetadata.equippedInstallations.length; @@ -87,24 +87,26 @@ export function updateParcelInfo( let balance = item.balance; installationIds.push(installationId); - installationBalances.push(balance); + totalInstallationsBalance = totalInstallationsBalance.plus( + balance + ); } parcel.equippedInstallations = installationIds; - parcel.equippedInstallationsBalance = installationBalances; + parcel.equippedInstallationsBalance = totalInstallationsBalance; - // Extract tile IDs and balances from the structured array + // Extract tile IDs and calculate total balance let tileIds = new Array(); - let tileBalances = new Array(); + let totalTilesBalance = BIGINT_ZERO; for (let i = 0; i < parcelMetadata.equippedTiles.length; i++) { let item = parcelMetadata.equippedTiles[i]; let tileId = item.tileId.toString(); let balance = item.balance; tileIds.push(tileId); - tileBalances.push(balance); + totalTilesBalance = totalTilesBalance.plus(balance); } parcel.equippedTiles = tileIds; - parcel.equippedTilesBalance = tileBalances; + parcel.equippedTilesBalance = totalTilesBalance; parcel.lastChanneledAlchemica = parcelMetadata.lastChanneledAlchemica; @@ -148,25 +150,21 @@ export const createParcelInstallation = ( installationId: BigInt ): Parcel => { let installations = parcel.equippedInstallations; - let installationsBalance = parcel.equippedInstallationsBalance; let id = installationId.toString(); // Find if this installation type already exists let existingIndex = installations.indexOf(id); if (existingIndex === -1) { - // First installation of this type - add to arrays + // First installation of this type - add to array installations.push(id); - installationsBalance.push(BIGINT_ONE); - } else { - // Installation type exists - increment balance - installationsBalance[existingIndex] = installationsBalance[ - existingIndex - ].plus(BIGINT_ONE); } + // Always increment total balance parcel.equippedInstallations = installations; - parcel.equippedInstallationsBalance = installationsBalance; + parcel.equippedInstallationsBalance = parcel.equippedInstallationsBalance.plus( + BIGINT_ONE + ); return parcel; }; @@ -175,34 +173,35 @@ export const removeParcelInstallation = ( installationId: BigInt ): Parcel => { let installations = parcel.equippedInstallations; - let installationsBalance = parcel.equippedInstallationsBalance; let id = installationId.toString(); // Find the installation type let existingIndex = installations.indexOf(id); if (existingIndex !== -1) { - // Decrement balance - installationsBalance[existingIndex] = installationsBalance[ - existingIndex - ].minus(BIGINT_ONE); + // Always decrement total balance + parcel.equippedInstallationsBalance = parcel.equippedInstallationsBalance.minus( + BIGINT_ONE + ); - // If balance reaches zero, remove from both arrays - if (installationsBalance[existingIndex].equals(BIGINT_ZERO)) { - let newInstallations = new Array(); - let newInstallationsBalance = new Array(); + // Check if we need to remove this installation type from array + // We need to count how many installations of this type remain + let count = 0; + for (let i = 0; i < installations.length; i++) { + if (installations[i] === id) { + count++; + } + } + // If this was the only installation of this type, remove from array + if (count === 1) { + let newInstallations = new Array(); for (let i = 0; i < installations.length; i++) { if (i !== existingIndex) { newInstallations.push(installations[i]); - newInstallationsBalance.push(installationsBalance[i]); } } - parcel.equippedInstallations = newInstallations; - parcel.equippedInstallationsBalance = newInstallationsBalance; - } else { - parcel.equippedInstallationsBalance = installationsBalance; } } @@ -211,58 +210,53 @@ export const removeParcelInstallation = ( export const createParcelTile = (parcel: Parcel, tileId: BigInt): Parcel => { let tiles = parcel.equippedTiles; - let tilesBalance = parcel.equippedTilesBalance; let id = tileId.toString(); // Find if this tile type already exists let existingIndex = tiles.indexOf(id); if (existingIndex === -1) { - // First tile of this type - add to arrays + // First tile of this type - add to array tiles.push(id); - tilesBalance.push(BIGINT_ONE); - } else { - // Tile type exists - increment balance - tilesBalance[existingIndex] = tilesBalance[existingIndex].plus( - BIGINT_ONE - ); } + // Always increment total balance parcel.equippedTiles = tiles; - parcel.equippedTilesBalance = tilesBalance; + parcel.equippedTilesBalance = parcel.equippedTilesBalance.plus(BIGINT_ONE); return parcel; }; export const removeParcelTile = (parcel: Parcel, tileId: BigInt): Parcel => { let tiles = parcel.equippedTiles; - let tilesBalance = parcel.equippedTilesBalance; let id = tileId.toString(); // Find the tile type let existingIndex = tiles.indexOf(id); if (existingIndex !== -1) { - // Decrement balance - tilesBalance[existingIndex] = tilesBalance[existingIndex].minus( + // Always decrement total balance + parcel.equippedTilesBalance = parcel.equippedTilesBalance.minus( BIGINT_ONE ); - // If balance reaches zero, remove from both arrays - if (tilesBalance[existingIndex].equals(BIGINT_ZERO)) { - let newTiles = new Array(); - let newTilesBalance = new Array(); + // Check if we need to remove this tile type from array + // We need to count how many tiles of this type remain + let count = 0; + for (let i = 0; i < tiles.length; i++) { + if (tiles[i] === id) { + count++; + } + } + // If this was the only tile of this type, remove from array + if (count === 1) { + let newTiles = new Array(); for (let i = 0; i < tiles.length; i++) { if (i !== existingIndex) { newTiles.push(tiles[i]); - newTilesBalance.push(tilesBalance[i]); } } - parcel.equippedTiles = newTiles; - parcel.equippedTilesBalance = newTilesBalance; - } else { - parcel.equippedTilesBalance = tilesBalance; } } diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index c8c73b9..d1166b4 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -22,6 +22,7 @@ import { // Removed ParcelWhitelistSetEvent import - no longer storing event entities import { BIGINT_ONE, + BIGINT_ZERO, DISCREPANT_PARCELS, StatCategory, } from "../helper/constants"; @@ -535,8 +536,8 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // STEP 1: Clear the equipped arrays to start fresh (skip removal since we're rebuilding from scratch) parcel.equippedInstallations = new Array(); parcel.equippedTiles = new Array(); - parcel.equippedInstallationsBalance = new Array(); - parcel.equippedTilesBalance = new Array(); + parcel.equippedInstallationsBalance = BIGINT_ZERO; + parcel.equippedTilesBalance = BIGINT_ZERO; // STEP 2: Equip installations from the new event for (let j = 0; j < parcelData.installations.length; j++) { From b64f3e0abf6ccad8ecc391eb3051fab6af6b41fa Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:07:57 +0100 Subject: [PATCH 5/8] fix: add logs to debug --- src/helper/constants.ts | 3 + src/helper/realm.ts | 54 +++++++++++++++ src/mappings/realm.ts | 150 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) diff --git a/src/helper/constants.ts b/src/helper/constants.ts index 1b68e5f..279642e 100644 --- a/src/helper/constants.ts +++ b/src/helper/constants.ts @@ -163,3 +163,6 @@ export const DISCREPANT_PARCELS = [ "9930", "9946", ]; + +// Debugging: set the parcel hash to enable scoped logs for a single parcel +export const DEBUG_PARCEL_HASH = "passively-smol-text"; diff --git a/src/helper/realm.ts b/src/helper/realm.ts index 5823174..39276b1 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -14,6 +14,7 @@ import { BIGINT_ZERO, REALM_DIAMOND, StatCategory, + DEBUG_PARCEL_HASH, } from "./constants"; import { getStat } from "./stats"; @@ -70,6 +71,20 @@ export function updateParcelInfo( parcel.kekBoost = boostArray[3]; if (isBase) { + // Scoped log: when updating parcel info, show current equipped arrays for the debug parcel + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[updateParcelInfo] realmId={}, hash={}, before equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", + [ + parcelId.toString(), + parcel.parcelHash || "", + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTiles.join(","), + parcel.equippedTilesBalance.toString(), + ] + ); + } parcel.surveyRound = parcelMetadata.surveyRound.toI32(); parcel.remainingAlchemica = parcelMetadata.alchemicaRemaining; @@ -114,6 +129,19 @@ export function updateParcelInfo( parcel.lastClaimedAlchemica = parcelMetadata.lastClaimedAlchemica; parcel.owner = parcelMetadata.owner; + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[updateParcelInfo] realmId={}, hash={}, after equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", + [ + parcelId.toString(), + parcel.parcelHash || "", + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTiles.join(","), + parcel.equippedTilesBalance.toString(), + ] + ); + } } } @@ -165,6 +193,19 @@ export const createParcelInstallation = ( parcel.equippedInstallationsBalance = parcel.equippedInstallationsBalance.plus( BIGINT_ONE ); + + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[createParcelInstallation] realmId={}, hash={}, add type={}, now instIds={}, instBal={}", + [ + parcel.id, + parcel.parcelHash || "", + id, + installations.join(","), + parcel.equippedInstallationsBalance.toString(), + ] + ); + } return parcel; }; @@ -205,6 +246,19 @@ export const removeParcelInstallation = ( } } + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[removeParcelInstallation] realmId={}, hash={}, remove type={}, now instIds={}, instBal={}", + [ + parcel.id, + parcel.parcelHash || "", + id, + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + ] + ); + } + return parcel; }; diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index d1166b4..721ad34 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -25,6 +25,7 @@ import { BIGINT_ZERO, DISCREPANT_PARCELS, StatCategory, + DEBUG_PARCEL_HASH, } from "../helper/constants"; import { getOrCreateInstallation, @@ -210,6 +211,23 @@ export function handleEquipInstallation(event: EquipInstallation): void { // create if not exist let parcel = getOrCreateParcel(event.params._realmId); + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + let typeInfo = getOrCreateInstallationType( + event.params._installationId + ); + log.warning( + "[handleEquipInstallation] realmId={}, hash={}, installId={}, typeName={}, x={}, y={}, tx={}", + [ + event.params._realmId.toString(), + parcel.parcelHash || "", + event.params._installationId.toString(), + typeInfo.name ? typeInfo.name! : "", + event.params._x.toString(), + event.params._y.toString(), + event.transaction.hash.toHexString(), + ] + ); + } parcel = createParcelInstallation(parcel, event.params._installationId); parcel.save(); @@ -224,6 +242,31 @@ export function handleEquipInstallation(event: EquipInstallation): void { installation.equipped = true; installation.save(); + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + // Count number of installed Altars on this parcel (by type name) + let altarIds = new Array(); + for (let i = 0; i < parcel.equippedInstallations.length; i++) { + let typ = getOrCreateInstallationType( + BigInt.fromString(parcel.equippedInstallations[i]) + ); + if (typ.name && typ.name!.indexOf("Altar") != -1) { + altarIds.push(typ.id); + } + } + log.warning( + "[handleEquipInstallation] after-save realmId={}, instIds={}, instBal={}, totalTiles={}, altarCount={}, altarTypeIds={}, block={}", + [ + parcel.id, + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTilesBalance.toString(), + altarIds.length.toString(), + altarIds.join(","), + event.block.number.toString(), + ] + ); + } + // update stats let parcelStats = getStat( StatCategory.PARCEL, @@ -257,6 +300,19 @@ export function handleUnequipInstallation(event: UnequipInstallation): void { // Event entity creation removed - no longer storing event entities let parcel = getOrCreateParcel(event.params._realmId); + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleUnequipInstallation] realmId={}, hash={}, installId={}, x={}, y={}, tx={}", + [ + event.params._realmId.toString(), + parcel.parcelHash || "", + event.params._installationId.toString(), + event.params._x.toString(), + event.params._y.toString(), + event.transaction.hash.toHexString(), + ] + ); + } parcel = removeParcelInstallation(parcel, event.params._installationId); parcel.save(); @@ -290,9 +346,36 @@ export function handleUnequipInstallation(event: UnequipInstallation): void { ); installation.equipped = false; installation.save(); + + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleUnequipInstallation] after-save realmId={}, instIds={}, instBal={}, block={}", + [ + parcel.id, + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + event.block.number.toString(), + ] + ); + } } export function handleInstallationUpgraded(event: InstallationUpgraded): void { + let debugParcel = getOrCreateParcel(event.params._realmId); + if (debugParcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleInstallationUpgraded] realmId={}, hash={}, prevId={}, nextId={}, x={}, y={}, tx={}", + [ + event.params._realmId.toString(), + debugParcel.parcelHash || "", + event.params._prevInstallationId.toString(), + event.params._nextInstallationId.toString(), + event.params._coordinateX.toString(), + event.params._coordinateY.toString(), + event.transaction.hash.toHexString(), + ] + ); + } // Event entity creation removed - no longer storing event entities let type = getOrCreateInstallationType(event.params._nextInstallationId); @@ -343,6 +426,19 @@ export function handleInstallationUpgraded(event: InstallationUpgraded): void { ); installation.equipped = true; installation.save(); + + if (debugParcel.parcelHash == DEBUG_PARCEL_HASH) { + let p = getOrCreateParcel(event.params._realmId); + log.warning( + "[handleInstallationUpgraded] after-save realmId={}, instIds={}, instBal={}, block={}", + [ + p.id, + p.equippedInstallations.join(","), + p.equippedInstallationsBalance.toString(), + event.block.number.toString(), + ] + ); + } } export function handleEquipTile(event: EquipTile): void { @@ -448,8 +544,38 @@ export function handleResyncParcel(event: ResyncParcel): void { const currentNetwork = dataSource.network(); const isBase = currentNetwork == "base-sepolia" || currentNetwork == "base"; + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleResyncParcel] realmId={}, hash={}, before update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", + [ + parcel.id, + parcel.parcelHash || "", + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTiles.join(","), + parcel.equippedTilesBalance.toString(), + event.block.number.toString(), + ] + ); + } + parcel = updateParcelInfo(parcel, isBase); + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleResyncParcel] realmId={}, hash={}, after update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", + [ + parcel.id, + parcel.parcelHash || "", + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTiles.join(","), + parcel.equippedTilesBalance.toString(), + event.block.number.toString(), + ] + ); + } + parcel.save(); } @@ -532,6 +658,16 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Get or create the parcel let parcel = getOrCreateParcel(realmId); + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleMigrateResyncParcel] realmId={}, hash={}, start rebuild (block={})", + [ + parcel.id, + parcel.parcelHash || "", + event.block.number.toString(), + ] + ); + } // STEP 1: Clear the equipped arrays to start fresh (skip removal since we're rebuilding from scratch) parcel.equippedInstallations = new Array(); @@ -592,6 +728,20 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Save the updated parcel parcel.save(); + + if (parcel.parcelHash == DEBUG_PARCEL_HASH) { + log.warning( + "[handleMigrateResyncParcel] realmId={}, hash={}, after rebuild -> instIds={}, instBal={}, tiles={}, tileBal={}", + [ + parcel.id, + parcel.parcelHash || "", + parcel.equippedInstallations.join(","), + parcel.equippedInstallationsBalance.toString(), + parcel.equippedTiles.join(","), + parcel.equippedTilesBalance.toString(), + ] + ); + } } } From 19fc5bb0fe485a0f1830aac166b0f7e0cbc83f98 Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:34:06 +0100 Subject: [PATCH 6/8] fix: building issue --- src/helper/realm.ts | 8 ++++---- src/mappings/realm.ts | 16 +++++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/helper/realm.ts b/src/helper/realm.ts index 39276b1..8aa769c 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -77,7 +77,7 @@ export function updateParcelInfo( "[updateParcelInfo] realmId={}, hash={}, before equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", [ parcelId.toString(), - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), parcel.equippedTiles.join(","), @@ -134,7 +134,7 @@ export function updateParcelInfo( "[updateParcelInfo] realmId={}, hash={}, after equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", [ parcelId.toString(), - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), parcel.equippedTiles.join(","), @@ -199,7 +199,7 @@ export const createParcelInstallation = ( "[createParcelInstallation] realmId={}, hash={}, add type={}, now instIds={}, instBal={}", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", id, installations.join(","), parcel.equippedInstallationsBalance.toString(), @@ -251,7 +251,7 @@ export const removeParcelInstallation = ( "[removeParcelInstallation] realmId={}, hash={}, remove type={}, now instIds={}, instBal={}", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", id, parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index 721ad34..a1507ec 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -219,7 +219,7 @@ export function handleEquipInstallation(event: EquipInstallation): void { "[handleEquipInstallation] realmId={}, hash={}, installId={}, typeName={}, x={}, y={}, tx={}", [ event.params._realmId.toString(), - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", event.params._installationId.toString(), typeInfo.name ? typeInfo.name! : "", event.params._x.toString(), @@ -305,7 +305,7 @@ export function handleUnequipInstallation(event: UnequipInstallation): void { "[handleUnequipInstallation] realmId={}, hash={}, installId={}, x={}, y={}, tx={}", [ event.params._realmId.toString(), - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", event.params._installationId.toString(), event.params._x.toString(), event.params._y.toString(), @@ -367,7 +367,9 @@ export function handleInstallationUpgraded(event: InstallationUpgraded): void { "[handleInstallationUpgraded] realmId={}, hash={}, prevId={}, nextId={}, x={}, y={}, tx={}", [ event.params._realmId.toString(), - debugParcel.parcelHash || "", + debugParcel.parcelHash + ? (debugParcel.parcelHash as string) + : "", event.params._prevInstallationId.toString(), event.params._nextInstallationId.toString(), event.params._coordinateX.toString(), @@ -549,7 +551,7 @@ export function handleResyncParcel(event: ResyncParcel): void { "[handleResyncParcel] realmId={}, hash={}, before update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), parcel.equippedTiles.join(","), @@ -566,7 +568,7 @@ export function handleResyncParcel(event: ResyncParcel): void { "[handleResyncParcel] realmId={}, hash={}, after update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), parcel.equippedTiles.join(","), @@ -663,7 +665,7 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { "[handleMigrateResyncParcel] realmId={}, hash={}, start rebuild (block={})", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", event.block.number.toString(), ] ); @@ -734,7 +736,7 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { "[handleMigrateResyncParcel] realmId={}, hash={}, after rebuild -> instIds={}, instBal={}, tiles={}, tileBal={}", [ parcel.id, - parcel.parcelHash || "", + parcel.parcelHash ? (parcel.parcelHash as string) : "", parcel.equippedInstallations.join(","), parcel.equippedInstallationsBalance.toString(), parcel.equippedTiles.join(","), From f7ad6793878ff65b77bcd65c38530be8dfe52882 Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Fri, 3 Oct 2025 14:56:31 +0100 Subject: [PATCH 7/8] fix: remove installations --- src/helper/realm.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helper/realm.ts b/src/helper/realm.ts index 8aa769c..fd935f7 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -229,7 +229,7 @@ export const removeParcelInstallation = ( // We need to count how many installations of this type remain let count = 0; for (let i = 0; i < installations.length; i++) { - if (installations[i] === id) { + if (installations[i] == id) { count++; } } @@ -297,7 +297,7 @@ export const removeParcelTile = (parcel: Parcel, tileId: BigInt): Parcel => { // We need to count how many tiles of this type remain let count = 0; for (let i = 0; i < tiles.length; i++) { - if (tiles[i] === id) { + if (tiles[i] == id) { count++; } } From 0fd3a37e01c939718569db6dc681c6a88f515841 Mon Sep 17 00:00:00 2001 From: Massimiliano <94859244+BromeRST@users.noreply.github.com> Date: Fri, 3 Oct 2025 18:14:20 +0100 Subject: [PATCH 8/8] fix: remove debug logs --- src/helper/constants.ts | 3 - src/helper/realm.ts | 55 +------------- src/mappings/realm.ts | 154 +--------------------------------------- 3 files changed, 2 insertions(+), 210 deletions(-) diff --git a/src/helper/constants.ts b/src/helper/constants.ts index 279642e..1b68e5f 100644 --- a/src/helper/constants.ts +++ b/src/helper/constants.ts @@ -163,6 +163,3 @@ export const DISCREPANT_PARCELS = [ "9930", "9946", ]; - -// Debugging: set the parcel hash to enable scoped logs for a single parcel -export const DEBUG_PARCEL_HASH = "passively-smol-text"; diff --git a/src/helper/realm.ts b/src/helper/realm.ts index fd935f7..557171b 100644 --- a/src/helper/realm.ts +++ b/src/helper/realm.ts @@ -1,4 +1,4 @@ -import { BigInt, log } from "@graphprotocol/graph-ts"; +import { BigInt } from "@graphprotocol/graph-ts"; import { NFTDisplayStatusUpdated, RealmDiamond, @@ -14,7 +14,6 @@ import { BIGINT_ZERO, REALM_DIAMOND, StatCategory, - DEBUG_PARCEL_HASH, } from "./constants"; import { getStat } from "./stats"; @@ -71,20 +70,6 @@ export function updateParcelInfo( parcel.kekBoost = boostArray[3]; if (isBase) { - // Scoped log: when updating parcel info, show current equipped arrays for the debug parcel - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[updateParcelInfo] realmId={}, hash={}, before equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", - [ - parcelId.toString(), - parcel.parcelHash ? (parcel.parcelHash as string) : "", - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTiles.join(","), - parcel.equippedTilesBalance.toString(), - ] - ); - } parcel.surveyRound = parcelMetadata.surveyRound.toI32(); parcel.remainingAlchemica = parcelMetadata.alchemicaRemaining; @@ -129,19 +114,6 @@ export function updateParcelInfo( parcel.lastClaimedAlchemica = parcelMetadata.lastClaimedAlchemica; parcel.owner = parcelMetadata.owner; - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[updateParcelInfo] realmId={}, hash={}, after equip snapshot -> instIds={}, instBal={}, tileIds={}, tileBal={}", - [ - parcelId.toString(), - parcel.parcelHash ? (parcel.parcelHash as string) : "", - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTiles.join(","), - parcel.equippedTilesBalance.toString(), - ] - ); - } } } @@ -194,18 +166,6 @@ export const createParcelInstallation = ( BIGINT_ONE ); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[createParcelInstallation] realmId={}, hash={}, add type={}, now instIds={}, instBal={}", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - id, - installations.join(","), - parcel.equippedInstallationsBalance.toString(), - ] - ); - } return parcel; }; @@ -246,19 +206,6 @@ export const removeParcelInstallation = ( } } - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[removeParcelInstallation] realmId={}, hash={}, remove type={}, now instIds={}, instBal={}", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - id, - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - ] - ); - } - return parcel; }; diff --git a/src/mappings/realm.ts b/src/mappings/realm.ts index a1507ec..ceadfdd 100644 --- a/src/mappings/realm.ts +++ b/src/mappings/realm.ts @@ -1,4 +1,4 @@ -import { BigInt, dataSource, log } from "@graphprotocol/graph-ts"; +import { BigInt, dataSource } from "@graphprotocol/graph-ts"; import { AlchemicaClaimed, ChannelAlchemica, @@ -25,7 +25,6 @@ import { BIGINT_ZERO, DISCREPANT_PARCELS, StatCategory, - DEBUG_PARCEL_HASH, } from "../helper/constants"; import { getOrCreateInstallation, @@ -211,23 +210,6 @@ export function handleEquipInstallation(event: EquipInstallation): void { // create if not exist let parcel = getOrCreateParcel(event.params._realmId); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - let typeInfo = getOrCreateInstallationType( - event.params._installationId - ); - log.warning( - "[handleEquipInstallation] realmId={}, hash={}, installId={}, typeName={}, x={}, y={}, tx={}", - [ - event.params._realmId.toString(), - parcel.parcelHash ? (parcel.parcelHash as string) : "", - event.params._installationId.toString(), - typeInfo.name ? typeInfo.name! : "", - event.params._x.toString(), - event.params._y.toString(), - event.transaction.hash.toHexString(), - ] - ); - } parcel = createParcelInstallation(parcel, event.params._installationId); parcel.save(); @@ -242,31 +224,6 @@ export function handleEquipInstallation(event: EquipInstallation): void { installation.equipped = true; installation.save(); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - // Count number of installed Altars on this parcel (by type name) - let altarIds = new Array(); - for (let i = 0; i < parcel.equippedInstallations.length; i++) { - let typ = getOrCreateInstallationType( - BigInt.fromString(parcel.equippedInstallations[i]) - ); - if (typ.name && typ.name!.indexOf("Altar") != -1) { - altarIds.push(typ.id); - } - } - log.warning( - "[handleEquipInstallation] after-save realmId={}, instIds={}, instBal={}, totalTiles={}, altarCount={}, altarTypeIds={}, block={}", - [ - parcel.id, - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTilesBalance.toString(), - altarIds.length.toString(), - altarIds.join(","), - event.block.number.toString(), - ] - ); - } - // update stats let parcelStats = getStat( StatCategory.PARCEL, @@ -300,19 +257,6 @@ export function handleUnequipInstallation(event: UnequipInstallation): void { // Event entity creation removed - no longer storing event entities let parcel = getOrCreateParcel(event.params._realmId); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleUnequipInstallation] realmId={}, hash={}, installId={}, x={}, y={}, tx={}", - [ - event.params._realmId.toString(), - parcel.parcelHash ? (parcel.parcelHash as string) : "", - event.params._installationId.toString(), - event.params._x.toString(), - event.params._y.toString(), - event.transaction.hash.toHexString(), - ] - ); - } parcel = removeParcelInstallation(parcel, event.params._installationId); parcel.save(); @@ -346,38 +290,9 @@ export function handleUnequipInstallation(event: UnequipInstallation): void { ); installation.equipped = false; installation.save(); - - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleUnequipInstallation] after-save realmId={}, instIds={}, instBal={}, block={}", - [ - parcel.id, - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - event.block.number.toString(), - ] - ); - } } export function handleInstallationUpgraded(event: InstallationUpgraded): void { - let debugParcel = getOrCreateParcel(event.params._realmId); - if (debugParcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleInstallationUpgraded] realmId={}, hash={}, prevId={}, nextId={}, x={}, y={}, tx={}", - [ - event.params._realmId.toString(), - debugParcel.parcelHash - ? (debugParcel.parcelHash as string) - : "", - event.params._prevInstallationId.toString(), - event.params._nextInstallationId.toString(), - event.params._coordinateX.toString(), - event.params._coordinateY.toString(), - event.transaction.hash.toHexString(), - ] - ); - } // Event entity creation removed - no longer storing event entities let type = getOrCreateInstallationType(event.params._nextInstallationId); @@ -428,19 +343,6 @@ export function handleInstallationUpgraded(event: InstallationUpgraded): void { ); installation.equipped = true; installation.save(); - - if (debugParcel.parcelHash == DEBUG_PARCEL_HASH) { - let p = getOrCreateParcel(event.params._realmId); - log.warning( - "[handleInstallationUpgraded] after-save realmId={}, instIds={}, instBal={}, block={}", - [ - p.id, - p.equippedInstallations.join(","), - p.equippedInstallationsBalance.toString(), - event.block.number.toString(), - ] - ); - } } export function handleEquipTile(event: EquipTile): void { @@ -546,38 +448,8 @@ export function handleResyncParcel(event: ResyncParcel): void { const currentNetwork = dataSource.network(); const isBase = currentNetwork == "base-sepolia" || currentNetwork == "base"; - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleResyncParcel] realmId={}, hash={}, before update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTiles.join(","), - parcel.equippedTilesBalance.toString(), - event.block.number.toString(), - ] - ); - } - parcel = updateParcelInfo(parcel, isBase); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleResyncParcel] realmId={}, hash={}, after update -> instIds={}, instBal={}, tiles={}, tileBal={}, block={}", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTiles.join(","), - parcel.equippedTilesBalance.toString(), - event.block.number.toString(), - ] - ); - } - parcel.save(); } @@ -660,16 +532,6 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Get or create the parcel let parcel = getOrCreateParcel(realmId); - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleMigrateResyncParcel] realmId={}, hash={}, start rebuild (block={})", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - event.block.number.toString(), - ] - ); - } // STEP 1: Clear the equipped arrays to start fresh (skip removal since we're rebuilding from scratch) parcel.equippedInstallations = new Array(); @@ -730,20 +592,6 @@ export function handleMigrateResyncParcel(event: MigrateResyncParcel): void { // Save the updated parcel parcel.save(); - - if (parcel.parcelHash == DEBUG_PARCEL_HASH) { - log.warning( - "[handleMigrateResyncParcel] realmId={}, hash={}, after rebuild -> instIds={}, instBal={}, tiles={}, tileBal={}", - [ - parcel.id, - parcel.parcelHash ? (parcel.parcelHash as string) : "", - parcel.equippedInstallations.join(","), - parcel.equippedInstallationsBalance.toString(), - parcel.equippedTiles.join(","), - parcel.equippedTilesBalance.toString(), - ] - ); - } } }