diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d461420..20f892c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,6 +18,11 @@ on: description: Run code coverage required: false default: true + smartContractVersion: + type: string + description: GitHub tag of the smart contract version to run the tests against + required: false + default: "main" concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -62,6 +67,8 @@ jobs: java-version: '11' - name: Build with Gradle + env: + SMART_CONTRACT_VERSION_TAG: ${{ github.event.inputs.smartContractVersion }} run: ./gradlew clean build --refresh-dependencies -Pversion=$VERSION -x koverReport - name: Generate code coverage reports diff --git a/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOExecutor.kt b/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOExecutor.kt index ee3beb6..cfe44d3 100644 --- a/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOExecutor.kt +++ b/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOExecutor.kt @@ -2,6 +2,7 @@ package tech.figure.validationoracle.client.client.base import cosmos.tx.v1beta1.ServiceOuterClass.BroadcastTxResponse import io.provenance.client.grpc.Signer +import tech.figure.validationoracle.client.domain.execute.ContractSettingsUpdate import tech.figure.validationoracle.client.domain.execute.EntityCreationRequest import tech.figure.validationoracle.client.domain.execute.EntityUpdateRequest import tech.figure.validationoracle.client.domain.execute.ValidationDefinitionCreationRequest @@ -20,7 +21,7 @@ import tech.figure.validationoracle.client.domain.execute.ValidationRequestUpdat interface VOExecutor { /** * Executes the validation oracle smart contract to create a new validation definition to allow a new validation - * type to be used in the smart contract instance. + * type to be used. * * @param request The [ValidationDefinitionCreationRequest] payload that will be sent to the smart contract. * @param signer Any implementation of [Signer] to sign the message programmatically. @@ -125,7 +126,7 @@ interface VOExecutor { ): BroadcastTxResponse /** - * Executes the validation oracle smart contract to updating an existing entity. + * Executes the validation oracle smart contract to update an existing entity. * * @param request The [EntityUpdateRequest] payload that will be sent to the smart contract. * @param signer Any implementation of [Signer] to sign the message programmatically. @@ -138,4 +139,19 @@ interface VOExecutor { signer: Signer, options: BroadcastOptions = BroadcastOptions(), ): BroadcastTxResponse + + /** + * Executes the validation oracle smart contract to update its settings. + * + * @param request The [EntityUpdateRequest] payload that will be sent to the smart contract. + * @param signer Any implementation of [Signer] to sign the message programmatically. + * See [AccountSigner][tech.figure.validationoracle.util.wallet.AccountSigner] for a provided implementation. + * @param options Various options that alter how the transaction is broadcast. + * See [BroadcastOptions] for more details. + */ + fun updateContractSettings( + request: ContractSettingsUpdate, + signer: Signer, + options: BroadcastOptions = BroadcastOptions(), + ): BroadcastTxResponse } diff --git a/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOQuerier.kt b/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOQuerier.kt index 32689ac..cebb527 100644 --- a/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOQuerier.kt +++ b/client/src/main/kotlin/tech/figure/validationoracle/client/client/base/VOQuerier.kt @@ -43,5 +43,8 @@ interface VOQuerier { */ fun queryValidationRequestsByValidator(validatorAddress: String): List + /** + * Retrieves information about an entity associated with the smart contract instance by the given address. + */ fun queryEntityByAddress(address: String): EntityDetail? } diff --git a/client/src/main/kotlin/tech/figure/validationoracle/client/client/impl/DefaultVOExecutor.kt b/client/src/main/kotlin/tech/figure/validationoracle/client/client/impl/DefaultVOExecutor.kt index 9e70f7e..13a0a31 100644 --- a/client/src/main/kotlin/tech/figure/validationoracle/client/client/impl/DefaultVOExecutor.kt +++ b/client/src/main/kotlin/tech/figure/validationoracle/client/client/impl/DefaultVOExecutor.kt @@ -13,6 +13,7 @@ import io.provenance.client.protobuf.extensions.toTxBody import tech.figure.validationoracle.client.client.base.BroadcastOptions import tech.figure.validationoracle.client.client.base.VOExecutor import tech.figure.validationoracle.client.client.base.VOQuerier +import tech.figure.validationoracle.client.domain.execute.ContractSettingsUpdate import tech.figure.validationoracle.client.domain.execute.EntityCreationRequest import tech.figure.validationoracle.client.domain.execute.EntityUpdateRequest import tech.figure.validationoracle.client.domain.execute.ValidationDefinitionCreationRequest @@ -82,6 +83,12 @@ class DefaultVOExecutor( options: BroadcastOptions, ): BroadcastTxResponse = doExecute(generateMsg(request, signer.address()), signer, options) + override fun updateContractSettings( + request: ContractSettingsUpdate, + signer: Signer, + options: BroadcastOptions, + ): BroadcastTxResponse = doExecute(generateMsg(request, signer.address()), signer, options) + /** * Constructs a generic [MsgExecuteContract] from a provided [ContractExecuteInput] message, * ensuring that the provided address is the signer. diff --git a/client/src/main/kotlin/tech/figure/validationoracle/client/domain/execute/ContractSettingsUpdate.kt b/client/src/main/kotlin/tech/figure/validationoracle/client/domain/execute/ContractSettingsUpdate.kt new file mode 100644 index 0000000..23857f9 --- /dev/null +++ b/client/src/main/kotlin/tech/figure/validationoracle/client/domain/execute/ContractSettingsUpdate.kt @@ -0,0 +1,10 @@ +package tech.figure.validationoracle.client.domain.execute + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import tech.figure.validationoracle.client.domain.execute.base.ContractExecuteInput +import tech.figure.validationoracle.client.domain.serialization.ContractSettingsUpdateSerializer + +@JsonSerialize(using = ContractSettingsUpdateSerializer::class) +data class ContractSettingsUpdate( + val newAdminAddress: String? = null, +) : ContractExecuteInput diff --git a/client/src/main/kotlin/tech/figure/validationoracle/client/domain/serialization/ContractSettingsUpdateSerializer.kt b/client/src/main/kotlin/tech/figure/validationoracle/client/domain/serialization/ContractSettingsUpdateSerializer.kt new file mode 100644 index 0000000..2759c22 --- /dev/null +++ b/client/src/main/kotlin/tech/figure/validationoracle/client/domain/serialization/ContractSettingsUpdateSerializer.kt @@ -0,0 +1,35 @@ +package tech.figure.validationoracle.client.domain.serialization + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.databind.JsonSerializer +import com.fasterxml.jackson.databind.SerializerProvider +import tech.figure.validationoracle.client.domain.execute.ContractSettingsUpdate + +/** + * The JSON structure of a contract entry point is impossible to represent with vanilla Jackson annotation setups. This + * serializer enables the object to be serialized correctly with its multiple-nested nodes without enabling special + * ObjectMapper features, allowing the object to be more universally applicable to external ObjectMapper singleton + * instances. + * + * This serializer outputs the values in the following format: + * ```json + * { + * "update_settings": { + * "new_admin_address": ... + * } + * } + * ``` + */ +class ContractSettingsUpdateSerializer : JsonSerializer() { + override fun serialize(value: ContractSettingsUpdate, gen: JsonGenerator, provider: SerializerProvider?) { + SafeJsonGenerator(gen).apply { + jsonObject { + jsonObject("update_settings") { + jsonObject("update") { + gen.writeStringField("new_admin_address", value.newAdminAddress) + } + } + } + } + } +} diff --git a/client/src/test/kotlin/tech/figure/validationoracle/client/client/ContractMetadataIntegrationTest.kt b/client/src/test/kotlin/tech/figure/validationoracle/client/client/ContractMetadataIntegrationTest.kt index c96108d..5087eb5 100644 --- a/client/src/test/kotlin/tech/figure/validationoracle/client/client/ContractMetadataIntegrationTest.kt +++ b/client/src/test/kotlin/tech/figure/validationoracle/client/client/ContractMetadataIntegrationTest.kt @@ -1,12 +1,18 @@ package tech.figure.validationoracle.client.client +import io.grpc.StatusRuntimeException +import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.Order import io.kotest.core.spec.Spec +import io.kotest.inspectors.forAtLeastOne import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe +import io.kotest.matchers.string.shouldContain import io.kotest.property.checkAll +import tech.figure.validationoracle.client.domain.execute.ContractSettingsUpdate import tech.figure.validationoracle.client.test.IntegrationTestBase import tech.figure.validationoracle.client.test.PrimitiveArbs.anyBech32TestnetAddress +import tech.figure.validationoracle.client.test.PrimitiveArbs.anyBlankString import tech.figure.validationoracle.client.test.PrimitiveArbs.anyNonEmptyString @Order(1) @@ -48,14 +54,32 @@ class ContractMetadataIntegrationTest : IntegrationTestBase({ } } } - "Updating the contract's settings" xshould { - "fail when given an empty body" { - // TODO: Implement - } + "Updating the contract's settings" should { "fail when given an invalid new admin address" { - // TODO: Implement + checkAll( + anyBlankString, + ) { randomInvalidAddress -> + shouldThrow { + voClient.updateContractSettings( + ContractSettingsUpdate( + newAdminAddress = randomInvalidAddress, + ), + SpecTestContainer.Provenance.contractAdminAccount, + ) + }.let { exception -> + listOf( + "invalid request: failed to execute message; message index: 0: " + + "Invalid request: new_admin_address was empty: execute wasm contract failed", + // TODO: In the contract code, see if error below can be captured into the error above + "invalid request: failed to execute message; message index: 0: Generic error: addr_validate " + + "errored: empty address string is not allowed: execute wasm contract failed", + ).forAtLeastOne { errorMessage -> + exception.message shouldContain errorMessage + } + } + } } - "succeed when given a valid request" { + "!succeed when given a valid request" { // TODO: Implement } } @@ -66,7 +90,6 @@ class ContractMetadataIntegrationTest : IntegrationTestBase({ * TODO: this function would ideally belong in the parent class and be invoked at "before all specs" instead */ override suspend fun beforeSpec(spec: Spec) { - instance.stop() instance.withServices( *specTestContainers.map { container -> container.serviceName }.toTypedArray(), ) diff --git a/client/src/test/kotlin/tech/figure/validationoracle/client/client/ValidationDefinitionIntegrationTest.kt b/client/src/test/kotlin/tech/figure/validationoracle/client/client/ValidationDefinitionIntegrationTest.kt index 2eb2d1b..43e9e83 100644 --- a/client/src/test/kotlin/tech/figure/validationoracle/client/client/ValidationDefinitionIntegrationTest.kt +++ b/client/src/test/kotlin/tech/figure/validationoracle/client/client/ValidationDefinitionIntegrationTest.kt @@ -1,7 +1,10 @@ package tech.figure.validationoracle.client.client +import io.grpc.StatusRuntimeException import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.Order +import io.kotest.matchers.string.shouldContain +import io.kotest.matchers.string.shouldContainIgnoringCase import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.orNull @@ -10,21 +13,19 @@ import tech.figure.validationoracle.client.domain.execute.ValidationDefinitionCr import tech.figure.validationoracle.client.test.IntegrationTestBase import tech.figure.validationoracle.client.test.PrimitiveArbs.anyBlankString import tech.figure.validationoracle.client.test.PrimitiveArbs.anyNonEmptyString -import tech.figure.validationoracle.util.enums.ProvenanceNetworkType -import tech.figure.validationoracle.util.wallet.AccountSigner @Order(2) class ValidationDefinitionIntegrationTest : IntegrationTestBase({ val voClient = getVoClient() - "Creating a new validation definition" xshould { - "fail on an invalid validation type" { + "Creating a new validation definition" should { + "!fail on an invalid validation type" { checkAll( anyBlankString, anyNonEmptyString.orNull(), Arb.boolean().orNull(), Arb.boolean().orNull(), ) { invalidValidationType, displayName, enabled, bindName -> - shouldThrow { // TODO: Check for a more specific type + shouldThrow { voClient.createValidationDefinition( ValidationDefinitionCreationRequest( validationType = invalidValidationType, @@ -32,14 +33,38 @@ class ValidationDefinitionIntegrationTest : IntegrationTestBase({ enabled = enabled, bindName = bindName, ), - AccountSigner.fromMnemonic("", ProvenanceNetworkType.TESTNET), // TODO: Set mnemonic + SpecTestContainer.Provenance.contractAdminAccount, ) }.let { exception -> - // TODO: Validate the exception message + // TODO: Re-enable this test case once contract is updated to require a non-empty validation type + exception.message shouldContain "invalid request: failed to execute message; " } } } - "succeed with a valid request body" { + "fail if executed by a party other than the contract admin" { + checkAll( + anyNonEmptyString, + anyNonEmptyString.orNull(), + Arb.boolean().orNull(), + Arb.boolean().orNull(), + ) { validationType, displayName, enabled, bindName -> + shouldThrow { + voClient.createValidationDefinition( + ValidationDefinitionCreationRequest( + validationType = validationType, + displayName = displayName, + enabled = enabled, + bindName = bindName, + ), + SpecTestContainer.Provenance.party1Account, + ) + }.let { exception -> + exception.message shouldContainIgnoringCase "invalid request: failed to execute message; " + + "message index: 0: Unauthorized: must be the contract admin: execute wasm contract failed" + } + } + } + "!succeed with a valid request body" { // TODO: Implement } } diff --git a/client/src/test/kotlin/tech/figure/validationoracle/client/test/IntegrationTestBase.kt b/client/src/test/kotlin/tech/figure/validationoracle/client/test/IntegrationTestBase.kt index 884d02f..382c020 100644 --- a/client/src/test/kotlin/tech/figure/validationoracle/client/test/IntegrationTestBase.kt +++ b/client/src/test/kotlin/tech/figure/validationoracle/client/test/IntegrationTestBase.kt @@ -4,40 +4,60 @@ import io.kotest.core.extensions.Extension import io.kotest.core.spec.style.WordSpec import io.provenance.client.grpc.GasEstimationMethod import io.provenance.client.grpc.PbClient +import io.provenance.client.grpc.Signer import mu.KLogger import mu.KotlinLogging -import org.testcontainers.containers.Container +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.testcontainers.containers.Container.ExecResult import org.testcontainers.containers.ContainerState import org.testcontainers.containers.DockerComposeContainer import org.testcontainers.containers.wait.strategy.Wait import org.testcontainers.containers.wait.strategy.WaitStrategy import tech.figure.validationoracle.client.client.base.ContractIdentifier import tech.figure.validationoracle.client.client.base.VOClient +import tech.figure.validationoracle.util.enums.ProvenanceNetworkType +import tech.figure.validationoracle.util.wallet.AccountSigner import java.io.File import java.net.URI +import java.security.Security import java.time.Duration private const val ResourceDirectory = "src/test/resources" // private const val MAXIMUM_SETUP_SCRIPT_WAIT_TIME_IN_SECONDS = 20L -val logger: KLogger = KotlinLogging.logger("IntegrationTestBaseClass") +val log: KLogger = KotlinLogging.logger("IntegrationTestBaseClass") // TODO: Needs SL4J provider to actually work abstract class IntegrationTestBase( body: WordSpec.() -> Unit, ) : WordSpec(body) { - protected open val log: KLogger = logger + init { + Security.addProvider(BouncyCastleProvider()) + } companion object { internal class KDockerComposeContainer(file: File) : DockerComposeContainer(file) + private const val CONTRACT_ADMIN_MNEMONIC = "mouse dove lava deputy east toddler long round person margin " + + "ecology auto fiber drink put buzz lesson van popular autumn marble flame prepare area" + private const val PARTY1_MNEMONIC = "nature crowd safe rifle amateur vapor dismiss inquiry flag shadow quiz " + + "fuel divide donate major fetch leader valve fence across fringe orbit poet evidence" + private const val PARTY2_MNEMONIC = "demise pyramid jelly early draw audit mom name divide dynamic beef way " + + "pond fence train spare quality kangaroo vibrant portion distance debris increase acoustic" + private const val PARTY3_MNEMONIC = "exact hidden thought shiver accuse copy supreme umbrella tell tiger " + + "during weird region lawn patrol balance lunar wheel much aware grit script dutch sauce" + @Suppress("ktlint:no-multi-spaces") private val defaultDockerComposeEnvironment: Map = configurableEnvironment( /** Images */ // TODO: Take versions as inputs in GitHub job, and output them in job's output Markdown - "PROVENANCE_VERSION" to "v1.13.1", - // "SMART_CONTRACT_VERSION_TAG" to "9c3c46cb4d8f188fbcda0a6b93e2d732a4a3a4f3", - "RUST_OPTIMIZER_VERSION" to "0.12.11", - "UBUNTU_VERSION" to "22.04", + "PROVENANCE_VERSION" to "v1.13.1", + "RUST_OPTIMIZER_VERSION" to "0.12.11", + "UBUNTU_VERSION" to "22.04", + /** Variables */ + "CONTRACT_ADMIN_MNEMONIC" to CONTRACT_ADMIN_MNEMONIC, + "PARTY1_MNEMONIC" to PARTY1_MNEMONIC, + "PARTY2_MNEMONIC" to PARTY2_MNEMONIC, + "PARTY3_MNEMONIC" to PARTY3_MNEMONIC, ) protected val dockerComposeEnvironmentOverrides: Map = emptyMap() @@ -46,7 +66,11 @@ abstract class IntegrationTestBase( KDockerComposeContainer(File("$ResourceDirectory/docker-compose.yml")).apply { withEnv(defaultDockerComposeEnvironment + dockerComposeEnvironmentOverrides) withRemoveImages(DockerComposeContainer.RemoveImages.ALL) - withLocalCompose(getEnvOr("USE_LOCAL_COMPOSE_FOR_TESTCONTAINERS", "true").toBoolean()) + withLocalCompose( + getEnvOr("USE_LOCAL_COMPOSE_FOR_TESTCONTAINERS", "true").toBoolean().also { + log.info("Local Docker Compose for tests = $it") + }, + ) } } @@ -74,11 +98,11 @@ abstract class IntegrationTestBase( ) } - enum class SpecTestContainer( // TODO: Possibly change into a sealed class instead + sealed class SpecTestContainer( val serviceName: String, val waitStrategy: WaitStrategy = Wait.defaultWaitStrategy(), ) { - PROVENANCE( + object Provenance : SpecTestContainer( "provenance", Wait.forLogMessage( ".*The contract was successfully instantiated to the local Provenance instance at address tp\\w+\\n.*", @@ -86,17 +110,24 @@ abstract class IntegrationTestBase( ).apply { withStartupTimeout(Duration.ofMinutes(5L)) }, - ), - ; + ) { + private fun getAccountFromMnemomic(mnemonic: String): AccountSigner = + AccountSigner.fromMnemonic(mnemonic, ProvenanceNetworkType.TESTNET) + + val contractAdminAccount: Signer by lazy { getAccountFromMnemomic(CONTRACT_ADMIN_MNEMONIC) } + val party1Account: Signer by lazy { getAccountFromMnemomic(PARTY1_MNEMONIC) } + val party2Account: Signer by lazy { getAccountFromMnemomic(PARTY2_MNEMONIC) } + val party3Account: Signer by lazy { getAccountFromMnemomic(PARTY3_MNEMONIC) } + } private val container: ContainerState by lazy { instance.getContainer(serviceName).get() } - fun runCommand(input: String): Container.ExecResult = + protected fun runCommand(input: String): ExecResult = container.execInContainer(*input.split(" ").toTypedArray()) - fun runBash(input: String): Container.ExecResult = + protected fun runBash(input: String): ExecResult = container.execInContainer("bash", "-c", *input.split(" ").toTypedArray()) /** @@ -118,5 +149,5 @@ abstract class IntegrationTestBase( /** * A list of the containers which are invoked in the test body. */ - protected val specTestContainers: List = listOf(SpecTestContainer.PROVENANCE) + protected val specTestContainers: List = listOf(SpecTestContainer.Provenance) } diff --git a/client/src/test/resources/docker-compose.yml b/client/src/test/resources/docker-compose.yml index 4cccdf6..83785d3 100644 --- a/client/src/test/resources/docker-compose.yml +++ b/client/src/test/resources/docker-compose.yml @@ -11,6 +11,10 @@ services: - ID=dev - LOG=${LOG:-provenanced.log} - PIO_HOME=/provenance + - CONTRACT_ADMIN_MNEMONIC=${CONTRACT_ADMIN_MNEMONIC:-mouse dove lava deputy east toddler long round person margin ecology auto fiber drink put buzz lesson van popular autumn marble flame prepare area} + - PARTY1_MNEMONIC=${PARTY1_MNEMONIC:-nature crowd safe rifle amateur vapor dismiss inquiry flag shadow quiz fuel divide donate major fetch leader valve fence across fringe orbit poet evidence} + - PARTY2_MNEMONIC=${PARTY2_MNEMONIC:-demise pyramid jelly early draw audit mom name divide dynamic beef way pond fence train spare quality kangaroo vibrant portion distance debris increase acoustic} + - PARTY3_MNEMONIC=${PARTY3_MNEMONIC:-exact hidden thought shiver accuse copy supreme umbrella tell tiger during weird region lawn patrol balance lunar wheel much aware grit script dutch sauce} volumes: - ./scripts:/scripts:ro - validation-oracle-integration-test-setup-volume:/outputs:ro diff --git a/client/src/test/resources/logback-test.xml b/client/src/test/resources/logback-test.xml new file mode 100644 index 0000000..e69de29 diff --git a/client/src/test/resources/scripts/start_provenance_and_store_vo_contract.sh b/client/src/test/resources/scripts/start_provenance_and_store_vo_contract.sh index 09f7977..da69bcb 100755 --- a/client/src/test/resources/scripts/start_provenance_and_store_vo_contract.sh +++ b/client/src/test/resources/scripts/start_provenance_and_store_vo_contract.sh @@ -23,11 +23,27 @@ PROVENANCED="/usr/bin/provenanced" ### Wait for Provenance to fully stand up, just to be safe sleep 5 +# TODO: Investigate getting accounts pre-initialized in the seed? ### Create an address which will act as the administrator of the smart contract -$PROVENANCED keys add marketplace-admin --home /provenance --keyring-backend test --testnet --hd-path "44'/1'/0'/0/0" \ - --output json | jq || exit 1 +echo "$CONTRACT_ADMIN_MNEMONIC" | $PROVENANCED keys add marketplace-admin --home /provenance --keyring-backend test \ + --testnet --hd-path "44'/1'/0'/0/0" --recover --output json | jq || exit 1 ADMIN_ACCOUNT="$($PROVENANCED keys show -a marketplace-admin --home /provenance --keyring-backend test -t)" || exit 1 +### Create an address which will act as a participant in the smart contract +echo "$PARTY1_MNEMONIC" | $PROVENANCED keys add party1 --home /provenance --keyring-backend test \ + --testnet --hd-path "44'/1'/0'/0/0" --recover --output json | jq || exit 1 +PARTY1_ACCOUNT="$($PROVENANCED keys show -a party1 --home /provenance --keyring-backend test -t)" || exit 1 + +### Create an address which will act as another participant in the smart contract +echo "$PARTY2_MNEMONIC" | $PROVENANCED keys add party2 --home /provenance --keyring-backend test \ + --testnet --hd-path "44'/1'/0'/0/0" --recover --output json | jq || exit 1 +PARTY2_ACCOUNT="$($PROVENANCED keys show -a party2 --home /provenance --keyring-backend test -t)" || exit 1 + +### Create an address which will act as yet another participant in the smart contract +echo "$PARTY3_MNEMONIC" | $PROVENANCED keys add party3 --home /provenance --keyring-backend test \ + --testnet --hd-path "44'/1'/0'/0/0" --recover --output json | jq || exit 1 +PARTY3_ACCOUNT="$($PROVENANCED keys show -a party3 --home /provenance --keyring-backend test -t)" || exit 1 + ### Define the address of a validator node in order to fund addresses VALIDATOR="$($PROVENANCED keys show -a validator --home /provenance --keyring-backend test -t)" || exit 1 @@ -48,6 +64,57 @@ $PROVENANCED tx bank send \ --testnet \ --output json | jq || exit 1 +### Create the party1 account +$PROVENANCED tx bank send \ + "$VALIDATOR" \ + "$PARTY1_ACCOUNT" \ + 350000000000nhash \ + --from="$VALIDATOR" \ + --keyring-backend=test \ + --home=/provenance \ + --chain-id=chain-local \ + --gas=auto \ + --gas-prices="1905nhash" \ + --gas-adjustment=1.5 \ + --broadcast-mode=block \ + --yes \ + --testnet \ + --output json | jq || exit 1 + +### Create the party2 account +$PROVENANCED tx bank send \ + "$VALIDATOR" \ + "$PARTY2_ACCOUNT" \ + 350000000000nhash \ + --from="$VALIDATOR" \ + --keyring-backend=test \ + --home=/provenance \ + --chain-id=chain-local \ + --gas=auto \ + --gas-prices="1905nhash" \ + --gas-adjustment=1.5 \ + --broadcast-mode=block \ + --yes \ + --testnet \ + --output json | jq || exit 1 + +### Create the party3 account +$PROVENANCED tx bank send \ + "$VALIDATOR" \ + "$PARTY3_ACCOUNT" \ + 350000000000nhash \ + --from="$VALIDATOR" \ + --keyring-backend=test \ + --home=/provenance \ + --chain-id=chain-local \ + --gas=auto \ + --gas-prices="1905nhash" \ + --gas-adjustment=1.5 \ + --broadcast-mode=block \ + --yes \ + --testnet \ + --output json | jq || exit 1 + ### Create an unrestricted name that we will bind the address of the smart contract to $PROVENANCED tx name bind \ "sc" \ @@ -120,6 +187,9 @@ fi ### Export the addresses export ADMIN_ACCOUNT +export PARTY1_ACCOUNT +export PARTY2_ACCOUNT +export PARTY3_ACCOUNT export VALIDATOR export VO_CONTRACT diff --git a/util/src/main/kotlin/tech/figure/validationoracle/util/enums/ProvenanceNetworkType.kt b/util/src/main/kotlin/tech/figure/validationoracle/util/enums/ProvenanceNetworkType.kt index eeb7210..3a733d0 100644 --- a/util/src/main/kotlin/tech/figure/validationoracle/util/enums/ProvenanceNetworkType.kt +++ b/util/src/main/kotlin/tech/figure/validationoracle/util/enums/ProvenanceNetworkType.kt @@ -10,7 +10,7 @@ import io.provenance.hdwallet.hrp.Hrp */ enum class ProvenanceNetworkType(val prefix: String, val hdPath: String) { MAINNET(prefix = Hrp.ProvenanceBlockchain.mainnet, hdPath = "m/44'/505'/0'/0/0"), - TESTNET(prefix = Hrp.ProvenanceBlockchain.testnet, hdPath = "m/44'/1'/0'/0/0'"), + TESTNET(prefix = Hrp.ProvenanceBlockchain.testnet, hdPath = "m/44'/1'/0'/0/0"), COSMOS_TESTNET(prefix = Hrp.ProvenanceBlockchain.testnet, hdPath = "m/44'/1'/0'/0/0"); fun toNetworkType(): NetworkType = NetworkType(prefix = prefix, path = hdPath)