diff --git a/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/Instructions.kt b/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/Instructions.kt index 0417ec972..91d270f6c 100644 --- a/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/Instructions.kt +++ b/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/Instructions.kt @@ -444,6 +444,18 @@ object Instructions { ), ) + /** + * Transfer domain ownership. + */ + fun transferDomainOwnership(sourceId: AccountId, value: IdBox.DomainId, destinationId: AccountId) = + InstructionBox.Transfer( + TransferBox( + sourceId = IdBox.AccountId(sourceId).evaluatesTo(), + `object` = Value.Id(value).evaluatesTo(), + destinationId = IdBox.AccountId(destinationId).evaluatesTo(), + ), + ) + /** * Evaluate one instruction if a [condition] is met and another one otherwise. */ @@ -480,6 +492,30 @@ object Instructions { } } + /** + * Revoke an account the [Permissions.CanSetKeyValueInUserAccount] permission + */ + fun revokeSetKeyValueAccount(accountId: AccountId, target: AccountId): InstructionBox { + return revokeSome(IdBox.AccountId(target)) { + PermissionToken( + definitionId = Permissions.CanSetKeyValueInUserAccount.type, + payload = accountId.asJsonString().asStringWithJson(), + ) + } + } + + /** + * Revoke an account the [Permissions.CanSetKeyValueInDomain] permission + */ + fun revokeSetKeyValueDomain(domainId: DomainId, target: AccountId): InstructionBox { + return revokeSome(IdBox.AccountId(target)) { + PermissionToken( + definitionId = Permissions.CanSetKeyValueInDomain.type, + payload = domainId.asJsonString().asStringWithJson(), + ) + } + } + /** * Revoke an account a given role. */ diff --git a/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/TransactionBuilder.kt b/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/TransactionBuilder.kt index ffa3f91c5..0de9d58cf 100644 --- a/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/TransactionBuilder.kt +++ b/modules/client/src/main/kotlin/jp/co/soramitsu/iroha2/transaction/TransactionBuilder.kt @@ -13,6 +13,7 @@ import jp.co.soramitsu.iroha2.generated.AssetValue import jp.co.soramitsu.iroha2.generated.AssetValueType import jp.co.soramitsu.iroha2.generated.DomainId import jp.co.soramitsu.iroha2.generated.Executable +import jp.co.soramitsu.iroha2.generated.IdBox import jp.co.soramitsu.iroha2.generated.InstructionBox import jp.co.soramitsu.iroha2.generated.IpfsPath import jp.co.soramitsu.iroha2.generated.Metadata @@ -393,6 +394,10 @@ class TransactionBuilder(builder: TransactionBuilder.() -> Unit = {}) { instructions.value.add(Instructions.transferAsset(sourceId, value, destinationId)) } + fun transferDomainOwnership(sourceId: AccountId, value: IdBox.DomainId, destinationId: AccountId) = this.apply { + instructions.value.add(Instructions.transferDomainOwnership(sourceId, value, destinationId)) + } + fun `if`(condition: Boolean, then: InstructionBox, otherwise: InstructionBox) = this.apply { instructions.value.add(Instructions.`if`(condition, then, otherwise)) } @@ -412,6 +417,12 @@ class TransactionBuilder(builder: TransactionBuilder.() -> Unit = {}) { fun revokeSetKeyValueAsset(assetId: AssetId, target: AccountId) = this.apply { instructions.value.add(Instructions.revokeSetKeyValueAsset(assetId, target)) } + fun revokeSetKeyValueAccount(accountId: AccountId, target: AccountId) = + this.apply { instructions.value.add(Instructions.revokeSetKeyValueAccount(accountId, target)) } + + fun revokeSetKeyValueDomain(domainId: DomainId, target: AccountId) = + this.apply { instructions.value.add(Instructions.revokeSetKeyValueDomain(domainId, target)) } + fun revokeRole( roleId: RoleId, accountId: AccountId, diff --git a/modules/client/src/test/kotlin/jp/co/soramitsu/iroha2/InstructionsTest.kt b/modules/client/src/test/kotlin/jp/co/soramitsu/iroha2/InstructionsTest.kt index 87ccefa0c..3e078af81 100644 --- a/modules/client/src/test/kotlin/jp/co/soramitsu/iroha2/InstructionsTest.kt +++ b/modules/client/src/test/kotlin/jp/co/soramitsu/iroha2/InstructionsTest.kt @@ -12,6 +12,7 @@ import jp.co.soramitsu.iroha2.generated.AssetDefinitionId import jp.co.soramitsu.iroha2.generated.AssetId import jp.co.soramitsu.iroha2.generated.AssetValue import jp.co.soramitsu.iroha2.generated.AssetValueType +import jp.co.soramitsu.iroha2.generated.IdBox import jp.co.soramitsu.iroha2.generated.Metadata import jp.co.soramitsu.iroha2.generated.Name import jp.co.soramitsu.iroha2.generated.PermissionToken @@ -35,6 +36,7 @@ import jp.co.soramitsu.iroha2.testengine.DEFAULT_ASSET_DEFINITION_ID import jp.co.soramitsu.iroha2.testengine.DEFAULT_ASSET_ID import jp.co.soramitsu.iroha2.testengine.DEFAULT_DOMAIN_ID import jp.co.soramitsu.iroha2.testengine.DefaultGenesis +import jp.co.soramitsu.iroha2.testengine.GENESIS import jp.co.soramitsu.iroha2.testengine.IROHA_CONFIG_DELIMITER import jp.co.soramitsu.iroha2.testengine.IrohaTest import jp.co.soramitsu.iroha2.testengine.NewAccountWithMetadata @@ -1020,6 +1022,37 @@ class InstructionsTest : IrohaTest() { assertEquals(27, domains.size) } + @Test + @WithIroha([DefaultGenesis::class]) + @Feature("Domains") + @Story("Account transfers domain ownership") + @SdkTestId("transfer_domain_ownership") + fun `transfer domain ownership`(): Unit = runBlocking { + val genesisAccountId = AccountId(GENESIS.asName(), GENESIS.asDomainId()) + var domain = QueryBuilder.findDomainById(DEFAULT_DOMAIN_ID) + .account(super.account) + .buildSigned(super.keyPair) + .let { query -> + client.sendQuery(query) + } + assertEquals(genesisAccountId, domain.ownedBy) + + client.tx { + transferDomainOwnership( + genesisAccountId, + IdBox.DomainId(DEFAULT_DOMAIN_ID), + BOB_ACCOUNT_ID, + ) + } + domain = QueryBuilder.findDomainById(DEFAULT_DOMAIN_ID) + .account(super.account) + .buildSigned(super.keyPair) + .let { query -> + client.sendQuery(query) + } + assertEquals(BOB_ACCOUNT_ID, domain.ownedBy) + } + private suspend fun registerAccount(id: AccountId, publicKey: PublicKey) { client.sendTransaction { account(super.account)