diff --git a/application.yml b/application.yml deleted file mode 100644 index 3ae66c47e9a..00000000000 --- a/application.yml +++ /dev/null @@ -1,9 +0,0 @@ -#hedera: -# mirror: -# importer: -# downloader: -# accessKey: {GOOG1E/AWS....} -# cloudProvider: "GCP/s3" -# gcpProjectId: {projectId} # N/A for AWS -# secretKey: {GOOG1E/AWS....} -# network: PREVIEWNET/TESTNET/MAINNET # Select one network diff --git a/build.gradle.kts b/build.gradle.kts index ad94cabbe55..ae70372f0f8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,18 +1,4 @@ -/* - * Copyright (C) 2022-2025 Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// SPDX-License-Identifier: Apache-2.0 import com.github.gradle.node.npm.task.NpmSetupTask import java.nio.file.Paths @@ -163,25 +149,7 @@ repositories { } spotless { - val licenseHeader = - """ -/* - * Copyright (C) ${'$'}YEAR Hedera Hashgraph, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */${"\n\n"} -""" - .trimIndent() + val licenseHeader = "// SPDX-License-Identifier: Apache-2.0\n\n" val npmExec = when (System.getProperty("os.name").lowercase().contains("windows")) { @@ -199,26 +167,34 @@ spotless { format("go") { endWithNewline() - licenseHeader(licenseHeader, "package").updateYearWithLatest(true) + licenseHeader(licenseHeader, "package") target("hedera-mirror-rosetta/**/*.go") - targetExclude("build/**") + targetExclude("**/build/**") + trimTrailingWhitespace() + } + format("helm") { + endWithNewline() + leadingTabsToSpaces(2) + licenseHeader(licenseHeader.replaceFirst("//", "#"), "^[a-zA-Z0-9{]+") + target("charts/**/*.yaml", "charts/**/*.yml") trimTrailingWhitespace() } format("javascript") { endWithNewline() leadingTabsToSpaces(2) - licenseHeader(licenseHeader, "$").updateYearWithLatest(true) + licenseHeader(licenseHeader, "$") prettier() .npmExecutable(npmExecutable) .npmInstallCache(Paths.get("${rootProject.rootDir}", ".gradle", "spotless")) .config(mapOf("bracketSpacing" to false, "printWidth" to 120, "singleQuote" to true)) - target("hedera-mirror-rest/**/*.js", "hedera-mirror-test/**/*.js") + target("hedera-mirror-rest/**/*.js", "hedera-mirror-test/k6/**/*.js", "tools/**/*.js") targetExclude("**/build/**", "**/node_modules/**", "**/__tests__/integration/*.test.js") } java { endWithNewline() + licenseHeader(licenseHeader, "package") palantirJavaFormat() - licenseHeader(licenseHeader, "package").updateYearWithLatest(true) + removeUnusedImports() target("**/*.java") targetExclude( "**/build/**", @@ -226,46 +202,79 @@ spotless { "hedera-mirror-rosetta/**", // Known issue with Java 21: https://github.com/palantir/palantir-java-format/issues/933 "hedera-mirror-rest-java/**/EntityServiceImpl.java", + "tools/**", ) toggleOffOn() + trimTrailingWhitespace() } kotlin { endWithNewline() ktfmt().kotlinlangStyle() - licenseHeader(licenseHeader, "package").updateYearWithLatest(true) + licenseHeader(licenseHeader, "package") target("buildSrc/**/*.kt") targetExclude("**/build/**") } kotlinGradle { endWithNewline() ktfmt().kotlinlangStyle() - licenseHeader(licenseHeader, "(description|import|plugins)").updateYearWithLatest(true) + licenseHeader(licenseHeader, "(description|import|plugins)") target("*.kts", "*/*.kts", "buildSrc/**/*.kts", "hedera-mirror-rest/*/*.kts") - targetExclude("**/build/**") + targetExclude("**/build/**", "**/node_modules/**") + trimTrailingWhitespace() } format("miscellaneous") { endWithNewline() leadingTabsToSpaces(2) - prettier().npmExecutable(npmExecutable) - target("**/*.json", "**/*.md", "**/*.yml", "**/*.yaml") - targetExclude("**/build/**", "**/charts/**", "**/node_modules/**", "**/package-lock.json") + prettier() + .npmExecutable(npmExecutable) + .npmInstallCache(Paths.get("${rootProject.rootDir}", ".gradle", "spotless")) + target("**/*.json", "**/*.md") + targetExclude( + "**/build/**", + "**/charts/**/dashboards/**", + "**/node_modules/**", + "**/package-lock.json", + ) trimTrailingWhitespace() } format("proto") { endWithNewline() leadingTabsToSpaces(4) - licenseHeader(licenseHeader, "(package|syntax)").updateYearWithLatest(true) + licenseHeader(licenseHeader, "(package|syntax)") target("hedera-mirror-protobuf/**/*.proto") - targetExclude("build/**") + targetExclude("**/build/**") + trimTrailingWhitespace() + } + format("shell") { + endWithNewline() + leadingTabsToSpaces(2) + licenseHeader(licenseHeader.replaceFirst("//", "#"), "^#!") + target("**/*.sh") + targetExclude("**/build/**", "**/node_modules/**") trimTrailingWhitespace() } sql { endWithNewline() leadingTabsToSpaces() - target("hedera-mirror-(common|importer|rest)/**/*.sql") + target( + "hedera-mirror-common/**/*.sql", + "hedera-mirror-importer/**/*.sql", + "hedera-mirror-rest/**/*.sql", + ) targetExclude("**/build/**", "**/node_modules/**") trimTrailingWhitespace() } + format("yaml") { + endWithNewline() + leadingTabsToSpaces(2) + prettier() + .npmExecutable(npmExecutable) + .npmInstallCache(Paths.get("${rootProject.rootDir}", ".gradle", "spotless")) + licenseHeader(licenseHeader.replaceFirst("//", "#"), "^[a-zA-Z0-9{]+") + target("**/*.yaml", "**/*.yml") + targetExclude("**/build/**", "charts/**", "**/node_modules/**") + trimTrailingWhitespace() + } } fun replaceVersion(files: String, match: String) { diff --git a/charts/README.md b/charts/README.md index 887fd29595f..a19efde66e2 100644 --- a/charts/README.md +++ b/charts/README.md @@ -86,6 +86,7 @@ a [Standalone NEG](https://cloud.google.com/kubernetes-engine/docs/how-to/standa 1. Create a Kubernetes cluster utilizing a custom subnet. This can be done by setting a unique name for the subnet in the UI or through the console with the following command + ```shell script gcloud container clusters create mirror-node \ --enable-ip-alias \ diff --git a/charts/hedera-mirror-graphql/postman.json b/charts/hedera-mirror-graphql/postman.json index 2014fd89f3a..d76cac4998f 100644 --- a/charts/hedera-mirror-graphql/postman.json +++ b/charts/hedera-mirror-graphql/postman.json @@ -1,288 +1,264 @@ { - "info": { - "_postman_id": "65d37cac-478e-40ca-bf7c-d981a4318140", - "name": "GraphQL API", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "24928384" - }, - "item": [ - { - "name": "Negative Tests", - "item": [ - { - "name": "Get Account Non Existing field", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Non Existing Field\", () => {", - " pm.expect(pm.response.code).to.equal(200);", - "", - " var response = pm.response.json();", - "", - " pm.expect(response.errors.length).to.equal(1);", - " pm.expect(response.errors[0].extensions.classification).to.equal(\"ValidationError\");", - " pm.expect(response.errors[0].message).to.contain(\"Field 'alais' in type 'Account' is undefined\");", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\n account(input: {\n entityId: {\n shard: 0, realm: 0, num: 12345}}) {\n alais\n autoRenewPeriod\n autoRenewAccount {\n alias\n deleted\n entityId {\n shard\n realm\n num\n }\n createdTimestamp\n }\n \n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{baseUrl}}/graphql/alpha", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "graphql", - "alpha" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "Get Account", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const default_account = pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\");", - "if (default_account) {", - " pm.test(\"Get By Entity Id (All Fields)\", () => {", - " pm.expect(pm.response.code).to.equal(200);", - " var response = pm.response.json();", - " var account = response.data.account;", - "", - " pm.expect(account).to.include.keys(", - " 'type', 'autoRenewAccount',", - " 'autoRenewPeriod', 'balance',", - " 'createdTimestamp', 'declineReward',", - " 'deleted', 'entityId',", - " 'expirationTimestamp', 'id',", - " 'key', 'maxAutomaticTokenAssociations',", - " 'memo', 'nonce',", - " 'obtainer', 'pendingReward',", - " 'receiverSigRequired', 'stakedAccount',", - " 'stakePeriodStart', 'timestamp',", - " 'type'", - " );", - " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", - " pm.expect(account.timestamp).to.have.keys('from', 'to');", - "", - " pm.expect(account.type).to.equal('ACCOUNT');", - " pm.expect(account.entityId.num).to.equal(parseInt(default_account));", - "});", - "}", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\n account(input: {\n entityId: {\n shard: 0, realm: 0, num: {{default_account}}}}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{baseUrl}}/graphql/alpha", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "graphql", - "alpha" - ] - } - }, - "response": [] - }, - { - "name": "Get Account By EvmAddress", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const default_evm_address = pm.variables.get(\"default_evm_address\") || pm.environment.get(\"default_evm_address\")", - "", - "if (default_evm_address) {", - " pm.test(\"Get By Entity EvmAddress (All Fields)\", () => {", - " pm.expect(pm.response.code).to.equal(200);", - "", - " var response = pm.response.json();", - " var account = response.data.account;", - "", - " pm.expect(account).to.include.keys(", - " 'type', 'autoRenewAccount',", - " 'autoRenewPeriod', 'balance',", - " 'createdTimestamp', 'declineReward',", - " 'deleted', 'entityId',", - " 'expirationTimestamp', 'id',", - " 'key', 'maxAutomaticTokenAssociations',", - " 'memo', 'nonce',", - " 'obtainer', 'pendingReward',", - " 'receiverSigRequired', 'stakedAccount',", - " 'stakePeriodStart', 'timestamp',", - " 'type'", - " );", - " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", - " pm.expect(account.timestamp).to.have.keys('from', 'to');", - "", - " pm.expect(account.type).to.equal('ACCOUNT');", - " pm.expect(account.entityId.num).to.equal(parseInt(pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\")));", - "", - " });", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\n account(input: {evmAddress: \"{{default_evm_address}}\"}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{baseUrl}}/graphql/alpha", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "graphql", - "alpha" - ] - } - }, - "response": [] - }, - { - "name": "Get Account By Alias", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const default_alias = pm.variables.get(\"default_alias\") || pm.environment.get(\"default_alias\")", - "if (default_alias) {", - " pm.test(\"Get By Alias (All Fields)\", () => {", - " pm.expect(pm.response.code).to.equal(200);", - "", - " var response = pm.response.json();", - " var account = response.data.account;", - "", - " pm.expect(account).to.include.keys(", - " 'type', 'autoRenewAccount',", - " 'autoRenewPeriod', 'balance',", - " 'createdTimestamp', 'declineReward',", - " 'deleted', 'entityId',", - " 'expirationTimestamp', 'id',", - " 'key', 'maxAutomaticTokenAssociations',", - " 'memo', 'nonce',", - " 'obtainer', 'pendingReward',", - " 'receiverSigRequired', 'stakedAccount',", - " 'stakePeriodStart', 'timestamp',", - " 'type'", - " );", - " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", - " pm.expect(account.timestamp).to.have.keys('from', 'to');", - "", - " pm.expect(account.type).to.equal('ACCOUNT');", - " pm.expect(account.entityId.num).to.equal(parseInt(pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\")));", - " });", - "}" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\n account(input: {alias: \"{{default_alias}}\"}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", - "variables": "" - } - }, - "url": { - "raw": "{{baseUrl}}/graphql/alpha", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "graphql", - "alpha" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ], - "variable": [ - { - "key": "default_account", - "value": "" - }, - { - "key": "baseUrl", - "value": "http://localhost:8083" - }, - { - "key": "default_evm_address", - "value": "" - }, - { - "key": "default_alias", - "value": "" - } - ] -} \ No newline at end of file + "info": { + "_postman_id": "65d37cac-478e-40ca-bf7c-d981a4318140", + "name": "GraphQL API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "24928384" + }, + "item": [ + { + "name": "Negative Tests", + "item": [ + { + "name": "Get Account Non Existing field", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Non Existing Field\", () => {", + " pm.expect(pm.response.code).to.equal(200);", + "", + " var response = pm.response.json();", + "", + " pm.expect(response.errors.length).to.equal(1);", + " pm.expect(response.errors[0].extensions.classification).to.equal(\"ValidationError\");", + " pm.expect(response.errors[0].message).to.contain(\"Field 'alais' in type 'Account' is undefined\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\n account(input: {\n entityId: {\n shard: 0, realm: 0, num: 12345}}) {\n alais\n autoRenewPeriod\n autoRenewAccount {\n alias\n deleted\n entityId {\n shard\n realm\n num\n }\n createdTimestamp\n }\n \n }\n}", + "variables": "" + } + }, + "url": { + "raw": "{{baseUrl}}/graphql/alpha", + "host": ["{{baseUrl}}"], + "path": ["graphql", "alpha"] + } + }, + "response": [] + } + ] + }, + { + "name": "Get Account", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const default_account = pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\");", + "if (default_account) {", + " pm.test(\"Get By Entity Id (All Fields)\", () => {", + " pm.expect(pm.response.code).to.equal(200);", + " var response = pm.response.json();", + " var account = response.data.account;", + "", + " pm.expect(account).to.include.keys(", + " 'type', 'autoRenewAccount',", + " 'autoRenewPeriod', 'balance',", + " 'createdTimestamp', 'declineReward',", + " 'deleted', 'entityId',", + " 'expirationTimestamp', 'id',", + " 'key', 'maxAutomaticTokenAssociations',", + " 'memo', 'nonce',", + " 'obtainer', 'pendingReward',", + " 'receiverSigRequired', 'stakedAccount',", + " 'stakePeriodStart', 'timestamp',", + " 'type'", + " );", + " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", + " pm.expect(account.timestamp).to.have.keys('from', 'to');", + "", + " pm.expect(account.type).to.equal('ACCOUNT');", + " pm.expect(account.entityId.num).to.equal(parseInt(default_account));", + "});", + "}", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\n account(input: {\n entityId: {\n shard: 0, realm: 0, num: {{default_account}}}}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", + "variables": "" + } + }, + "url": { + "raw": "{{baseUrl}}/graphql/alpha", + "host": ["{{baseUrl}}"], + "path": ["graphql", "alpha"] + } + }, + "response": [] + }, + { + "name": "Get Account By EvmAddress", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const default_evm_address = pm.variables.get(\"default_evm_address\") || pm.environment.get(\"default_evm_address\")", + "", + "if (default_evm_address) {", + " pm.test(\"Get By Entity EvmAddress (All Fields)\", () => {", + " pm.expect(pm.response.code).to.equal(200);", + "", + " var response = pm.response.json();", + " var account = response.data.account;", + "", + " pm.expect(account).to.include.keys(", + " 'type', 'autoRenewAccount',", + " 'autoRenewPeriod', 'balance',", + " 'createdTimestamp', 'declineReward',", + " 'deleted', 'entityId',", + " 'expirationTimestamp', 'id',", + " 'key', 'maxAutomaticTokenAssociations',", + " 'memo', 'nonce',", + " 'obtainer', 'pendingReward',", + " 'receiverSigRequired', 'stakedAccount',", + " 'stakePeriodStart', 'timestamp',", + " 'type'", + " );", + " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", + " pm.expect(account.timestamp).to.have.keys('from', 'to');", + "", + " pm.expect(account.type).to.equal('ACCOUNT');", + " pm.expect(account.entityId.num).to.equal(parseInt(pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\")));", + "", + " });", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\n account(input: {evmAddress: \"{{default_evm_address}}\"}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", + "variables": "" + } + }, + "url": { + "raw": "{{baseUrl}}/graphql/alpha", + "host": ["{{baseUrl}}"], + "path": ["graphql", "alpha"] + } + }, + "response": [] + }, + { + "name": "Get Account By Alias", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const default_alias = pm.variables.get(\"default_alias\") || pm.environment.get(\"default_alias\")", + "if (default_alias) {", + " pm.test(\"Get By Alias (All Fields)\", () => {", + " pm.expect(pm.response.code).to.equal(200);", + "", + " var response = pm.response.json();", + " var account = response.data.account;", + "", + " pm.expect(account).to.include.keys(", + " 'type', 'autoRenewAccount',", + " 'autoRenewPeriod', 'balance',", + " 'createdTimestamp', 'declineReward',", + " 'deleted', 'entityId',", + " 'expirationTimestamp', 'id',", + " 'key', 'maxAutomaticTokenAssociations',", + " 'memo', 'nonce',", + " 'obtainer', 'pendingReward',", + " 'receiverSigRequired', 'stakedAccount',", + " 'stakePeriodStart', 'timestamp',", + " 'type'", + " );", + " pm.expect(account.entityId).to.have.keys('shard', 'realm', 'num');", + " pm.expect(account.timestamp).to.have.keys('from', 'to');", + "", + " pm.expect(account.type).to.equal('ACCOUNT');", + " pm.expect(account.entityId.num).to.equal(parseInt(pm.variables.get(\"default_account\") || pm.environment.get(\"default_account\")));", + " });", + "}" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "graphql", + "graphql": { + "query": "{\n account(input: {alias: \"{{default_alias}}\"}) {\n alias\n autoRenewAccount {\n entityId {\n shard\n realm\n num\n }\n }\n autoRenewPeriod\n balance\n createdTimestamp\n declineReward\n deleted\n entityId {\n shard\n realm\n num\n }\n expirationTimestamp\n id\n key\n maxAutomaticTokenAssociations\n memo\n nonce\n obtainer {\n entityId {\n shard\n realm\n num\n }\n }\n pendingReward\n receiverSigRequired\n stakedAccount {\n entityId {\n shard\n realm\n num\n }\n }\n stakePeriodStart\n timestamp {\n from\n to\n }\n type\n }\n}", + "variables": "" + } + }, + "url": { + "raw": "{{baseUrl}}/graphql/alpha", + "host": ["{{baseUrl}}"], + "path": ["graphql", "alpha"] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [""] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [""] + } + } + ], + "variable": [ + { + "key": "default_account", + "value": "" + }, + { + "key": "baseUrl", + "value": "http://localhost:8083" + }, + { + "key": "default_evm_address", + "value": "" + }, + { + "key": "default_alias", + "value": "" + } + ] +} diff --git a/charts/hedera-mirror-importer/values.yaml b/charts/hedera-mirror-importer/values.yaml index c014f6ce73b..04b04bd83c7 100644 --- a/charts/hedera-mirror-importer/values.yaml +++ b/charts/hedera-mirror-importer/values.yaml @@ -1,5 +1,6 @@ -# Base64 encoded contents of a bootstrap address book -addressBook: "" +# SPDX-License-Identifier: Apache-2.0 + +addressBook: "" # Base64 encoded contents of a bootstrap address book affinity: podAntiAffinity: diff --git a/charts/hedera-mirror-rest-java/postman.json b/charts/hedera-mirror-rest-java/postman.json index ff2dc3665c1..c970be8b2ef 100644 --- a/charts/hedera-mirror-rest-java/postman.json +++ b/charts/hedera-mirror-rest-java/postman.json @@ -1,71 +1,69 @@ { - "info": { - "_postman_id": "29c9dec1-e1ee-443b-a0be-b8be031f3001", - "name": "Java REST API", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "28978590" - }, - "item": [ - { - "name": "Positive tests", - "item": [ - { - "name": "Get NFT Allowances for Account ID", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200);", - "});", - "", - "const expectedResponse = {", - " \"allowances\": [],", - " \"links\": {", - " \"next\": null", - " }", - "};", - "pm.test(\"Body is object\", function () {", - " pm.response.to.have.jsonBody(expectedResponse);", - "});" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "{{baseUrl}}/api/v1/accounts/{{accountId}}/allowances/nfts", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "api", - "v1", - "accounts", - "{{accountId}}", - "allowances", - "nfts" - ] - } - }, - "response": [] - } - ] - } - ], - "variable": [ - { - "key": "baseUrl", - "value": "http://localhost:8084" - }, - { - "key": "accountId", - "value": "0.0.2" - } - ] + "info": { + "_postman_id": "29c9dec1-e1ee-443b-a0be-b8be031f3001", + "name": "Java REST API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "28978590" + }, + "item": [ + { + "name": "Positive tests", + "item": [ + { + "name": "Get NFT Allowances for Account ID", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "const expectedResponse = {", + " \"allowances\": [],", + " \"links\": {", + " \"next\": null", + " }", + "};", + "pm.test(\"Body is object\", function () {", + " pm.response.to.have.jsonBody(expectedResponse);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v1/accounts/{{accountId}}/allowances/nfts", + "host": ["{{baseUrl}}"], + "path": [ + "api", + "v1", + "accounts", + "{{accountId}}", + "allowances", + "nfts" + ] + } + }, + "response": [] + } + ] + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:8084" + }, + { + "key": "accountId", + "value": "0.0.2" + } + ] } diff --git a/charts/hedera-mirror-rosetta/postman.json b/charts/hedera-mirror-rosetta/postman.json index 97d14f22e9b..07a528ead43 100644 --- a/charts/hedera-mirror-rosetta/postman.json +++ b/charts/hedera-mirror-rosetta/postman.json @@ -41,13 +41,8 @@ }, "url": { "raw": "{{base_url}}/network/list", - "host": [ - "{{base_url}}" - ], - "path": [ - "network", - "list" - ] + "host": ["{{base_url}}"], + "path": ["network", "list"] } }, "response": [] @@ -109,13 +104,8 @@ }, "url": { "raw": "{{base_url}}/network/options", - "host": [ - "{{base_url}}" - ], - "path": [ - "network", - "options" - ] + "host": ["{{base_url}}"], + "path": ["network", "options"] } }, "response": [] @@ -167,13 +157,8 @@ }, "url": { "raw": "{{base_url}}/network/status", - "host": [ - "{{base_url}}" - ], - "path": [ - "network", - "status" - ] + "host": ["{{base_url}}"], + "path": ["network", "status"] } }, "response": [] @@ -236,13 +221,8 @@ }, "url": { "raw": "{{base_url}}/account/balance", - "host": [ - "{{base_url}}" - ], - "path": [ - "account", - "balance" - ] + "host": ["{{base_url}}"], + "path": ["account", "balance"] } }, "response": [] @@ -308,12 +288,8 @@ }, "url": { "raw": "{{base_url}}/block", - "host": [ - "{{base_url}}" - ], - "path": [ - "block" - ] + "host": ["{{base_url}}"], + "path": ["block"] } }, "response": [] @@ -366,12 +342,8 @@ }, "url": { "raw": "{{base_url}}/block", - "host": [ - "{{base_url}}" - ], - "path": [ - "block" - ] + "host": ["{{base_url}}"], + "path": ["block"] } }, "response": [] @@ -424,13 +396,8 @@ }, "url": { "raw": "{{base_url}}/block/transaction", - "host": [ - "{{base_url}}" - ], - "path": [ - "block", - "transaction" - ] + "host": ["{{base_url}}"], + "path": ["block", "transaction"] } }, "response": [] @@ -445,9 +412,7 @@ "script": { "id": "85972e64-1f88-4ea2-bbae-3261c5b98e59", "type": "text/javascript", - "exec": [ - "" - ] + "exec": [""] } }, { @@ -455,9 +420,7 @@ "script": { "id": "bf7e852f-6001-40e9-88bc-d88441d9c2cc", "type": "text/javascript", - "exec": [ - "" - ] + "exec": [""] } } ], diff --git a/charts/hedera-mirror-rosetta/values.yaml b/charts/hedera-mirror-rosetta/values.yaml index 4f901c6db9a..2c425ae3ba3 100644 --- a/charts/hedera-mirror-rosetta/values.yaml +++ b/charts/hedera-mirror-rosetta/values.yaml @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: @@ -30,7 +32,7 @@ config: {} # Environment variables to add to the container. The value can either be a string or an EnvVarSource. Evaluated as a template. env: - CONFIG_PATH: "/usr/etc/hedera/" + HEDERA_MIRROR_ROSETTA_API_CONFIG: "/usr/etc/hedera/" # FOO: # valueFrom: # secretKeyRef: diff --git a/charts/hedera-mirror-web3/postman.json b/charts/hedera-mirror-web3/postman.json index f727350d43e..6ac9641c938 100644 --- a/charts/hedera-mirror-web3/postman.json +++ b/charts/hedera-mirror-web3/postman.json @@ -49,15 +49,8 @@ }, "url": { "raw": "{{baseUrl}}/api/v1/contracts/call", - "host": [ - "{{baseUrl}}" - ], - "path": [ - "api", - "v1", - "contracts", - "call" - ] + "host": ["{{baseUrl}}"], + "path": ["api", "v1", "contracts", "call"] } }, "response": [] diff --git a/charts/marketplace/gcp/README.md b/charts/marketplace/gcp/README.md index d0f64a58ed5..24748ebe6b1 100644 --- a/charts/marketplace/gcp/README.md +++ b/charts/marketplace/gcp/README.md @@ -336,30 +336,30 @@ To ensure a smooth upgrade process: 2. Delete the `${APP_NAME}-importer` Stateful Set workload. 3. Install the v0.37 solution 4. Scale down the Importer Deployment resource - ```shell - kubectl scale deployment "${APP_NAME}-importer" --replicas=0 - ``` -4. Scale down the REST API Deployment resource - ```shell - kubectl scale deployment "${APP_NAME}-rest" --replicas=0 - ``` -5. Modify the `mirror-passwords` Kubernetes Secret resource - ```shell - kubectl edit secrets mirror-passwords - ``` -6. Set the `HEDERA_MIRROR_IMPORTER_DB_USERNAME` value to `bWlycm9yX25vZGU=` (the base64 encoded value of the + ```shell + kubectl scale deployment "${APP_NAME}-importer" --replicas=0 + ``` +5. Scale down the REST API Deployment resource + ```shell + kubectl scale deployment "${APP_NAME}-rest" --replicas=0 + ``` +6. Modify the `mirror-passwords` Kubernetes Secret resource + ```shell + kubectl edit secrets mirror-passwords + ``` +7. Set the `HEDERA_MIRROR_IMPORTER_DB_USERNAME` value to `bWlycm9yX25vZGU=` (the base64 encoded value of the default `mirror_node` value) -7. Set the `HEDERA_MIRROR_IMPORTER_DB_RESTUSERNAME` value to `bWlycm9yX2FwaQ==` (the base64 encoded value of the +8. Set the `HEDERA_MIRROR_IMPORTER_DB_RESTUSERNAME` value to `bWlycm9yX2FwaQ==` (the base64 encoded value of the default `mirror_api` value) -8. Scale up the Importer Deployment resource - ```shell - kubectl scale deployment "${APP_NAME}-importer" --replicas=1 - ``` -9. Scale up the REST API Deployment resource +9. Scale up the Importer Deployment resource + ```shell + kubectl scale deployment "${APP_NAME}-importer" --replicas=1 + ``` +10. Scale up the REST API Deployment resource ```shell kubectl scale deployment "${APP_NAME}-rest" --replicas=1 ``` -10. Post importer and rest operation confirmation, delete the leftover `data-${APP_NAME}-importer-0` persistent volume +11. Post importer and rest operation confirmation, delete the leftover `data-${APP_NAME}-importer-0` persistent volume claim (Importer is no longer stateful) ```shell kubectl delete pvc "data-${APP_NAME}-importer-0" diff --git a/codecov.yml b/codecov.yml index e836f00668a..2c55fd7c6f7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,8 @@ -# We upload multiple separate reports, one for each GitHub action +# SPDX-License-Identifier: Apache-2.0 + codecov: notify: - after_n_builds: 7 + after_n_builds: 7 # We upload multiple separate reports, one for each GitHub action comment: after_n_builds: 7 coverage: diff --git a/docker-compose.yml b/docker-compose.yml index 90ae6d79603..a66bae361fc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,21 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 + services: api-proxy: + configs: + - source: proxy-config + target: /etc/nginx/conf.d/default.conf image: nginx:1-alpine restart: unless-stopped ports: - 8080:8080 tty: true - configs: - - source: api-proxy-inline-config - target: /etc/nginx/conf.d/default.conf db: - image: postgres:16-alpine environment: PGDATA: /var/lib/postgresql/data POSTGRES_HOST_AUTH_METHOD: scram-sha-256 POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256 POSTGRES_PASSWORD: postgres_password + image: postgres:16-alpine ports: - 5432:5432 restart: unless-stopped @@ -27,54 +29,60 @@ services: - ./hedera-mirror-importer/src/main/resources/db/scripts/init.sh:/docker-entrypoint-initdb.d/init.sh graphql: - image: gcr.io/mirrornode/hedera-mirror-graphql:0.125.0-SNAPSHOT - pull_policy: always + configs: + - source: app-config + target: /usr/etc/hedera/application.yml deploy: replicas: 0 environment: HEDERA_MIRROR_GRAPHQL_DB_HOST: db - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-graphql/ + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ + image: gcr.io/mirrornode/hedera-mirror-graphql:0.125.0-SNAPSHOT ports: - 8083:8083 + pull_policy: always restart: unless-stopped tty: true - volumes: - - ./application.yml:/usr/etc/hedera-mirror-graphql/application.yml grpc: - image: gcr.io/mirrornode/hedera-mirror-grpc:0.125.0-SNAPSHOT - pull_policy: always - restart: unless-stopped + configs: + - source: app-config + target: /usr/etc/hedera/application.yml environment: HEDERA_MIRROR_GRPC_DB_HOST: db - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-grpc/ + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ SPRING_DATA_REDIS_HOST: redis + image: gcr.io/mirrornode/hedera-mirror-grpc:0.125.0-SNAPSHOT ports: - 5600:5600 - volumes: - - ./application.yml:/usr/etc/hedera-mirror-grpc/application.yml - - importer: - image: gcr.io/mirrornode/hedera-mirror-importer:0.125.0-SNAPSHOT pull_policy: always restart: unless-stopped + tty: true + + importer: + configs: + - source: app-config + target: /usr/etc/hedera/application.yml environment: HEDERA_MIRROR_IMPORTER_DB_HOST: db - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-importer/ + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ SPRING_DATA_REDIS_HOST: redis - volumes: - - ./application.yml:/usr/etc/hedera-mirror-importer/application.yml + image: gcr.io/mirrornode/hedera-mirror-importer:0.125.0-SNAPSHOT + pull_policy: always + restart: unless-stopped + tty: true monitor: + configs: + - source: app-config + target: /usr/etc/hedera/application.yml deploy: replicas: 0 + environment: + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ image: gcr.io/mirrornode/hedera-mirror-monitor:0.125.0-SNAPSHOT pull_policy: always restart: unless-stopped - environment: - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-monitor/ - volumes: - - ./application.yml:/usr/etc/hedera-mirror-monitor/application.yml redis: image: redis:6-alpine @@ -86,58 +94,78 @@ services: tty: true rest: - image: gcr.io/mirrornode/hedera-mirror-rest:0.125.0-SNAPSHOT - pull_policy: always + configs: + - source: app-config + target: /usr/etc/hedera/application.yml environment: + CONFIG_PATH: /usr/etc/hedera/ HEDERA_MIRROR_REST_DB_HOST: db HEDERA_MIRROR_REST_REDIS_URI: redis://redis:6379 + image: gcr.io/mirrornode/hedera-mirror-rest:0.125.0-SNAPSHOT + pull_policy: always ports: - 5551:5551 restart: unless-stopped tty: true rest-java: - image: gcr.io/mirrornode/hedera-mirror-rest-java:0.125.0-SNAPSHOT - pull_policy: always + configs: + - source: app-config + target: /usr/etc/hedera/application.yml environment: HEDERA_MIRROR_RESTJAVA_DB_HOST: db - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-rest-java/ + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ + image: gcr.io/mirrornode/hedera-mirror-rest-java:0.125.0-SNAPSHOT + pull_policy: always ports: - 8084:8084 restart: unless-stopped tty: true - volumes: - - ./application.yml:/usr/etc/hedera-mirror-rest-java/application.yml rosetta: - image: gcr.io/mirrornode/hedera-mirror-rosetta:0.125.0-SNAPSHOT + configs: + - source: app-config + target: /usr/etc/hedera/application.yml deploy: replicas: 0 - pull_policy: always environment: + HEDERA_MIRROR_ROSETTA_API_CONFIG: /usr/etc/hedera/application.yml HEDERA_MIRROR_ROSETTA_DB_HOST: db + image: gcr.io/mirrornode/hedera-mirror-rosetta:0.125.0-SNAPSHOT + pull_policy: always ports: - 5700:5700 restart: unless-stopped tty: true - volumes: - - ./application.yml:/src/hedera-mirror-rosetta/application.yml web3: - image: gcr.io/mirrornode/hedera-mirror-web3:0.125.0-SNAPSHOT - pull_policy: always + configs: + - source: app-config + target: /usr/etc/hedera/application.yml environment: HEDERA_MIRROR_WEB3_DB_HOST: db - SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera-mirror-web3/ + SPRING_CONFIG_ADDITIONAL_LOCATION: file:/usr/etc/hedera/ + image: gcr.io/mirrornode/hedera-mirror-web3:0.125.0-SNAPSHOT + pull_policy: always ports: - 8545:8545 restart: unless-stopped tty: true - volumes: - - ./application.yml:/usr/etc/hedera-mirror-web3/application.yml configs: - api-proxy-inline-config: + app-config: + content: | + hedera: + mirror: + importer: + network: DEMO # Select one of PREVIEWNET/TESTNET/MAINNET and populate below config + # downloader: + # accessKey: {GOOG1E/AWS....} + # cloudProvider: "GCP/S3" + # gcpProjectId: {projectId} # N/A for AWS + # secretKey: {GOOG1E/AWS....} + + proxy-config: content: | # YAML uses $ for variable substitution, so we use $$ when using nginx variables. diff --git a/hedera-mirror-rosetta/scripts/deploy/deploy.sh b/hedera-mirror-rosetta/scripts/deploy/deploy.sh deleted file mode 100755 index 14f1c7017c6..00000000000 --- a/hedera-mirror-rosetta/scripts/deploy/deploy.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -set -ex - -cd "$(dirname "${0}")/.." - -# name of the service and directories -name=hedera-mirror-rosetta -binary="/usr/bin/${name}" -configdir="/usr/etc/${name}" -configfile="${configdir}/application.yml" -execname="$(ls -1 ${name}*)" - -if [[ ! -f "${execname}" ]]; then - echo "Can't find ${execname}. Aborting" - exit 1 -fi - -mkdir -p "${configdir}" -systemctl stop "${name}.service" || true - -if [[ ! -f "${configfile}" ]]; then - echo "Fresh install of ${name}" - read -rp "Database hostname: " dbHost - read -rp "Database name: " dbName - read -rp "Rosetta user password: " dbPassword - read -rp "Database port: " dbPort - read -rp "Rosetta user: " dbUser - cat > "${configfile}" <