diff --git a/webserver/server/app/controllers/DelegationForPoolController.ts b/webserver/server/app/controllers/DelegationForPoolController.ts index 05c32613..6e0f6193 100644 --- a/webserver/server/app/controllers/DelegationForPoolController.ts +++ b/webserver/server/app/controllers/DelegationForPoolController.ts @@ -10,7 +10,7 @@ import type { DelegationForPoolResponse, DelegationForPoolSingleResponse } from '../../../shared/models/DelegationForPool'; -import {POOL_DELEGATION_LIMIT, PROJECTED_NFT_LIMIT} from '../../../shared/constants'; +import {POOL_DELEGATION_LIMIT } from '../../../shared/constants'; const route = Routes.delegationForPool; @@ -40,7 +40,7 @@ export class DelegationForPoolController extends Controller { const after = requestBody.after != undefined ? requestBody.after : 0; const until = requestBody.untilSlot != undefined ? requestBody.untilSlot : Number.MAX_VALUE; - const limit = requestBody.limit != undefined ? requestBody.limit : PROJECTED_NFT_LIMIT.MAX_LIMIT; + const limit = requestBody.limit != undefined ? requestBody.limit : POOL_DELEGATION_LIMIT.MAX_LIMIT; if (limit > POOL_DELEGATION_LIMIT.MAX_LIMIT) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return @@ -83,5 +83,6 @@ export class DelegationForPoolController extends Controller { return { result: result, after: newAfter, - }; } + }; + } } diff --git a/webserver/server/app/models/delegation/delegationsForPool.queries.ts b/webserver/server/app/models/delegation/delegationsForPool.queries.ts index 17c40f20..3117c8e6 100644 --- a/webserver/server/app/models/delegation/delegationsForPool.queries.ts +++ b/webserver/server/app/models/delegation/delegationsForPool.queries.ts @@ -23,12 +23,12 @@ export interface ISqlStakeDelegationByPoolQuery { result: ISqlStakeDelegationByPoolResult; } -const sqlStakeDelegationByPoolIR: any = {"usedParamSet":{"pools":true,"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"pools","required":true,"transform":{"type":"array_spread"},"locs":[{"a":176,"b":182},{"a":590,"b":596},{"a":657,"b":663}]},{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":688,"b":697},{"a":1083,"b":1092}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":720,"b":729},{"a":1126,"b":1135}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1151,"b":1157}]}],"statement":"SELECT \n\tencode(credential, 'hex') as credential,\n\tencode(\"Transaction\".hash, 'hex') as tx_id,\n\t\"Block\".slot,\n\tCASE WHEN \"StakeDelegationCredentialRelation\".pool_credential IN :pools! THEN encode(\"StakeDelegationCredentialRelation\".pool_credential, 'hex') ELSE NULL END AS pool\nFROM \"StakeDelegationCredentialRelation\"\nJOIN \"StakeCredential\" ON stake_credential = \"StakeCredential\".id\nJOIN \"Transaction\" ON \"Transaction\".id = \"StakeDelegationCredentialRelation\".tx_id\nJOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE \n (\n\t\t\"StakeDelegationCredentialRelation\".pool_credential IN :pools! OR\n\t \t\"StakeDelegationCredentialRelation\".previous_pool IN :pools!\n\t) AND\n\t\"Block\".slot > :min_slot! AND\n\t\"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"Block\".height as height FROM \"StakeDelegationCredentialRelation\"\n JOIN \"Transaction\" ON \"Transaction\".id = \"StakeDelegationCredentialRelation\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; +const sqlStakeDelegationByPoolIR: any = {"usedParamSet":{"pools":true,"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"pools","required":true,"transform":{"type":"array_spread"},"locs":[{"a":175,"b":181},{"a":589,"b":595},{"a":656,"b":662},{"a":1218,"b":1224},{"a":1298,"b":1304}]},{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":687,"b":696},{"a":1351,"b":1360}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":719,"b":728},{"a":1394,"b":1403}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1419,"b":1425}]}],"statement":"SELECT\n\tencode(credential, 'hex') as credential,\n\tencode(\"Transaction\".hash, 'hex') as tx_id,\n\t\"Block\".slot,\n\tCASE WHEN \"StakeDelegationCredentialRelation\".pool_credential IN :pools! THEN encode(\"StakeDelegationCredentialRelation\".pool_credential, 'hex') ELSE NULL END AS pool\nFROM \"StakeDelegationCredentialRelation\"\nJOIN \"StakeCredential\" ON stake_credential = \"StakeCredential\".id\nJOIN \"Transaction\" ON \"Transaction\".id = \"StakeDelegationCredentialRelation\".tx_id\nJOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE \n (\n\t\t\"StakeDelegationCredentialRelation\".pool_credential IN :pools! OR\n\t \t\"StakeDelegationCredentialRelation\".previous_pool IN :pools!\n\t) AND\n\t\"Block\".slot > :min_slot! AND\n\t\"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"Block\".height as height FROM \"StakeDelegationCredentialRelation\"\n JOIN \"StakeCredential\" ON stake_credential = \"StakeCredential\".id\n JOIN \"Transaction\" ON \"Transaction\".id = \"StakeDelegationCredentialRelation\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n (\n \"StakeDelegationCredentialRelation\".pool_credential IN :pools! OR\n \"StakeDelegationCredentialRelation\".previous_pool IN :pools!\n ) AND\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; /** * Query generated from SQL: * ``` - * SELECT + * SELECT * encode(credential, 'hex') as credential, * encode("Transaction".hash, 'hex') as tx_id, * "Block".slot, @@ -47,9 +47,14 @@ const sqlStakeDelegationByPoolIR: any = {"usedParamSet":{"pools":true,"min_slot" * AND "Block".height <= ( * SELECT MAX("Heights".height) FROM * (SELECT "Block".height as height FROM "StakeDelegationCredentialRelation" + * JOIN "StakeCredential" ON stake_credential = "StakeCredential".id * JOIN "Transaction" ON "Transaction".id = "StakeDelegationCredentialRelation".tx_id * JOIN "Block" ON "Transaction".block_id = "Block".id * WHERE + * ( + * "StakeDelegationCredentialRelation".pool_credential IN :pools! OR + * "StakeDelegationCredentialRelation".previous_pool IN :pools! + * ) AND * "Block".slot > :min_slot! * AND "Block".slot <= :max_slot! * LIMIT :limit!) AS "Heights" diff --git a/webserver/server/app/models/delegation/delegationsForPool.sql b/webserver/server/app/models/delegation/delegationsForPool.sql index bb1410fc..d5fed631 100644 --- a/webserver/server/app/models/delegation/delegationsForPool.sql +++ b/webserver/server/app/models/delegation/delegationsForPool.sql @@ -2,7 +2,7 @@ @name sqlStakeDelegationByPool @param pools -> (...) */ -SELECT +SELECT encode(credential, 'hex') as credential, encode("Transaction".hash, 'hex') as tx_id, "Block".slot, @@ -21,9 +21,14 @@ WHERE AND "Block".height <= ( SELECT MAX("Heights".height) FROM (SELECT "Block".height as height FROM "StakeDelegationCredentialRelation" + JOIN "StakeCredential" ON stake_credential = "StakeCredential".id JOIN "Transaction" ON "Transaction".id = "StakeDelegationCredentialRelation".tx_id JOIN "Block" ON "Transaction".block_id = "Block".id WHERE + ( + "StakeDelegationCredentialRelation".pool_credential IN :pools! OR + "StakeDelegationCredentialRelation".previous_pool IN :pools! + ) AND "Block".slot > :min_slot! AND "Block".slot <= :max_slot! LIMIT :limit!) AS "Heights" diff --git a/webserver/server/app/models/projected_nft/projectedNftRange.queries.ts b/webserver/server/app/models/projected_nft/projectedNftRange.queries.ts index 8157142a..cce6b43e 100644 --- a/webserver/server/app/models/projected_nft/projectedNftRange.queries.ts +++ b/webserver/server/app/models/projected_nft/projectedNftRange.queries.ts @@ -30,7 +30,7 @@ export interface ISqlProjectedNftRangeQuery { result: ISqlProjectedNftRangeResult; } -const sqlProjectedNftRangeIR: any = {"usedParamSet":{"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1219,"b":1228},{"a":1575,"b":1584}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1254,"b":1263},{"a":1618,"b":1627}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1643,"b":1649}]}],"statement":"SELECT\n encode(\"ProjectedNFT\".owner_address, 'hex') as owner_address,\n\n encode(\"ProjectedNFT\".previous_utxo_tx_hash, 'hex') as previous_tx_hash,\n \"ProjectedNFT\".previous_utxo_tx_output_index as previous_tx_output_index,\n\n CASE\n WHEN \"TransactionOutput\".output_index = NULL THEN NULL\n ELSE \"TransactionOutput\".output_index\n END AS action_output_index,\n\n encode(\"Transaction\".hash, 'hex') as action_tx_id,\n\n \"ProjectedNFT\".policy_id as policy_id,\n \"ProjectedNFT\".asset_name as asset_name,\n \"ProjectedNFT\".amount as amount,\n\n CASE\n WHEN \"ProjectedNFT\".operation = 0 THEN 'Lock'\n WHEN \"ProjectedNFT\".operation = 1 THEN 'Unlocking'\n WHEN \"ProjectedNFT\".operation = 2 THEN 'Claim'\n ELSE 'Invalid'\n END AS status,\n\n encode(\"ProjectedNFT\".plutus_datum, 'hex') as plutus_datum,\n \"ProjectedNFT\".for_how_long as for_how_long,\n\n \"Block\".slot as action_slot\nFROM \"ProjectedNFT\"\n LEFT JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"ProjectedNFT\".hololocker_utxo_id\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"Block\".height as height FROM \"ProjectedNFT\"\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; +const sqlProjectedNftRangeIR: any = {"usedParamSet":{"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1219,"b":1228},{"a":1600,"b":1609}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1254,"b":1263},{"a":1643,"b":1652}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1668,"b":1674}]}],"statement":"SELECT\n encode(\"ProjectedNFT\".owner_address, 'hex') as owner_address,\n\n encode(\"ProjectedNFT\".previous_utxo_tx_hash, 'hex') as previous_tx_hash,\n \"ProjectedNFT\".previous_utxo_tx_output_index as previous_tx_output_index,\n\n CASE\n WHEN \"TransactionOutput\".output_index = NULL THEN NULL\n ELSE \"TransactionOutput\".output_index\n END AS action_output_index,\n\n encode(\"Transaction\".hash, 'hex') as action_tx_id,\n\n \"ProjectedNFT\".policy_id as policy_id,\n \"ProjectedNFT\".asset_name as asset_name,\n \"ProjectedNFT\".amount as amount,\n\n CASE\n WHEN \"ProjectedNFT\".operation = 0 THEN 'Lock'\n WHEN \"ProjectedNFT\".operation = 1 THEN 'Unlocking'\n WHEN \"ProjectedNFT\".operation = 2 THEN 'Claim'\n ELSE 'Invalid'\n END AS status,\n\n encode(\"ProjectedNFT\".plutus_datum, 'hex') as plutus_datum,\n \"ProjectedNFT\".for_how_long as for_how_long,\n\n \"Block\".slot as action_slot\nFROM \"ProjectedNFT\"\n LEFT JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"ProjectedNFT\".hololocker_utxo_id\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"ProjectedNFT\".id as id, \"Block\".height as height FROM \"ProjectedNFT\"\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; /** * Query generated from SQL: @@ -72,7 +72,7 @@ const sqlProjectedNftRangeIR: any = {"usedParamSet":{"min_slot":true,"max_slot": * AND "Block".slot <= :max_slot! * AND "Block".height <= ( * SELECT MAX("Heights".height) FROM - * (SELECT "Block".height as height FROM "ProjectedNFT" + * (SELECT "ProjectedNFT".id as id, "Block".height as height FROM "ProjectedNFT" * JOIN "Transaction" ON "Transaction".id = "ProjectedNFT".tx_id * JOIN "Block" ON "Transaction".block_id = "Block".id * WHERE diff --git a/webserver/server/app/models/projected_nft/projectedNftRange.sql b/webserver/server/app/models/projected_nft/projectedNftRange.sql index 19001d67..aad22aa5 100644 --- a/webserver/server/app/models/projected_nft/projectedNftRange.sql +++ b/webserver/server/app/models/projected_nft/projectedNftRange.sql @@ -38,7 +38,7 @@ WHERE AND "Block".slot <= :max_slot! AND "Block".height <= ( SELECT MAX("Heights".height) FROM - (SELECT "Block".height as height FROM "ProjectedNFT" + (SELECT "ProjectedNFT".id as id, "Block".height as height FROM "ProjectedNFT" JOIN "Transaction" ON "Transaction".id = "ProjectedNFT".tx_id JOIN "Block" ON "Transaction".block_id = "Block".id WHERE diff --git a/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.queries.ts b/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.queries.ts index 8f673004..714f6ca9 100644 --- a/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.queries.ts +++ b/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.queries.ts @@ -31,7 +31,7 @@ export interface ISqlProjectedNftRangeByAddressQuery { result: ISqlProjectedNftRangeByAddressResult; } -const sqlProjectedNftRangeByAddressIR: any = {"usedParamSet":{"owner_address":true,"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"owner_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":1250,"b":1264}]},{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1289,"b":1298},{"a":1669,"b":1678}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1324,"b":1333},{"a":1716,"b":1725}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1745,"b":1751}]}],"statement":"SELECT\n encode(\"ProjectedNFT\".owner_address, 'hex') as owner_address,\n\n encode(\"ProjectedNFT\".previous_utxo_tx_hash, 'hex') as previous_tx_hash,\n \"ProjectedNFT\".previous_utxo_tx_output_index as previous_tx_output_index,\n\n CASE\n WHEN \"TransactionOutput\".output_index = NULL THEN NULL\n ELSE \"TransactionOutput\".output_index\n END AS action_output_index,\n\n encode(\"Transaction\".hash, 'hex') as action_tx_id,\n\n \"ProjectedNFT\".policy_id as policy_id,\n \"ProjectedNFT\".asset_name as asset_name,\n \"ProjectedNFT\".amount as amount,\n\n CASE\n WHEN \"ProjectedNFT\".operation = 0 THEN 'Lock'\n WHEN \"ProjectedNFT\".operation = 1 THEN 'Unlocking'\n WHEN \"ProjectedNFT\".operation = 2 THEN 'Claim'\n ELSE 'Invalid'\n END AS status,\n\n encode(\"ProjectedNFT\".plutus_datum, 'hex') as plutus_datum,\n \"ProjectedNFT\".for_how_long as for_how_long,\n\n \"Block\".slot as action_slot\nFROM \"ProjectedNFT\"\n LEFT JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"ProjectedNFT\".hololocker_utxo_id\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE\n encode(\"ProjectedNFT\".owner_address, 'hex') = :owner_address!\n AND \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"Block\".height as height FROM \"ProjectedNFT\"\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; +const sqlProjectedNftRangeByAddressIR: any = {"usedParamSet":{"owner_address":true,"min_slot":true,"max_slot":true,"limit":true},"params":[{"name":"owner_address","required":true,"transform":{"type":"scalar"},"locs":[{"a":1250,"b":1264},{"a":1700,"b":1714}]},{"name":"min_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1289,"b":1298},{"a":1751,"b":1760}]},{"name":"max_slot","required":true,"transform":{"type":"scalar"},"locs":[{"a":1324,"b":1333},{"a":1798,"b":1807}]},{"name":"limit","required":true,"transform":{"type":"scalar"},"locs":[{"a":1827,"b":1833}]}],"statement":"SELECT\n encode(\"ProjectedNFT\".owner_address, 'hex') as owner_address,\n\n encode(\"ProjectedNFT\".previous_utxo_tx_hash, 'hex') as previous_tx_hash,\n \"ProjectedNFT\".previous_utxo_tx_output_index as previous_tx_output_index,\n\n CASE\n WHEN \"TransactionOutput\".output_index = NULL THEN NULL\n ELSE \"TransactionOutput\".output_index\n END AS action_output_index,\n\n encode(\"Transaction\".hash, 'hex') as action_tx_id,\n\n \"ProjectedNFT\".policy_id as policy_id,\n \"ProjectedNFT\".asset_name as asset_name,\n \"ProjectedNFT\".amount as amount,\n\n CASE\n WHEN \"ProjectedNFT\".operation = 0 THEN 'Lock'\n WHEN \"ProjectedNFT\".operation = 1 THEN 'Unlocking'\n WHEN \"ProjectedNFT\".operation = 2 THEN 'Claim'\n ELSE 'Invalid'\n END AS status,\n\n encode(\"ProjectedNFT\".plutus_datum, 'hex') as plutus_datum,\n \"ProjectedNFT\".for_how_long as for_how_long,\n\n \"Block\".slot as action_slot\nFROM \"ProjectedNFT\"\n LEFT JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"ProjectedNFT\".hololocker_utxo_id\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\nWHERE\n encode(\"ProjectedNFT\".owner_address, 'hex') = :owner_address!\n AND \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n AND \"Block\".height <= (\n SELECT MAX(\"Heights\".height) FROM\n (SELECT \"Block\".height as height FROM \"ProjectedNFT\"\n JOIN \"Transaction\" ON \"Transaction\".id = \"ProjectedNFT\".tx_id\n JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE\n encode(\"ProjectedNFT\".owner_address, 'hex') = :owner_address!\n AND \"Block\".slot > :min_slot!\n AND \"Block\".slot <= :max_slot!\n LIMIT :limit!) AS \"Heights\"\n )\nORDER BY (\"Block\".height, \"Transaction\".tx_index) ASC"}; /** * Query generated from SQL: @@ -78,7 +78,8 @@ const sqlProjectedNftRangeByAddressIR: any = {"usedParamSet":{"owner_address":tr * JOIN "Transaction" ON "Transaction".id = "ProjectedNFT".tx_id * JOIN "Block" ON "Transaction".block_id = "Block".id * WHERE - * "Block".slot > :min_slot! + * encode("ProjectedNFT".owner_address, 'hex') = :owner_address! + * AND "Block".slot > :min_slot! * AND "Block".slot <= :max_slot! * LIMIT :limit!) AS "Heights" * ) diff --git a/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.sql b/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.sql index ccba0eb7..083efdca 100644 --- a/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.sql +++ b/webserver/server/app/models/projected_nft/projectedNftRangeByAddress.sql @@ -43,7 +43,8 @@ WHERE JOIN "Transaction" ON "Transaction".id = "ProjectedNFT".tx_id JOIN "Block" ON "Transaction".block_id = "Block".id WHERE - "Block".slot > :min_slot! + encode("ProjectedNFT".owner_address, 'hex') = :owner_address! + AND "Block".slot > :min_slot! AND "Block".slot <= :max_slot! LIMIT :limit!) AS "Heights" )