From 61fe5f2034512cb9ef592918e6cb4e833242b16a Mon Sep 17 00:00:00 2001 From: Sebastien Guillemot Date: Sun, 15 Sep 2024 02:48:15 +0900 Subject: [PATCH] Add full input UTXO as part of input context (#184) --- .../sqlHistoryForAddresses.queries.ts | 12 +++++------- .../transaction/sqlHistoryForAddresses.sql | 6 +++--- .../sqlHistoryForCredentials.queries.ts | 12 +++++------- .../transaction/sqlHistoryForCredentials.sql | 6 +++--- .../app/services/TransactionHistoryService.ts | 17 ++++------------- webserver/shared/models/PolicyIdAssetMap.ts | 5 +++-- webserver/shared/models/TransactionHistory.ts | 11 +++++++---- webserver/shared/models/TransactionOutput.ts | 5 ++--- webserver/shared/models/common.ts | 5 +++++ 9 files changed, 37 insertions(+), 42 deletions(-) diff --git a/webserver/server/app/models/transaction/sqlHistoryForAddresses.queries.ts b/webserver/server/app/models/transaction/sqlHistoryForAddresses.queries.ts index 53899d00..e8962bd1 100644 --- a/webserver/server/app/models/transaction/sqlHistoryForAddresses.queries.ts +++ b/webserver/server/app/models/transaction/sqlHistoryForAddresses.queries.ts @@ -3,8 +3,6 @@ import { PreparedQuery } from '@pgtyped/runtime'; export type BufferArray = (Buffer)[]; -export type Json = null | boolean | number | string | Json[] | { [key: string]: Json }; - export type NumberOrString = number | string; /** 'SqlHistoryForAddresses' parameters type */ @@ -24,7 +22,7 @@ export interface ISqlHistoryForAddressesResult { hash: Buffer; height: number; id: string | null; - input_addresses: Json | null; + input_utxo: BufferArray | null; is_valid: boolean; metadata: Buffer | null; payload: Buffer; @@ -38,7 +36,7 @@ export interface ISqlHistoryForAddressesQuery { result: ISqlHistoryForAddressesResult; } -const sqlHistoryForAddressesIR: any = {"usedParamSet":{"addresses":true,"until_tx_id":true,"after_tx_id":true,"limit":true,"with_input_context":true},"params":[{"name":"addresses","required":false,"transform":{"type":"scalar"},"locs":[{"a":91,"b":100}]},{"name":"until_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":373,"b":384},{"a":788,"b":799},{"a":1250,"b":1261}]},{"name":"after_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":440,"b":451},{"a":854,"b":865},{"a":1325,"b":1336}]},{"name":"limit","required":false,"transform":{"type":"scalar"},"locs":[{"a":516,"b":521},{"a":929,"b":934},{"a":1409,"b":1414},{"a":2215,"b":2220},{"a":3446,"b":3451}]},{"name":"with_input_context","required":true,"transform":{"type":"scalar"},"locs":[{"a":3493,"b":3512},{"a":3576,"b":3595}]}],"statement":"WITH\n address_row AS (\n SELECT *\n FROM \"Address\"\n WHERE \"Address\".payload = ANY (:addresses)\n ),\n outputs AS (\n SELECT DISTINCT ON (\"TransactionOutput\".tx_id) \"TransactionOutput\".tx_id\n FROM \"TransactionOutput\"\n INNER JOIN address_row ON \"TransactionOutput\".address_id = address_row.id\n WHERE\n \"TransactionOutput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionOutput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionOutput\".tx_id ASC\n LIMIT (:limit)\n ),\n inputs AS (\n SELECT DISTINCT ON (\"TransactionInput\".tx_id) \"TransactionInput\".tx_id\n FROM \"TransactionInput\"\n INNER JOIN address_row ON \"TransactionInput\".address_id = address_row.id\n WHERE\n \"TransactionInput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionInput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionInput\".tx_id ASC\n LIMIT (:limit)\n ),\n ref_inputs AS (\n SELECT DISTINCT ON (\"TransactionReferenceInput\".tx_id) \"TransactionReferenceInput\".tx_id\n FROM \"TransactionReferenceInput\"\n INNER JOIN address_row ON \"TransactionReferenceInput\".address_id = address_row.id\n WHERE\n \"TransactionReferenceInput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionReferenceInput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionReferenceInput\".tx_id ASC\n LIMIT (:limit)\n ),\n base_query AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n NULL :: bytea as metadata,\n NULL :: json as input_addresses\n FROM \"Transaction\"\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE \"Transaction\".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs)\n ORDER BY \"Transaction\".id ASC\n LIMIT (:limit)\n ),\n query_with_inputs_and_metadata AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n \"TransactionMetadata\".payload AS metadata,\n json_agg(DISTINCT \"Address\".PAYLOAD) input_addresses\n FROM \"Transaction\"\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n INNER JOIN \"TransactionInput\" ON \"TransactionInput\".tx_id = \"Transaction\".id\n INNER JOIN \"Address\" ON \"Address\".id = \"TransactionInput\".address_id\n LEFT JOIN \"TransactionMetadata\" ON \"Transaction\".id = \"TransactionMetadata\".tx_id\n WHERE \"Transaction\".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs)\n GROUP BY \"Transaction\".id, \"Block\".id, \"TransactionMetadata\".id\n ORDER BY \"Transaction\".id ASC\n LIMIT (:limit)\n )\nSELECT * FROM base_query WHERE NOT :with_input_context!\nUNION ALL\n(SELECT * from query_with_inputs_and_metadata WHERE :with_input_context!)"}; +const sqlHistoryForAddressesIR: any = {"usedParamSet":{"addresses":true,"until_tx_id":true,"after_tx_id":true,"limit":true,"with_input_context":true},"params":[{"name":"addresses","required":false,"transform":{"type":"scalar"},"locs":[{"a":91,"b":100}]},{"name":"until_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":373,"b":384},{"a":788,"b":799},{"a":1250,"b":1261}]},{"name":"after_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":440,"b":451},{"a":854,"b":865},{"a":1325,"b":1336}]},{"name":"limit","required":false,"transform":{"type":"scalar"},"locs":[{"a":516,"b":521},{"a":929,"b":934},{"a":1409,"b":1414},{"a":2213,"b":2218},{"a":3458,"b":3463}]},{"name":"with_input_context","required":true,"transform":{"type":"scalar"},"locs":[{"a":3505,"b":3524},{"a":3588,"b":3607}]}],"statement":"WITH\n address_row AS (\n SELECT *\n FROM \"Address\"\n WHERE \"Address\".payload = ANY (:addresses)\n ),\n outputs AS (\n SELECT DISTINCT ON (\"TransactionOutput\".tx_id) \"TransactionOutput\".tx_id\n FROM \"TransactionOutput\"\n INNER JOIN address_row ON \"TransactionOutput\".address_id = address_row.id\n WHERE\n \"TransactionOutput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionOutput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionOutput\".tx_id ASC\n LIMIT (:limit)\n ),\n inputs AS (\n SELECT DISTINCT ON (\"TransactionInput\".tx_id) \"TransactionInput\".tx_id\n FROM \"TransactionInput\"\n INNER JOIN address_row ON \"TransactionInput\".address_id = address_row.id\n WHERE\n \"TransactionInput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionInput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionInput\".tx_id ASC\n LIMIT (:limit)\n ),\n ref_inputs AS (\n SELECT DISTINCT ON (\"TransactionReferenceInput\".tx_id) \"TransactionReferenceInput\".tx_id\n FROM \"TransactionReferenceInput\"\n INNER JOIN address_row ON \"TransactionReferenceInput\".address_id = address_row.id\n WHERE\n \"TransactionReferenceInput\".tx_id <= (:until_tx_id)\n AND\n \"TransactionReferenceInput\".tx_id > (:after_tx_id)\n ORDER BY \"TransactionReferenceInput\".tx_id ASC\n LIMIT (:limit)\n ),\n base_query AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n NULL :: bytea as metadata,\n NULL :: bytea[] as input_utxo\n FROM \"Transaction\"\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n WHERE \"Transaction\".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs)\n ORDER BY \"Transaction\".id ASC\n LIMIT (:limit)\n ),\n query_with_inputs_and_metadata AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n \"TransactionMetadata\".payload AS metadata,\n array_agg(\"TransactionOutput\".PAYLOAD) input_utxo\n FROM \"Transaction\"\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n INNER JOIN \"TransactionInput\" ON \"TransactionInput\".tx_id = \"Transaction\".id\n INNER JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"TransactionInput\".utxo_id\n LEFT JOIN \"TransactionMetadata\" ON \"Transaction\".id = \"TransactionMetadata\".tx_id\n WHERE \"Transaction\".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs)\n GROUP BY \"Transaction\".id, \"Block\".id, \"TransactionMetadata\".id\n ORDER BY \"Transaction\".id ASC\n LIMIT (:limit)\n )\nSELECT * FROM base_query WHERE NOT :with_input_context!\nUNION ALL\n(SELECT * from query_with_inputs_and_metadata WHERE :with_input_context!)"}; /** * Query generated from SQL: @@ -94,7 +92,7 @@ const sqlHistoryForAddressesIR: any = {"usedParamSet":{"addresses":true,"until_t * "Block".era as "era!", * "Block".height as "height!", * NULL :: bytea as metadata, - * NULL :: json as input_addresses + * NULL :: bytea[] as input_utxo * FROM "Transaction" * INNER JOIN "Block" ON "Transaction".block_id = "Block".id * WHERE "Transaction".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs) @@ -113,11 +111,11 @@ const sqlHistoryForAddressesIR: any = {"usedParamSet":{"addresses":true,"until_t * "Block".era as "era!", * "Block".height as "height!", * "TransactionMetadata".payload AS metadata, - * json_agg(DISTINCT "Address".PAYLOAD) input_addresses + * array_agg("TransactionOutput".PAYLOAD) input_utxo * FROM "Transaction" * INNER JOIN "Block" ON "Transaction".block_id = "Block".id * INNER JOIN "TransactionInput" ON "TransactionInput".tx_id = "Transaction".id - * INNER JOIN "Address" ON "Address".id = "TransactionInput".address_id + * INNER JOIN "TransactionOutput" ON "TransactionOutput".id = "TransactionInput".utxo_id * LEFT JOIN "TransactionMetadata" ON "Transaction".id = "TransactionMetadata".tx_id * WHERE "Transaction".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs) * GROUP BY "Transaction".id, "Block".id, "TransactionMetadata".id diff --git a/webserver/server/app/models/transaction/sqlHistoryForAddresses.sql b/webserver/server/app/models/transaction/sqlHistoryForAddresses.sql index 34658c77..19e77315 100644 --- a/webserver/server/app/models/transaction/sqlHistoryForAddresses.sql +++ b/webserver/server/app/models/transaction/sqlHistoryForAddresses.sql @@ -50,7 +50,7 @@ WITH "Block".era as "era!", "Block".height as "height!", NULL :: bytea as metadata, - NULL :: json as input_addresses + NULL :: bytea[] as input_utxo FROM "Transaction" INNER JOIN "Block" ON "Transaction".block_id = "Block".id WHERE "Transaction".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs) @@ -69,11 +69,11 @@ WITH "Block".era as "era!", "Block".height as "height!", "TransactionMetadata".payload AS metadata, - json_agg(DISTINCT "Address".PAYLOAD) input_addresses + array_agg("TransactionOutput".PAYLOAD) input_utxo FROM "Transaction" INNER JOIN "Block" ON "Transaction".block_id = "Block".id INNER JOIN "TransactionInput" ON "TransactionInput".tx_id = "Transaction".id - INNER JOIN "Address" ON "Address".id = "TransactionInput".address_id + INNER JOIN "TransactionOutput" ON "TransactionOutput".id = "TransactionInput".utxo_id LEFT JOIN "TransactionMetadata" ON "Transaction".id = "TransactionMetadata".tx_id WHERE "Transaction".id IN (SELECT * FROM inputs UNION ALL SELECT * from ref_inputs UNION ALL SELECT * from outputs) GROUP BY "Transaction".id, "Block".id, "TransactionMetadata".id diff --git a/webserver/server/app/models/transaction/sqlHistoryForCredentials.queries.ts b/webserver/server/app/models/transaction/sqlHistoryForCredentials.queries.ts index e02270de..87845cba 100644 --- a/webserver/server/app/models/transaction/sqlHistoryForCredentials.queries.ts +++ b/webserver/server/app/models/transaction/sqlHistoryForCredentials.queries.ts @@ -3,8 +3,6 @@ import { PreparedQuery } from '@pgtyped/runtime'; export type BufferArray = (Buffer)[]; -export type Json = null | boolean | number | string | Json[] | { [key: string]: Json }; - export type NumberOrString = number | string; /** 'SqlHistoryForCredentials' parameters type */ @@ -25,7 +23,7 @@ export interface ISqlHistoryForCredentialsResult { hash: Buffer; height: number; id: string | null; - input_addresses: Json | null; + input_utxo: BufferArray | null; is_valid: boolean; metadata: Buffer | null; payload: Buffer; @@ -39,7 +37,7 @@ export interface ISqlHistoryForCredentialsQuery { result: ISqlHistoryForCredentialsResult; } -const sqlHistoryForCredentialsIR: any = {"usedParamSet":{"credentials":true,"relation":true,"until_tx_id":true,"after_tx_id":true,"limit":true,"with_input_context":true},"params":[{"name":"credentials","required":false,"transform":{"type":"scalar"},"locs":[{"a":288,"b":299}]},{"name":"relation","required":false,"transform":{"type":"scalar"},"locs":[{"a":354,"b":362}]},{"name":"until_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":464,"b":475}]},{"name":"after_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":527,"b":538}]},{"name":"limit","required":false,"transform":{"type":"scalar"},"locs":[{"a":598,"b":603}]},{"name":"with_input_context","required":true,"transform":{"type":"scalar"},"locs":[{"a":2446,"b":2465},{"a":2529,"b":2548}]}],"statement":"WITH\n tx_relations AS (\n SELECT DISTINCT ON (\"TxCredentialRelation\".tx_id) \"TxCredentialRelation\".tx_id\n FROM \"StakeCredential\"\n INNER JOIN \"TxCredentialRelation\" ON \"TxCredentialRelation\".credential_id = \"StakeCredential\".id\n WHERE\n \"StakeCredential\".credential = ANY (:credentials)\n AND\n (\"TxCredentialRelation\".relation & (:relation)) > 0\n AND\n \n \"TxCredentialRelation\".tx_id <= (:until_tx_id)\n AND \n \"TxCredentialRelation\".tx_id > (:after_tx_id)\n ORDER BY \"TxCredentialRelation\".tx_id ASC\n LIMIT (:limit)\n ),\n base_query AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n NULL :: bytea as metadata,\n NULL :: json as input_addresses\n FROM tx_relations\n INNER JOIN \"Transaction\" ON tx_relations.tx_id = \"Transaction\".id\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n ),\n query_with_inputs_and_metadata AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash as \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n \"TransactionMetadata\".payload AS metadata,\n json_agg(DISTINCT \"Address\".PAYLOAD) input_addresses\n FROM tx_relations\n INNER JOIN \"Transaction\" ON tx_relations.tx_id = \"Transaction\".id\n INNER JOIN \"TransactionInput\" ON \"TransactionInput\".tx_id = \"Transaction\".id\n INNER JOIN \"Address\" ON \"Address\".id = \"TransactionInput\".address_id\n LEFT JOIN \"TransactionMetadata\" ON \"Transaction\".id = \"TransactionMetadata\".tx_id\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n GROUP BY \"Transaction\".id, \"Block\".id, \"TransactionMetadata\".id\n )\nSELECT * FROM base_query WHERE NOT :with_input_context!\nUNION ALL (SELECT * FROM query_with_inputs_and_metadata WHERE :with_input_context!)"}; +const sqlHistoryForCredentialsIR: any = {"usedParamSet":{"credentials":true,"relation":true,"until_tx_id":true,"after_tx_id":true,"limit":true,"with_input_context":true},"params":[{"name":"credentials","required":false,"transform":{"type":"scalar"},"locs":[{"a":288,"b":299}]},{"name":"relation","required":false,"transform":{"type":"scalar"},"locs":[{"a":354,"b":362}]},{"name":"until_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":464,"b":475}]},{"name":"after_tx_id","required":false,"transform":{"type":"scalar"},"locs":[{"a":527,"b":538}]},{"name":"limit","required":false,"transform":{"type":"scalar"},"locs":[{"a":598,"b":603}]},{"name":"with_input_context","required":true,"transform":{"type":"scalar"},"locs":[{"a":2458,"b":2477},{"a":2541,"b":2560}]}],"statement":"WITH\n tx_relations AS (\n SELECT DISTINCT ON (\"TxCredentialRelation\".tx_id) \"TxCredentialRelation\".tx_id\n FROM \"StakeCredential\"\n INNER JOIN \"TxCredentialRelation\" ON \"TxCredentialRelation\".credential_id = \"StakeCredential\".id\n WHERE\n \"StakeCredential\".credential = ANY (:credentials)\n AND\n (\"TxCredentialRelation\".relation & (:relation)) > 0\n AND\n \n \"TxCredentialRelation\".tx_id <= (:until_tx_id)\n AND \n \"TxCredentialRelation\".tx_id > (:after_tx_id)\n ORDER BY \"TxCredentialRelation\".tx_id ASC\n LIMIT (:limit)\n ),\n base_query AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash AS \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n NULL :: bytea as metadata,\n NULL :: bytea[] as input_utxo\n FROM tx_relations\n INNER JOIN \"Transaction\" ON tx_relations.tx_id = \"Transaction\".id\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n ),\n query_with_inputs_and_metadata AS (\n SELECT \"Transaction\".id,\n \"Transaction\".payload as \"payload!\",\n \"Transaction\".hash as \"hash!\",\n \"Transaction\".tx_index as \"tx_index!\",\n \"Transaction\".is_valid as \"is_valid!\",\n \"Block\".hash as \"block_hash!\",\n \"Block\".epoch as \"epoch!\",\n \"Block\".slot as \"slot!\",\n \"Block\".era as \"era!\",\n \"Block\".height as \"height!\",\n \"TransactionMetadata\".payload AS metadata,\n array_agg(\"TransactionOutput\".PAYLOAD) input_utxo\n FROM tx_relations\n INNER JOIN \"Transaction\" ON tx_relations.tx_id = \"Transaction\".id\n INNER JOIN \"TransactionInput\" ON \"TransactionInput\".tx_id = \"Transaction\".id\n INNER JOIN \"TransactionOutput\" ON \"TransactionOutput\".id = \"TransactionInput\".utxo_id\n LEFT JOIN \"TransactionMetadata\" ON \"Transaction\".id = \"TransactionMetadata\".tx_id\n INNER JOIN \"Block\" ON \"Transaction\".block_id = \"Block\".id\n GROUP BY \"Transaction\".id, \"Block\".id, \"TransactionMetadata\".id\n )\nSELECT * FROM base_query WHERE NOT :with_input_context!\nUNION ALL (SELECT * FROM query_with_inputs_and_metadata WHERE :with_input_context!)"}; /** * Query generated from SQL: @@ -73,7 +71,7 @@ const sqlHistoryForCredentialsIR: any = {"usedParamSet":{"credentials":true,"rel * "Block".era as "era!", * "Block".height as "height!", * NULL :: bytea as metadata, - * NULL :: json as input_addresses + * NULL :: bytea[] as input_utxo * FROM tx_relations * INNER JOIN "Transaction" ON tx_relations.tx_id = "Transaction".id * INNER JOIN "Block" ON "Transaction".block_id = "Block".id @@ -90,11 +88,11 @@ const sqlHistoryForCredentialsIR: any = {"usedParamSet":{"credentials":true,"rel * "Block".era as "era!", * "Block".height as "height!", * "TransactionMetadata".payload AS metadata, - * json_agg(DISTINCT "Address".PAYLOAD) input_addresses + * array_agg("TransactionOutput".PAYLOAD) input_utxo * FROM tx_relations * INNER JOIN "Transaction" ON tx_relations.tx_id = "Transaction".id * INNER JOIN "TransactionInput" ON "TransactionInput".tx_id = "Transaction".id - * INNER JOIN "Address" ON "Address".id = "TransactionInput".address_id + * INNER JOIN "TransactionOutput" ON "TransactionOutput".id = "TransactionInput".utxo_id * LEFT JOIN "TransactionMetadata" ON "Transaction".id = "TransactionMetadata".tx_id * INNER JOIN "Block" ON "Transaction".block_id = "Block".id * GROUP BY "Transaction".id, "Block".id, "TransactionMetadata".id diff --git a/webserver/server/app/models/transaction/sqlHistoryForCredentials.sql b/webserver/server/app/models/transaction/sqlHistoryForCredentials.sql index fc2b1c3f..83df176c 100644 --- a/webserver/server/app/models/transaction/sqlHistoryForCredentials.sql +++ b/webserver/server/app/models/transaction/sqlHistoryForCredentials.sql @@ -28,7 +28,7 @@ WITH "Block".era as "era!", "Block".height as "height!", NULL :: bytea as metadata, - NULL :: json as input_addresses + NULL :: bytea[] as input_utxo FROM tx_relations INNER JOIN "Transaction" ON tx_relations.tx_id = "Transaction".id INNER JOIN "Block" ON "Transaction".block_id = "Block".id @@ -45,11 +45,11 @@ WITH "Block".era as "era!", "Block".height as "height!", "TransactionMetadata".payload AS metadata, - json_agg(DISTINCT "Address".PAYLOAD) input_addresses + array_agg("TransactionOutput".PAYLOAD) input_utxo FROM tx_relations INNER JOIN "Transaction" ON tx_relations.tx_id = "Transaction".id INNER JOIN "TransactionInput" ON "TransactionInput".tx_id = "Transaction".id - INNER JOIN "Address" ON "Address".id = "TransactionInput".address_id + INNER JOIN "TransactionOutput" ON "TransactionOutput".id = "TransactionInput".utxo_id LEFT JOIN "TransactionMetadata" ON "Transaction".id = "TransactionMetadata".tx_id INNER JOIN "Block" ON "Transaction".block_id = "Block".id GROUP BY "Transaction".id, "Block".id, "TransactionMetadata".id diff --git a/webserver/server/app/services/TransactionHistoryService.ts b/webserver/server/app/services/TransactionHistoryService.ts index cbd40dab..4fd744d2 100644 --- a/webserver/server/app/services/TransactionHistoryService.ts +++ b/webserver/server/app/services/TransactionHistoryService.ts @@ -46,8 +46,8 @@ export async function historyForCredentials( }, ...(request.withInputContext && { metadata: entry.metadata && entry.metadata.toString('hex'), - inputCredentials: entry.input_addresses - ? (entry.input_addresses as string[]).map(getPaymentCred) + inputs: entry.input_utxo + ? entry.input_utxo.map(buf => buf.toString('hex')) : [], }), }, @@ -93,20 +93,11 @@ export async function historyForAddresses( }, ...(request.withInputContext && { metadata: entry.metadata && entry.metadata.toString('hex'), - inputCredentials: entry.input_addresses - ? (entry.input_addresses as string[]).map(getPaymentCred) + inputs: entry.input_utxo + ? entry.input_utxo.map(buf => buf.toString('hex')) : [], }), }, })), }; } - -function getPaymentCred(addressRaw: string): string { - const address = Address.from_raw_bytes(Buffer.from(addressRaw.slice(2), 'hex')); - - const paymentCred = address.payment_cred(); - const addressBytes = paymentCred?.to_cbor_bytes(); - - return Buffer.from(addressBytes as Uint8Array).toString('hex'); -} diff --git a/webserver/shared/models/PolicyIdAssetMap.ts b/webserver/shared/models/PolicyIdAssetMap.ts index a25ae333..927b2c97 100644 --- a/webserver/shared/models/PolicyIdAssetMap.ts +++ b/webserver/shared/models/PolicyIdAssetMap.ts @@ -1,3 +1,5 @@ +import type { UnboundHex } from "./common"; + /** * @pattern [0-9a-fA-F]{56} * @example "b863bc7369f46136ac1048adb2fa7dae3af944c3bbb2be2f216a8d4f" @@ -9,10 +11,9 @@ export type PolicyId = string; */ export type AssetName = string; /** - * @pattern [0-9a-fA-F]* * @example "a365636f6c6f72672330303030383065696d616765783a697066733a2f2f697066732f516d534b593167317a5375506b3536635869324b38524e766961526b44485633505a756a7474663755676b343379646e616d656a4265727279204e617679" */ -type Cip25Metadata = string; +type Cip25Metadata = UnboundHex; export type PolicyIdAssetMapType = { // https://github.com/lukeautry/tsoa/issues/1204#issuecomment-1133229741 diff --git a/webserver/shared/models/TransactionHistory.ts b/webserver/shared/models/TransactionHistory.ts index 873988d8..f77f32bc 100644 --- a/webserver/shared/models/TransactionHistory.ts +++ b/webserver/shared/models/TransactionHistory.ts @@ -1,7 +1,7 @@ import type { Address } from "./Address"; import type { BlockSubset } from "./BlockLatest"; -import type { Pagination, RelationFilter, SlotLimits } from "./common"; +import type { Pagination, RelationFilter, SlotLimits, UnboundHex } from "./common"; export type TransactionHistoryRequest = { addresses: Address[]; @@ -37,14 +37,17 @@ export type TransactionInfo = { hash: string; /** * cbor-encoded transaction - * @pattern [0-9a-fA-F]* * @example "84a500818258209cb4f8c2eecccc9f1e13768046f37ef56dcb5a4dc44f58907fe4ae21d7cf621d020181825839019cb581f4337a6142e477af6e00fe41b1fc4a5944a575681b8499a3c0bd07ce733b5911eb657e7aff5d35f8b0682fe0380f7621af2bbcb2f71b0000000586321393021a0002a389031a004b418c048183028200581cbd07ce733b5911eb657e7aff5d35f8b0682fe0380f7621af2bbcb2f7581c53215c471b7ac752e3ddf8f2c4c1e6ed111857bfaa675d5e31ce8bcea1008282582073e584cda9fe483fbefb81c251e616018a2b493ef56820f0095b63adede54ff758404f13df42ef1684a3fd55255d8368c9ecbd15b55e2761a2991cc4f401a753c16d6da1da158e84b87b4de9715af7d9adc0d79a7c1f2c3097228e02b20be4616a0c82582066c606974819f457ceface78ee3c4d181a84ca9927a3cfc92ef8c0b6dd4576e8584014ae9ee9ed5eb5700b6c5ac270543671f5d4f943d4726f4614dc061174ee29db44b9e7fc58e6c98c13fad8594f2633c5ec70a9a87f5cbf130308a42edb553001f5f6" */ - payload: string; + payload: UnboundHex; metadata?: string | null; - inputCredentials?: string[]; + /** + * cbor-encoded TransactionOutput structure of each UTXO in the input + * @example "825839019cb581f4337a6142e477af6e00fe41b1fc4a5944a575681b8499a3c0bd07ce733b5911eb657e7aff5d35f8b0682fe0380f7621af2bbcb2f71b0000000586321393" + */ + inputs?: UnboundHex[]; }; export type TxAndBlockInfo = { diff --git a/webserver/shared/models/TransactionOutput.ts b/webserver/shared/models/TransactionOutput.ts index a41f5dd1..6d59ef84 100644 --- a/webserver/shared/models/TransactionOutput.ts +++ b/webserver/shared/models/TransactionOutput.ts @@ -1,4 +1,4 @@ -import type { UtxoPointer } from "./common"; +import type { UnboundHex, UtxoPointer } from "./common"; import { BlockInfo } from "./TransactionHistory"; export type TransactionOutputRequest = { @@ -9,10 +9,9 @@ export type UtxoAndBlockInfo = { block: BlockInfo; utxo: UtxoPointer & { /** - * @pattern [0-9a-fA-F]* * @example "825839019cb581f4337a6142e477af6e00fe41b1fc4a5944a575681b8499a3c0bd07ce733b5911eb657e7aff5d35f8b0682fe0380f7621af2bbcb2f71b0000000586321393" */ - payload: string; + payload: UnboundHex; }; }; export type TransactionOutputResponse = { diff --git a/webserver/shared/models/common.ts b/webserver/shared/models/common.ts index 5a5c7d22..83549da6 100644 --- a/webserver/shared/models/common.ts +++ b/webserver/shared/models/common.ts @@ -42,6 +42,11 @@ export enum RelationFilterType { NO_FILTER = 0xff, } +/** +* @pattern [0-9a-fA-F]* +*/ +export type UnboundHex = string; + export type BlockTxPair = { /** * block hash