diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c68ca7b..29f21a84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,24 @@ Changelog ========= +## 1.0.0 +## Features +- `Block.transactionsCount` - An optimised version of the aggregate query. +- `Cardano.networkName` - Unlocks application-side logic based on the network it's connected to. +- `Transaction.size` - New +## Fixes +- The aggregated and known very large numbers are now typed as String. Cardano JS has utilities to work with these return values, currently limited to currency conversion. +- `cardano` query return value is accurately defined to always return an object of type `Cardano` +- `Transaction.fee` was a String, now a `BigInt` + +### Chores +- The PostgreSQL views have been incorperated upstream, and are no longer managed in this codebase. +- Updates to Hasura 1.0.0-beta.10 +- Includes script to dump a sample using a Cardano Docker stack. +- Improves CI process by consolidating the Jest snapshot files. +- Renamed npm scripts `start-dependencies` and `stop-dependencies` for alignment with `start:*` and `stop:*` +- `Cardano` now matches the postgres view, and is an improvement over the previous version which performed two queries. + ## 0.4.0 ### Features - Block.nextBlock diff --git a/README.md b/README.md index 54544437..2206752a 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,5 @@ Integrated query UI and documentation is available in the GraphQL Playground, av - [API Consumer Documentation](./docs/api_consumer) - [Developer Documentation](./docs/developer) - [Updating Hasura Metadata](./docs/hasura) +- [Refresh Test DB Dump](./docs/refresh_db) diff --git a/docker/docker-compose.service-deps.yml b/docker/docker-compose.service-deps.yml index add77d82..ce686380 100644 --- a/docker/docker-compose.service-deps.yml +++ b/docker/docker-compose.service-deps.yml @@ -1,7 +1,7 @@ version: '3.7' services: hasura: - image: hasura/graphql-engine:v1.0.0-beta.6.cli-migrations + image: hasura/graphql-engine:v1.0.0-beta.10.cli-migrations ports: - "8090:8080" depends_on: diff --git a/docker/docker-compose.test.yml b/docker/docker-compose.test.yml index 00fbdffa..9c753000 100644 --- a/docker/docker-compose.test.yml +++ b/docker/docker-compose.test.yml @@ -10,7 +10,7 @@ services: ports: - ${API_PORT:-3100}:3100 hasura: - image: hasura/graphql-engine:v1.0.0-beta.6.cli-migrations + image: hasura/graphql-engine:v1.0.0-beta.10.cli-migrations depends_on: - "postgres" restart: always diff --git a/docs/refresh_db/README.md b/docs/refresh_db/README.md new file mode 100644 index 00000000..428ce96c --- /dev/null +++ b/docs/refresh_db/README.md @@ -0,0 +1,8 @@ +# Refresh Test DB Dump + +1. clone `cardano-docker-stack` from GH +2. From cardano-docker-stack, run `./scripts/start_mainnet.sh` +3. Once the stack starts, use `docker ps` to identify `cardano-explorer` container. Then use `docker logs -f _container_name_` to monitor the block height as the explorer receives and writes blocks. +4. Once block height is above 70000, run `yarn refresh-db` from the root directory of `cardano-graphql` + +Note: It is _expected_ that some of the snapshot values will change and need to be updated, as you will not dump the db at the exact same block as the last dump \ No newline at end of file diff --git a/hasura/migrations/metadata.json b/hasura/migrations/metadata.json index 1f41f825..4aef9c5e 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},{"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 +{"functions":["utxo_set_at_block"],"remote_schemas":[],"query_collections":[],"allowlist":[],"tables":[{"table":"Block","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"object_relationships":[{"using":{"manual_configuration":{"remote_table":"slot_leader","column_mapping":{"createdBy":"id"}}},"name":"creator","comment":null},{"using":{"manual_configuration":{"remote_table":"Epoch","column_mapping":{"epochNo":"number"}}},"name":"epoch","comment":null},{"using":{"manual_configuration":{"remote_table":"Block","column_mapping":{"nextBlockId":"id"}}},"name":"nextBlock","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,"computed_fields":[],"columns":["fees","id","merkelRootHash","number","previousBlockId","nextBlockId","createdBy","size","transactionsCount","epochNo","slotNo","slotWithinEpoch","createdAt"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"Cardano","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"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":false,"computed_fields":[],"columns":["blockHeight","currentEpochNo","slotDuration","startTime","protocolConst","networkName"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"Epoch","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"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,"computed_fields":[],"columns":["output","transactionsCount","number","startedAt","lastBlockTime"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"Transaction","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"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,"computed_fields":[],"columns":["blockId","fee","id","totalOutput","size","includedAt"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"TransactionInput","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"computed_fields":[],"columns":["address","value","txId","sourceTxId","sourceTxIndex"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"TransactionOutput","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"computed_fields":[],"columns":["address","value","txId","index"],"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"Utxo","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"computed_fields":[],"columns":["address","value","txId","index"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]},{"table":"slot_leader","is_enum":false,"configuration":{"custom_root_fields":{"select":null,"select_by_pk":null,"select_aggregate":null,"insert":null,"update":null,"delete":null},"custom_column_names":{}},"object_relationships":[],"array_relationships":[],"insert_permissions":[],"select_permissions":[{"role":"cardano-graphql","comment":null,"permission":{"allow_aggregations":true,"computed_fields":[],"columns":["id","hash","description"],"limit":100,"filter":{}}}],"update_permissions":[],"delete_permissions":[],"event_triggers":[],"computed_fields":[]}]} \ No newline at end of file diff --git a/package.json b/package.json index 52516cc9..05bdbb78 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,24 @@ { "name": "cardano-graphql", - "version": "0.4.0", + "version": "1.0.0-rc.0", "description": "GraphQL API for Cardano with client-consumable types generated", "scripts": { "codegen:external": "graphql-codegen --config ./codegen.external.yml", "codegen:internal": "graphql-codegen", "lint": "eslint \"src/**/*.ts\"", "dev": "yarn codegen:internal --watch", - "dev:test": "HASURA_URI=http://localhost:8090/v1/graphql stmux -w always -e ERROR -M -- [[ \"yarn dev\" .. \"yarn start-dependencies\" .. \"tsc --watch --noEmit\" .. \"yarn test:integration --watchAll\" ]]", + "dev:test": "HASURA_URI=http://localhost:8090/v1/graphql stmux -w always -e ERROR -M -- [[ \"yarn dev\" .. \"yarn start:dependencies\" .. \"tsc --watch --noEmit\" .. \"yarn test:integration --watchAll\" ]]", "dev:start": "HASURA_URI=http://localhost:8090/v1/graphql stmux -w always -e ERROR -M -- [[ \"docker-compose -f docker/docker-compose.service-deps.yml up\" .. \"ts-node-dev --no-notify --respawn --transpileOnly src/index.ts\" ]]", "build": "rm -rf dist && yarn codegen:internal && yarn codegen:external && tsc && npx cpx src/**/*.graphql dist", - "test:integration": "NODE_ENV=test jest integration", - "test:e2e": "NODE_ENV=test jest e2e", + "test:integration": "NODE_ENV=test TEST_MODE=integration jest suite", + "test:e2e": "NODE_ENV=test TEST_MODE=e2e jest suite", "start": "HASURA_URI=http://localhost:8090/v1/graphql node dist/index.js", - "start-dependencies": "docker-compose -f docker/docker-compose.service-deps.yml up", + "start:dependencies": "docker-compose -f docker/docker-compose.service-deps.yml up", "start:test-stack": "docker-compose -f docker/docker-compose.test.yml up", - "stop-dependencies": "docker-compose -f docker/docker-compose.service-deps.yml down", + "stop:dependencies": "docker-compose -f docker/docker-compose.service-deps.yml down", "stop:test-stack": "docker-compose -f docker/docker-compose.test.yml down", - "loadtest:byron-staging": "artillery run test/loadtest/byron-staging-config.yml" + "loadtest:byron-staging": "artillery run test/loadtest/byron-staging-config.yml", + "refresh-db": "sh ./test/postgres/refresh_dump.sh" }, "contributors": [ "Rhys Bartels-Waller (https://iohk.io)", @@ -56,6 +57,7 @@ "apollo-server-core": "^2.8.1", "apollo-server-testing": "^2.8.1", "artillery": "^1.6.0-29", + "bignumber.js": "9.0.0", "cpx": "^1.5.0", "eslint": "^6.1.0", "eslint-config-standard": "^13.0.1", diff --git a/src/__test__/__snapshots__/integration.test.ts.snap b/src/__test__/__snapshots__/integration.test.ts.snap deleted file mode 100644 index 872d976b..00000000 --- a/src/__test__/__snapshots__/integration.test.ts.snap +++ /dev/null @@ -1,420 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`blocks Can return aggregated data 1`] = ` -Object { - "blocks": Array [ - Object { - "number": 29021, - "transactions_aggregate": Object { - "aggregate": Object { - "avg": Object { - "fee": 171158, - "totalOutput": 2846601153795, - }, - "count": 2, - "max": Object { - "fee": 171246, - "totalOutput": 4924799478660, - }, - "min": Object { - "fee": 171070, - "totalOutput": 768402828930, - }, - "sum": Object { - "fee": 342316, - "totalOutput": 5693202307590, - }, - }, - }, - }, - ], -} -`; - -exports[`blocks Can return blocks by number 1`] = ` -Object { - "blocks": Array [ - Object { - "id": "bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380", - }, - ], -} -`; - -exports[`blocks Can return filtered aggregated data 1`] = ` -Object { - "blocks": Array [ - Object { - "number": 29021, - "transactions_aggregate": Object { - "aggregate": Object { - "count": 2, - }, - }, - }, - ], -} -`; - -exports[`blocks are linked to their predecessor, and the chain can be traversed 1`] = ` -Object { - "blocks": Array [ - Object { - "id": "bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380", - "previousBlock": Object { - "number": 29021, - "previousBlock": Object { - "number": 29020, - "previousBlock": Object { - "number": 29019, - }, - }, - }, - }, - ], -} -`; - -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 { - "blockHeight": 31070, - "currentEpoch": Object { - "number": 1, - }, - "protocolConst": 2160, - "slotDuration": 20000, - "startTime": "2017-09-23T21:44:51", - }, -} -`; - -exports[`epochs Can return aggregated Epoch data 1`] = ` -Object { - "epochs_aggregate": Object { - "aggregate": Object { - "count": "2", - "max": Object { - "number": "1", - "output": "17282903106017760", - "transactionsCount": "5344", - }, - "min": Object { - "output": "10378568796482912", - "transactionsCount": "33", - }, - "sum": Object { - "output": "27661471902500670", - "transactionsCount": "5377", - }, - }, - }, -} -`; - -exports[`epochs Can return aggregated data 1`] = ` -Object { - "epochs": Array [ - Object { - "blocks_aggregate": Object { - "aggregate": Object { - "avg": Object { - "fees": 28103.350131787032, - "size": 881.9561412756984, - }, - "count": 9485, - "max": Object { - "fees": 684456, - "size": 648087, - }, - "min": Object { - "fees": 0, - "size": 631, - }, - "sum": Object { - "fees": 266560276, - "size": 8365354, - }, - }, - }, - "number": 1, - }, - ], -} -`; - -exports[`epochs Can return filtered aggregated data 1`] = ` -Object { - "epochs": Array [ - Object { - "blocks_aggregate": Object { - "aggregate": Object { - "count": 1120, - }, - }, - "number": 1, - }, - ], -} -`; - -exports[`epochs Returns epoch details by number 1`] = ` -Object { - "epochs": Array [ - Object { - "lastBlockTime": "2017-10-01T02:25:51", - "number": 1, - "output": "17282903106017760", - "startedAt": "2017-09-28T21:45:51", - "transactionsCount": "5344", - }, - ], -} -`; - -exports[`epochs Returns epoch details by number range 1`] = ` -Object { - "epochs": Array [ - Object { - "lastBlockTime": "2017-10-01T02:25:51", - "number": 1, - "output": "17282903106017760", - "startedAt": "2017-09-28T21:45:51", - "transactionsCount": "5344", - }, - ], -} -`; - -exports[`transactions Can return aggregated data 1`] = ` -Object { - "transactions": Array [ - Object { - "fee": "171246", - "id": "05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102", - "inputs_aggregate": Object { - "aggregate": Object { - "avg": Object { - "value": 4924799649906, - }, - "count": 1, - "max": Object { - "value": 4924799649906, - }, - "min": Object { - "value": 4924799649906, - }, - "sum": Object { - "value": 4924799649906, - }, - }, - }, - "outputs_aggregate": Object { - "aggregate": Object { - "avg": Object { - "value": 2462399739330, - }, - "count": 2, - "max": Object { - "value": 4824799478660, - }, - "min": Object { - "value": 100000000000, - }, - "sum": Object { - "value": 4924799478660, - }, - }, - }, - }, - Object { - "fee": "171070", - "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", - "inputs_aggregate": Object { - "aggregate": Object { - "avg": Object { - "value": 768403000000, - }, - "count": 1, - "max": Object { - "value": 768403000000, - }, - "min": Object { - "value": 768403000000, - }, - "sum": Object { - "value": 768403000000, - }, - }, - }, - "outputs_aggregate": Object { - "aggregate": Object { - "avg": Object { - "value": 384201414465, - }, - "count": 2, - "max": Object { - "value": 768401828930, - }, - "min": Object { - "value": 1000000, - }, - "sum": Object { - "value": 768402828930, - }, - }, - }, - }, - ], -} -`; - -exports[`transactions Can return filtered aggregated data 1`] = ` -Object { - "transactions": Array [ - Object { - "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", - "inputs_aggregate": Object { - "aggregate": Object { - "count": 1, - }, - }, - "outputs_aggregate": Object { - "aggregate": Object { - "count": 1, - }, - }, - }, - ], -} -`; - -exports[`transactions Returns transactions by IDs 1`] = ` -Object { - "transactions": Array [ - Object { - "block": Object { - "number": 29021, - }, - "fee": "171246", - "id": "05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102", - "inputs": Array [ - Object { - "address": "DdzFFzCqrht5ExAdoZVExXoZTpoMYGKxva3thvvvHapsLZQzSX3kCqwgqi5NSM2oUtHYYDqsSnvSGbqkarB6cSgDZohUhLWZ9KFdDWsa", - "value": "4924799649906", - }, - ], - "outputs": Array [ - Object { - "address": "DdzFFzCqrhsxVv8Sjuj35Zkw42T9WjwXa6DasrNknm5M3bPVDnWJWwhX5NymoZncUArTfFYZ9sYGaA9htKSNYoK5Vkzx2vUtunAFt3eE", - "value": "4824799478660", - }, - Object { - "address": "DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s", - "value": "100000000000", - }, - ], - "totalOutput": "4924799478660", - }, - Object { - "block": Object { - "number": 29021, - }, - "fee": "171070", - "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", - "inputs": Array [ - Object { - "address": "DdzFFzCqrhsggyaAMAUTjGtjBr1CTp8tTcHYWbqtoyQBZcaYHM16rjbUDawTwoVaEPawAMPLJmpJVXHBNxZnTgmQzqAcNDe6XvMe5BkB", - "value": "768403000000", - }, - ], - "outputs": Array [ - Object { - "address": "DdzFFzCqrhsuz652nVpjktdtiV44uWJLHv83m61S33gzfB4TBx7SKp3DgM18fBJznMrbUdsEFEvXW4LYqVKFE9fjMgVhmJP2LBhUvEe8", - "value": "768401828930", - }, - Object { - "address": "DdzFFzCqrhsgrGt7zHydkE4cKxjB7SgsdnMPUFxYEwBu1u4sGobxZL5Xo3eDycCrtSYAUyw9aAsZZxFpTdgur6MwYDYMwAZ4xNGKRD3o", - "value": "1000000", - }, - ], - "totalOutput": "768402828930", - }, - ], -} -`; - -exports[`utxos Can be scoped by address 1`] = ` -Object { - "utxos": Array [ - Object { - "address": "DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s", - "value": "100000000000", - }, - Object { - "address": "DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s", - "value": "150000000000", - }, - ], -} -`; - -exports[`utxos Can be scoped by list of addresses 1`] = ` -Object { - "utxos": Array [ - Object { - "address": "Ae2tdPwUPEZGvXJ3ebp4LDgBhbxekAH2oKZgfahKq896fehv8oCJxmGJgLt", - "value": "1153846000000", - }, - Object { - "address": "DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s", - "value": "100000000000", - }, - Object { - "address": "DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s", - "value": "150000000000", - }, - ], -} -`; - -exports[`utxos Can return aggregated UTXO data 1`] = ` -Object { - "utxos_aggregate": Object { - "aggregate": Object { - "avg": Object { - "value": "26556.16176470588", - }, - "count": 68, - "max": Object { - "value": "175212", - }, - "min": Object { - "value": "1", - }, - "sum": Object { - "value": "1805819", - }, - }, - }, -} -`; diff --git a/src/__test__/__snapshots__/e2e.test.ts.snap b/src/__test__/__snapshots__/suite.test.ts.snap similarity index 78% rename from src/__test__/__snapshots__/e2e.test.ts.snap rename to src/__test__/__snapshots__/suite.test.ts.snap index 872d976b..fc9bb68d 100644 --- a/src/__test__/__snapshots__/e2e.test.ts.snap +++ b/src/__test__/__snapshots__/suite.test.ts.snap @@ -9,20 +9,24 @@ Object { "aggregate": Object { "avg": Object { "fee": 171158, + "size": 218, "totalOutput": 2846601153795, }, - "count": 2, + "count": "2", "max": Object { - "fee": 171246, - "totalOutput": 4924799478660, + "fee": "171246", + "size": "220", + "totalOutput": "4924799478660", }, "min": Object { - "fee": 171070, - "totalOutput": 768402828930, + "fee": "171070", + "size": "216", + "totalOutput": "768402828930", }, "sum": Object { - "fee": 342316, - "totalOutput": 5693202307590, + "fee": "342316", + "size": "436", + "totalOutput": "5693202307590", }, }, }, @@ -48,7 +52,7 @@ Object { "number": 29021, "transactions_aggregate": Object { "aggregate": Object { - "count": 2, + "count": "2", }, }, }, @@ -97,10 +101,11 @@ Object { exports[`cardano Returns key information about the network 1`] = ` Object { "cardano": Object { - "blockHeight": 31070, + "blockHeight": 70205, "currentEpoch": Object { - "number": 1, + "number": 3, }, + "networkName": "mainnet", "protocolConst": 2160, "slotDuration": 20000, "startTime": "2017-09-23T21:44:51", @@ -112,19 +117,19 @@ exports[`epochs Can return aggregated Epoch data 1`] = ` Object { "epochs_aggregate": Object { "aggregate": Object { - "count": "2", + "count": "4", "max": Object { - "number": "1", - "output": "17282903106017760", - "transactionsCount": "5344", + "number": 3, + "output": "101402912214214220", + "transactionsCount": "12870", }, "min": Object { "output": "10378568796482912", "transactionsCount": "33", }, "sum": Object { - "output": "27661471902500670", - "transactionsCount": "5377", + "output": "185850210776378720", + "transactionsCount": "18007", }, }, }, @@ -138,21 +143,21 @@ Object { "blocks_aggregate": Object { "aggregate": Object { "avg": Object { - "fees": 28103.350131787032, - "size": 881.9561412756984, + "fees": 47846.34914312181, + "size": 868.0383047707272, }, - "count": 9485, + "count": "21590", "max": Object { - "fees": 684456, - "size": 648087, + "fees": "1377042", + "size": "648087", }, "min": Object { - "fees": 0, - "size": 631, + "fees": "0", + "size": "631", }, "sum": Object { - "fees": 266560276, - "size": 8365354, + "fees": "1033002678", + "size": "18740947", }, }, }, @@ -168,7 +173,7 @@ Object { Object { "blocks_aggregate": Object { "aggregate": Object { - "count": 1120, + "count": "2408", }, }, "number": 1, @@ -181,11 +186,11 @@ exports[`epochs Returns epoch details by number 1`] = ` Object { "epochs": Array [ Object { - "lastBlockTime": "2017-10-01T02:25:51", + "lastBlockTime": "2017-10-03T21:43:51", "number": 1, - "output": "17282903106017760", + "output": "101402912214214220", "startedAt": "2017-09-28T21:45:51", - "transactionsCount": "5344", + "transactionsCount": "12870", }, ], } @@ -195,11 +200,11 @@ exports[`epochs Returns epoch details by number range 1`] = ` Object { "epochs": Array [ Object { - "lastBlockTime": "2017-10-01T02:25:51", + "lastBlockTime": "2017-10-03T21:43:51", "number": 1, - "output": "17282903106017760", + "output": "101402912214214220", "startedAt": "2017-09-28T21:45:51", - "transactionsCount": "5344", + "transactionsCount": "12870", }, ], } @@ -209,77 +214,77 @@ exports[`transactions Can return aggregated data 1`] = ` Object { "transactions": Array [ Object { - "fee": "171246", + "fee": 171246, "id": "05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102", "inputs_aggregate": Object { "aggregate": Object { "avg": Object { - "value": 4924799649906, + "value": "4924799649906", }, - "count": 1, + "count": "1", "max": Object { - "value": 4924799649906, + "value": "4924799649906", }, "min": Object { - "value": 4924799649906, + "value": "4924799649906", }, "sum": Object { - "value": 4924799649906, + "value": "4924799649906", }, }, }, "outputs_aggregate": Object { "aggregate": Object { "avg": Object { - "value": 2462399739330, + "value": "2462399739330", }, - "count": 2, + "count": "2", "max": Object { - "value": 4824799478660, + "value": "4824799478660", }, "min": Object { - "value": 100000000000, + "value": "100000000000", }, "sum": Object { - "value": 4924799478660, + "value": "4924799478660", }, }, }, }, Object { - "fee": "171070", + "fee": 171070, "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", "inputs_aggregate": Object { "aggregate": Object { "avg": Object { - "value": 768403000000, + "value": "768403000000", }, - "count": 1, + "count": "1", "max": Object { - "value": 768403000000, + "value": "768403000000", }, "min": Object { - "value": 768403000000, + "value": "768403000000", }, "sum": Object { - "value": 768403000000, + "value": "768403000000", }, }, }, "outputs_aggregate": Object { "aggregate": Object { "avg": Object { - "value": 384201414465, + "value": "384201414465", }, - "count": 2, + "count": "2", "max": Object { - "value": 768401828930, + "value": "768401828930", }, "min": Object { - "value": 1000000, + "value": "1000000", }, "sum": Object { - "value": 768402828930, + "value": "768402828930", }, }, }, @@ -295,12 +300,12 @@ Object { "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", "inputs_aggregate": Object { "aggregate": Object { - "count": 1, + "count": "1", }, }, "outputs_aggregate": Object { "aggregate": Object { - "count": 1, + "count": "1", }, }, }, @@ -315,7 +320,7 @@ Object { "block": Object { "number": 29021, }, - "fee": "171246", + "fee": 171246, "id": "05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102", "inputs": Array [ Object { @@ -333,13 +338,14 @@ Object { "value": "100000000000", }, ], + "size": 220, "totalOutput": "4924799478660", }, Object { "block": Object { "number": 29021, }, - "fee": "171070", + "fee": 171070, "id": "e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae", "inputs": Array [ Object { @@ -357,6 +363,7 @@ Object { "value": "1000000", }, ], + "size": 216, "totalOutput": "768402828930", }, ], @@ -402,9 +409,9 @@ Object { "utxos_aggregate": Object { "aggregate": Object { "avg": Object { - "value": "26556.16176470588", + "value": "24072.92420537897", }, - "count": 68, + "count": "409", "max": Object { "value": "175212", }, @@ -412,7 +419,7 @@ Object { "value": "1", }, "sum": Object { - "value": "1805819", + "value": "9845826", }, }, }, diff --git a/src/__test__/data_assertions/block_assertions.ts b/src/__test__/data_assertions/block_assertions.ts index e5ad2cfd..b5c12dfd 100644 --- a/src/__test__/data_assertions/block_assertions.ts +++ b/src/__test__/data_assertions/block_assertions.ts @@ -6,7 +6,7 @@ export const block29021 = { number: 1 }, epochNo: 1, - fees: '342316', + fees: 342316, id: '00aea2405f7cf4eb1d9e6694770ea25eeb113b857e377d22641aa1099742615d', merkelRootHash: '1acc618aebd703ab201ef790a379a0bd8748ac7a4ed4bf425e0b12f8b7afd812', createdAt: '2017-09-30T15:03:11', @@ -23,7 +23,8 @@ export const block29021 = { number: 29022 }, size: 1349, - transactions: [tx05ad8b.basic, txe68043.basic] + transactions: [tx05ad8b.basic, txe68043.basic], + transactionsCount: '2' }, aggregated: { number: 29021, @@ -31,20 +32,24 @@ export const block29021 = { aggregate: { avg: { fee: 171158, + size: 218, totalOutput: 2846601153795 }, - count: 2, + count: '2', max: { - fee: 171246, - totalOutput: 4924799478660 + fee: '171246', + size: '220', + totalOutput: '4924799478660' }, min: { - fee: 171070, - totalOutput: 768402828930 + fee: '171070', + size: '216', + totalOutput: '768402828930' }, sum: { - fee: 342316, - totalOutput: 5693202307590 + fee: '342316', + size: '436', + totalOutput: '5693202307590' } } } @@ -53,7 +58,7 @@ export const block29021 = { number: 29021, transactions_aggregate: { aggregate: { - count: 2 + count: '2' } } } @@ -65,7 +70,7 @@ export const block29022 = { number: 1 }, epochNo: 1, - fees: '0', + fees: 0, id: 'bf13d9a80ad99a4f34edb8a3262dd8120e29bbe182732cd3b00bf3d1bb7c2380', merkelRootHash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8', number: 29022, @@ -82,6 +87,7 @@ export const block29022 = { size: 631, slotNo: 29036, slotWithinEpoch: 7436, - transactions: [] as any + transactions: [] as any, + transactionsCount: '0' } } diff --git a/src/__test__/data_assertions/epoch_assertions.ts b/src/__test__/data_assertions/epoch_assertions.ts index 2fd5d557..d120a132 100644 --- a/src/__test__/data_assertions/epoch_assertions.ts +++ b/src/__test__/data_assertions/epoch_assertions.ts @@ -4,30 +4,30 @@ export const epoch1 = { basic: { startedAt: '2017-09-28T21:45:51', - lastBlockTime: '2017-10-01T02:25:51', - output: '17282903106017760', + lastBlockTime: '2017-10-03T21:43:51', + output: '101402912214214220', number: 1, - transactionsCount: '5344' + transactionsCount: '12870' }, aggregated: { blocks_aggregate: { aggregate: { avg: { - fees: 28103.350131787032, - size: 881.9561412756984 + fees: 47846.34914312181, + size: 868.0383047707272 }, - count: 9485, + count: '21590', max: { - fees: 684456, - size: 648087 + fees: '1377042', + size: '648087' }, min: { - fees: 0, - size: 631 + fees: '0', + size: '631' }, sum: { - fees: 266560276, - size: 8365354 + fees: '1033002678', + size: '18740947' } } }, diff --git a/src/__test__/data_assertions/transaction_assertions.ts b/src/__test__/data_assertions/transaction_assertions.ts index 61e0237e..af1befc3 100644 --- a/src/__test__/data_assertions/transaction_assertions.ts +++ b/src/__test__/data_assertions/transaction_assertions.ts @@ -4,7 +4,7 @@ export const txe68043 = { block: { number: 29021 }, - fee: '171070', + fee: 171070, id: 'e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae', includedAt: '2017-09-30T15:03:11', inputs: [{ @@ -18,42 +18,43 @@ export const txe68043 = { address: 'DdzFFzCqrhsgrGt7zHydkE4cKxjB7SgsdnMPUFxYEwBu1u4sGobxZL5Xo3eDycCrtSYAUyw9aAsZZxFpTdgur6MwYDYMwAZ4xNGKRD3o', value: '1000000' }], + size: 216, totalOutput: '768402828930' }, aggregated: { - fee: '171070', + fee: 171070, id: 'e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae', inputs_aggregate: { aggregate: { avg: { - value: 768403000000 + value: '768403000000' }, - count: 1, + count: '1', max: { - value: 768403000000 + value: '768403000000' }, min: { - value: 768403000000 + value: '768403000000' }, sum: { - value: 768403000000 + value: '768403000000' } } }, outputs_aggregate: { aggregate: { avg: { - value: 384201414465 + value: '384201414465' }, - count: 2, + count: '2', max: { - value: 768401828930 + value: '768401828930' }, min: { - value: 1000000 + value: '1000000' }, sum: { - value: 768402828930 + value: '768402828930' } } } @@ -62,12 +63,12 @@ export const txe68043 = { id: 'e680432562b3b71fe44ca4eb8e29cb181d3a0858b3e2a643a55f7513d901bcae', inputs_aggregate: { aggregate: { - count: 0 + count: '0' } }, outputs_aggregate: { aggregate: { - count: 1 + count: '1' } } } @@ -78,7 +79,7 @@ export const tx05ad8b = { block: { number: 29021 }, - fee: '171246', + fee: 171246, id: '05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102', includedAt: '2017-09-30T15:03:11', inputs: [{ @@ -92,42 +93,43 @@ export const tx05ad8b = { address: 'DdzFFzCqrhskotfhVwhLvNFaVGpA6C4yR9DXe56oEL4Ewmze51f1uQsc1cQb8qUyqgzjUPBgFZiVbuQu7BaXrQkouyvzjYjLqfJpKG5s', value: '100000000000' }], + size: 220, totalOutput: '4924799478660' }, aggregated: { - fee: '171246', + fee: 171246, id: '05ad8b467095e0886713a38231ab9fe84e4031a433a9400ebf70ec9415e20102', inputs_aggregate: { aggregate: { avg: { - value: 4924799649906 + value: '4924799649906' }, - count: 1, + count: '1', max: { - value: 4924799649906 + value: '4924799649906' }, min: { - value: 4924799649906 + value: '4924799649906' }, sum: { - value: 4924799649906 + value: '4924799649906' } } }, outputs_aggregate: { aggregate: { avg: { - value: 2462399739330 + value: '2462399739330' }, - count: 2, + count: '2', max: { - value: 4824799478660 + value: '4824799478660' }, min: { - value: 100000000000 + value: '100000000000' }, sum: { - value: 4924799478660 + value: '4924799478660' } } } diff --git a/src/__test__/e2e.test.ts b/src/__test__/e2e_client.ts similarity index 82% rename from src/__test__/e2e.test.ts rename to src/__test__/e2e_client.ts index c3be459d..d02a7778 100644 --- a/src/__test__/e2e.test.ts +++ b/src/__test__/e2e_client.ts @@ -2,9 +2,8 @@ import { ApolloClient, gql, InMemoryCache } from 'apollo-boost' import { createHttpLink } from 'apollo-link-http' import { RetryPromise } from 'promise-exponential-retry' import fetch from 'cross-fetch' -import * as tests from './tests' -const createClient = async () => { +export const createClient = async () => { const client = new ApolloClient({ cache: new InMemoryCache({ addTypename: false @@ -23,4 +22,3 @@ const createClient = async () => { }, 50) return client } -Object.values(tests).forEach(test => test(createClient)) diff --git a/src/__test__/integration.test.ts b/src/__test__/integration.test.ts deleted file mode 100644 index 32e036e9..00000000 --- a/src/__test__/integration.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createTestClient } from 'apollo-server-testing' -import * as tests from './tests' -import { TestApolloServer } from './TestApolloServer' - -const createClient = async () => createTestClient(await TestApolloServer()) -Object.values(tests).forEach(test => test(createClient)) diff --git a/src/__test__/integration_client.ts b/src/__test__/integration_client.ts new file mode 100644 index 00000000..555fcf98 --- /dev/null +++ b/src/__test__/integration_client.ts @@ -0,0 +1,4 @@ +import { createTestClient } from 'apollo-server-testing' +import { TestApolloServer } from './TestApolloServer' + +export const createClient = async () => createTestClient(await TestApolloServer()) diff --git a/src/__test__/suite.test.ts b/src/__test__/suite.test.ts new file mode 100644 index 00000000..c6fd36c0 --- /dev/null +++ b/src/__test__/suite.test.ts @@ -0,0 +1,12 @@ +import * as tests from './tests' + +const { TEST_MODE } = process.env +if (!TEST_MODE || (TEST_MODE !== 'e2e' && TEST_MODE !== 'integration')) { + throw new Error('Test mode must be provided (e2e || integration)') +} + +const createClient = TEST_MODE === 'e2e' + ? require('./e2e_client').createClient + : require('./integration_client').createClient + +Object.values(tests).forEach(test => test(createClient)) diff --git a/src/__test__/tests/blocks.query.test.ts b/src/__test__/tests/blocks.query.test.ts index f5fe4bc5..96834627 100644 --- a/src/__test__/tests/blocks.query.test.ts +++ b/src/__test__/tests/blocks.query.test.ts @@ -104,8 +104,10 @@ export function blocksTests (makeClient: () => Promise) { value address } + size totalOutput } + transactionsCount } }` }) @@ -122,19 +124,23 @@ export function blocksTests (makeClient: () => Promise) { aggregate { avg { fee + size totalOutput } count max { fee + size totalOutput } min { fee + size totalOutput } sum { fee + size totalOutput } } @@ -154,7 +160,7 @@ export function blocksTests (makeClient: () => Promise) { transactions_aggregate( where: { _and: [ - { fee: { _gt: 10 }}, + { fee: { _gt: "10" }}, { totalOutput: { _lt: "4924799478670" } } ] }) { diff --git a/src/__test__/tests/cardano.query.test.ts b/src/__test__/tests/cardano.query.test.ts index 0c6ccc5c..5fc987a6 100644 --- a/src/__test__/tests/cardano.query.test.ts +++ b/src/__test__/tests/cardano.query.test.ts @@ -17,6 +17,7 @@ export function cardanoTests (createClient: () => Promise) { currentEpoch { number } + networkName protocolConst slotDuration startTime diff --git a/src/__test__/tests/epochs.query.test.ts b/src/__test__/tests/epochs.query.test.ts index 1eec168d..6d07d986 100644 --- a/src/__test__/tests/epochs.query.test.ts +++ b/src/__test__/tests/epochs.query.test.ts @@ -63,7 +63,7 @@ export function epochTests (createClient: () => Promise) { const result = await client.query({ query: gql`query { epochs( where: { number: { _eq: 1 }}) { - blocks_aggregate ( where: { + blocks_aggregate ( where: { _and: [{ slotNo: { _is_null: false }, createdBy: { _eq: "SlotLeader-6c9e14978b9d6629" }, diff --git a/src/__test__/tests/transactions.query.test.ts b/src/__test__/tests/transactions.query.test.ts index 5ddabcfb..542d66ca 100644 --- a/src/__test__/tests/transactions.query.test.ts +++ b/src/__test__/tests/transactions.query.test.ts @@ -1,3 +1,4 @@ +import BigNumber from 'bignumber.js' import gql from 'graphql-tag' import { tx05ad8b, txe68043 } from '../data_assertions' import { TestClient } from '../TestClient' @@ -30,6 +31,7 @@ export function transactionTests (createClient: () => Promise) { address value } + size totalOutput } }` @@ -87,7 +89,8 @@ export function transactionTests (createClient: () => Promise) { expect(result.data.transactions.length).toBe(2) const { transactions: txs } = result.data expect(txs).toEqual([tx05ad8b.aggregated, txe68043.aggregated]) - expect(txs[1].inputs_aggregate.aggregate.sum.value).toEqual(txs[1].outputs_aggregate.aggregate.sum.value + parseInt(txs[1].fee)) + const outputsPlusFee = new BigNumber(txs[1].outputs_aggregate.aggregate.sum.value).plus(txs[1].fee).toString() + expect(txs[1].inputs_aggregate.aggregate.sum.value).toEqual(outputsPlusFee) expect(result.data).toMatchSnapshot() }) it('Can return filtered aggregated data', async () => { @@ -97,7 +100,7 @@ export function transactionTests (createClient: () => Promise) { where: { id: { _eq: \"${txe68043.aggregated_filtered.id}\"}} ) { id - inputs_aggregate ( where: { value: { _gt: 3842014 }}) { + inputs_aggregate ( where: { value: { _gt: "3842014" }}) { aggregate { count } diff --git a/src/__test__/tests/utxos.query.test.ts b/src/__test__/tests/utxos.query.test.ts index aaa07d65..fe664840 100644 --- a/src/__test__/tests/utxos.query.test.ts +++ b/src/__test__/tests/utxos.query.test.ts @@ -67,7 +67,7 @@ export function utxosTests (createClient: () => Promise) { } }` }) - expect(result.data.utxos_aggregate.aggregate.count).toBe(68) + expect(result.data.utxos_aggregate.aggregate.count).toBe('409') expect(result.data).toMatchSnapshot() }) }) diff --git a/src/resolvers/hasura_resolvers.ts b/src/resolvers/hasura_resolvers.ts index ed5df857..5503dd09 100644 --- a/src/resolvers/hasura_resolvers.ts +++ b/src/resolvers/hasura_resolvers.ts @@ -44,26 +44,14 @@ export const hasuraResolvers: Resolvers = { }) }, cardano: async (_root, _args, context, info) => { - // These two queries are very lightweight, just selecting single rows, - // Could optimise, but there's little performance gain - const cardanoResult = await delegateToSchema({ + const result = await delegateToSchema({ context, fieldName: 'Cardano', info, operation: 'query', schema: context.hasura }) - const metaResult = await delegateToSchema({ - context, - fieldName: 'Meta', - info, - operation: 'query', - schema: context.hasura - }) - return { - ...cardanoResult ? cardanoResult[0] : undefined, - ...metaResult ? metaResult[0] : undefined - } + return result[0] }, transactions: (_root, args, context, info) => { return delegateToSchema({ diff --git a/src/schema.graphql b/src/schema.graphql index 153952ec..62d53e17 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -33,7 +33,7 @@ type Query { offset: Int where: Epoch_bool_exp ): Epoch_aggregate! - cardano: Cardano + cardano: Cardano! transactions ( limit: Int order_by: [Transaction_order_by!] @@ -63,6 +63,7 @@ type Query { type Cardano { blockHeight: Int! currentEpoch: Epoch! + networkName: String! protocolConst: Int! slotDuration: Int! startTime: DateTime! @@ -70,7 +71,7 @@ type Cardano { type Transaction { block: Block - fee: String! + fee: BigInt! id: Hash32HexString! inputs ( limit: Int @@ -96,6 +97,7 @@ type Transaction { offset: Int where: Coin_bool_exp ): Coin_aggregate + size: BigInt! totalOutput: String! includedAt: DateTime! } @@ -104,6 +106,7 @@ input Transaction_order_by { block: order_by fee: order_by includedAt: order_by + size: order_by totalOutput: order_by } @@ -117,6 +120,7 @@ input Transaction_bool_exp { includedAt: Date_comparison_exp inputs: Coin_bool_exp outputs: Coin_bool_exp + size: BigInt_comparison_exp totalOutput: text_comparison_exp } @@ -125,31 +129,35 @@ type Transaction_aggregate { } type Transaction_aggregate_fields { - avg: Transaction_avg_fields - count: Int - max: Transaction_max_fields - min: Transaction_min_fields - sum: Transaction_sum_fields + avg: Transaction_avg_fields! + count: String! + max: Transaction_max_fields! + min: Transaction_min_fields! + sum: Transaction_sum_fields! } type Transaction_avg_fields { fee: Float + size: Float totalOutput: Float } type Transaction_max_fields { - fee: BigInt - totalOutput: BigInt + fee: String + size: String + totalOutput: String } type Transaction_min_fields { - fee: BigInt - totalOutput: BigInt + fee: String + size: String + totalOutput: String } type Transaction_sum_fields { - fee: BigInt - totalOutput: BigInt + fee: String + size: String + totalOutput: String } type TransactionInput { @@ -170,7 +178,7 @@ input Coin_bool_exp { _not: Coin_bool_exp _or: [Coin_bool_exp] address: text_comparison_exp - value: BigInt_comparison_exp + value: text_comparison_exp } type Coin_aggregate { @@ -178,27 +186,27 @@ type Coin_aggregate { } type Coin_aggregate_fields { - avg: Coin_avg_fields - count: Int - max: Coin_max_fields - min: Coin_min_fields - sum: Coin_sum_fields + avg: Coin_avg_fields! + count: String! + max: Coin_max_fields! + min: Coin_min_fields! + sum: Coin_sum_fields! } type Coin_avg_fields { - value: BigInt + value: String } type Coin_max_fields { - value: BigInt + value: String } type Coin_min_fields { - value: BigInt + value: String } type Coin_sum_fields { - value: BigInt + value: String } type TransactionOutput { @@ -213,11 +221,11 @@ type Utxo_aggregate { } type Utxo_aggregate_fields { - avg: Uxto_avg_fields - count: Int - max: Uxto_max_fields - min: Uxto_min_fields - sum: Uxto_sum_fields + avg: Uxto_avg_fields! + count: String! + max: Uxto_max_fields! + min: Uxto_min_fields! + sum: Uxto_sum_fields! } type Uxto_avg_fields { @@ -242,8 +250,8 @@ type Block { createdBy: String! # Genesis block does not belong to the 0th epoch, therefore it could be null epoch: Epoch - epochNo: Int! - fees: String! + epochNo: Int + fees: BigInt! id: Hash32HexString! # Ouroboros Classic Epoch Boundary blocks (EBB) do not have a merkel root merkelRootHash: Hash32HexString @@ -255,7 +263,7 @@ type Block { slotWithinEpoch: Int previousBlock: Block nextBlock: Block - size: Int! + size: BigInt! transactions( limit: Int order_by: [Transaction_order_by!] @@ -268,6 +276,7 @@ type Block { offset: Int where: Transaction_bool_exp ): Transaction_aggregate! + transactionsCount: String! } input Block_bool_exp { @@ -282,10 +291,11 @@ input Block_bool_exp { number: Int_comparison_exp previousBlock: Block_bool_exp nextBlock: Block_bool_exp - size: Int_comparison_exp + size: BigInt_comparison_exp slotNo: Int_comparison_exp slotWithinEpoch: Int_comparison_exp transactions: Transaction_bool_exp + transactionsCount: text_comparison_exp } input Block_order_by { @@ -297,6 +307,7 @@ input Block_order_by { size: order_by slotNo: order_by_with_nulls slotWithinEpoch: order_by_with_nulls + transactionsCount: order_by } type Block_aggregate { @@ -304,11 +315,11 @@ type Block_aggregate { } type Block_aggregate_fields { - avg: Block_avg_fields - count: Int - max: Block_max_fields - min: Block_min_fields - sum: Block_sum_fields + avg: Block_avg_fields! + count: String! + max: Block_max_fields! + min: Block_min_fields! + sum: Block_sum_fields! } type Block_avg_fields { @@ -317,18 +328,18 @@ type Block_avg_fields { } type Block_max_fields { - fees: BigInt - size: BigInt + fees: String + size: String } type Block_min_fields { - fees: BigInt - size: BigInt + fees: String + size: String } type Block_sum_fields { - fees: BigInt - size: BigInt + fees: String + size: String } type Epoch { @@ -379,7 +390,7 @@ type Epoch_aggregate_fields { } type Epoch_max_fields { - number: String! + number: Int! output: String! transactionsCount: String! } @@ -463,9 +474,9 @@ input Percentage_comparison_exp { _eq: Percentage _gt: Percentage _gte: Percentage - _lt: Int - _lte: Int - _neq: Int + _lt: Percentage + _lte: Percentage + _neq: Percentage } # All fields are combined with logical 'AND'. diff --git a/test/postgres/init/002_views.sql b/test/postgres/init/002_views.sql deleted file mode 100644 index 0b7b2c1c..00000000 --- a/test/postgres/init/002_views.sql +++ /dev/null @@ -1,144 +0,0 @@ --- Create all the views. - --- The views are always created because all views are deleted at the start ot the --- migration process. - --- Conventions: --- * VIEWs use TitleCase table names and camelCase columns for easy differentiation from tables. - --- The standard utxo view which shows all unspent transaction outputs. -create view "Utxo" as select - address, - value, - tx.hash as "txId", - index -from tx -join tx_out - on tx.id = tx_out.tx_id -left outer join tx_in - on tx_out.tx_id = tx_in.tx_out_id - and tx_out.index = tx_in.tx_out_index -where tx_in.tx_in_id is null; - -create view "TransactionOutput" as -select - address, - value, - tx.hash as "txId", - index -from tx -join tx_out - on tx.id = tx_out.tx_id; - -create view "TransactionInput" as -select - source_tx_out.address, - source_tx_out.value, - tx.hash as "txId", - source_tx.hash as "sourceTxId", - tx_in.tx_out_index as "sourceTxIndex" -from - tx -join tx_in - on tx_in.tx_in_id = tx.id -join tx_out as source_tx_out - on tx_in.tx_out_id = source_tx_out.tx_id - and tx_in.tx_out_index = source_tx_out.index -join tx as source_tx - on source_tx_out.tx_id = source_tx.id; - - -create view "Meta" as -select - slot_duration as "slotDuration", - start_time as "startTime", - protocol_const as "protocolConst" -from meta -limit 1; - -create view "Block" as -select - CAST(COALESCE((select sum(tx.fee) from tx where tx.block = block.id), 0) as integer) as "fees", - block."hash" as id, - 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, - -- this is written by the node-client and makes identification - -- of EBBs simpler, as EBBs don't have a slot_no - block.epoch_no as "epochNo", - block.slot_no as "slotNo", - case when block.slot_no > 0 - then block.slot_no - (block.epoch_no * (10 * (select protocol_const from meta))) - else 0 - end as "slotWithinEpoch", - block.time as "createdAt" -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; - -create view "Transaction" as -select - block.hash as "blockId", - COALESCE(tx.fee, 0) as fee, - tx.hash as id, - cast((select sum("value") from tx_out where tx_id = tx.id) as bigint) as "totalOutput", - block.time as "includedAt" -from - tx -inner join block - on block.id = tx.block; - -create view "Epoch" as -select - cast(sum(tx_out.value) as bigint) as output, - count(distinct tx.hash) as "transactionsCount", - block.epoch_no as "number", - min(block.time) as "startedAt", - max(block.time) as "lastBlockTime" -from block -join tx - on tx.block = block.id -join tx_out - on tx_out.tx_id = tx.id -where epoch_no is not null -group by block.epoch_no -order by block.epoch_no; - --- This function plays really nicely with Hasura, --- and allows us to query the utxo set at any block height --- https://docs.hasura.io/1.0/graphql/manual/queries/custom-functions.html -CREATE FUNCTION utxo_set_at_block("blockId" hash32type) -RETURNS SETOF "TransactionOutput" AS $$ - select - "TransactionOutput".address, - "TransactionOutput".value, - "TransactionOutput"."txId", - "TransactionOutput".index - from tx - join tx_out - on tx.id = tx_out.tx_id - join "TransactionOutput" - on tx.hash = "TransactionOutput"."txId" - left outer join tx_in - on tx_out.tx_id = tx_in.tx_out_id - and tx_out.index = tx_in.tx_out_index - where tx_in.tx_in_id is null - and tx.block <= (select id from block where hash = "blockId") -$$ LANGUAGE sql STABLE; - -create view "Cardano" as -select - number as "blockHeight", - "epochNo" as "currentEpochNo" -from "Block" -where number is not null -order by number desc -limit 1; \ No newline at end of file diff --git a/test/postgres/init/003_indices.info b/test/postgres/init/003_indices.info deleted file mode 100644 index ff9d6623..00000000 --- a/test/postgres/init/003_indices.info +++ /dev/null @@ -1,30 +0,0 @@ --- Part of the dump. Still need to be PR'd into cardano-explorer -CREATE INDEX idx_block_slot_no -ON block(slot_no); - -CREATE INDEX idx_block_block_no -ON block(block_no); - -CREATE INDEX idx_block_epoch_no -ON block(epoch_no); - -CREATE INDEX idx_block_previous -ON block(previous); - -CREATE INDEX idx_block_hash -ON block(hash); - -CREATE INDEX idx_tx_block -ON tx(block); - -CREATE INDEX idx_tx_hash -ON tx(hash); - -CREATE INDEX idx_tx_in_source_tx -ON tx_in(tx_in_id); - -CREATE INDEX idx_tx_in_consuming_tx -ON tx_in(tx_out_id); - -CREATE INDEX idx_tx_out_tx -ON tx_out(tx_id); diff --git a/test/postgres/init/cexplorer.pg_dump b/test/postgres/init/cexplorer.pg_dump index 4592d700..8ff8f380 100644 Binary files a/test/postgres/init/cexplorer.pg_dump and b/test/postgres/init/cexplorer.pg_dump differ diff --git a/test/postgres/refresh_dump.sh b/test/postgres/refresh_dump.sh new file mode 100644 index 00000000..72474f35 --- /dev/null +++ b/test/postgres/refresh_dump.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# To run this script, have the mainnet cardano-docker-stack running, and ensure the block height is above 70000 +# (Block height is most easily checked by checking the logs of explorer-node container) +docker exec -t --user postgres --workdir /var/lib/postgresql cardano-docker-stack_postgres_1 pg_dump -F c -d explorer -f cexplorer.pg_dump +docker cp cardano-docker-stack_postgres_1:/var/lib/postgresql/cexplorer.pg_dump test/postgres/init/cexplorer.pg_dump \ No newline at end of file diff --git a/wallaby.conf.js b/wallaby.conf.js index 63b6f271..ab166291 100644 --- a/wallaby.conf.js +++ b/wallaby.conf.js @@ -3,13 +3,16 @@ module.exports = function () { files: [ 'src/**/*.ts', 'src/**/*.graphql', - '!src/**/integration.test.ts' + '!src/**/suite.test.ts' ], tests: [ - 'src/**/integration.test.ts' + 'src/**/suite.test.ts' ], env: { + params: { + env: 'TEST_MODE=integration' + }, type: 'node' }, workers: { diff --git a/yarn.lock b/yarn.lock index 7d1b856f..06c0db8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,6 +2015,11 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" +bignumber.js@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" + integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"