diff --git a/Jenkinsfile b/Jenkinsfile index bbb1fc23..a7e4a0ce 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -24,7 +24,6 @@ pipeline { stage('Test') { steps { sh "CARDANO_GRAPHQL_VERSION=${env.GIT_COMMIT} yarn mainnet:stack" - sh "CARDANO_GRAPHQL_VERSION=${env.GIT_COMMIT} yarn mainnet_candidate_4:stack" sh 'sleep 15' sh 'TEST_MODE=e2e yarn workspaces run test --ci' } diff --git a/docker-compose.yml b/docker-compose.yml index fae652e3..0c18ef6c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,8 @@ services: - POSTGRES_DB_FILE=/run/secrets/postgres_db - POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password - POSTGRES_USER_FILE=/run/secrets/postgres_user + ports: + - ${POSTGRES_PORT:-5432}:5432 secrets: - postgres_db - postgres_password @@ -22,7 +24,7 @@ services: max-size: "200k" max-file: "10" cardano-node: - image: inputoutput/cardano-node:${CARDANO_NODE_VERSION:-1.18.0} + image: rhyslbw/cardano-node:${CARDANO_NODE_VERSION:-a4b6dae699fa21dc3c025c8a83d1718475cb3afc} command: [ "run", "--config", "/config/config.json", @@ -42,7 +44,7 @@ services: max-size: "400k" max-file: "20" cardano-db-sync-extended: - image: inputoutput/cardano-db-sync:${CARDANO_DB_SYNC_VERSION:-3.1.0} + image: inputoutput/cardano-db-sync:${CARDANO_DB_SYNC_VERSION:-36e7621fa5ecb4be923569f735b74d60a26da6c1} command: [ "--config", "/config/config.json", "--socket-path", "/node-ipc/node.socket" @@ -101,6 +103,7 @@ services: target: server image: inputoutput/cardano-graphql:${CARDANO_GRAPHQL_VERSION:-2.0.0} environment: + - ALLOW_INTROSPECTION=true - CACHE_ENABLED=true - GENESIS_FILE_BYRON=/genesis/byron.json - GENESIS_FILE_SHELLEY=/genesis/shelley.json @@ -115,6 +118,10 @@ services: ports: - ${API_PORT:-3100}:3100 restart: on-failure + secrets: + - postgres_db + - postgres_password + - postgres_user logging: driver: "json-file" options: diff --git a/nix/nixos/cardano-graphql-service.nix b/nix/nixos/cardano-graphql-service.nix index 03e5da86..c52598c6 100644 --- a/nix/nixos/cardano-graphql-service.nix +++ b/nix/nixos/cardano-graphql-service.nix @@ -9,6 +9,20 @@ in { services.cardano-graphql = { enable = lib.mkEnableOption "cardano-explorer graphql service"; + dbHost = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + }; + + dbPassword = lib.mkOption { + type = lib.types.str; + }; + + dbPort = lib.mkOption { + type = lib.types.int; + default = 5432; + }; + dbUser = lib.mkOption { type = lib.types.str; default = "cexplorer"; @@ -116,8 +130,12 @@ in { POOL_METADATA_PROXY = cfg.smashUrl; GENESIS_FILE_BYRON = cfg.genesisByron; GENESIS_FILE_SHELLEY = cfg.genesisShelley; - HASURA_URI = hasuraBaseUri; + POSTGRES_DB = cfg.db; + POSTGRES_HOST = cfg.dbHost; + POSTGRES_PASSWORD = cfg.dbPassword; + POSTGRES_PORT = cfg.dbPort; + POSTGRES_USER = cfg.dbUser; PROMETHEUS_METRICS = boolToNodeJSEnv cfg.enablePrometheus; TRACING = boolToNodeJSEnv (cfg.enableTracing || cfg.enablePrometheus); ALLOW_INTROSPECTION = boolToNodeJSEnv cfg.allowIntrospection; diff --git a/package.json b/package.json index c4d05013..f0db325a 100644 --- a/package.json +++ b/package.json @@ -11,21 +11,16 @@ "cleanup": "yarn workspaces run cleanup && shx rm -rf node_modules", "cli:install": "yarn workspace @cardano-graphql/cli global:add", "cli:uninstall": "yarn workspace @cardano-graphql/cli global:remove", - "mainnet:stack": "API_PORT=3100 HASURA_PORT=8090 NETWORK=mainnet docker-compose -p mainnet up --build -d", + "mainnet:stack": "API_PORT=3100 HASURA_PORT=8090 NETWORK=mainnet POSTGRES_PORT=5442 docker-compose -p mainnet up --build -d", "mainnet:up": "yarn mainnet:stack && docker-compose -p mainnet logs -f", - "mainnet:dev": "API_PORT=3100 HASURA_PORT=8090 NETWORK=mainnet yarn service-dependencies -p mainnet up --build", + "mainnet:dev": "API_PORT=3100 HASURA_PORT=8090 NETWORK=mainnet POSTGRES_PORT=5442 yarn service-dependencies -p mainnet up --build", "mainnet:down": "docker-compose -p mainnet down", - "mainnet:server": "API_PORT=3100 GENESIS_FILE_BYRON=${PWD}/config/network/mainnet/genesis/byron.json GENESIS_FILE_SHELLEY=${PWD}/config/network/mainnet/genesis/shelley.json HASURA_URI=http://localhost:8090 yarn workspace @cardano-graphql/server start", - "testnet:stack": "API_PORT=3101 HASURA_PORT=8091 NETWORK=testnet docker-compose -p testnet up --build -d", + "mainnet:server": "ALLOW_INTROSPECTION=true API_PORT=3100 GENESIS_FILE_BYRON=${PWD}/config/network/mainnet/genesis/byron.json GENESIS_FILE_SHELLEY=${PWD}/config/network/mainnet/genesis/shelley.json HASURA_URI=http://localhost:8090 POSTGRES_PORT=5442 yarn workspace @cardano-graphql/server start", + "testnet:stack": "API_PORT=3101 HASURA_PORT=8091 NETWORK=testnet POSTGRES_PORT=5443 docker-compose -p testnet up --build -d", "testnet:up": "yarn testnet:stack && docker-compose -p testnet logs -f", - "testnet:dev": "API_PORT=3101 HASURA_PORT=8091 NETWORK=testnet yarn service-dependencies -p testnet up --build", + "testnet:dev": "API_PORT=3101 HASURA_PORT=8091 NETWORK=testnet POSTGRES_PORT=5443 yarn service-dependencies -p testnet up --build", "testnet:down": "docker-compose -p testnet down", - "testnet:server": "API_PORT=3101 GENESIS_FILE_BYRON=${PWD}/config/network/testnet/genesis/byron.json GENESIS_FILE_SHELLEY=${PWD}/config/network/testnet/genesis/shelley.json HASURA_URI=http://localhost:8091 yarn workspace @cardano-graphql/server start", - "mainnet_candidate_4:stack": "API_PORT=3102 HASURA_PORT=8092 NETWORK=mainnet_candidate_4 docker-compose -p mainnet_candidate_4 up --build -d", - "mainnet_candidate_4:up": "yarn mainnet_candidate_4:stack && docker-compose -p mainnet_candidate_4 logs -f", - "mainnet_candidate_4:dev": "API_PORT=3102 HASURA_PORT=8092 NETWORK=mainnet_candidate_4 yarn service-dependencies -p mainnet_candidate_4 up --build", - "mainnet_candidate_4:down": "docker-compose -p mainnet_candidate_4 down", - "mainnet_candidate_4:server": "API_PORT=3102 GENESIS_FILE_BYRON=${PWD}/config/network/mainnet_candidate_4/genesis/byron.json GENESIS_FILE_SHELLEY=${PWD}/config/network/mainnet_candidate_4/genesis/shelley.json HASURA_URI=http://localhost:8092 yarn workspace @cardano-graphql/server start", + "testnet:server": "ALLOW_INTROSPECTION=true API_PORT=3101 GENESIS_FILE_BYRON=${PWD}/config/network/testnet/genesis/byron.json GENESIS_FILE_SHELLEY=${PWD}/config/network/testnet/genesis/shelley.json HASURA_URI=http://localhost:8091 POSTGRES_PORT=5443 yarn workspace @cardano-graphql/server start", "lint": "yarn workspaces run lint", "loadtest:byron-staging": "artillery run test/loadtest/byron-staging-config.yml", "publish-packages": "yarn workspaces run publish", @@ -58,6 +53,7 @@ "@types/lodash.set": "^4.3.6", "@types/node": "^14.0.13", "@types/node-fetch": "^2.5.7", + "@types/pg": "^7.14.4", "@types/set-interval-async": "^1.0.0", "@types/tmp": "^0.2.0", "@typescript-eslint/eslint-plugin": "^3.2.0", diff --git a/packages-cache/@babel-runtime-7.5.0.tgz b/packages-cache/@babel-runtime-7.5.0.tgz deleted file mode 100644 index 60ad6c42..00000000 Binary files a/packages-cache/@babel-runtime-7.5.0.tgz and /dev/null differ diff --git a/packages-cache/@types-pg-7.14.4.tgz b/packages-cache/@types-pg-7.14.4.tgz new file mode 100644 index 00000000..20297f01 Binary files /dev/null and b/packages-cache/@types-pg-7.14.4.tgz differ diff --git a/packages-cache/@types-pg-types-1.11.5.tgz b/packages-cache/@types-pg-types-1.11.5.tgz new file mode 100644 index 00000000..1ab49235 Binary files /dev/null and b/packages-cache/@types-pg-types-1.11.5.tgz differ diff --git a/packages-cache/buffer-writer-2.0.0.tgz b/packages-cache/buffer-writer-2.0.0.tgz new file mode 100644 index 00000000..e7230031 Binary files /dev/null and b/packages-cache/buffer-writer-2.0.0.tgz differ diff --git a/packages-cache/packet-reader-1.0.0.tgz b/packages-cache/packet-reader-1.0.0.tgz new file mode 100644 index 00000000..48f7abea Binary files /dev/null and b/packages-cache/packet-reader-1.0.0.tgz differ diff --git a/packages-cache/parse-json-4.0.0.tgz b/packages-cache/parse-json-4.0.0.tgz new file mode 100644 index 00000000..d353c1b8 Binary files /dev/null and b/packages-cache/parse-json-4.0.0.tgz differ diff --git a/packages-cache/pg-8.3.0.tgz b/packages-cache/pg-8.3.0.tgz new file mode 100644 index 00000000..c4083ac9 Binary files /dev/null and b/packages-cache/pg-8.3.0.tgz differ diff --git a/packages-cache/pg-connection-string-2.3.0.tgz b/packages-cache/pg-connection-string-2.3.0.tgz new file mode 100644 index 00000000..c29e60cf Binary files /dev/null and b/packages-cache/pg-connection-string-2.3.0.tgz differ diff --git a/packages-cache/pg-format-1.0.4.tgz b/packages-cache/pg-format-1.0.4.tgz new file mode 100644 index 00000000..3201e69d Binary files /dev/null and b/packages-cache/pg-format-1.0.4.tgz differ diff --git a/packages-cache/pg-int8-1.0.1.tgz b/packages-cache/pg-int8-1.0.1.tgz new file mode 100644 index 00000000..753b781d Binary files /dev/null and b/packages-cache/pg-int8-1.0.1.tgz differ diff --git a/packages-cache/pg-listen-1.6.0.tgz b/packages-cache/pg-listen-1.6.0.tgz new file mode 100644 index 00000000..a009b2ca Binary files /dev/null and b/packages-cache/pg-listen-1.6.0.tgz differ diff --git a/packages-cache/pg-pool-3.2.1.tgz b/packages-cache/pg-pool-3.2.1.tgz new file mode 100644 index 00000000..fd29f797 Binary files /dev/null and b/packages-cache/pg-pool-3.2.1.tgz differ diff --git a/packages-cache/pg-protocol-1.2.5.tgz b/packages-cache/pg-protocol-1.2.5.tgz new file mode 100644 index 00000000..70f15e1b Binary files /dev/null and b/packages-cache/pg-protocol-1.2.5.tgz differ diff --git a/packages-cache/pg-types-2.2.0.tgz b/packages-cache/pg-types-2.2.0.tgz new file mode 100644 index 00000000..ce1531d0 Binary files /dev/null and b/packages-cache/pg-types-2.2.0.tgz differ diff --git a/packages-cache/pgpass-1.0.2.tgz b/packages-cache/pgpass-1.0.2.tgz new file mode 100644 index 00000000..8c92cac9 Binary files /dev/null and b/packages-cache/pgpass-1.0.2.tgz differ diff --git a/packages-cache/postgres-array-2.0.0.tgz b/packages-cache/postgres-array-2.0.0.tgz new file mode 100644 index 00000000..38a04a62 Binary files /dev/null and b/packages-cache/postgres-array-2.0.0.tgz differ diff --git a/packages-cache/postgres-bytea-1.0.0.tgz b/packages-cache/postgres-bytea-1.0.0.tgz new file mode 100644 index 00000000..620fd8fb Binary files /dev/null and b/packages-cache/postgres-bytea-1.0.0.tgz differ diff --git a/packages-cache/postgres-date-1.0.5.tgz b/packages-cache/postgres-date-1.0.5.tgz new file mode 100644 index 00000000..4f588511 Binary files /dev/null and b/packages-cache/postgres-date-1.0.5.tgz differ diff --git a/packages-cache/postgres-interval-1.2.0.tgz b/packages-cache/postgres-interval-1.2.0.tgz new file mode 100644 index 00000000..044586fa Binary files /dev/null and b/packages-cache/postgres-interval-1.2.0.tgz differ diff --git a/packages-cache/semver-4.3.2.tgz b/packages-cache/semver-4.3.2.tgz new file mode 100644 index 00000000..6a8fcd30 Binary files /dev/null and b/packages-cache/semver-4.3.2.tgz differ diff --git a/packages-cache/set-interval-async-1.0.33.tgz b/packages-cache/set-interval-async-1.0.33.tgz deleted file mode 100644 index 244fcbf6..00000000 Binary files a/packages-cache/set-interval-async-1.0.33.tgz and /dev/null differ diff --git a/packages-cache/split-1.0.1.tgz b/packages-cache/split-1.0.1.tgz new file mode 100644 index 00000000..2a871f3f Binary files /dev/null and b/packages-cache/split-1.0.1.tgz differ diff --git a/packages-cache/typed-emitter-0.1.0.tgz b/packages-cache/typed-emitter-0.1.0.tgz new file mode 100644 index 00000000..a44a7d25 Binary files /dev/null and b/packages-cache/typed-emitter-0.1.0.tgz differ diff --git a/packages/api-cardano-db-hasura/hasura/project/migrations/1589369664961_init/up.sql b/packages/api-cardano-db-hasura/hasura/project/migrations/1589369664961_init/up.sql index a0fd57b6..0bca2456 100644 --- a/packages/api-cardano-db-hasura/hasura/project/migrations/1589369664961_init/up.sql +++ b/packages/api-cardano-db-hasura/hasura/project/migrations/1589369664961_init/up.sql @@ -34,7 +34,7 @@ CREATE VIEW "Delegation" AS SELECT delegation.id AS "id", ( - SELECT stake_address.hash + SELECT stake_address.view FROM stake_address WHERE stake_address.id = delegation.addr_id ) AS "address", @@ -63,7 +63,7 @@ SELECT reward.amount AS "amount", reward.id AS "id", ( - SELECT stake_address.hash + SELECT stake_address.view FROM stake_address WHERE stake_address.id = reward.addr_id ) AS "address", @@ -82,7 +82,7 @@ CREATE VIEW "StakeDeregistration" AS SELECT stake_deregistration.id AS "id", ( - SELECT stake_address.hash + SELECT stake_address.view FROM stake_address WHERE stake_address.id = stake_deregistration.addr_id ) AS "address", @@ -107,7 +107,7 @@ SELECT block.block_no AS "blockNo", pool.registered_tx_id AS "updated_in_tx_id", pool.pledge AS "pledge", - ( SELECT stake_address.hash FROM stake_address WHERE stake_address.id = pool.reward_addr_id) AS "rewardAddress", + ( SELECT stake_address.view FROM stake_address WHERE stake_address.id = pool.reward_addr_id) AS "rewardAddress", pool_meta_data.url AS "url" FROM pool_update AS pool INNER JOIN pool_meta_data ON pool.meta = pool_meta_data.id @@ -119,7 +119,7 @@ CREATE VIEW "StakeRegistration" AS SELECT stake_registration.id AS "id", ( - SELECT stake_address.hash + SELECT stake_address.view FROM stake_address WHERE stake_address.id = stake_registration.addr_id ) AS "address", @@ -186,7 +186,7 @@ SELECT withdrawal.amount AS "amount", withdrawal.id AS "id", ( - SELECT stake_address.hash + SELECT stake_address.view FROM stake_address WHERE stake_address.id = withdrawal.addr_id ) AS "address", diff --git a/packages/api-cardano-db-hasura/package.json b/packages/api-cardano-db-hasura/package.json index 3a23986a..b419ad01 100644 --- a/packages/api-cardano-db-hasura/package.json +++ b/packages/api-cardano-db-hasura/package.json @@ -47,7 +47,8 @@ "graphql-bigint": "^1.0.0", "graphql-scalars": "^1.2.1", "p-retry": "^4.2.0", - "set-interval-async": "^1.0.33" + "pg": "^8.3.0", + "pg-listen": "^1.6.0" }, "devDependencies": { "@cardano-graphql/util-dev": "2.0.0", diff --git a/packages/api-cardano-db-hasura/src/Config.ts b/packages/api-cardano-db-hasura/src/Config.ts new file mode 100644 index 00000000..f32cbb6b --- /dev/null +++ b/packages/api-cardano-db-hasura/src/Config.ts @@ -0,0 +1,11 @@ + +export interface Config { + db: { + database: string, + host: string, + password: string, + port: number + user: string, + }, + hasuraUri: string +} diff --git a/packages/api-cardano-db-hasura/src/Db.ts b/packages/api-cardano-db-hasura/src/Db.ts index 8150f7e6..5eaad0c1 100644 --- a/packages/api-cardano-db-hasura/src/Db.ts +++ b/packages/api-cardano-db-hasura/src/Db.ts @@ -1,113 +1,48 @@ -import { ApolloClient, gql, InMemoryCache, NormalizedCacheObject } from 'apollo-boost' -import { createHttpLink } from 'apollo-link-http' -import fetch from 'cross-fetch' -import utc from 'dayjs/plugin/utc' -import dayjs from 'dayjs' -import { exec } from 'child_process' -import { clearIntervalAsync, setIntervalAsync, SetIntervalAsyncTimer } from 'set-interval-async/dynamic' -import path from 'path' -import pRetry from 'p-retry' -import util from '@cardano-graphql/util' - -dayjs.extend(utc) +import { ClientConfig } from 'pg' +import createSubscriber, { Subscriber } from 'pg-listen' export class Db { - hasuraClient: ApolloClient - hasuraUri: string - monitorTimer: SetIntervalAsyncTimer + pgSubscriber: Subscriber - constructor (hasuraUri: string) { - this.hasuraUri = hasuraUri - this.hasuraClient = new ApolloClient({ - cache: new InMemoryCache({ - addTypename: false - }), - defaultOptions: { - query: { - fetchPolicy: 'network-only' - } - }, - link: createHttpLink({ - uri: `${this.hasuraUri}/v1/graphql`, - fetch, - headers: { - 'X-Hasura-Role': 'cardano-graphql' - } - }) + constructor (pgClientConfig: ClientConfig) { + this.pgSubscriber = createSubscriber(pgClientConfig, { + parse: (value) => value }) } - public async init (): Promise { - // Todo: optimal solution dependent on https://github.com/input-output-hk/cardano-db-sync/issues/182 - await this.applySchemaAndMetadata() - this.monitorDbState() - } - - public async shutdown () { - await clearIntervalAsync(this.monitorTimer) - } - - private monitorDbState () { - this.monitorTimer = setIntervalAsync( - async () => { - try { - await this.getMeta() - } catch (error) { - if (error.message === 'GraphQL error: field "cardano" not found in type: \'query_root\'' || error.message === 'GraphQL error: database query error') { - console.warn('Re-applying PostgreSQL migrations and Hasura metadata') - await this.applySchemaAndMetadata() - } else { - console.error(error) - } - } - }, - 10000 - ) - } - - async getMeta () { - const result = await this.hasuraClient.query({ - query: gql`query { - cardano { - tip { - forgedAt - } - }}` + public async init ({ onDbSetup }: { onDbSetup: Function }): Promise { + this.pgSubscriber.events.on('connected', async () => { + console.log('DbClient.pgSubscriber: Connected') + await onDbSetup() }) - const { tip } = result.data?.cardano[0] - const currentUtc = dayjs().utc() - const tipUtc = dayjs.utc(tip.forgedAt) - return { - initialized: tipUtc.isAfter(currentUtc.subtract(120, 'second')), - syncPercentage: (tipUtc.valueOf() / currentUtc.valueOf()) * 100 - } - } - - public async applySchemaAndMetadata () { - await pRetry(async () => { - await this.hasuraCli('migrate apply --down all') - await this.hasuraCli('migrate apply --up all') - await this.hasuraCli('metadata clear') - await this.hasuraCli('metadata apply') - }, { - factor: 1.75, - retries: 9, - onFailedAttempt: util.onFailedAttemptFor('Applying PostgreSQL schema and Hasura metadata') + this.pgSubscriber.events.on('reconnect', (attempt) => { + console.warn(`DbClient.pgSubscriber: Reconnecting attempt ${attempt}`) + }) + this.pgSubscriber.events.on('error', (error) => { + console.error('DbClient.pgSubscriber: Fatal database connection error:', error) + process.exit(1) }) + this.pgSubscriber.notifications.on('cardano_db_sync_startup', async payload => { + switch (payload) { + case 'init' : + console.log('DbClient.pgSubscriber: cardano-db-sync-extended starting, schema will be reset') + break + case 'db-setup' : + await onDbSetup() + break + default : + console.error(`DbClient.pgSubscriber: Unknown message payload ${payload}`) + } + }) + try { + await this.pgSubscriber.connect() + await this.pgSubscriber.listenTo('cardano_db_sync_startup') + } catch (error) { + console.error(error) + } } - private hasuraCli (command: string) { - return new Promise((resolve, reject) => { - exec( - `hasura --skip-update-check --project ${path.resolve(__dirname, '..', 'hasura', 'project')} --endpoint ${this.hasuraUri} ${command}`, - (error, stdout) => { - if (error) { - reject(error) - } - console.log(stdout) - resolve() - } - ) - }) + public async shutdown () { + await this.pgSubscriber.close() } } diff --git a/packages/api-cardano-db-hasura/src/HasuraClient.ts b/packages/api-cardano-db-hasura/src/HasuraClient.ts new file mode 100644 index 00000000..5d8f17b4 --- /dev/null +++ b/packages/api-cardano-db-hasura/src/HasuraClient.ts @@ -0,0 +1,110 @@ +import { ApolloClient, gql, InMemoryCache, NormalizedCacheObject } from 'apollo-boost' +import { createHttpLink } from 'apollo-link-http' +import util from '@cardano-graphql/util' +import { exec } from 'child_process' +import fetch from 'cross-fetch' +import dayjs from 'dayjs' +import utc from 'dayjs/plugin/utc' +import { DocumentNode, print } from 'graphql' +import { introspectSchema, wrapSchema } from '@graphql-tools/wrap' +import pRetry from 'p-retry' +import path from 'path' + +dayjs.extend(utc) + +export class HasuraClient { + private client: ApolloClient + readonly hasuraUri: string + + constructor (hasuraUri: string) { + this.hasuraUri = hasuraUri + this.client = new ApolloClient({ + cache: new InMemoryCache({ + addTypename: false + }), + defaultOptions: { + query: { + fetchPolicy: 'network-only' + } + }, + link: createHttpLink({ + uri: `${this.hasuraUri}/v1/graphql`, + fetch, + headers: { + 'X-Hasura-Role': 'cardano-graphql' + } + }) + }) + } + + public async applySchemaAndMetadata () { + await pRetry(async () => { + await this.hasuraCli('migrate apply --down all') + await this.hasuraCli('migrate apply --up all') + await this.hasuraCli('metadata clear') + await this.hasuraCli('metadata apply') + }, { + factor: 1.75, + retries: 9, + onFailedAttempt: util.onFailedAttemptFor('Applying PostgreSQL schema and Hasura metadata') + }) + } + + public async buildHasuraSchema () { + const executor = async ({ document, variables }: { document: DocumentNode, variables?: Object }) => { + const query = print(document) + try { + const fetchResult = await fetch(`${this.hasuraUri}/v1/graphql`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Hasura-Role': 'cardano-graphql' + }, + body: JSON.stringify({ query, variables }) + }) + return fetchResult.json() + } catch (error) { + console.error(error) + throw error + } + } + + return wrapSchema({ + schema: await introspectSchema(executor), + executor + }) + } + + public async getMeta () { + const result = await this.client.query({ + query: gql`query { + cardano { + tip { + forgedAt + } + }}` + }) + const { tip } = result.data?.cardano[0] + const currentUtc = dayjs().utc() + const tipUtc = dayjs.utc(tip.forgedAt) + return { + initialized: tipUtc.isAfter(currentUtc.subtract(120, 'second')), + syncPercentage: (tipUtc.valueOf() / currentUtc.valueOf()) * 100 + } + } + + async hasuraCli (command: string) { + return new Promise((resolve, reject) => { + exec( + `hasura --skip-update-check --project ${path.resolve(__dirname, '..', 'hasura', 'project')} --endpoint ${this.hasuraUri} ${command}`, + (error, stdout) => { + if (error) { + reject(error) + } + console.log(stdout) + resolve() + } + ) + }) + } +} diff --git a/packages/api-cardano-db-hasura/src/buildHasuraSchema.ts b/packages/api-cardano-db-hasura/src/buildHasuraSchema.ts deleted file mode 100644 index 79cc3dd0..00000000 --- a/packages/api-cardano-db-hasura/src/buildHasuraSchema.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { fetch } from 'cross-fetch' -import { introspectSchema, wrapSchema } from '@graphql-tools/wrap' -import { DocumentNode, print } from 'graphql' - -export async function buildHasuraSchema (hasuraUri: string) { - const executor = async ({ document, variables }: { document: DocumentNode, variables?: Object }) => { - const query = print(document) - try { - const fetchResult = await fetch(`${hasuraUri}/v1/graphql`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Hasura-Role': 'cardano-graphql' - }, - body: JSON.stringify({ query, variables }) - }) - return fetchResult.json() - } catch (error) { - console.error(error) - throw error - } - } - - return wrapSchema({ - schema: await introspectSchema(executor), - executor - }) -} diff --git a/packages/api-cardano-db-hasura/src/example_queries/epochs/aggregateDataWithinEpoch.graphql b/packages/api-cardano-db-hasura/src/example_queries/epochs/aggregateDataWithinEpoch.graphql index 6d3c7c9d..bf19469c 100644 --- a/packages/api-cardano-db-hasura/src/example_queries/epochs/aggregateDataWithinEpoch.graphql +++ b/packages/api-cardano-db-hasura/src/example_queries/epochs/aggregateDataWithinEpoch.graphql @@ -3,7 +3,7 @@ query aggregatedDataWithinEpoch ( ) { epochs( where: { number: { _eq: $number }}) { blocksCount - blocks_aggregate ( where: { slotNo: { _is_null: false }}) { + blocks_aggregate { aggregate { avg { fees diff --git a/packages/api-cardano-db-hasura/src/executableSchema.ts b/packages/api-cardano-db-hasura/src/executableSchema.ts index e8b7a63d..72bf4d97 100644 --- a/packages/api-cardano-db-hasura/src/executableSchema.ts +++ b/packages/api-cardano-db-hasura/src/executableSchema.ts @@ -2,13 +2,12 @@ import fs from 'fs' import { ApolloError } from 'apollo-server' import { makeExecutableSchema } from '@graphql-tools/schema' import { delegateToSchema } from '@graphql-tools/delegate' -import { GraphQLSchema } from 'graphql' import pRetry from 'p-retry' import path from 'path' import util from '@cardano-graphql/util' -import { buildHasuraSchema } from './buildHasuraSchema' -import { Db } from './Db' import { Resolvers } from './graphql_types' +import { HasuraClient } from './HasuraClient' +import { GraphQLSchema } from 'graphql' const GraphQLBigInt = require('graphql-bigint') @@ -19,10 +18,10 @@ export const scalarResolvers = { Percentage: util.scalars.Percentage } as any -export async function buildSchema (hasuraUri: string, db: Db) { +export async function buildSchema (hasuraClient: HasuraClient) { let hasuraSchema: GraphQLSchema await pRetry(async () => { - hasuraSchema = await buildHasuraSchema(hasuraUri) + hasuraSchema = await hasuraClient.buildHasuraSchema() }, { factor: 1.75, retries: 9, @@ -66,7 +65,7 @@ export async function buildSchema (hasuraUri: string, db: Db) { }, cardanoDbMeta: async () => { try { - return db.getMeta() + return hasuraClient.getMeta() } catch (error) { throw new ApolloError(error) } diff --git a/packages/api-cardano-db-hasura/src/index.ts b/packages/api-cardano-db-hasura/src/index.ts index 55849875..4f011de3 100644 --- a/packages/api-cardano-db-hasura/src/index.ts +++ b/packages/api-cardano-db-hasura/src/index.ts @@ -1,3 +1,5 @@ +export * from './Config' export * from './Db' export * from './executableSchema' export * from './graphql_types' +export * from './HasuraClient' diff --git a/packages/api-cardano-db-hasura/src/util.ts b/packages/api-cardano-db-hasura/src/util.ts new file mode 100644 index 00000000..be658143 --- /dev/null +++ b/packages/api-cardano-db-hasura/src/util.ts @@ -0,0 +1,11 @@ +import { Config } from './Config' +import fs from 'fs-extra' +import path from 'path' + +export async function readSecrets (rootDir: string): Promise> { + return { + database: (await fs.readFile(path.join(rootDir, 'postgres_db'), 'utf8')).toString(), + password: (await fs.readFile(path.join(rootDir, 'postgres_password'), 'utf8')).toString(), + user: (await fs.readFile(path.join(rootDir, 'postgres_user'), 'utf8')).toString() + } +} diff --git a/packages/api-cardano-db-hasura/test/__snapshots__/epochs.query.test.ts.snap b/packages/api-cardano-db-hasura/test/__snapshots__/epochs.query.test.ts.snap index 68603d8c..0e3c7900 100644 --- a/packages/api-cardano-db-hasura/test/__snapshots__/epochs.query.test.ts.snap +++ b/packages/api-cardano-db-hasura/test/__snapshots__/epochs.query.test.ts.snap @@ -27,17 +27,17 @@ exports[`epochs Can return aggregated data 1`] = ` Object { "epochs": Array [ Object { - "blocksCount": "21589", + "blocksCount": "21590", "blocks_aggregate": Object { "aggregate": Object { "avg": Object { - "fees": 47848.56538051786, - "size": 838.0591968131919, + "fees": 47846.34914312181, + "size": 868.0383047707272, }, - "count": "21589", + "count": "21590", "max": Object { "fees": "1377042", - "size": "4787", + "size": "648087", }, "min": Object { "fees": "0", @@ -45,7 +45,7 @@ Object { }, "sum": Object { "fees": "1033002678", - "size": "18092860", + "size": "18740947", }, }, }, @@ -74,11 +74,11 @@ exports[`epochs Returns epoch details by number 1`] = ` Object { "epochs": Array [ Object { - "blocksCount": "21589", - "lastBlockTime": "2017-10-03T21:43:51Z", + "blocksCount": "21590", + "lastBlockTime": "2017-10-03T21:44:31Z", "number": 1, "output": "101402912214214220", - "startedAt": "2017-09-28T21:45:51Z", + "startedAt": "2017-09-28T21:44:51Z", "transactionsCount": "12870", }, ], @@ -89,11 +89,11 @@ exports[`epochs Returns epoch details by number range 1`] = ` Object { "epochs": Array [ Object { - "blocksCount": "21589", - "lastBlockTime": "2017-10-03T21:43:51Z", + "blocksCount": "21590", + "lastBlockTime": "2017-10-03T21:44:31Z", "number": 1, "output": "101402912214214220", - "startedAt": "2017-09-28T21:45:51Z", + "startedAt": "2017-09-28T21:44:51Z", "transactionsCount": "12870", }, ], diff --git a/packages/api-cardano-db-hasura/test/blocks.query.test.ts b/packages/api-cardano-db-hasura/test/blocks.query.test.ts index 92453fdc..f48e9d1a 100644 --- a/packages/api-cardano-db-hasura/test/blocks.query.test.ts +++ b/packages/api-cardano-db-hasura/test/blocks.query.test.ts @@ -13,7 +13,7 @@ function loadQueryNode (name: string): Promise { describe('blocks', () => { let client: TestClient beforeAll(async () => { - client = await buildClient('http://localhost:3100', 'http://localhost:8090') + client = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) }, 60000) it('caps the response to 100 blocks', async () => { diff --git a/packages/api-cardano-db-hasura/test/cardano.query.test.ts b/packages/api-cardano-db-hasura/test/cardano.query.test.ts index 90279790..d0d368e4 100644 --- a/packages/api-cardano-db-hasura/test/cardano.query.test.ts +++ b/packages/api-cardano-db-hasura/test/cardano.query.test.ts @@ -12,7 +12,7 @@ function loadQueryNode (name: string): Promise { describe('cardano', () => { let client: TestClient beforeAll(async () => { - client = await buildClient('http://localhost:3100', 'http://localhost:8090') + client = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) }, 60000) it('Returns core information about the current state of the network', async () => { diff --git a/packages/api-cardano-db-hasura/test/data_assertions/epoch_assertions.ts b/packages/api-cardano-db-hasura/test/data_assertions/epoch_assertions.ts index a07c9e68..2ca9035c 100644 --- a/packages/api-cardano-db-hasura/test/data_assertions/epoch_assertions.ts +++ b/packages/api-cardano-db-hasura/test/data_assertions/epoch_assertions.ts @@ -1,24 +1,24 @@ export const epoch1 = { basic: { - startedAt: '2017-09-28T21:45:51Z', - blocksCount: '21589', - lastBlockTime: '2017-10-03T21:43:51Z', + startedAt: '2017-09-28T21:44:51Z', + blocksCount: '21590', + lastBlockTime: '2017-10-03T21:44:31Z', output: '101402912214214220', number: 1, transactionsCount: '12870' }, aggregated: { - blocksCount: '21589', + blocksCount: '21590', blocks_aggregate: { aggregate: { avg: { - fees: 47848.56538051786, - size: 838.0591968131919 + fees: 47846.34914312181, + size: 868.0383047707272 }, - count: '21589', + count: '21590', max: { fees: '1377042', - size: '4787' + size: '648087' }, min: { fees: '0', @@ -26,7 +26,7 @@ export const epoch1 = { }, sum: { fees: '1033002678', - size: '18092860' + size: '18740947' } } }, diff --git a/packages/api-cardano-db-hasura/test/epochs.query.test.ts b/packages/api-cardano-db-hasura/test/epochs.query.test.ts index 430cf103..56756ece 100644 --- a/packages/api-cardano-db-hasura/test/epochs.query.test.ts +++ b/packages/api-cardano-db-hasura/test/epochs.query.test.ts @@ -14,7 +14,7 @@ function loadQueryNode (name: string): Promise { describe('epochs', () => { let client: TestClient beforeAll(async () => { - client = await buildClient('http://localhost:3100', 'http://localhost:8090') + client = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) }, 60000) it('Returns epoch details by number', async () => { diff --git a/packages/api-cardano-db-hasura/test/shelley.query.test.ts b/packages/api-cardano-db-hasura/test/shelley.query.test.ts index e9e96c5f..012a28ac 100644 --- a/packages/api-cardano-db-hasura/test/shelley.query.test.ts +++ b/packages/api-cardano-db-hasura/test/shelley.query.test.ts @@ -13,8 +13,8 @@ describe('Shelley era queries', () => { let mainnetClient: TestClient let mc4Client: TestClient beforeAll(async () => { - mainnetClient = await buildClient('http://localhost:3100', 'http://localhost:8090') - mc4Client = await buildClient('http://localhost:3102', 'http://localhost:8092') + mainnetClient = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) + mc4Client = await buildClient('http://localhost:3102', 'http://localhost:8092', 5444) }, 15000) it('will not throw errors during the Byron era', async () => { diff --git a/packages/api-cardano-db-hasura/test/shelley.query.test.ts.txt b/packages/api-cardano-db-hasura/test/shelley.query.test.ts.txt new file mode 100644 index 00000000..b725045f --- /dev/null +++ b/packages/api-cardano-db-hasura/test/shelley.query.test.ts.txt @@ -0,0 +1,1153 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Shelley era queries Shelley era smoke test 1`] = ` +Object { + "delegations": Array [ + Object { + "address": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe1279cf18e075b222f093746f4f9cad980fd3fc5fcc5f69decef4f9ee9", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe191f35028792a55b4ad9746f22e1e11cdc283cf6b9bdba6bf70de8d57", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe177c471153f77eae747be09eb2540daccf4160eeec813a8fa3aa0edde", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe124735ff745a56705a0dfb6e849319c647f4b9510a7866c45e7efb706", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe1aa983a9d8267ac89224040e58c845e2049ff53059293886dec55021c", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + ], + "delegations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "25682", + "max": null, + "sum": null, + }, + }, + "stakeDeregistrations": Array [], + "stakeDeregistrations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "0", + "max": null, + "sum": null, + }, + }, + "stakePools": Array [ + Object { + "fixedCost": "340000000", + "hash": "153806dbcd134ddee69a8c5204e38ac80448f62342f8c23cfe4b7edf", + "margin": 0.015, + "metadataHash": "ca7d12decf886e31f5226b5946c62edc81a7e40af95ce7cd6465122e309d5626", + "owners": Array [ + Object { + "hash": "0e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + }, + ], + "pledge": "450000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "54.220.20.40", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "updatedIn": Object { + "hash": "841cca81da918feb9fa7257a34630eac95794be712ed3faae6df64f215ce25f2", + }, + "url": "https://raw.githubusercontent.com/Octalus/cardano/master/p.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735", + "margin": 0.049, + "metadataHash": "47c0c68cb57f4a5b4a87bad896fc274678e7aea98e200fa14a1cb40c0cab1d8c", + "owners": Array [ + Object { + "hash": "4f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + }, + ], + "pledge": "510000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "updatedIn": Object { + "hash": "a96c79773b7506211eb56bf94886a2face17657d1009f52fb5ea05f19cc8823e", + }, + "url": "https://stakenuts.com/mainnet.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "c1ede3cc9133209466774d4826044e408db13d6fe6df751a73500f16", + "margin": 0.02, + "metadataHash": "1b2a3015cb4901241f398a6e1703c7f74a6362344a470c9904c8f045a1b56ba0", + "owners": Array [ + Object { + "hash": "3b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + }, + ], + "pledge": "501000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "updatedIn": Object { + "hash": "37f5682e2622c821175bab9d5637b7321ecacc5ec6636f69c77e68ea915831ca", + }, + "url": "https://metadata.zenithpool.io", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "01df29429173d263c7533a22742dae19f16a08798b7a57873c34cf58", + "margin": 0.02, + "metadataHash": "4e03bf5d4734b9c0857943c94630c43446941d0a505058cb03c7c5deabfb5122", + "owners": Array [ + Object { + "hash": "8d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + }, + ], + "pledge": "50000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "78.47.141.62", + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "95.217.220.249", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe18d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + "updatedIn": Object { + "hash": "e8951eddb19b697bc74549aa9d4f956a8be8d5cf2c7a8e13878b8e785b1b0499", + }, + "url": "https://data.pooltool.io/md/6e5dcfbc-7f73-406e-b9ab-78fd7cbed7c5", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "6b6164af70861c5537cc9c8e50fdae35139ca2c8c6fbb42e8b7e6bfb", + "margin": 0.05, + "metadataHash": "79e7cf8d936bf0ced040516b288e2edc76f2f87af5400f92010a682de3a052e9", + "owners": Array [ + Object { + "hash": "8c8eaf655c2a64b49ead3b937309121222f6d8747fa5657c0550e0d4", + }, + ], + "pledge": "3300000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "139.162.148.181", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe15ca7f050cb2c6ce98154ffb04a43c4aa866134d3d6ce278c1e241331", + "updatedIn": Object { + "hash": "0e57b977f762ff907a026f7c13fb6ceb28266e5fa3c0c9dfe76e780df7b44006", + }, + "url": "https://pool.adascan.net/meta/v1/poolmeta.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "00000036d515e12e18cd3c88c74f09a67984c2c279a5296aa96efe89", + "margin": 0.02, + "metadataHash": "f86369a042b696530a9fb6f900e09b6e232511f29652d49f6d1d871d2569558b", + "owners": Array [ + Object { + "hash": "03a6539a5570f39319582af64c80e4b3874369ddc8a41065d833d440", + }, + Object { + "hash": "03faca8b32f93db7f8a6716330d87d63a5ea911c14d4ed1e2a233530", + }, + Object { + "hash": "2de39242b5fe6bcf85fcf9216691d7a78297ebcbbf81e3f6927a53e2", + }, + Object { + "hash": "3d8c7608966b4bbdf513a14d5961f4d989d96cc8a98f6aed3d67aeea", + }, + Object { + "hash": "62393dbf2e9acad56e6f501aa99d4ca40a613efe7466e029be3e3808", + }, + Object { + "hash": "ca91e316db3a696ba48ffce1f89eb20de50e205ae7709851ea341b9d", + }, + Object { + "hash": "df74d77e7e5942cfc74924c7ef261713062265edb0c702ef8d90cd24", + }, + ], + "pledge": "2500000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1876c8abaa636168c7d43623be103c6bfffcfb0337c05ffd1a7ea72e5", + "updatedIn": Object { + "hash": "cc59d4f15db2b8a526db013653500ab33ed55b7cda04f8106f8b63928187df3f", + }, + "url": "https://stakepool.at/atada.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "6ec027701fa6c9f4a593f7e7108cb2f5af54361080f7bed1c835349d", + "margin": 0.03, + "metadataHash": "f9d5e977d38c1eb387cfdec0677284d11a3f9129855b542bd332d636f9bd7bbf", + "owners": Array [], + "pledge": "1100000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe10ab602b5afd9672c5fefc019d21076709eaf4941b77eee97e42fbee2", + "updatedIn": Object { + "hash": "bacd140908ba8153d772cebe88879c00ad36025cab988203b0a2d560ddad3628", + }, + "url": "https://tinyurl.com/y3aryqrz", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "8a1ab06f3a8c823b7111955c287efbe3c96ad9a68aa2359832e0bc30", + "margin": 0.036, + "metadataHash": "588db1c310d430bd4ee12a39eeda3e845fb9cae3fd92ec32a119a3ba2136b2d8", + "owners": Array [], + "pledge": "168000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1d1c53050b2a78d5e01bf1b7fc43aef37e9b685ec812414417bf8c360", + "updatedIn": Object { + "hash": "9af898c1a3f4bd8832894e7a08e425d48dd6fbe91051d0e953635a3d3d454063", + }, + "url": "http://dezent.online/deznt.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "00beef0a9be2f6d897ed24a613cf547bb20cd282a04edfc53d477114", + "margin": 0.02, + "metadataHash": "1ee5e93ad103da84fa67622a3c3be025fd89ec61acc959dbe4b3b1117d39a37e", + "owners": Array [ + Object { + "hash": "f8d85dee99bffa2b5c68d591423d64b0940b6efc767ca94713efbc8d", + }, + ], + "pledge": "250000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1f8d85dee99bffa2b5c68d591423d64b0940b6efc767ca94713efbc8d", + "updatedIn": Object { + "hash": "fce1cb9a1e8f81577d135b93cc4bac312eb98c7eb47fd27d6ab1581e78b37762", + }, + "url": "https://bluecheesestakehouse.com/bcsh.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "d2f12c2f3094ed0784f048fe93a62d8b061525b356e043be084470d9", + "margin": 0.01, + "metadataHash": "f742e03daefb083d86a71c4dc757e43752742844b0a9bc3cbada2d9e70ec13ef", + "owners": Array [ + Object { + "hash": "d853d271c977461596bf596d70cd23931f517da74ad12339a3c9b554", + }, + ], + "pledge": "850000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "45.83.107.139", + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "45.83.107.231", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1d853d271c977461596bf596d70cd23931f517da74ad12339a3c9b554", + "updatedIn": Object { + "hash": "f55a0ac35bc2b4eaa1b4fc17606812abcce4fa0855072455a48d204411907cb2", + }, + "url": "https://tap-ada.at/poolmeta.json", + "withdrawals": null, + }, + ], + "stakePools_aggregate": Object { + "aggregate": Object { + "avg": Object { + "margin": 0.0332090204326923, + }, + "count": "832", + "max": Object { + "margin": 1, + }, + "sum": Object { + "margin": 27.629905, + }, + }, + }, + "stakeRegistrations": Array [ + Object { + "address": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "transaction": Object { + "hash": "f3a0835d9359ed79f8301ba61ff263188c180ffd6dfddaba60a7e31b8366c38e", + }, + }, + Object { + "address": "\\\\xe18d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + "transaction": Object { + "hash": "46df1a1fae460ff92e614201693512fac1ed207fbf7c0c37acff01edcf4754ad", + }, + }, + Object { + "address": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "transaction": Object { + "hash": "af5cc722a027dd49619121f227d16a6b0c5808a398c83be6d6e36836d4ac3fcc", + }, + }, + Object { + "address": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "transaction": Object { + "hash": "91f88c21679fdc95cb0712dc8a755eab20fdf9e919871c3c668515c830572090", + }, + }, + Object { + "address": "\\\\xe1279cf18e075b222f093746f4f9cad980fd3fc5fcc5f69decef4f9ee9", + "transaction": Object { + "hash": "f0024159d124a128db522031c4a3e7b255ee511600afa92ff52b2504702e4e1d", + }, + }, + Object { + "address": "\\\\xe191f35028792a55b4ad9746f22e1e11cdc283cf6b9bdba6bf70de8d57", + "transaction": Object { + "hash": "23c4d82ab647314f583f05b3bf9826bcffc6f0283764ca58c1f9e95e084b8e36", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "transaction": Object { + "hash": "3485af236ba4776a95cefe5d6b4400dff6129c5753521e3774a950766c3c8359", + }, + }, + Object { + "address": "\\\\xe1a246e742fd9fd4f89eff61bf38fcd6bdf9de180e65563d8787d53349", + "transaction": Object { + "hash": "ce11d00bca68cead221f784e1b55db02327ea1dbaef0b914a47eadc70ae6536d", + }, + }, + Object { + "address": "\\\\xe177c471153f77eae747be09eb2540daccf4160eeec813a8fa3aa0edde", + "transaction": Object { + "hash": "017f0406afc8522b10ff954deaba38f96d2bf02ab5e4b75fd95b87ef4842d45d", + }, + }, + Object { + "address": "\\\\xe124735ff745a56705a0dfb6e849319c647f4b9510a7866c45e7efb706", + "transaction": Object { + "hash": "9b0bbb8d281cccc6282f97b0eb427be950fea3adb91775c87dd27a7491509316", + }, + }, + ], + "stakeRegistrations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "42742", + "max": null, + "sum": null, + }, + }, + "withdrawals": Array [ + Object { + "address": "\\\\xe1558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001", + "amount": "14520198574", + "transaction": Object { + "hash": "2383af0582da2b18039fab49ef4bb246f7d23d4304e36eb48f9387ff80adc769", + }, + }, + Object { + "address": "\\\\xe1951d0aa8a8ea112e74668ab3124a2035d8e600a1aa1ac1662347df0a", + "amount": "228007595115", + "transaction": Object { + "hash": "e89e7039c4fb14807c626a4ebbe197f2b76b14d370dba18660ca16915b392e2a", + }, + }, + Object { + "address": "\\\\xe1da26b6ac8fd112c9d818bed11fd37c455a36aed78972fb9e6cfe73cf", + "amount": "225299733749", + "transaction": Object { + "hash": "03f78e316fa9a9336d8af35e662aedf5082b2ea1a4b909a69cbf57e454d268a0", + }, + }, + Object { + "address": "\\\\xe1777c9b83eb57b1b9f838132089c34dca6d2c8c556d1f6807664f6b51", + "amount": "84700372786", + "transaction": Object { + "hash": "7c8cbb2c7d8db56fc20f765869a08f2a79c4838f7f3aef6e12138957251eb0df", + }, + }, + Object { + "address": "\\\\xe1f2a2445639e43998d9bf4c85b88025e51b24ef551ce87246239e1979", + "amount": "175238386633", + "transaction": Object { + "hash": "bf1d3b3711558daf6930cf788c489af54655b2466ebc0ea0c462717f774579fb", + }, + }, + Object { + "address": "\\\\xe12e9ef637f4de66086cf23f51d1a55523ea1f767d03e6428ed0c953b4", + "amount": "32767550107", + "transaction": Object { + "hash": "0703502c90f8985d2ea75a9777e245361c14271ca6b3ce27fe045c9f608b4f54", + }, + }, + Object { + "address": "\\\\xe164a78878a5b12455cd20a64a6052b1fe5466f6617b253a2083b7bd5f", + "amount": "284886079252", + "transaction": Object { + "hash": "72fd6855bec11cb01dd88bf7406acfcc7ee35e412f7b6c5de2f584bad4cc3135", + }, + }, + Object { + "address": "\\\\xe1989e76cc6ba2beb98331c0fd31635a76815c5cee49cd84a5b481b3c0", + "amount": "608989246", + "transaction": Object { + "hash": "96afbe9662be24d1d2f7a44d8b666fee76d7298c583b508370fe5c933dd27095", + }, + }, + Object { + "address": "\\\\xe13dba4a74e83ee788873b6bc6981de867a2b1aa803e7e4966d91adbee", + "amount": "53147254809", + "transaction": Object { + "hash": "004ddc25cffaf702416200c9186db9b9c1cb42dff0e8c1ac46cb5994bfc27e93", + }, + }, + Object { + "address": "\\\\xe18a5c067dc29ca48cb83f2eb2714c246bf4b8bc913796065c5761a7dc", + "amount": "241318351211", + "transaction": Object { + "hash": "a93a7200e3e52ca9bb43212a6ef876c08ef5cf7dc828ee41a21a1abfdd1a4e7f", + }, + }, + ], +} +`; + +exports[`Shelley era queries will not throw errors during the Byron era 1`] = ` +Object { + "delegations": Array [ + Object { + "address": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe1279cf18e075b222f093746f4f9cad980fd3fc5fcc5f69decef4f9ee9", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe191f35028792a55b4ad9746f22e1e11cdc283cf6b9bdba6bf70de8d57", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe177c471153f77eae747be09eb2540daccf4160eeec813a8fa3aa0edde", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe124735ff745a56705a0dfb6e849319c647f4b9510a7866c45e7efb706", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + Object { + "address": "\\\\xe1aa983a9d8267ac89224040e58c845e2049ff53059293886dec55021c", + "stakePool": Object { + "fixedCost": "340000000", + }, + }, + ], + "delegations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "25682", + "max": null, + "sum": null, + }, + }, + "stakeDeregistrations": Array [], + "stakeDeregistrations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "0", + "max": null, + "sum": null, + }, + }, + "stakePools": Array [ + Object { + "fixedCost": "340000000", + "hash": "153806dbcd134ddee69a8c5204e38ac80448f62342f8c23cfe4b7edf", + "margin": 0.015, + "metadataHash": "ca7d12decf886e31f5226b5946c62edc81a7e40af95ce7cd6465122e309d5626", + "owners": Array [ + Object { + "hash": "0e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + }, + ], + "pledge": "450000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "54.220.20.40", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "updatedIn": Object { + "hash": "841cca81da918feb9fa7257a34630eac95794be712ed3faae6df64f215ce25f2", + }, + "url": "https://raw.githubusercontent.com/Octalus/cardano/master/p.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735", + "margin": 0.049, + "metadataHash": "47c0c68cb57f4a5b4a87bad896fc274678e7aea98e200fa14a1cb40c0cab1d8c", + "owners": Array [ + Object { + "hash": "4f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + }, + ], + "pledge": "510000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "updatedIn": Object { + "hash": "a96c79773b7506211eb56bf94886a2face17657d1009f52fb5ea05f19cc8823e", + }, + "url": "https://stakenuts.com/mainnet.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "c1ede3cc9133209466774d4826044e408db13d6fe6df751a73500f16", + "margin": 0.02, + "metadataHash": "1b2a3015cb4901241f398a6e1703c7f74a6362344a470c9904c8f045a1b56ba0", + "owners": Array [ + Object { + "hash": "3b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + }, + ], + "pledge": "501000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "updatedIn": Object { + "hash": "37f5682e2622c821175bab9d5637b7321ecacc5ec6636f69c77e68ea915831ca", + }, + "url": "https://metadata.zenithpool.io", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "01df29429173d263c7533a22742dae19f16a08798b7a57873c34cf58", + "margin": 0.02, + "metadataHash": "4e03bf5d4734b9c0857943c94630c43446941d0a505058cb03c7c5deabfb5122", + "owners": Array [ + Object { + "hash": "8d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + }, + ], + "pledge": "50000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "78.47.141.62", + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "95.217.220.249", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe18d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + "updatedIn": Object { + "hash": "e8951eddb19b697bc74549aa9d4f956a8be8d5cf2c7a8e13878b8e785b1b0499", + }, + "url": "https://data.pooltool.io/md/6e5dcfbc-7f73-406e-b9ab-78fd7cbed7c5", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "6b6164af70861c5537cc9c8e50fdae35139ca2c8c6fbb42e8b7e6bfb", + "margin": 0.05, + "metadataHash": "79e7cf8d936bf0ced040516b288e2edc76f2f87af5400f92010a682de3a052e9", + "owners": Array [ + Object { + "hash": "8c8eaf655c2a64b49ead3b937309121222f6d8747fa5657c0550e0d4", + }, + ], + "pledge": "3300000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "139.162.148.181", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe15ca7f050cb2c6ce98154ffb04a43c4aa866134d3d6ce278c1e241331", + "updatedIn": Object { + "hash": "0e57b977f762ff907a026f7c13fb6ceb28266e5fa3c0c9dfe76e780df7b44006", + }, + "url": "https://pool.adascan.net/meta/v1/poolmeta.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "00000036d515e12e18cd3c88c74f09a67984c2c279a5296aa96efe89", + "margin": 0.02, + "metadataHash": "f86369a042b696530a9fb6f900e09b6e232511f29652d49f6d1d871d2569558b", + "owners": Array [ + Object { + "hash": "03a6539a5570f39319582af64c80e4b3874369ddc8a41065d833d440", + }, + Object { + "hash": "03faca8b32f93db7f8a6716330d87d63a5ea911c14d4ed1e2a233530", + }, + Object { + "hash": "2de39242b5fe6bcf85fcf9216691d7a78297ebcbbf81e3f6927a53e2", + }, + Object { + "hash": "3d8c7608966b4bbdf513a14d5961f4d989d96cc8a98f6aed3d67aeea", + }, + Object { + "hash": "62393dbf2e9acad56e6f501aa99d4ca40a613efe7466e029be3e3808", + }, + Object { + "hash": "ca91e316db3a696ba48ffce1f89eb20de50e205ae7709851ea341b9d", + }, + Object { + "hash": "df74d77e7e5942cfc74924c7ef261713062265edb0c702ef8d90cd24", + }, + ], + "pledge": "2500000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1876c8abaa636168c7d43623be103c6bfffcfb0337c05ffd1a7ea72e5", + "updatedIn": Object { + "hash": "cc59d4f15db2b8a526db013653500ab33ed55b7cda04f8106f8b63928187df3f", + }, + "url": "https://stakepool.at/atada.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "6ec027701fa6c9f4a593f7e7108cb2f5af54361080f7bed1c835349d", + "margin": 0.03, + "metadataHash": "f9d5e977d38c1eb387cfdec0677284d11a3f9129855b542bd332d636f9bd7bbf", + "owners": Array [], + "pledge": "1100000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe10ab602b5afd9672c5fefc019d21076709eaf4941b77eee97e42fbee2", + "updatedIn": Object { + "hash": "bacd140908ba8153d772cebe88879c00ad36025cab988203b0a2d560ddad3628", + }, + "url": "https://tinyurl.com/y3aryqrz", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "8a1ab06f3a8c823b7111955c287efbe3c96ad9a68aa2359832e0bc30", + "margin": 0.036, + "metadataHash": "588db1c310d430bd4ee12a39eeda3e845fb9cae3fd92ec32a119a3ba2136b2d8", + "owners": Array [], + "pledge": "168000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1d1c53050b2a78d5e01bf1b7fc43aef37e9b685ec812414417bf8c360", + "updatedIn": Object { + "hash": "9af898c1a3f4bd8832894e7a08e425d48dd6fbe91051d0e953635a3d3d454063", + }, + "url": "http://dezent.online/deznt.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "00beef0a9be2f6d897ed24a613cf547bb20cd282a04edfc53d477114", + "margin": 0.02, + "metadataHash": "1ee5e93ad103da84fa67622a3c3be025fd89ec61acc959dbe4b3b1117d39a37e", + "owners": Array [ + Object { + "hash": "f8d85dee99bffa2b5c68d591423d64b0940b6efc767ca94713efbc8d", + }, + ], + "pledge": "250000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": null, + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1f8d85dee99bffa2b5c68d591423d64b0940b6efc767ca94713efbc8d", + "updatedIn": Object { + "hash": "fce1cb9a1e8f81577d135b93cc4bac312eb98c7eb47fd27d6ab1581e78b37762", + }, + "url": "https://bluecheesestakehouse.com/bcsh.metadata.json", + "withdrawals": null, + }, + Object { + "fixedCost": "340000000", + "hash": "d2f12c2f3094ed0784f048fe93a62d8b061525b356e043be084470d9", + "margin": 0.01, + "metadataHash": "f742e03daefb083d86a71c4dc757e43752742844b0a9bc3cbada2d9e70ec13ef", + "owners": Array [ + Object { + "hash": "d853d271c977461596bf596d70cd23931f517da74ad12339a3c9b554", + }, + ], + "pledge": "850000000000", + "relays": Array [ + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "45.83.107.139", + "ipv6": null, + }, + Object { + "dnsName": null, + "dnsSrvName": null, + "ipv4": "45.83.107.231", + "ipv6": null, + }, + ], + "retirement": null, + "rewardAddress": "\\\\xe1d853d271c977461596bf596d70cd23931f517da74ad12339a3c9b554", + "updatedIn": Object { + "hash": "f55a0ac35bc2b4eaa1b4fc17606812abcce4fa0855072455a48d204411907cb2", + }, + "url": "https://tap-ada.at/poolmeta.json", + "withdrawals": null, + }, + ], + "stakePools_aggregate": Object { + "aggregate": Object { + "avg": Object { + "margin": 0.0332090204326923, + }, + "count": "832", + "max": Object { + "margin": 1, + }, + "sum": Object { + "margin": 27.629905, + }, + }, + }, + "stakeRegistrations": Array [ + Object { + "address": "\\\\xe10e5b086df87a2a0c5c398b41d413f84176c527da5e5cb641f4598844", + "transaction": Object { + "hash": "f3a0835d9359ed79f8301ba61ff263188c180ffd6dfddaba60a7e31b8366c38e", + }, + }, + Object { + "address": "\\\\xe18d0ea87fb33ca385998da1eb4fd8d3347ff3a86c90eebf796934c096", + "transaction": Object { + "hash": "46df1a1fae460ff92e614201693512fac1ed207fbf7c0c37acff01edcf4754ad", + }, + }, + Object { + "address": "\\\\xe14f39feccb595162d892abd1e03d80de8e76b8a2015139430e032b2be", + "transaction": Object { + "hash": "af5cc722a027dd49619121f227d16a6b0c5808a398c83be6d6e36836d4ac3fcc", + }, + }, + Object { + "address": "\\\\xe13b8e0f979e635ad352bf982e60bf23c60d9bb3e14550889f23f422d5", + "transaction": Object { + "hash": "91f88c21679fdc95cb0712dc8a755eab20fdf9e919871c3c668515c830572090", + }, + }, + Object { + "address": "\\\\xe1279cf18e075b222f093746f4f9cad980fd3fc5fcc5f69decef4f9ee9", + "transaction": Object { + "hash": "f0024159d124a128db522031c4a3e7b255ee511600afa92ff52b2504702e4e1d", + }, + }, + Object { + "address": "\\\\xe191f35028792a55b4ad9746f22e1e11cdc283cf6b9bdba6bf70de8d57", + "transaction": Object { + "hash": "23c4d82ab647314f583f05b3bf9826bcffc6f0283764ca58c1f9e95e084b8e36", + }, + }, + Object { + "address": "\\\\xe15ed4a0f3e25416845b16bbde8f5bcc8f7125172d972ebcfd7f0f6e76", + "transaction": Object { + "hash": "3485af236ba4776a95cefe5d6b4400dff6129c5753521e3774a950766c3c8359", + }, + }, + Object { + "address": "\\\\xe1a246e742fd9fd4f89eff61bf38fcd6bdf9de180e65563d8787d53349", + "transaction": Object { + "hash": "ce11d00bca68cead221f784e1b55db02327ea1dbaef0b914a47eadc70ae6536d", + }, + }, + Object { + "address": "\\\\xe177c471153f77eae747be09eb2540daccf4160eeec813a8fa3aa0edde", + "transaction": Object { + "hash": "017f0406afc8522b10ff954deaba38f96d2bf02ab5e4b75fd95b87ef4842d45d", + }, + }, + Object { + "address": "\\\\xe124735ff745a56705a0dfb6e849319c647f4b9510a7866c45e7efb706", + "transaction": Object { + "hash": "9b0bbb8d281cccc6282f97b0eb427be950fea3adb91775c87dd27a7491509316", + }, + }, + ], + "stakeRegistrations_aggregate": Object { + "aggregate": Object { + "avg": null, + "count": "42742", + "max": null, + "sum": null, + }, + }, + "withdrawals": Array [ + Object { + "address": "\\\\xe1558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001", + "amount": "14520198574", + "transaction": Object { + "hash": "2383af0582da2b18039fab49ef4bb246f7d23d4304e36eb48f9387ff80adc769", + }, + }, + Object { + "address": "\\\\xe1951d0aa8a8ea112e74668ab3124a2035d8e600a1aa1ac1662347df0a", + "amount": "228007595115", + "transaction": Object { + "hash": "e89e7039c4fb14807c626a4ebbe197f2b76b14d370dba18660ca16915b392e2a", + }, + }, + Object { + "address": "\\\\xe1da26b6ac8fd112c9d818bed11fd37c455a36aed78972fb9e6cfe73cf", + "amount": "225299733749", + "transaction": Object { + "hash": "03f78e316fa9a9336d8af35e662aedf5082b2ea1a4b909a69cbf57e454d268a0", + }, + }, + Object { + "address": "\\\\xe1777c9b83eb57b1b9f838132089c34dca6d2c8c556d1f6807664f6b51", + "amount": "84700372786", + "transaction": Object { + "hash": "7c8cbb2c7d8db56fc20f765869a08f2a79c4838f7f3aef6e12138957251eb0df", + }, + }, + Object { + "address": "\\\\xe1f2a2445639e43998d9bf4c85b88025e51b24ef551ce87246239e1979", + "amount": "175238386633", + "transaction": Object { + "hash": "bf1d3b3711558daf6930cf788c489af54655b2466ebc0ea0c462717f774579fb", + }, + }, + Object { + "address": "\\\\xe12e9ef637f4de66086cf23f51d1a55523ea1f767d03e6428ed0c953b4", + "amount": "32767550107", + "transaction": Object { + "hash": "0703502c90f8985d2ea75a9777e245361c14271ca6b3ce27fe045c9f608b4f54", + }, + }, + Object { + "address": "\\\\xe164a78878a5b12455cd20a64a6052b1fe5466f6617b253a2083b7bd5f", + "amount": "284886079252", + "transaction": Object { + "hash": "72fd6855bec11cb01dd88bf7406acfcc7ee35e412f7b6c5de2f584bad4cc3135", + }, + }, + Object { + "address": "\\\\xe1989e76cc6ba2beb98331c0fd31635a76815c5cee49cd84a5b481b3c0", + "amount": "608989246", + "transaction": Object { + "hash": "96afbe9662be24d1d2f7a44d8b666fee76d7298c583b508370fe5c933dd27095", + }, + }, + Object { + "address": "\\\\xe13dba4a74e83ee788873b6bc6981de867a2b1aa803e7e4966d91adbee", + "amount": "53147254809", + "transaction": Object { + "hash": "004ddc25cffaf702416200c9186db9b9c1cb42dff0e8c1ac46cb5994bfc27e93", + }, + }, + Object { + "address": "\\\\xe18a5c067dc29ca48cb83f2eb2714c246bf4b8bc913796065c5761a7dc", + "amount": "241318351211", + "transaction": Object { + "hash": "a93a7200e3e52ca9bb43212a6ef876c08ef5cf7dc828ee41a21a1abfdd1a4e7f", + }, + }, + ], +} +`; diff --git a/packages/api-cardano-db-hasura/test/transactions.query.test.ts b/packages/api-cardano-db-hasura/test/transactions.query.test.ts index bffeaad0..ab5f0c39 100644 --- a/packages/api-cardano-db-hasura/test/transactions.query.test.ts +++ b/packages/api-cardano-db-hasura/test/transactions.query.test.ts @@ -15,8 +15,8 @@ describe('transactions', () => { let mainnetClient: TestClient let mc4Client: TestClient beforeAll(async () => { - mainnetClient = await buildClient('http://localhost:3100', 'http://localhost:8090') - mc4Client = await buildClient('http://localhost:3102', 'http://localhost:8092') + mainnetClient = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) + mc4Client = await buildClient('http://localhost:3102', 'http://localhost:8092', 5444) }, 60000) it('Returns transactions by hashes', async () => { diff --git a/packages/api-cardano-db-hasura/test/util.ts b/packages/api-cardano-db-hasura/test/util.ts index 668d4c75..35863e33 100644 --- a/packages/api-cardano-db-hasura/test/util.ts +++ b/packages/api-cardano-db-hasura/test/util.ts @@ -4,8 +4,12 @@ import { Db } from '@src/Db' import pRetry from 'p-retry' import { gql } from 'apollo-boost' import util from '@cardano-graphql/util' +import { HasuraClient } from '@src/HasuraClient' +import path from 'path' +import { readSecrets } from '@src/util' +import { Config } from '@src/Config' -export async function buildClient (apiUri: string, hasuraUri: string) { +export async function buildClient (apiUri: string, hasuraUri: Config['hasuraUri'], dbPort: Config['db']['port']) { if (process.env.TEST_MODE === 'e2e') { const client = await utilDev.createE2EClient(apiUri) await pRetry(async () => { @@ -25,9 +29,15 @@ export async function buildClient (apiUri: string, hasuraUri: string) { }) return client } else { - const db = new Db(hasuraUri) - await db.init() - const schema = await buildSchema(hasuraUri, db) + const hasuraClient = new HasuraClient(hasuraUri) + const db = new Db({ + ...{ host: 'localhost', port: dbPort }, + ...await readSecrets(path.resolve(__dirname, '..', '..', '..', 'config', 'secrets')) + }) + await db.init({ + onDbSetup: hasuraClient.applySchemaAndMetadata.bind(hasuraClient) + }) + const schema = await buildSchema(hasuraClient) return utilDev.createIntegrationClient(schema) } } diff --git a/packages/api-cardano-db-hasura/test/utxos.query.test.ts b/packages/api-cardano-db-hasura/test/utxos.query.test.ts index aa8d3102..ee439483 100644 --- a/packages/api-cardano-db-hasura/test/utxos.query.test.ts +++ b/packages/api-cardano-db-hasura/test/utxos.query.test.ts @@ -16,7 +16,7 @@ function loadTestOperationDocument (name: string): Promise { describe('utxos', () => { let client: TestClient beforeAll(async () => { - client = await buildClient('http://localhost:3100', 'http://localhost:8090') + client = await buildClient('http://localhost:3100', 'http://localhost:8090', 5442) }, 60000) it('Can be scoped by address', async () => { diff --git a/packages/server/package.json b/packages/server/package.json index 9f7c5d37..f5c3b764 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -10,7 +10,7 @@ "lint": "eslint --ignore-path ../../.eslintignore \"**/*.ts\"", "prepack": "yarn build", "prestart": "yarn build", - "start": "node dist/index.js", + "start": "POSTGRES_DB_FILE=../../config/secrets/postgres_db POSTGRES_HOST=localhost POSTGRES_USER_FILE=../../config/secrets/postgres_user POSTGRES_PASSWORD_FILE=../../config/secrets/postgres_password node dist/index.js", "test": "yarn build && NODE_ENV=test jest -c ./test/jest.config.js" }, "repository": { diff --git a/packages/server/src/CompleteApiServer.ts b/packages/server/src/CompleteApiServer.ts index 5c94bf79..a5448e66 100644 --- a/packages/server/src/CompleteApiServer.ts +++ b/packages/server/src/CompleteApiServer.ts @@ -1,6 +1,6 @@ import { Config } from './config' import { Server } from './Server' -import { buildSchema as buildCardanoDbHasuraSchema, Db } from '@cardano-graphql/api-cardano-db-hasura' +import { buildSchema as buildCardanoDbHasuraSchema, Db, HasuraClient } from '@cardano-graphql/api-cardano-db-hasura' import { buildSchema as buildGenesisSchema } from '@cardano-graphql/api-genesis' import { GraphQLSchema } from 'graphql' @@ -15,9 +15,12 @@ export async function CompleteApiServer (config: Config): Promise { })) } if (config.hasuraUri !== undefined) { - const db = new Db(config.hasuraUri) - await db.init() - schemas.push(await buildCardanoDbHasuraSchema(config.hasuraUri, db)) + const hasuraClient = new HasuraClient(config.hasuraUri) + const db = new Db(config.db) + await db.init({ + onDbSetup: hasuraClient.applySchemaAndMetadata.bind(hasuraClient) + }) + schemas.push(await buildCardanoDbHasuraSchema(hasuraClient)) } return new Server(schemas, config) } diff --git a/packages/server/src/config.ts b/packages/server/src/config.ts index a694264d..86470737 100644 --- a/packages/server/src/config.ts +++ b/packages/server/src/config.ts @@ -1,10 +1,11 @@ +import { Config as ApiCardanoDbHasuraConfig } from '@cardano-graphql/api-cardano-db-hasura' import { MissingConfig } from './errors' +import fs from 'fs-extra' import { Config as ServerConfig } from './Server' -export type Config = ServerConfig & { +export type Config = ServerConfig & ApiCardanoDbHasuraConfig & { genesisFileByron: string genesisFileShelley: string - hasuraUri: string } export async function getConfig (): Promise { @@ -17,6 +18,14 @@ export async function getConfig (): Promise { genesisFileByron, genesisFileShelley, hasuraUri, + postgresDb, + postgresDbFile, + postgresHost, + postgresPassword, + postgresPasswordFile, + postgresPort, + postgresUser, + postgresUserFile, prometheusMetrics, queryDepthLimit, tracing @@ -28,6 +37,33 @@ export async function getConfig (): Promise { GENESIS_FILE_SHELLEY and GENESIS_FILE_SHELLEY` ) } + if (!postgresDbFile && !postgresDb) { + throw new MissingConfig('POSTGRES_DB_FILE or POSTGRES_DB env not set') + } + if (!postgresHost) { + throw new MissingConfig('POSTGRES_HOST env not set') + } + if (!postgresPasswordFile && !postgresPassword) { + throw new MissingConfig('POSTGRES_PASSWORD_FILE or POSTGRES_PASSWORD env not set') + } + if (!postgresPort) { + throw new MissingConfig('POSTGRES_PORT env not set') + } + if (!postgresUserFile && !postgresUser) { + throw new MissingConfig('POSTGRES_USER_FILE or POSTGRES_USER env not set') + } + let db: Config['db'] + try { + db = { + database: postgresDb || (await fs.readFile(postgresDbFile, 'utf8')).toString(), + host: postgresHost, + password: postgresPassword || (await fs.readFile(postgresPasswordFile, 'utf8')).toString(), + port: postgresPort, + user: postgresUser || (await fs.readFile(postgresUserFile, 'utf8')).toString() + } + } catch (error) { + throw new MissingConfig('Database configuration cannot be read') + } return { allowIntrospection: (process.env.NODE_ENV === 'production' && allowIntrospection) || @@ -36,6 +72,7 @@ export async function getConfig (): Promise { allowListPath, apiPort: apiPort || 3100, cacheEnabled: cacheEnabled || false, + db, genesisFileByron, genesisFileShelley, hasuraUri, @@ -55,6 +92,14 @@ function filterAndTypecastEnvs (env: any) { GENESIS_FILE_BYRON, GENESIS_FILE_SHELLEY, HASURA_URI, + POSTGRES_DB, + POSTGRES_DB_FILE, + POSTGRES_HOST, + POSTGRES_PASSWORD, + POSTGRES_PASSWORD_FILE, + POSTGRES_PORT, + POSTGRES_USER, + POSTGRES_USER_FILE, PROMETHEUS_METRICS, QUERY_DEPTH_LIMIT, TRACING, @@ -73,6 +118,14 @@ function filterAndTypecastEnvs (env: any) { genesisFileByron: GENESIS_FILE_BYRON, genesisFileShelley: GENESIS_FILE_SHELLEY, hasuraUri: HASURA_URI, + postgresDb: POSTGRES_DB, + postgresDbFile: POSTGRES_DB_FILE, + postgresHost: POSTGRES_HOST, + postgresPassword: POSTGRES_PASSWORD, + postgresPasswordFile: POSTGRES_PASSWORD_FILE, + postgresPort: Number(POSTGRES_PORT), + postgresUser: POSTGRES_USER, + postgresUserFile: POSTGRES_USER_FILE, prometheusMetrics: PROMETHEUS_METRICS === 'true', queryDepthLimit: Number(QUERY_DEPTH_LIMIT), tracing: TRACING === 'true' diff --git a/yarn.lock b/yarn.lock index 426e3988..c0bb02bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -507,13 +507,6 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.0.tgz#49dcbcd637099a55d3a61e590a00d6861393b1b5" - integrity sha512-2xsuyZ0R0RBFwjgae5NpXk8FcfH4qovj5cEM5VEeB7KXnKqzaisIu2HSV/mCEISolJJuR4wkViUGYujA8MH9tw== - dependencies: - regenerator-runtime "^0.13.2" - "@babel/runtime@^7.0.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" @@ -1479,6 +1472,19 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/pg-types@*": + version "1.11.5" + resolved "https://registry.yarnpkg.com/@types/pg-types/-/pg-types-1.11.5.tgz#1eebbe62b6772fcc75c18957a90f933d155e005b" + integrity sha512-L8ogeT6vDzT1vxlW3KITTCt+BVXXVkLXfZ/XNm6UqbcJgxf+KPO7yjWx7dQQE8RW07KopL10x2gNMs41+IkMGQ== + +"@types/pg@^7.14.4": + version "7.14.4" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-7.14.4.tgz#15cfcfd9300f94fd44e6191a1b0ba18d2de209f6" + integrity sha512-yCKVMCcFPZSFHGg+8qjY368uf3ruyDBPjxvOU2ZcGa/vRFo5Ti5Y6z6vl+2hxtwm9VMWUGb6TWkIk3cIV8C0Cw== + dependencies: + "@types/node" "*" + "@types/pg-types" "*" + "@types/prettier@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.1.tgz#b6e98083f13faa1e5231bfa3bdb1b0feff536b6d" @@ -2538,6 +2544,11 @@ buffer-from@1.x, buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== + buffer@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" @@ -6398,6 +6409,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== + param-case@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" @@ -6552,6 +6568,72 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +pg-connection-string@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.3.0.tgz#c13fcb84c298d0bfa9ba12b40dd6c23d946f55d6" + integrity sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w== + +pg-format@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/pg-format/-/pg-format-1.0.4.tgz#27734236c2ad3f4e5064915a59334e20040a828e" + integrity sha1-J3NCNsKtP05QZJFaWTNOIAQKgo4= + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-listen@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/pg-listen/-/pg-listen-1.6.0.tgz#49c631114a99458685520159e03334155bb9f7df" + integrity sha512-8TR/u/rhckczPHUY2Vf2ma0pmguSazhrHYoSIDrGKn0XO2Ix93ZUBGZD4Pp6SxUU95psoktiJ6sy7DWYS7b4Qg== + dependencies: + debug "^4.1.1" + pg-format "^1.0.4" + typed-emitter "^0.1.0" + +pg-pool@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.2.1.tgz#5f4afc0f58063659aeefa952d36af49fa28b30e0" + integrity sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA== + +pg-protocol@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.2.5.tgz#28a1492cde11646ff2d2d06bdee42a3ba05f126c" + integrity sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.3.0.tgz#941383300d38eef51ecb88a0188cec441ab64d81" + integrity sha512-jQPKWHWxbI09s/Z9aUvoTbvGgoj98AU7FDCcQ7kdejupn/TcNpx56v2gaOTzXkzOajmOEJEdi9eTh9cA2RVAjQ== + dependencies: + buffer-writer "2.0.0" + packet-reader "1.0.0" + pg-connection-string "^2.3.0" + pg-pool "^3.2.1" + pg-protocol "^1.2.5" + pg-types "^2.1.0" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + dependencies: + split "^1.0.0" + picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -6607,6 +6689,28 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + +postgres-date@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.5.tgz#710b27de5f27d550f6e80b5d34f7ba189213c2ee" + integrity sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6851,7 +6955,7 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" -regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== @@ -7165,6 +7269,11 @@ scuid@^1.0.2: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= + semver@7.x, semver@^7.2.1, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" @@ -7209,13 +7318,6 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-interval-async@^1.0.33: - version "1.0.33" - resolved "https://registry.yarnpkg.com/set-interval-async/-/set-interval-async-1.0.33.tgz#f9a0a2ad7d8fb62cd6eac0ce088a6d631602089c" - integrity sha512-cKV9rLl707sWirvrZEL8XxyOxaPowueFRYKruRRj2cKHRd+M0JGg6IPqoUZVXkvaOZxvM3ulqDdNJuG5MmngxA== - dependencies: - "@babel/runtime" "7.5.0" - set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -7460,6 +7562,13 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -7789,7 +7898,7 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through@^2.3.6: +through@2, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -8059,6 +8168,11 @@ type@^2.0.0: resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== +typed-emitter@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-0.1.0.tgz#ca532f100ccbf850e3a73b8ebf43d43e4f1f3849" + integrity sha512-Tfay0l6gJMP5rkil8CzGbLthukn+9BN/VXWcABVFPjOoelJ+koW8BuPZYk+h/L+lEeIp1fSzVRiWRPIjKVjPdg== + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"