diff --git a/CHANGELOG.md b/CHANGELOG.md index bc85fbef..5c68ca7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changelog ========= +## 0.4.0 +### Features +- Block.nextBlock +- Block.epochNo is a workaround for the less performant Block.epoch.number + ## 0.3.0 ### Features - Can now scope aggregated queries to the same filters as the non-aggregated counterparts diff --git a/hasura/migrations/metadata.json b/hasura/migrations/metadata.json index c8cf5c71..1f41f825 100644 --- a/hasura/migrations/metadata.json +++ b/hasura/migrations/metadata.json @@ -1 +1 @@ -{"functions":["utxo_set_at_block"],"remote_schemas":[],"query_collections":[],"allowlist":[],"tables":[{"table":"Meta","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":false,"columns":["slotDuration","startTime","protocolConst"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Utxo","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","index"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"TransactionOutput","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","index"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Cardano","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Epoch","column_mapping":{"currentEpochNo":"number"}}},"name":"currentEpoch","comment":null}],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["blockHeight","currentEpochNo"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Block","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Epoch","column_mapping":{"epochNo":"number"}}},"name":"epoch","comment":null},{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"previousBlockId":"id"}}},"name":"previousBlock","comment":null}],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"Transaction","column_mapping":{"id":"blockId"}}},"name":"transactions","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["createdAt","createdBy","epochNo","fees","id","merkelRootHash","number","previousBlockId","size","slotNo","slotWithinEpoch"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Transaction","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"blockId":"id"}}},"name":"block","comment":null}],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"TransactionInput","column_mapping":{"id":"txId"}}},"name":"inputs","comment":null},{"using":{"manual_configuration":{"remote_table":"TransactionOutput","column_mapping":{"id":"txId"}}},"name":"outputs","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["blockId","fee","id","totalOutput","includedAt"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Epoch","is_enum":false,"object_relationships":[],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"number":"epochNo"}}},"name":"blocks","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["output","transactionsCount","number","startedAt","lastBlockTime"],"limit":10,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"TransactionInput","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","sourceTxId","sourceTxIndex"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]}]} \ No newline at end of file +{"functions":["utxo_set_at_block"],"remote_schemas":[],"query_collections":[],"allowlist":[],"tables":[{"table":"Meta","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":false,"columns":["slotDuration","startTime","protocolConst"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Utxo","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","index"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"TransactionOutput","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","index"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Cardano","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Epoch","column_mapping":{"currentEpochNo":"number"}}},"name":"currentEpoch","comment":null}],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["blockHeight","currentEpochNo"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Block","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Epoch","column_mapping":{"epochNo":"number"}}},"name":"epoch","comment":null},{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"previousBlockId":"id"}}},"name":"previousBlock","comment":null},{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"nextBlockId":"id"}}},"name":"nextBlock","comment":null}],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"Transaction","column_mapping":{"id":"blockId"}}},"name":"transactions","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["createdAt","createdBy","epochNo","fees","id","merkelRootHash","number","previousBlockId","size","slotNo","slotWithinEpoch"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Transaction","is_enum":false,"object_relationships":[{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"blockId":"id"}}},"name":"block","comment":null}],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"TransactionInput","column_mapping":{"id":"txId"}}},"name":"inputs","comment":null},{"using":{"manual_configuration":{"remote_table":"TransactionOutput","column_mapping":{"id":"txId"}}},"name":"outputs","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["blockId","fee","id","totalOutput","includedAt"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"Epoch","is_enum":false,"object_relationships":[],"array_relationships":[{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"number":"epochNo"}}},"name":"blocks","comment":null}],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["output","transactionsCount","number","startedAt","lastBlockTime"],"limit":10,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]},{"table":"TransactionInput","is_enum":false,"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"columns":["address","value","txId","sourceTxId","sourceTxIndex"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[]}]} \ No newline at end of file diff --git a/package.json b/package.json index 981552f6..52516cc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cardano-graphql", - "version": "0.3.0", + "version": "0.4.0", "description": "GraphQL API for Cardano with client-consumable types generated", "scripts": { "codegen:external": "graphql-codegen --config ./codegen.external.yml", diff --git a/src/__test__/__snapshots__/e2e.test.ts.snap b/src/__test__/__snapshots__/e2e.test.ts.snap index 3c5252fb..872d976b 100644 --- a/src/__test__/__snapshots__/e2e.test.ts.snap +++ b/src/__test__/__snapshots__/e2e.test.ts.snap @@ -75,6 +75,25 @@ Object { } `; +exports[`blocks are linked to their successor, and the chain can be traversed 1`] = ` +Object { + "blocks": Array [ + Object { + "id": "bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380", + "nextBlock": Object { + "nextBlock": Object { + "nextBlock": Object { + "number": 29025, + }, + "number": 29024, + }, + "number": 29023, + }, + }, + ], +} +`; + exports[`cardano Returns key information about the network 1`] = ` Object { "cardano": Object { diff --git a/src/__test__/__snapshots__/integration.test.ts.snap b/src/__test__/__snapshots__/integration.test.ts.snap index 3c5252fb..872d976b 100644 --- a/src/__test__/__snapshots__/integration.test.ts.snap +++ b/src/__test__/__snapshots__/integration.test.ts.snap @@ -75,6 +75,25 @@ Object { } `; +exports[`blocks are linked to their successor, and the chain can be traversed 1`] = ` +Object { + "blocks": Array [ + Object { + "id": "bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380", + "nextBlock": Object { + "nextBlock": Object { + "nextBlock": Object { + "number": 29025, + }, + "number": 29024, + }, + "number": 29023, + }, + }, + ], +} +`; + exports[`cardano Returns key information about the network 1`] = ` Object { "cardano": Object { diff --git a/src/__test__/data_assertions/block_assertions.ts b/src/__test__/data_assertions/block_assertions.ts index e6e1974f..e5ad2cfd 100644 --- a/src/__test__/data_assertions/block_assertions.ts +++ b/src/__test__/data_assertions/block_assertions.ts @@ -5,6 +5,7 @@ export const block29021 = { epoch: { number: 1 }, + epochNo: 1, fees: '342316', id: '00aea2405f7cf4eb1d9e6694770ea25eeb113b857e377d22641aa1099742615d', merkelRootHash: '1acc618aebd703ab201ef790a379a0bd8748ac7a4ed4bf425e0b12f8b7afd812', @@ -17,6 +18,10 @@ export const block29021 = { id: '663c25ee1434e6d29f8bd08bd52ddbb16a30bb54ca3c69c815e3de7bc4c42770', number: 29020 }, + nextBlock: { + id: 'bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380', + number: 29022 + }, size: 1349, transactions: [tx05ad8b.basic, txe68043.basic] }, @@ -59,6 +64,7 @@ export const block29022 = { epoch: { number: 1 }, + epochNo: 1, fees: '0', id: 'bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380', merkelRootHash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8', @@ -69,6 +75,10 @@ export const block29022 = { id: '00aea2405f7cf4eb1d9e6694770ea25eeb113b857e377d22641aa1099742615d', number: 29021 }, + nextBlock: { + id: '9a20077183a044fbe41a6ac71747b3463966ba724cd0478786a3df5000b37008', + number: 29023 + }, size: 631, slotNo: 29036, slotWithinEpoch: 7436, diff --git a/src/__test__/tests/blocks.query.test.ts b/src/__test__/tests/blocks.query.test.ts index 8bb4df62..f5fe4bc5 100644 --- a/src/__test__/tests/blocks.query.test.ts +++ b/src/__test__/tests/blocks.query.test.ts @@ -70,6 +70,7 @@ export function blocksTests (makeClient: () => Promise) { epoch { number } + epochNo fees id merkelRootHash @@ -80,6 +81,10 @@ export function blocksTests (makeClient: () => Promise) { id number } + nextBlock { + id + number + } size slotNo slotWithinEpoch @@ -185,5 +190,26 @@ export function blocksTests (makeClient: () => Promise) { expect(result.data.blocks[0].previousBlock.previousBlock.previousBlock.number).toBe(29019) expect(result.data).toMatchSnapshot() }) + + it('are linked to their successor, and the chain can be traversed', async () => { + const result = await client.query({ + query: gql`query { + blocks (where: { number: { _eq: 29022}}) { + id + nextBlock { + number + nextBlock { + number + nextBlock { + number + } + } + } + } + }` + }) + expect(result.data.blocks[0].nextBlock.nextBlock.nextBlock.number).toBe(29025) + expect(result.data).toMatchSnapshot() + }) }) } diff --git a/src/schema.graphql b/src/schema.graphql index 06eb9c56..153952ec 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -242,6 +242,7 @@ type Block { createdBy: String! # Genesis block does not belong to the 0th epoch, therefore it could be null epoch: Epoch + epochNo: Int! fees: String! id: Hash32HexString! # Ouroboros Classic Epoch Boundary blocks (EBB) do not have a merkel root @@ -253,6 +254,7 @@ type Block { # Ouroboros Classic Epoch Boundary blocks (EBB) do not have a slot number slotWithinEpoch: Int previousBlock: Block + nextBlock: Block size: Int! transactions( limit: Int @@ -279,6 +281,7 @@ input Block_bool_exp { id: Hash32HexString_comparison_exp number: Int_comparison_exp previousBlock: Block_bool_exp + nextBlock: Block_bool_exp size: Int_comparison_exp slotNo: Int_comparison_exp slotWithinEpoch: Int_comparison_exp diff --git a/test/postgres/init/002_views.sql b/test/postgres/init/002_views.sql index 31841043..0b7b2c1c 100644 --- a/test/postgres/init/002_views.sql +++ b/test/postgres/init/002_views.sql @@ -63,6 +63,7 @@ select block.merkel_root as "merkelRootHash", block.block_no as number, previous_block."hash" as "previousBlockId", + next_block."hash" as "nextBlockId", slot_leader."desciption" as "createdBy", block.size as size, -- Even though we have epochNo defined in the Slot view, @@ -78,6 +79,8 @@ select from block left outer join block as previous_block on block.previous = previous_block.id +left outer join block as next_block + on next_block.previous = block.id left outer join slot_leader on block.slot_leader = slot_leader.id;