diff --git a/LATEST_RELEASE b/LATEST_RELEASE index 42045aca..c2c0004f 100644 --- a/LATEST_RELEASE +++ b/LATEST_RELEASE @@ -1 +1 @@ -0.3.4 +0.3.5 diff --git a/VERSION b/VERSION index c2c0004f..449d7e73 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.5 +0.3.6 diff --git a/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/config/SpliceConfig.scala b/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/config/SpliceConfig.scala index f742ab74..c419dc5f 100644 --- a/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/config/SpliceConfig.scala +++ b/apps/app/src/main/scala/org/lfdecentralizedtrust/splice/config/SpliceConfig.scala @@ -9,12 +9,6 @@ import cats.syntax.either.* import cats.syntax.functor.* import org.lfdecentralizedtrust.splice.auth.AuthConfig import org.lfdecentralizedtrust.splice.environment.DarResources -import org.lfdecentralizedtrust.splice.http.v0.definitions.{ - AppConfiguration, - Domain, - ReleaseConfiguration, - Timespan, -} import org.lfdecentralizedtrust.splice.http.UrlValidator import org.lfdecentralizedtrust.splice.scan.admin.api.client.BftScanConnection.BftScanClientConfig import org.lfdecentralizedtrust.splice.scan.config.{ @@ -590,16 +584,6 @@ object SpliceConfig { deriveReader[ValidatorSynchronizerConfig] implicit val offsetDateTimeConfigurationReader: ConfigReader[java.time.OffsetDateTime] = implicitly[ConfigReader[String]].map(java.time.OffsetDateTime.parse) - implicit val timespanConfigurationReader: ConfigReader[Timespan] = deriveReader[Timespan] - implicit val domainConfigurationReader: ConfigReader[Domain] = deriveReader[Domain] - implicit val releaseConfigurationReader: ConfigReader[ReleaseConfiguration] = - deriveReader[ReleaseConfiguration] - implicit val appConfigurationReader: ConfigReader[AppConfiguration] = - deriveReader[AppConfiguration] - implicit val initialRegisteredAppReader: ConfigReader[InitialRegisteredApp] = - deriveReader[InitialRegisteredApp] - implicit val initialInstalledAppReader: ConfigReader[InitialInstalledApp] = - deriveReader[InitialInstalledApp] implicit val transferPreapprovalConfigReader: ConfigReader[TransferPreapprovalConfig] = deriveReader[TransferPreapprovalConfig].emap { conf => Either.cond( @@ -851,16 +835,6 @@ object SpliceConfig { deriveWriter[ValidatorSynchronizerConfig] implicit val offsetDateTimeConfigurationWriter: ConfigWriter[java.time.OffsetDateTime] = implicitly[ConfigWriter[String]].contramap(_.toString) - implicit val timespanConfigurationWriter: ConfigWriter[Timespan] = deriveWriter[Timespan] - implicit val domainConfigurationWriter: ConfigWriter[Domain] = deriveWriter[Domain] - implicit val releaseConfigurationWriter: ConfigWriter[ReleaseConfiguration] = - deriveWriter[ReleaseConfiguration] - implicit val appConfigurationWriter: ConfigWriter[AppConfiguration] = - deriveWriter[AppConfiguration] - implicit val initialRegisteredAppWriter: ConfigWriter[InitialRegisteredApp] = - deriveWriter[InitialRegisteredApp] - implicit val initialInstalledAppWriter: ConfigWriter[InitialInstalledApp] = - deriveWriter[InitialInstalledApp] implicit val transferPreapprovalConfigWriter: ConfigWriter[TransferPreapprovalConfig] = deriveWriter[TransferPreapprovalConfig] implicit val migrateValidatorPartyConfigWriter: ConfigWriter[MigrateValidatorPartyConfig] = diff --git a/apps/app/src/test/resources/include/scans/_scan.conf b/apps/app/src/test/resources/include/scans/_scan.conf index 0c9d3e7f..3578cd83 100644 --- a/apps/app/src/test/resources/include/scans/_scan.conf +++ b/apps/app/src/test/resources/include/scans/_scan.conf @@ -9,7 +9,7 @@ serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/include/splitwell-apps/provider-splitwell-backend.conf b/apps/app/src/test/resources/include/splitwell-apps/provider-splitwell-backend.conf index 60d25f77..df3557e5 100644 --- a/apps/app/src/test/resources/include/splitwell-apps/provider-splitwell-backend.conf +++ b/apps/app/src/test/resources/include/splitwell-apps/provider-splitwell-backend.conf @@ -9,7 +9,7 @@ providerSplitwellBackend { serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/include/svs/_sv.conf b/apps/app/src/test/resources/include/svs/_sv.conf index d67aa179..1c23c018 100644 --- a/apps/app/src/test/resources/include/svs/_sv.conf +++ b/apps/app/src/test/resources/include/svs/_sv.conf @@ -9,7 +9,7 @@ serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/include/validators/_validator.conf b/apps/app/src/test/resources/include/validators/_validator.conf index 96dc2613..749e6af1 100644 --- a/apps/app/src/test/resources/include/validators/_validator.conf +++ b/apps/app/src/test/resources/include/validators/_validator.conf @@ -8,7 +8,7 @@ serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/local-sv-node/scan-app/app.conf b/apps/app/src/test/resources/local-sv-node/scan-app/app.conf index 1904185b..5f043bab 100644 --- a/apps/app/src/test/resources/local-sv-node/scan-app/app.conf +++ b/apps/app/src/test/resources/local-sv-node/scan-app/app.conf @@ -30,7 +30,7 @@ canton { serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/local-sv-node/sv-app/app.conf b/apps/app/src/test/resources/local-sv-node/sv-app/app.conf index 3e1a3a8a..245a6b23 100644 --- a/apps/app/src/test/resources/local-sv-node/sv-app/app.conf +++ b/apps/app/src/test/resources/local-sv-node/sv-app/app.conf @@ -9,7 +9,7 @@ _sv { serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/local-sv-node/validator-app/app.conf b/apps/app/src/test/resources/local-sv-node/validator-app/app.conf index 92b87259..69d7afcc 100644 --- a/apps/app/src/test/resources/local-sv-node/validator-app/app.conf +++ b/apps/app/src/test/resources/local-sv-node/validator-app/app.conf @@ -10,7 +10,7 @@ canton { serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/resources/local-validator-node/validator-app/app.conf b/apps/app/src/test/resources/local-validator-node/validator-app/app.conf index 57befddd..b5fc5319 100644 --- a/apps/app/src/test/resources/local-validator-node/validator-app/app.conf +++ b/apps/app/src/test/resources/local-validator-node/validator-app/app.conf @@ -10,7 +10,7 @@ canton { serverName = ${?POSTGRES_HOST} portNumber = "5432" portNumber = ${?POSTGRES_PORT} - databaseName = "cn_apps" + databaseName = "splice_apps" user = "canton" user = ${?POSTGRES_USER} password = "supersafe" diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SplitwellFrontendIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SplitwellFrontendIntegrationTest.scala index 7c74a2f6..c8e38cc5 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SplitwellFrontendIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SplitwellFrontendIntegrationTest.scala @@ -82,6 +82,9 @@ class SplitwellFrontendIntegrationTest withFrontEnd("aliceSplitwell") { implicit webDriver => eventuallyClickOn(className("add-user-link")) + eventually() { + findAll(className("balances-table-row")).toSeq should have length 2 + } inside(find(className("enter-payment-amount-field"))) { case Some(field) => field.underlying.click() @@ -221,6 +224,9 @@ class SplitwellFrontendIntegrationTest withFrontEnd("aliceSplitwell") { implicit webDriver => eventuallyClickOn(className("add-user-link")) + eventually() { + findAll(className("balances-table-row")).toSeq should have length 1 + } addTeamLunch(1000) } diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ValidatorReonboardingIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ValidatorReonboardingIntegrationTest.scala index fbfed4ab..04621302 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ValidatorReonboardingIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/ValidatorReonboardingIntegrationTest.scala @@ -43,7 +43,7 @@ class ValidatorReonboardingIntegrationTest Seq( "participant_alice_validator", "participant_alice_validator_reonboard_new", - "cn_apps_reonboard", + "splice_apps_reonboard", ) ++ super.usesDbs // Runs against a temporary Canton instance. @@ -111,7 +111,7 @@ class ValidatorReonboardingIntegrationTest config = c.config .withValue( "properties.databaseName", - ConfigValueFactory.fromAnyRef("cn_apps_reonboard"), + ConfigValueFactory.fromAnyRef("splice_apps_reonboard"), ) ) case _ => throw new IllegalArgumentException("Only Postgres is supported") diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletSweepIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletSweepIntegrationTest.scala index 25314734..e604188e 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletSweepIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletSweepIntegrationTest.scala @@ -1,5 +1,11 @@ package org.lfdecentralizedtrust.splice.integration.tests +import com.digitalasset.canton.config.CantonRequireTypes.InstanceName +import com.digitalasset.canton.config.RequireTypes.NonNegativeNumeric +import com.digitalasset.canton.integration.BaseEnvironmentDefinition +import com.digitalasset.canton.logging.SuppressionRule +import com.digitalasset.canton.topology.PartyId +import io.grpc.{Status, StatusRuntimeException} import org.lfdecentralizedtrust.splice.automation.Trigger import org.lfdecentralizedtrust.splice.config.ConfigTransforms import org.lfdecentralizedtrust.splice.config.ConfigTransforms.{ @@ -7,6 +13,10 @@ import org.lfdecentralizedtrust.splice.config.ConfigTransforms.{ updateAllValidatorConfigs, updateAutomationConfig, } +import org.lfdecentralizedtrust.splice.console.{ + ValidatorAppBackendReference, + WalletAppClientReference, +} import org.lfdecentralizedtrust.splice.environment.{BaseLedgerConnection, EnvironmentImpl} import org.lfdecentralizedtrust.splice.integration.EnvironmentDefinition import org.lfdecentralizedtrust.splice.integration.tests.SpliceTests.{ @@ -20,17 +30,12 @@ import org.lfdecentralizedtrust.splice.wallet.automation.{ WalletPreapprovalSweepTrigger, } import org.lfdecentralizedtrust.splice.wallet.config.{AutoAcceptTransfersConfig, WalletSweepConfig} -import com.digitalasset.canton.config.CantonRequireTypes.InstanceName -import com.digitalasset.canton.config.RequireTypes.NonNegativeNumeric -import com.digitalasset.canton.integration.BaseEnvironmentDefinition -import com.digitalasset.canton.logging.SuppressionRule -import com.digitalasset.canton.topology.PartyId import org.slf4j.event.Level -import io.grpc.{Status, StatusRuntimeException} +import java.util.UUID import scala.concurrent.duration.DurationInt -class WalletSweepIntegrationTest +abstract class WalletSweepIntegrationTest extends IntegrationTestWithSharedEnvironment with WalletTestUtil with TriggerTestUtil { @@ -39,119 +44,56 @@ class WalletSweepIntegrationTest val minBalanceUsd: BigDecimal = BigDecimal(2) val amuletPrice: BigDecimal = BigDecimal(1) + val isSweepingToValidator: Boolean = true + override def walletAmuletPrice = SpliceUtil.damlDecimal(amuletPrice.bigDecimal) - override def environmentDefinition - : BaseEnvironmentDefinition[EnvironmentImpl, SpliceTestConsoleEnvironment] = - EnvironmentDefinition - .simpleTopology1Sv(this.getClass.getSimpleName) - .addConfigTransforms((_, config) => { - val aliceParticipant = - ConfigTransforms - .getParticipantIds(config.parameters.clock)("alice_validator_user") - val alicePartyHint = - config.validatorApps(InstanceName.tryCreate("aliceValidator")).validatorPartyHint.value - val alicePartyId = PartyId - .tryFromProtoPrimitive( - s"${alicePartyHint}::${aliceParticipant.split("::").last}" - ) - val bobParticipant = - ConfigTransforms - .getParticipantIds(config.parameters.clock)("bob_validator_user") - val bobPartyHint = - config.validatorApps(InstanceName.tryCreate("bobValidator")).validatorPartyHint.value - val bobPartyId = PartyId - .tryFromProtoPrimitive( - s"${bobPartyHint}::${bobParticipant.split("::").last}" - ) - val sv1Participant = - ConfigTransforms - .getParticipantIds(config.parameters.clock)("sv1") - val sv1LedgerApiUser = - config.svApps(InstanceName.tryCreate("sv1")).svPartyHint.value - val sv1PartyId = PartyId - .tryFromProtoPrimitive( - s"${BaseLedgerConnection - .sanitizeUserIdToPartyString(sv1LedgerApiUser)}::${sv1Participant.split("::").last}" - ) - updateAllValidatorConfigs { case (name, c) => - if (name == "sv1Validator") { - c.copy( - walletSweep = Map( - sv1PartyId.toProtoPrimitive -> WalletSweepConfig( - NonNegativeNumeric.tryCreate(maxBalanceUsd), - NonNegativeNumeric.tryCreate(minBalanceUsd), - alicePartyId, - ) - ) - ) - } else if (name == "aliceValidator") { - c.copy( - autoAcceptTransfers = Map( - alicePartyId.toProtoPrimitive -> - AutoAcceptTransfersConfig(fromParties = Seq(sv1PartyId)) - ) - ) - } else if (name == "bobValidator") { - c.copy( - walletSweep = Map( - bobPartyId.toProtoPrimitive -> WalletSweepConfig( - NonNegativeNumeric.tryCreate(maxBalanceUsd), - NonNegativeNumeric.tryCreate(minBalanceUsd), - alicePartyId, - useTransferPreapproval = true, - ) - ) - ) - } else { - c - } - }(config) - }) - .withAmuletPrice(amuletPrice) - .addConfigTransforms((_, config) => - updateAutomationConfig(ConfigurableApp.Validator)( - // Disable by default so we can explictly control when it runs - _.withPausedTrigger[WalletPreapprovalSweepTrigger] - )(config) - ) - .withSequencerConnectionsFromScanDisabled() + def walletClient(implicit env: SpliceTestConsoleEnvironment): WalletAppClientReference + def user(implicit env: SpliceTestConsoleEnvironment): String + + def onboard( + walletClient: WalletAppClientReference, + user: String, + validatorBackend: ValidatorAppBackendReference, + )(implicit env: SpliceTestConsoleEnvironment): PartyId "SV1's wallet" should { "not be swept if the balance is under the maximum allowed balance" in { implicit env => - onboardWalletUser(aliceValidatorWalletClient, aliceValidatorBackend) + onboard(walletClient, user, aliceValidatorBackend) sv1WalletClient.tap(maxBalanceUsd - 5) val sv1BalanceAtStart = sv1WalletClient.balance().unlockedQty.longValue - val aliceBalanceAtStart = aliceValidatorWalletClient.balance().unlockedQty.longValue + val aliceBalanceAtStart = walletClient.balance().unlockedQty.longValue clue("sv1 should keep its amulets") { eventually() { sv1WalletClient.balance().unlockedQty.longValue shouldBe sv1BalanceAtStart - aliceValidatorWalletClient.balance().unlockedQty.longValue shouldBe aliceBalanceAtStart + walletClient.balance().unlockedQty.longValue shouldBe aliceBalanceAtStart } } } "be swept if the balance is above the maximum allowed balance" in { implicit env => - onboardWalletUser(aliceValidatorWalletClient, aliceValidatorBackend) + onboard(walletClient, user, aliceValidatorBackend) + sv1WalletClient.tap(maxBalanceUsd + 2) - val aliceBalanceAtStart = aliceValidatorWalletClient.balance().unlockedQty.longValue + val aliceBalanceAtStart = walletClient.balance().unlockedQty.longValue clue( s"sv1 should transfer its amulets to alice and still have a minimal balance of $minBalanceUsd" ) { eventually(40.seconds) { assertSweepCompleted() - aliceValidatorWalletClient.balance().unlockedQty.longValue should be > aliceBalanceAtStart + walletClient.balance().unlockedQty.longValue should be > aliceBalanceAtStart } } + } "check that the sweep is completed even if the first offer is not immediately accepted." in { implicit env => - onboardWalletUser(aliceValidatorWalletClient, aliceValidatorBackend) + onboard(walletClient, user, aliceValidatorBackend) sweepAndTransfersAreIdle() - val aliceBalanceAtStart = aliceValidatorWalletClient.balance().unlockedQty.longValue + val aliceBalanceAtStart = walletClient.balance().unlockedQty.longValue setTriggersWithin( triggersToPauseAtStart = autoAcceptTransferOffersTriggers, @@ -171,9 +113,9 @@ class WalletSweepIntegrationTest { _ => eventually() { sv1Balance() shouldBe >(maxBalanceUsd) - val txOffers = aliceValidatorWalletClient.listTransferOffers() + val txOffers = walletClient.listTransferOffers() txOffers should have size 1 - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listAcceptedTransferOffers() shouldBe empty ccToDollars( txOffers.headOption.value.payload.amount.amount, amuletPrice.bigDecimal, @@ -198,32 +140,33 @@ class WalletSweepIntegrationTest { _ => sv1Balance() - firstTransferAmountUsd shouldBe >(maxBalanceUsd) eventually() { - aliceValidatorWalletClient.listTransferOffers() should have size 2 - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listTransferOffers() should have size 2 + walletClient.listAcceptedTransferOffers() shouldBe empty } }, ) } clue("After resuming auto-accept, SV1 is drained and Alice receives funds") { eventually(40.seconds) { - aliceValidatorWalletClient.listTransferOffers() shouldBe empty - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listTransferOffers() shouldBe empty + walletClient.listAcceptedTransferOffers() shouldBe empty assertSweepCompleted() - aliceValidatorWalletClient + walletClient .balance() .unlockedQty .longValue should be > aliceBalanceAtStart } } } + } "check that the sweep is completed even if an offer is rejected" in { implicit env => - onboardWalletUser(aliceValidatorWalletClient, aliceValidatorBackend) + onboard(walletClient, user, aliceValidatorBackend) sweepAndTransfersAreIdle() - val aliceBalanceAtStart = aliceValidatorWalletClient.balance().unlockedQty.longValue + val aliceBalanceAtStart = walletClient.balance().unlockedQty.longValue setTriggersWithin(triggersToPauseAtStart = autoAcceptTransferOffersTriggers, Seq.empty) { actAndCheck( @@ -233,23 +176,23 @@ class WalletSweepIntegrationTest "Alice sees exactly one transfer offer", { _ => eventually() { - aliceValidatorWalletClient.listTransferOffers() should have size 1 - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listTransferOffers() should have size 1 + walletClient.listAcceptedTransferOffers() shouldBe empty } }, ) clue("Alice cancels the transfer offer") { - aliceValidatorWalletClient.rejectTransferOffer( - aliceValidatorWalletClient.listTransferOffers().head.contractId + walletClient.rejectTransferOffer( + walletClient.listTransferOffers().head.contractId ) } } clue("After resuming auto-accept, SV1 is drained and Alice receives funds") { eventually(40.seconds) { - aliceValidatorWalletClient.listTransferOffers() shouldBe empty - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listTransferOffers() shouldBe empty + walletClient.listAcceptedTransferOffers() shouldBe empty assertSweepCompleted() - aliceValidatorWalletClient + walletClient .balance() .unlockedQty .longValue should be > aliceBalanceAtStart @@ -259,7 +202,8 @@ class WalletSweepIntegrationTest "sweep through transfer preapproval should work" in { implicit env => onboardWalletUser(bobValidatorWalletClient, bobValidatorBackend) - val alicePartyId = onboardWalletUser(aliceValidatorWalletClient, aliceValidatorBackend) + val alicePartyId = onboard(walletClient, user, aliceValidatorBackend) + inside( bobValidatorBackend .userWalletAutomation(bobValidatorWalletClient.config.ledgerApiUser) @@ -274,8 +218,11 @@ class WalletSweepIntegrationTest } actAndCheck( "Alice creates transfer preapproval", { - aliceValidatorWalletClient.tap(50.0) - aliceValidatorWalletClient.createTransferPreapproval() + aliceValidatorWalletClient.tap( + 50.0 + ) // validator needs to have some funds to create preapproval + walletClient.tap(50.0) + walletClient.createTransferPreapproval() }, )( "Transfer preapproval is visible in scan", @@ -298,7 +245,7 @@ class WalletSweepIntegrationTest bobValidatorWalletClient.balance().unlockedQty should beAround(20.0) }, ) - val previousBalance = aliceValidatorWalletClient.balance().unlockedQty.longValue + val previousBalance = walletClient.balance().unlockedQty.longValue actAndCheck( "Sweep kicks in", bobValidatorBackend @@ -311,7 +258,7 @@ class WalletSweepIntegrationTest "balances are updated", _ => { bobValidatorWalletClient.balance().unlockedQty should beAround(2) - aliceValidatorWalletClient.balance().unlockedQty should beAround(previousBalance + 18) + walletClient.balance().unlockedQty should beAround(previousBalance + 18) }, ) bobValidatorBackend @@ -333,8 +280,8 @@ class WalletSweepIntegrationTest clue("There are no outstanding transfer offers to accept or complete") { eventually() { sv1Balance() shouldBe <(maxBalanceUsd) - aliceValidatorWalletClient.listTransferOffers() shouldBe empty - aliceValidatorWalletClient.listAcceptedTransferOffers() shouldBe empty + walletClient.listTransferOffers() shouldBe empty + walletClient.listAcceptedTransferOffers() shouldBe empty } } @@ -342,10 +289,10 @@ class WalletSweepIntegrationTest private def autoAcceptTransferOffersTriggers(implicit environment: SpliceTestConsoleEnvironment ): Seq[Trigger] = { - val aliceUserName = aliceValidatorWalletClient.config.ledgerApiUser + val username = walletClient.config.ledgerApiUser Seq( aliceValidatorBackend - .userWalletAutomation(aliceUserName) + .userWalletAutomation(username) .futureValue .trigger[AutoAcceptTransferOffersTrigger] ) @@ -359,3 +306,212 @@ class WalletSweepIntegrationTest } } + +class WalletSweepToValidatorOperatorIntegrationTest extends WalletSweepIntegrationTest { + + override def walletClient(implicit env: SpliceTestConsoleEnvironment): WalletAppClientReference = + aliceValidatorWalletClient + override def user(implicit env: SpliceTestConsoleEnvironment): String = + aliceValidatorBackend.config.validatorPartyHint.value + + override def onboard( + walletClient: WalletAppClientReference, + user: String, + validatorBackend: ValidatorAppBackendReference, + )(implicit env: SpliceTestConsoleEnvironment): PartyId = { + onboardWalletUser(walletClient, validatorBackend) + } + + override def environmentDefinition + : BaseEnvironmentDefinition[EnvironmentImpl, SpliceTestConsoleEnvironment] = + EnvironmentDefinition + .simpleTopology1Sv(this.getClass.getSimpleName) + .addConfigTransforms((_, config) => { + val aliceParticipant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("alice_validator_user") + val alicePartyHint = + config.validatorApps(InstanceName.tryCreate("aliceValidator")).validatorPartyHint.value + val alicePartyId = PartyId + .tryFromProtoPrimitive( + s"${alicePartyHint}::${aliceParticipant.split("::").last}" + ) + val bobParticipant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("bob_validator_user") + val bobPartyHint = + config.validatorApps(InstanceName.tryCreate("bobValidator")).validatorPartyHint.value + val bobPartyId = PartyId + .tryFromProtoPrimitive( + s"${bobPartyHint}::${bobParticipant.split("::").last}" + ) + val sv1Participant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("sv1") + val sv1LedgerApiUser = + config.svApps(InstanceName.tryCreate("sv1")).svPartyHint.value + val sv1PartyId = PartyId + .tryFromProtoPrimitive( + s"${BaseLedgerConnection + .sanitizeUserIdToPartyString(sv1LedgerApiUser)}::${sv1Participant.split("::").last}" + ) + updateAllValidatorConfigs { case (name, c) => + if (name == "sv1Validator") { + c.copy( + walletSweep = Map( + sv1PartyId.toProtoPrimitive -> WalletSweepConfig( + NonNegativeNumeric.tryCreate(maxBalanceUsd), + NonNegativeNumeric.tryCreate(minBalanceUsd), + alicePartyId, + ) + ) + ) + } else if (name == "aliceValidator") { + c.copy( + autoAcceptTransfers = Map( + alicePartyId.toProtoPrimitive -> + AutoAcceptTransfersConfig(fromParties = Seq(sv1PartyId)) + ) + ) + } else if (name == "bobValidator") { + c.copy( + walletSweep = Map( + bobPartyId.toProtoPrimitive -> WalletSweepConfig( + NonNegativeNumeric.tryCreate(maxBalanceUsd), + NonNegativeNumeric.tryCreate(minBalanceUsd), + alicePartyId, + useTransferPreapproval = true, + ) + ) + ) + } else { + c + } + }(config) + }) + .withAmuletPrice(amuletPrice) + .addConfigTransforms((_, config) => + updateAutomationConfig(ConfigurableApp.Validator)( + // Disable by default so we can explictly control when it runs + _.withPausedTrigger[WalletPreapprovalSweepTrigger] + )(config) + ) + .withSequencerConnectionsFromScanDisabled() + +} + +class WalletSweepToEndUserIntegrationTest extends WalletSweepIntegrationTest { + + override val isSweepingToValidator = false + + override def walletClient(implicit env: SpliceTestConsoleEnvironment): WalletAppClientReference = + aliceWalletClient + + val username = "alice-end-user-" + UUID.randomUUID().toString.take(5) + override def user(implicit env: SpliceTestConsoleEnvironment): String = username + + override def onboard( + walletClient: WalletAppClientReference, + user: String, + validatorBackend: ValidatorAppBackendReference, + )(implicit env: SpliceTestConsoleEnvironment): PartyId = { + val aliceParticipant = + ConfigTransforms + .getParticipantIds(env.environment.config.parameters.clock)("alice_validator_user") + val aliceEndUserPartyId = PartyId + .tryFromProtoPrimitive( + s"$user::${aliceParticipant.split("::").last}" + ) + if ( + !aliceValidatorBackend.participantClientWithAdminToken.ledger_api.parties + .list() + .exists(e => e.party == aliceEndUserPartyId) + ) { + aliceValidatorBackend.participantClientWithAdminToken.ledger_api.parties.allocate(user, "") + } + val newPartyId = + aliceValidatorBackend.onboardUser( + walletClient.config.ledgerApiUser, + Some(aliceEndUserPartyId), + ) + waitForWalletUser(walletClient) + newPartyId + } + + override def environmentDefinition + : BaseEnvironmentDefinition[EnvironmentImpl, SpliceTestConsoleEnvironment] = + EnvironmentDefinition + .simpleTopology1Sv(this.getClass.getSimpleName) + .addConfigTransforms((_, config) => { + val aliceParticipant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("alice_validator_user") + val aliceUser = username + val alicePartyId = PartyId + .tryFromProtoPrimitive( + s"$aliceUser::${aliceParticipant.split("::").last}" + ) + val bobParticipant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("bob_validator_user") + val bobPartyHint = + config.validatorApps(InstanceName.tryCreate("bobValidator")).validatorPartyHint.value + val bobPartyId = PartyId + .tryFromProtoPrimitive( + s"$bobPartyHint::${bobParticipant.split("::").last}" + ) + val sv1Participant = + ConfigTransforms + .getParticipantIds(config.parameters.clock)("sv1") + val sv1LedgerApiUser = + config.svApps(InstanceName.tryCreate("sv1")).svPartyHint.value + val sv1PartyId = PartyId + .tryFromProtoPrimitive( + s"${BaseLedgerConnection + .sanitizeUserIdToPartyString(sv1LedgerApiUser)}::${sv1Participant.split("::").last}" + ) + updateAllValidatorConfigs { case (name, c) => + if (name == "sv1Validator") { + c.copy( + walletSweep = Map( + sv1PartyId.toProtoPrimitive -> WalletSweepConfig( + NonNegativeNumeric.tryCreate(maxBalanceUsd), + NonNegativeNumeric.tryCreate(minBalanceUsd), + alicePartyId, + ) + ) + ) + } else if (name == "aliceValidator") { + c.copy( + autoAcceptTransfers = Map( + alicePartyId.toProtoPrimitive -> + AutoAcceptTransfersConfig(fromParties = Seq(sv1PartyId)) + ) + ) + } else if (name == "bobValidator") { + c.copy( + walletSweep = Map( + bobPartyId.toProtoPrimitive -> WalletSweepConfig( + NonNegativeNumeric.tryCreate(maxBalanceUsd), + NonNegativeNumeric.tryCreate(minBalanceUsd), + alicePartyId, + useTransferPreapproval = true, + ) + ) + ) + } else { + c + } + }(config) + }) + .withAmuletPrice(amuletPrice) + .addConfigTransforms((_, config) => + updateAutomationConfig(ConfigurableApp.Validator)( + // Disable by default so we can explictly control when it runs + _.withPausedTrigger[WalletPreapprovalSweepTrigger] + // .withPausedTrigger[WalletTransferOfferSweepTrigger] + )(config) + ) + .withSequencerConnectionsFromScanDisabled() + +} diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTransactionHistoryFrontendIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTransactionHistoryFrontendIntegrationTest.scala index 46559766..e49a0ecc 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTransactionHistoryFrontendIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTransactionHistoryFrontendIntegrationTest.scala @@ -17,7 +17,6 @@ import org.lfdecentralizedtrust.splice.wallet.store.{ NotificationTxLogEntry, TxLogEntry as walletLogEntry, } -import com.digitalasset.canton.topology.PartyId import org.lfdecentralizedtrust.splice.config.ConfigTransforms import org.scalatest.Assertion @@ -190,6 +189,7 @@ class WalletTransactionHistoryFrontendIntegrationTest "show extra traffic purchases" in { implicit env => withFrontEnd("sv1") { implicit webDriver => val sv1WalletUser = sv1ValidatorBackend.config.validatorWalletUser.value + val sv1Party = sv1ValidatorBackend.getValidatorPartyId() browseToSv1Wallet(sv1WalletUser) val trafficAmount = 10_000_000L val (_, trafficCostCc) = computeSynchronizerFees(trafficAmount) @@ -201,7 +201,6 @@ class WalletTransactionHistoryFrontendIntegrationTest _ => { val txs = findAll(className("tx-row")).toSeq val sv1ValidatorParty = sv1WalletClient.userStatus().party - val dsoParty = sv1ScanBackend.getDsoPartyId() val sv1Name = sv1Backend .getDsoInfo() @@ -218,7 +217,7 @@ class WalletTransactionHistoryFrontendIntegrationTest expectedAction = "Sent", expectedSubtype = "Extra Traffic Purchase", expectedPartyDescription = Some( - s"${expectedAns(dsoParty, s"dso.$ansAcronym")} ${expectedAns(PartyId.tryFromProtoPrimitive(sv1ValidatorParty), s"${sv1Name.toLowerCase}.sv.$ansAcronym")}" + s"Automation ${expectedAns(sv1Party, s"${sv1Name.toLowerCase}.sv.$ansAcronym")}" ), expectedAmountAmulet = -trafficCostCc, ) diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesIntegrationTest.scala index c38e809e..a278b02e 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesIntegrationTest.scala @@ -80,11 +80,7 @@ class WalletTxLogWithSynchronizerFeesIntegrationTest -totalCostCc - smallAmount, -totalCostCc, ) - inside(logEntry.receivers) { case Seq(receiver) => - receiver.party shouldBe dsoParty.toProtoPrimitive - // domain fees paid is immediately burnt by DSO - receiver.amount shouldBe 0 - } + logEntry.receivers shouldBe empty }, { case logEntry: BalanceChangeTxLogEntry => logEntry.subtype.value shouldBe walletLogEntry.BalanceChangeTransactionSubtype.Tap.toProto @@ -119,11 +115,7 @@ class WalletTxLogWithSynchronizerFeesIntegrationTest -totalCostCc - smallAmount, -totalCostCc, ) - inside(logEntry.receivers) { case Seq(receiver) => - receiver.party shouldBe dsoParty.toProtoPrimitive - // domain fees paid is immediately burnt by DSO - receiver.amount shouldBe 0 - } + logEntry.receivers shouldBe empty }, { case logEntry: BalanceChangeTxLogEntry => logEntry.subtype.value shouldBe walletLogEntry.BalanceChangeTransactionSubtype.Tap.toProto diff --git a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest.scala b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest.scala index ad0d288c..ae1416f1 100644 --- a/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest.scala +++ b/apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest.scala @@ -99,11 +99,7 @@ class WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest -totalCostCc - smallAmount, -totalCostCc, ) - inside(logEntry.receivers) { case Seq(receiver) => - receiver.party shouldBe dsoParty.toProtoPrimitive - // domain fees paid is immediately burnt by DSO - receiver.amount shouldBe 0 - } + logEntry.receivers shouldBe empty }, { case logEntry: TransferTxLogEntry => logEntry.subtype.value shouldBe walletLogEntry.TransferTransactionSubtype.P2PPaymentCompleted.toProto @@ -163,11 +159,7 @@ class WalletTxLogWithSynchronizerFeesNoDevNetTimeBasedIntegrationTest -totalCostCc - smallAmount, -totalCostCc, ) - inside(logEntry.receivers) { case Seq(receiver) => - receiver.party shouldBe dsoParty.toProtoPrimitive - // domain fees paid is immediately burnt by DSO - receiver.amount shouldBe 0 - } + logEntry.receivers shouldBe empty }, { case logEntry: TransferTxLogEntry => logEntry.subtype.value shouldBe walletLogEntry.TransferTransactionSubtype.P2PPaymentCompleted.toProto diff --git a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/environment/DarResources.scala b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/environment/DarResources.scala index 13a3b33d..85172f14 100644 --- a/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/environment/DarResources.scala +++ b/apps/common/src/main/scala/org/lfdecentralizedtrust/splice/environment/DarResources.scala @@ -18,6 +18,7 @@ object DarResources { val amulet_0_1_4 = DarResource("splice-amulet-0.1.4.dar") val amulet_0_1_5 = DarResource("splice-amulet-0.1.5.dar") val amulet_0_1_6 = DarResource("splice-amulet-0.1.6.dar") + val amulet_0_1_7 = DarResource("splice-amulet-0.1.7.dar") val amulet_current = DarResource("splice-amulet-current.dar") val amulet = PackageResource( amulet_current, @@ -29,6 +30,7 @@ object DarResources { amulet_0_1_4, amulet_0_1_5, amulet_0_1_6, + amulet_0_1_7, ), ) @@ -42,6 +44,7 @@ object DarResources { val dsoGovernance_0_1_7 = DarResource("splice-dso-governance-0.1.7.dar") val dsoGovernance_0_1_8 = DarResource("splice-dso-governance-0.1.8.dar") val dsoGovernance_0_1_9 = DarResource("splice-dso-governance-0.1.9.dar") + val dsoGovernance_0_1_10 = DarResource("splice-dso-governance-0.1.10.dar") val dsoGovernance_current = DarResource("splice-dso-governance-current.dar") val dsoGovernance = PackageResource( dsoGovernance_current, @@ -56,6 +59,7 @@ object DarResources { dsoGovernance_0_1_7, dsoGovernance_0_1_8, dsoGovernance_0_1_9, + dsoGovernance_0_1_10, ), ) @@ -66,6 +70,7 @@ object DarResources { val amuletNameService_0_1_4 = DarResource("splice-amulet-name-service-0.1.4.dar") val amuletNameService_0_1_5 = DarResource("splice-amulet-name-service-0.1.5.dar") val amuletNameService_0_1_6 = DarResource("splice-amulet-name-service-0.1.6.dar") + val amuletNameService_0_1_7 = DarResource("splice-amulet-name-service-0.1.7.dar") val amuletNameService_current = DarResource("splice-amulet-name-service-current.dar") val amuletNameService = PackageResource( amuletNameService_current, @@ -77,6 +82,7 @@ object DarResources { amuletNameService_0_1_4, amuletNameService_0_1_5, amuletNameService_0_1_6, + amuletNameService_0_1_7, ), ) @@ -87,6 +93,7 @@ object DarResources { val splitwell_0_1_4 = DarResource("splitwell-0.1.4.dar") val splitwell_0_1_5 = DarResource("splitwell-0.1.5.dar") val splitwell_0_1_6 = DarResource("splitwell-0.1.6.dar") + val splitwell_0_1_7 = DarResource("splitwell-0.1.7.dar") val splitwell_current = DarResource("splitwell-current.dar") val splitwell = PackageResource( splitwell_current, @@ -98,6 +105,7 @@ object DarResources { splitwell_0_1_4, splitwell_0_1_5, splitwell_0_1_6, + splitwell_0_1_7, ), ) @@ -108,6 +116,7 @@ object DarResources { val wallet_0_1_4 = DarResource("splice-wallet-0.1.4.dar") val wallet_0_1_5 = DarResource("splice-wallet-0.1.5.dar") val wallet_0_1_6 = DarResource("splice-wallet-0.1.6.dar") + val wallet_0_1_7 = DarResource("splice-wallet-0.1.7.dar") val wallet_current = DarResource("splice-wallet-current.dar") val wallet = PackageResource( wallet_current, @@ -119,6 +128,7 @@ object DarResources { wallet_0_1_4, wallet_0_1_5, wallet_0_1_6, + wallet_0_1_7, ), ) @@ -129,6 +139,7 @@ object DarResources { val walletPayments_0_1_4 = DarResource("splice-wallet-payments-0.1.4.dar") val walletPayments_0_1_5 = DarResource("splice-wallet-payments-0.1.5.dar") val walletPayments_0_1_6 = DarResource("splice-wallet-payments-0.1.6.dar") + val walletPayments_0_1_7 = DarResource("splice-wallet-payments-0.1.7.dar") val walletPayments_current = DarResource("splice-wallet-payments-current.dar") val walletPayments = PackageResource( walletPayments_current, @@ -140,6 +151,7 @@ object DarResources { walletPayments_0_1_4, walletPayments_0_1_5, walletPayments_0_1_6, + walletPayments_0_1_7, ), ) diff --git a/apps/package-lock.json b/apps/package-lock.json index fc0c31bd..e75fd3f8 100644 --- a/apps/package-lock.json +++ b/apps/package-lock.json @@ -26,13 +26,13 @@ "wallet/external-openapi-ts-client" ], "dependencies": { - "@daml.js/ans": "file:common/frontend/daml.js/splice-amulet-name-service-0.1.6", - "@daml.js/splice-amulet": "file:common/frontend/daml.js/splice-amulet-0.1.6", - "@daml.js/splice-dso-governance": "file:common/frontend/daml.js/splice-dso-governance-0.1.9", + "@daml.js/ans": "file:common/frontend/daml.js/splice-amulet-name-service-0.1.7", + "@daml.js/splice-amulet": "file:common/frontend/daml.js/splice-amulet-0.1.7", + "@daml.js/splice-dso-governance": "file:common/frontend/daml.js/splice-dso-governance-0.1.10", "@daml.js/splice-validator-lifecycle": "file:common/frontend/daml.js/splice-validator-lifecycle-0.1.1", - "@daml.js/splice-wallet": "file:common/frontend/daml.js/splice-wallet-0.1.6", - "@daml.js/splice-wallet-payments": "file:common/frontend/daml.js/splice-wallet-payments-0.1.6", - "@daml.js/splitwell": "file:common/frontend/daml.js/splitwell-0.1.6", + "@daml.js/splice-wallet": "file:common/frontend/daml.js/splice-wallet-0.1.7", + "@daml.js/splice-wallet-payments": "file:common/frontend/daml.js/splice-wallet-payments-0.1.7", + "@daml.js/splitwell": "file:common/frontend/daml.js/splitwell-0.1.7", "xunit-viewer": "^10.6.1" } }, @@ -1696,6 +1696,19 @@ "common/frontend/daml.js/splice-amulet-0.1.6": { "name": "@daml.js/splice-amulet-0.1.6", "version": "0.0.0", + "extraneous": true, + "license": "UNLICENSED", + "dependencies": { + "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/c3bb0c5d04799b3f11bad7c3c102963e115cf53da3e4afcbcfd9f06ebd82b4ff": "file:../c3bb0c5d04799b3f11bad7c3c102963e115cf53da3e4afcbcfd9f06ebd82b4ff", + "@mojotech/json-type-validation": "^3.1.0" + } + }, + "common/frontend/daml.js/splice-amulet-0.1.7": { + "name": "@daml.js/splice-amulet-0.1.7", + "version": "0.0.0", "license": "UNLICENSED", "dependencies": { "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", @@ -1786,6 +1799,7 @@ "common/frontend/daml.js/splice-amulet-name-service-0.1.6": { "name": "@daml.js/splice-amulet-name-service-0.1.6", "version": "0.0.0", + "extraneous": true, "license": "UNLICENSED", "dependencies": { "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", @@ -1795,6 +1809,18 @@ "@mojotech/json-type-validation": "^3.1.0" } }, + "common/frontend/daml.js/splice-amulet-name-service-0.1.7": { + "name": "@daml.js/splice-amulet-name-service-0.1.7", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/splice-amulet-0.1.7": "file:../splice-amulet-0.1.7", + "@daml.js/splice-wallet-payments-0.1.7": "file:../splice-wallet-payments-0.1.7", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "common/frontend/daml.js/splice-dso-governance-0.1.0": { "name": "@daml.js/splice-dso-governance-0.1.0", "version": "0.0.0", @@ -1827,6 +1853,21 @@ "@mojotech/json-type-validation": "^3.1.0" } }, + "common/frontend/daml.js/splice-dso-governance-0.1.10": { + "name": "@daml.js/splice-dso-governance-0.1.10", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/c3bb0c5d04799b3f11bad7c3c102963e115cf53da3e4afcbcfd9f06ebd82b4ff": "file:../c3bb0c5d04799b3f11bad7c3c102963e115cf53da3e4afcbcfd9f06ebd82b4ff", + "@daml.js/splice-amulet-0.1.7": "file:../splice-amulet-0.1.7", + "@daml.js/splice-amulet-name-service-0.1.7": "file:../splice-amulet-name-service-0.1.7", + "@daml.js/splice-wallet-payments-0.1.7": "file:../splice-wallet-payments-0.1.7", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "common/frontend/daml.js/splice-dso-governance-0.1.2": { "name": "@daml.js/splice-dso-governance-0.1.2", "version": "0.0.0", @@ -1910,6 +1951,7 @@ "common/frontend/daml.js/splice-dso-governance-0.1.9": { "name": "@daml.js/splice-dso-governance-0.1.9", "version": "0.0.0", + "extraneous": true, "license": "UNLICENSED", "dependencies": { "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", @@ -2028,6 +2070,7 @@ "common/frontend/daml.js/splice-wallet-0.1.6": { "name": "@daml.js/splice-wallet-0.1.6", "version": "0.0.0", + "extraneous": true, "license": "UNLICENSED", "dependencies": { "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", @@ -2038,6 +2081,19 @@ "@mojotech/json-type-validation": "^3.1.0" } }, + "common/frontend/daml.js/splice-wallet-0.1.7": { + "name": "@daml.js/splice-wallet-0.1.7", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/splice-amulet-0.1.7": "file:../splice-amulet-0.1.7", + "@daml.js/splice-wallet-payments-0.1.7": "file:../splice-wallet-payments-0.1.7", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "common/frontend/daml.js/splice-wallet-payments-0.1.0": { "name": "@daml.js/splice-wallet-payments-0.1.0", "version": "0.0.0", @@ -2119,6 +2175,7 @@ "common/frontend/daml.js/splice-wallet-payments-0.1.6": { "name": "@daml.js/splice-wallet-payments-0.1.6", "version": "0.0.0", + "extraneous": true, "license": "UNLICENSED", "dependencies": { "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", @@ -2128,6 +2185,18 @@ "@mojotech/json-type-validation": "^3.1.0" } }, + "common/frontend/daml.js/splice-wallet-payments-0.1.7": { + "name": "@daml.js/splice-wallet-payments-0.1.7", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/splice-amulet-0.1.7": "file:../splice-amulet-0.1.7", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "common/frontend/daml.js/splitwell-0.1.0": { "name": "@daml.js/splitwell-0.1.0", "version": "0.0.0", @@ -2201,6 +2270,7 @@ "common/frontend/daml.js/splitwell-0.1.6": { "name": "@daml.js/splitwell-0.1.6", "version": "0.0.0", + "extraneous": true, "license": "UNLICENSED", "dependencies": { "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", @@ -2211,6 +2281,19 @@ "@mojotech/json-type-validation": "^3.1.0" } }, + "common/frontend/daml.js/splitwell-0.1.7": { + "name": "@daml.js/splitwell-0.1.7", + "version": "0.0.0", + "license": "UNLICENSED", + "dependencies": { + "@daml.js/5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4": "file:../5aee9b21b8e9a4c4975b5f4c4198e6e6e8469df49e2010820e792f393db870f4", + "@daml.js/9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69": "file:../9e70a8b3510d617f8a136213f33d6a903a10ca0eeec76bb06ba55d1ed9680f69", + "@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": "file:../b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946", + "@daml.js/splice-amulet-0.1.7": "file:../splice-amulet-0.1.7", + "@daml.js/splice-wallet-payments-0.1.7": "file:../splice-wallet-payments-0.1.7", + "@mojotech/json-type-validation": "^3.1.0" + } + }, "common/frontend/daml.js/splitwell-0.2.0": { "name": "@daml.js/splitwell-0.2.0", "version": "0.0.0", @@ -4536,7 +4619,7 @@ "link": true }, "node_modules/@daml.js/ans": { - "resolved": "common/frontend/daml.js/splice-amulet-name-service-0.1.6", + "resolved": "common/frontend/daml.js/splice-amulet-name-service-0.1.7", "link": true }, "node_modules/@daml.js/b70db8369e1c461d5c70f1c86f526a29e9776c655e6ffc2560f95b05ccb8b946": { @@ -4548,19 +4631,19 @@ "link": true }, "node_modules/@daml.js/splice-amulet": { - "resolved": "common/frontend/daml.js/splice-amulet-0.1.6", + "resolved": "common/frontend/daml.js/splice-amulet-0.1.7", "link": true }, - "node_modules/@daml.js/splice-amulet-0.1.6": { - "resolved": "common/frontend/daml.js/splice-amulet-0.1.6", + "node_modules/@daml.js/splice-amulet-0.1.7": { + "resolved": "common/frontend/daml.js/splice-amulet-0.1.7", "link": true }, - "node_modules/@daml.js/splice-amulet-name-service-0.1.6": { - "resolved": "common/frontend/daml.js/splice-amulet-name-service-0.1.6", + "node_modules/@daml.js/splice-amulet-name-service-0.1.7": { + "resolved": "common/frontend/daml.js/splice-amulet-name-service-0.1.7", "link": true }, "node_modules/@daml.js/splice-dso-governance": { - "resolved": "common/frontend/daml.js/splice-dso-governance-0.1.9", + "resolved": "common/frontend/daml.js/splice-dso-governance-0.1.10", "link": true }, "node_modules/@daml.js/splice-validator-lifecycle": { @@ -4568,19 +4651,19 @@ "link": true }, "node_modules/@daml.js/splice-wallet": { - "resolved": "common/frontend/daml.js/splice-wallet-0.1.6", + "resolved": "common/frontend/daml.js/splice-wallet-0.1.7", "link": true }, "node_modules/@daml.js/splice-wallet-payments": { - "resolved": "common/frontend/daml.js/splice-wallet-payments-0.1.6", + "resolved": "common/frontend/daml.js/splice-wallet-payments-0.1.7", "link": true }, - "node_modules/@daml.js/splice-wallet-payments-0.1.6": { - "resolved": "common/frontend/daml.js/splice-wallet-payments-0.1.6", + "node_modules/@daml.js/splice-wallet-payments-0.1.7": { + "resolved": "common/frontend/daml.js/splice-wallet-payments-0.1.7", "link": true }, "node_modules/@daml.js/splitwell": { - "resolved": "common/frontend/daml.js/splitwell-0.1.6", + "resolved": "common/frontend/daml.js/splitwell-0.1.7", "link": true }, "node_modules/@daml/ledger": { diff --git a/apps/package.json b/apps/package.json index 4e15451c..2a457224 100644 --- a/apps/package.json +++ b/apps/package.json @@ -21,13 +21,13 @@ "wallet/external-openapi-ts-client" ], "dependencies": { - "@daml.js/ans": "file:common/frontend/daml.js/splice-amulet-name-service-0.1.6", - "@daml.js/splice-amulet": "file:common/frontend/daml.js/splice-amulet-0.1.6", - "@daml.js/splice-dso-governance": "file:common/frontend/daml.js/splice-dso-governance-0.1.9", + "@daml.js/ans": "file:common/frontend/daml.js/splice-amulet-name-service-0.1.7", + "@daml.js/splice-amulet": "file:common/frontend/daml.js/splice-amulet-0.1.7", + "@daml.js/splice-dso-governance": "file:common/frontend/daml.js/splice-dso-governance-0.1.10", "@daml.js/splice-validator-lifecycle": "file:common/frontend/daml.js/splice-validator-lifecycle-0.1.1", - "@daml.js/splice-wallet": "file:common/frontend/daml.js/splice-wallet-0.1.6", - "@daml.js/splice-wallet-payments": "file:common/frontend/daml.js/splice-wallet-payments-0.1.6", - "@daml.js/splitwell": "file:common/frontend/daml.js/splitwell-0.1.6", + "@daml.js/splice-wallet": "file:common/frontend/daml.js/splice-wallet-0.1.7", + "@daml.js/splice-wallet-payments": "file:common/frontend/daml.js/splice-wallet-payments-0.1.7", + "@daml.js/splitwell": "file:common/frontend/daml.js/splitwell-0.1.7", "xunit-viewer": "^10.6.1" } } diff --git a/apps/sv/frontend/src/components/Layout.tsx b/apps/sv/frontend/src/components/Layout.tsx index b58ec9c7..c656f255 100644 --- a/apps/sv/frontend/src/components/Layout.tsx +++ b/apps/sv/frontend/src/components/Layout.tsx @@ -8,6 +8,7 @@ import { Box, Button, Divider, Stack, Typography } from '@mui/material'; import Container from '@mui/material/Container'; import Link from '@mui/material/Link'; +import { useElectionContext } from '../contexts/SvContext'; import { useNetworkInstanceName } from '../hooks/index'; import { useSvConfig } from '../utils'; @@ -28,6 +29,8 @@ const Layout: React.FC = (props: LayoutProps) => { const actionsPending = listVoteRequestsQuery.data?.filter( vr => vr.payload.votes.entriesArray().find(e => e[1].sv === svPartyId) === undefined ); + const electionContextQuery = useElectionContext(); + const electionRequests = electionContextQuery?.data?.ranking; return ( @@ -57,7 +60,7 @@ const Layout: React.FC = (props: LayoutProps) => { { name: 'Information', path: 'dso' }, { name: 'Validator Onboarding', path: 'validator-onboarding' }, { name: `${config.spliceInstanceNames.amuletName} Price`, path: 'amulet-price' }, - { name: 'Delegate Election', path: 'delegate' }, + { name: 'Delegate Election', path: 'delegate', badgeCount: electionRequests?.length }, { name: 'Governance', path: 'votes', badgeCount: actionsPending?.length }, ]} > diff --git a/apps/sv/frontend/src/components/votes/actions/SetDsoRulesConfig.tsx b/apps/sv/frontend/src/components/votes/actions/SetDsoRulesConfig.tsx index 5bf5ac44..5048f5cb 100644 --- a/apps/sv/frontend/src/components/votes/actions/SetDsoRulesConfig.tsx +++ b/apps/sv/frontend/src/components/votes/actions/SetDsoRulesConfig.tsx @@ -20,38 +20,30 @@ const SetDsoRulesConfig: React.FC<{ const [configuration, setConfiguration] = useState | undefined>( undefined ); - const [nextScheduledSynchronizerUpgrade, setNextScheduledSynchronizerUpgrade] = - useState(false); const dateFormat = 'YYYY-MM-DDTHH:mm:ss[Z]'; - - const addDefaultSynchronizerUpgradeSchedule = () => { - const nextScheduledSynchronizerUpgrade = { - // default schedule an domain upgrade in 3 days - time: dayjs.utc().add(3, 'day').format(dateFormat), - migrationId: '1', - }; - setDsoRulesConfigAction({ - ...configuration, - nextScheduledSynchronizerUpgrade, - }); - }; - - const removeSynchronizerUpgradeSchedule = () => { - setDsoRulesConfigAction({ - ...configuration, - nextScheduledSynchronizerUpgrade: null, - }); + const defaultNextScheduledSynchronizerUpgrade = { + time: dayjs.utc().add(3, 'day').format(dateFormat), + migrationId: '1', }; + const [nextScheduledSynchronizerUpgrade, setNextScheduledSynchronizerUpgrade] = useState( + defaultNextScheduledSynchronizerUpgrade + ); + const [shouldScheduleDomainUpgrade] = useState(false); const handleSynchronizerUpgradeChange = (event: React.ChangeEvent) => { const checked = event.target.checked; if (checked) { - addDefaultSynchronizerUpgradeSchedule(); + setDsoRulesConfigAction({ + ...configuration, + nextScheduledSynchronizerUpgrade, + }); } else { - removeSynchronizerUpgradeSchedule(); + setDsoRulesConfigAction({ + ...configuration, + nextScheduledSynchronizerUpgrade: null, + }); } - setNextScheduledSynchronizerUpgrade(checked); }; const isScheduledDateValid = (scheduledDate: string) => { @@ -66,9 +58,11 @@ const SetDsoRulesConfig: React.FC<{ JSONValue > ); - setNextScheduledSynchronizerUpgrade( - !!dsoInfosQuery.data?.dsoRules.payload.config.nextScheduledSynchronizerUpgrade - ); + const upgradeConfig = + dsoInfosQuery.data?.dsoRules.payload.config.nextScheduledSynchronizerUpgrade; + if (upgradeConfig) { + setNextScheduledSynchronizerUpgrade(upgradeConfig); + } } }, [configuration, dsoInfosQuery]); @@ -123,7 +117,7 @@ const SetDsoRulesConfig: React.FC<{ control={ - for { - // We retry here because this mutates the AmuletRules and rounds contracts, - // which can lead to races. - _ <- retryProvider.retryForClientCalls( - "onboard_validator", - "onboard validator via DsoRules", - onboardValidator(partyId, body.secret, vo, body.version, body.contactPoint), - logger, - ) - } yield v0.SvResource.OnboardValidatorResponseOK + // Check whether a validator license already exists for this party, + // because when recovering from an ACS snapshot "used secret" information will get lost. + dsoStore + .lookupValidatorLicenseWithOffset(PartyId.tryFromProtoPrimitive(body.partyId)) + .flatMap { + case QueryResult(_, Some(_)) => + // This validator is already onboarded - nothing to do + Future.successful(v0.SvResource.OnboardValidatorResponseOK) + case QueryResult(_, None) => + for { + // We retry here because this mutates the AmuletRules and rounds contracts, + // which can lead to races. + _ <- retryProvider.retryForClientCalls( + "onboard_validator", + "onboard validator via DsoRules", + onboardValidator(partyId, body.secret, vo, body.version, body.contactPoint), + logger, + ) + } yield v0.SvResource.OnboardValidatorResponseOK + } } case Left(error) => Future.failed(HttpErrorHandler.badRequest(error)) diff --git a/apps/validator/src/main/openapi/json-api-proxy-internal.yaml b/apps/validator/src/main/openapi/json-api-proxy-internal.yaml deleted file mode 100644 index 5628af1d..00000000 --- a/apps/validator/src/main/openapi/json-api-proxy-internal.yaml +++ /dev/null @@ -1,117 +0,0 @@ -openapi: 3.0.0 -info: - title: Validator API - version: 0.0.1 -tags: - - name: validator -servers: - - url: https://example.com/api/validator/jsonApiProxy -paths: - /v1/user: - post: - tags: [json_api_public] - x-jvm-package: json_api_public - operationId: "jsonApiUser" - parameters: - - in: header - name: authorization - schema: - type: string - required: true - requestBody: - required: true - content: - application/json: - schema: - type: object - responses: - "200": - description: ok - content: - application/json: - schema: - type: object - /v1/query: - post: - tags: [json_api_public] - x-jvm-package: json_api_public - operationId: "jsonApiQuery" - parameters: - - in: header - name: authorization - schema: - type: string - required: true - requestBody: - required: true - content: - application/json: - schema: - type: object - responses: - "200": - description: ok - content: - application/json: - schema: - type: object - /v1/create: - post: - tags: [json_api_public] - x-jvm-package: json_api_public - operationId: "jsonApiCreate" - parameters: - - in: header - name: authorization - schema: - type: string - required: true - requestBody: - required: true - content: - application/json: - schema: - type: object - responses: - "200": - description: ok - content: - application/json: - schema: - type: object - /v1/exercise: - post: - tags: [json_api_public] - x-jvm-package: json_api_public - operationId: "jsonApiExercise" - parameters: - - in: header - name: authorization - schema: - type: string - required: true - requestBody: - required: true - content: - application/json: - schema: - type: object - responses: - "200": - description: ok - content: - application/json: - schema: - type: object - - -components: - schemas: - # A dummy component, to avoid an empty all.ts in the generated typescript - Dummy: - type: object - required: - - name - properties: - name: - type: string diff --git a/apps/validator/src/main/openapi/validator-internal.yaml b/apps/validator/src/main/openapi/validator-internal.yaml index 5cfe8f21..00760a63 100644 --- a/apps/validator/src/main/openapi/validator-internal.yaml +++ b/apps/validator/src/main/openapi/validator-internal.yaml @@ -569,287 +569,6 @@ components: items: type: string - CheckAppAuthorizedResponse: - type: object - required: - - redirect_uri - properties: - redirect_uri: - type: string - - OpenIDConfigurationResponse: - type: object - required: - - issuer - - authorization_endpoint - - token_endpoint - - jwks_uri - properties: - issuer: - type: string - authorization_endpoint: - type: string - token_endpoint: - type: string - jwks_uri: - type: string - - JwksResponse: - type: object - properties: - keys: - type: array - items: - "$ref": "#/components/schemas/Jwk" - required: - - keys - - Jwk: - type: object - properties: - kid: - type: string - kty: - type: string - alg: - type: string - use: - type: string - n: - type: string - e: - type: string - required: - - kid - - kty - - alg - - use - - n - - e - - TokenResponse: - type: object - properties: - access_token: - type: string - token_type: - type: string - # TODO(#6839): consider adding expires_in, refresh_token, scope - required: - - access_token - - token_type - - ListInstalledAppsResponse: - type: object - required: - - apps - properties: - apps: - type: array - items: - "$ref": "#/components/schemas/InstalledApp" - - ListRegisteredAppsResponse: - type: object - required: - - apps - properties: - apps: - type: array - items: - "$ref": "#/components/schemas/RegisteredApp" - - InstalledApp: - type: object - required: - - provider - - latest_configuration - - approved_release_configurations - - unapproved_release_configurations - properties: - provider: - type: string - latest_configuration: - $ref: "#/components/schemas/AppConfiguration" - approved_release_configurations: - type: array - items: - $ref: "#/components/schemas/ReleaseConfiguration" - unapproved_release_configurations: - description: | - The configurations in latest_configuration excluding the ones in - approved_release_configurations. We pass this separately to avoid having - to do a structural equality check in the frontend. - type: array - items: - $ref: "#/components/schemas/UnapprovedReleaseConfiguration" - - UnapprovedReleaseConfiguration: - type: object - required: - - release_configuration_index - - release_configuration - properties: - release_configuration_index: - type: integer - format: int32 - release_configuration: - $ref: "#/components/schemas/ReleaseConfiguration" - - RegisteredApp: - type: object - required: - - provider - - app_url - - configuration - properties: - provider: - type: string - app_url: - type: string - configuration: - $ref: "#/components/schemas/AppConfiguration" - - AppConfiguration: - type: object - required: - - version - - name - - ui_uri - - allowed_redirect_uris - - release_configurations - properties: - version: - type: integer - format: int64 - name: - type: string - ui_uri: - type: string - allowed_redirect_uris: - type: array - items: - type: string - release_configurations: - description: "Multiple release configurations are used to support rolling upgrades." - type: array - items: - $ref: "#/components/schemas/ReleaseConfiguration" - - GetAppConfigurationResult: - type: object - required: - - provider - - configuration - properties: - provider: - type: string - configuration: - $ref: "#/components/schemas/AppConfiguration" - - ReleaseConfiguration: - type: object - required: - - domains - - release_version - - required_for - properties: - domains: - type: array - items: - $ref: "#/components/schemas/Domain" - release_version: - type: string - required_for: - $ref: "#/components/schemas/Timespan" - - Timespan: - type: object - properties: - from: - type: string - format: date-time - to: - type: string - format: date-time - - AppRelease: - type: object - required: - - version - - dar_hashes - properties: - version: - type: string - dar_hashes: - type: array - items: - type: string - - # The file used in the bundle on upload - # TODO(#6839) Consider using AppRelease instead and compute - # hashes as part of bundling. Note that this is non-trivial - # since it's not just a sha256sum of the DAR file itself. It includes - # the purpose which isn't easy to replicate in bash. - AppReleaseUpload: - type: object - required: - - version - properties: - version: - type: string - - Domain: - type: object - required: - - alias - - url - properties: - alias: - type: string - url: - type: string - - DarFile: - type: object - required: - - base64_dar - properties: - # base64 because guardrail doesn't support generating binary files on the client side - base64_dar: - type: string - - InstallAppRequest: - type: object - required: - - app_url - properties: - app_url: - type: string - - UpdateAppConfigurationRequest: - type: object - required: - - configuration - properties: - configuration: - $ref: "#/components/schemas/AppConfiguration" - - ApproveAppReleaseConfigurationRequest: - type: object - required: - - configuration_version - - release_configuration_index - properties: - configuration_version: - type: integer - format: int64 - release_configuration_index: - description: | - Index into the release configurations specified on the app configuration. - type: integer - format: int32 - SequencerConnections: type: object required: diff --git a/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/config/ValidatorAppConfig.scala b/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/config/ValidatorAppConfig.scala index ec6b7ba3..044db0f2 100644 --- a/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/config/ValidatorAppConfig.scala +++ b/apps/validator/src/main/scala/org/lfdecentralizedtrust/splice/validator/config/ValidatorAppConfig.scala @@ -6,7 +6,6 @@ package org.lfdecentralizedtrust.splice.validator.config import org.apache.pekko.http.scaladsl.model.Uri import org.lfdecentralizedtrust.splice.auth.AuthConfig import org.lfdecentralizedtrust.splice.config.* -import org.lfdecentralizedtrust.splice.http.v0.definitions import org.lfdecentralizedtrust.splice.scan.admin.api.client.BftScanConnection.BftScanClientConfig import org.lfdecentralizedtrust.splice.scan.config.ScanAppClientConfig import org.lfdecentralizedtrust.splice.sv.SvAppClientConfig @@ -44,12 +43,6 @@ object ValidatorOnboardingConfig { } } -final case class InitialRegisteredApp( - providerUserId: String, - config: definitions.AppConfiguration, - releaseFile: String, -) - final case class InitialInstalledApp(appUrl: Uri) final case class BuyExtraTrafficConfig( diff --git a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/AutoAcceptTransferOffersTrigger.scala b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/AutoAcceptTransferOffersTrigger.scala index 53316b0b..346a82a7 100644 --- a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/AutoAcceptTransferOffersTrigger.scala +++ b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/AutoAcceptTransferOffersTrigger.scala @@ -51,7 +51,7 @@ class AutoAcceptTransferOffersTrigger( ] )(implicit tc: TraceContext): Future[TaskOutcome] = { if ( - transferOffer.contract.payload.receiver == store.key.validatorParty.toProtoPrimitive && autoAcceptTransfers.fromParties + transferOffer.contract.payload.receiver == store.key.endUserParty.toProtoPrimitive && autoAcceptTransfers.fromParties .contains(Codec.tryDecode(Codec.Party)(transferOffer.contract.payload.sender)) ) { for { @@ -72,7 +72,7 @@ class AutoAcceptTransferOffersTrigger( res <- connection .submit( Seq(store.key.validatorParty), - Seq(), + Seq(store.key.endUserParty), cmd, priority = commandPriority, ) diff --git a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/WalletTransferOfferSweepTrigger.scala b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/WalletTransferOfferSweepTrigger.scala index 3c059852..25dab900 100644 --- a/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/WalletTransferOfferSweepTrigger.scala +++ b/apps/wallet/src/main/scala/org/lfdecentralizedtrust/splice/wallet/automation/WalletTransferOfferSweepTrigger.scala @@ -94,7 +94,7 @@ class WalletTransferOfferSweepTrigger( connection .submit( Seq(store.key.validatorParty), - Seq(), + Seq(store.key.endUserParty), cmd, ) .noDedup diff --git a/build.sbt b/build.sbt index a1380c60..26ec38c5 100644 --- a/build.sbt +++ b/build.sbt @@ -527,21 +527,20 @@ lazy val `apps-validator` = directory = "scan-proxy-openapi-ts-client", ), Compile / guardrailTasks := - List("validator-internal", "json-api-proxy-internal", "ans-external", "scan-proxy").flatMap( - api => - List( - ScalaServer( - new File(s"apps/validator/src/main/openapi/${api}.yaml"), - pkg = "org.lfdecentralizedtrust.splice.http.v0", - modules = List("pekko-http-v1.0.0", "circe"), - customExtraction = true, - ), - ScalaClient( - new File(s"apps/validator/src/main/openapi/${api}.yaml"), - pkg = "org.lfdecentralizedtrust.splice.http.v0", - modules = List("pekko-http-v1.0.0", "circe"), - ), - ) + List("validator-internal", "ans-external", "scan-proxy").flatMap(api => + List( + ScalaServer( + new File(s"apps/validator/src/main/openapi/${api}.yaml"), + pkg = "org.lfdecentralizedtrust.splice.http.v0", + modules = List("pekko-http-v1.0.0", "circe"), + customExtraction = true, + ), + ScalaClient( + new File(s"apps/validator/src/main/openapi/${api}.yaml"), + pkg = "org.lfdecentralizedtrust.splice.http.v0", + modules = List("pekko-http-v1.0.0", "circe"), + ), + ) ), ) @@ -970,35 +969,6 @@ lazy val `apps-splitwell` = modules = List("pekko-http-v1.0.0", "circe"), ), ), - Compile / resourceGenerators += Def.task { - val log = streams.value.log - val splitwellOutput = (`splitwell-daml` / Compile / damlBuild).value - val splitwellDar = ((`splitwell-daml` / Compile / damlBuild).value).head.toString - val output1_0 = - baseDirectory.value / "src" / "test" / "resources" / "splitwell-bundle-1.0.0.tar.gz" - val output2_0 = - baseDirectory.value / "src" / "test" / "resources" / "splitwell-bundle-2.0.0.tar.gz" - // TODO(#16859) Remove this after bumping the base version - val createBundle = baseDirectory.value / "../../scripts/create-bundle-for-app-mgr.sh" - val cacheDir = streams.value.cacheDirectory - val cache = FileFunction.cached(cacheDir) { _ => - runCommand( - Seq(createBundle.toString, splitwellDar, "splitwell", "1.0.0", output1_0.toString), - log, - None, - None, - ) - runCommand( - Seq(createBundle.toString, splitwellDar, "splitwell", "2.0.0", output2_0.toString), - log, - None, - None, - ) - Set(output1_0, output2_0) - - } - cache((createBundle +: splitwellOutput).toSet).toSeq - }.taskValue, ) lazy val pulumi = diff --git a/cluster/pulumi/infra/grafana-dashboards/canton-network/cometbft.json b/cluster/pulumi/infra/grafana-dashboards/canton-network/cometbft.json index e3b092d4..59b74f89 100644 --- a/cluster/pulumi/infra/grafana-dashboards/canton-network/cometbft.json +++ b/cluster/pulumi/infra/grafana-dashboards/canton-network/cometbft.json @@ -19,16 +19,11 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 96, + "id": 2281, "links": [], - "liveNow": false, "panels": [ { "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, "gridPos": { "h": 1, "w": 24, @@ -37,15 +32,6 @@ }, "id": 64, "panels": [], - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], "title": "$chain_id overview", "type": "row" }, @@ -85,7 +71,6 @@ "x": 0, "y": 1 }, - "hideTimeOverride": false, "id": 4, "maxDataPoints": 100, "options": { @@ -93,6 +78,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -104,7 +90,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -159,7 +145,6 @@ "x": 6, "y": 1 }, - "hideTimeOverride": false, "id": 40, "maxDataPoints": 100, "options": { @@ -167,6 +152,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -178,7 +164,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -214,6 +200,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -274,7 +261,6 @@ "x": 12, "y": 1 }, - "hideTimeOverride": true, "id": 65, "options": { "legend": { @@ -288,7 +274,7 @@ "sort": "none" } }, - "pluginVersion": "10.0.2", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -342,13 +328,13 @@ "x": 18, "y": 1 }, - "hideTimeOverride": false, "id": 47, "options": { "colorMode": "value", "graphMode": "area", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -360,7 +346,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -396,6 +382,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -446,7 +433,6 @@ "x": 0, "y": 5 }, - "hideTimeOverride": false, "id": 66, "maxDataPoints": 100, "options": { @@ -461,7 +447,7 @@ "sort": "none" } }, - "pluginVersion": "10.0.2", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -499,6 +485,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -559,7 +546,6 @@ "x": 12, "y": 5 }, - "hideTimeOverride": true, "id": 39, "options": { "legend": { @@ -573,7 +559,7 @@ "sort": "none" } }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -608,6 +594,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", @@ -691,7 +678,6 @@ "x": 0, "y": 9 }, - "hideTimeOverride": false, "id": 15, "options": { "legend": { @@ -710,7 +696,7 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -771,6 +757,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", @@ -854,7 +841,6 @@ "x": 12, "y": 9 }, - "hideTimeOverride": false, "id": 48, "options": { "legend": { @@ -873,7 +859,7 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -961,7 +947,6 @@ "x": 0, "y": 18 }, - "hideTimeOverride": true, "id": 67, "options": { "alignValue": "left", @@ -978,7 +963,7 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1017,6 +1002,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", @@ -1100,7 +1086,6 @@ "x": 12, "y": 18 }, - "hideTimeOverride": false, "id": 49, "options": { "legend": { @@ -1118,7 +1103,7 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1154,6 +1139,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", @@ -1237,7 +1223,6 @@ "x": 0, "y": 25 }, - "hideTimeOverride": false, "id": 50, "options": { "legend": { @@ -1254,7 +1239,7 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1291,6 +1276,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -1341,7 +1327,6 @@ "x": 12, "y": 25 }, - "hideTimeOverride": false, "id": 68, "options": { "legend": { @@ -1355,7 +1340,7 @@ "sort": "none" } }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1381,10 +1366,6 @@ }, { "collapsed": false, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, "gridPos": { "h": 1, "w": 24, @@ -1394,15 +1375,6 @@ "id": 55, "panels": [], "repeat": "instance", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "refId": "A" - } - ], "title": "instance overview: $instance", "type": "row" }, @@ -1448,7 +1420,6 @@ "x": 0, "y": 31 }, - "hideTimeOverride": true, "id": 53, "options": { "minVizHeight": 75, @@ -1465,7 +1436,7 @@ "showThresholdMarkers": true, "sizing": "auto" }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1524,7 +1495,6 @@ "x": 6, "y": 31 }, - "hideTimeOverride": true, "id": 56, "options": { "minVizHeight": 75, @@ -1541,7 +1511,7 @@ "showThresholdMarkers": true, "sizing": "auto" }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1595,7 +1565,6 @@ "x": 12, "y": 31 }, - "hideTimeOverride": true, "id": 60, "maxDataPoints": 100, "options": { @@ -1603,6 +1572,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -1614,7 +1584,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1668,7 +1638,6 @@ "x": 18, "y": 31 }, - "hideTimeOverride": true, "id": 61, "maxDataPoints": 100, "options": { @@ -1676,6 +1645,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -1687,7 +1657,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1723,6 +1693,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -1750,7 +1721,6 @@ }, "decimals": 0, "mappings": [], - "max": 50, "thresholds": { "mode": "absolute", "steps": [ @@ -1778,7 +1748,6 @@ "x": 0, "y": 35 }, - "hideTimeOverride": true, "id": 70, "options": { "legend": { @@ -1792,7 +1761,7 @@ "sort": "none" } }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1829,6 +1798,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -1879,7 +1849,6 @@ "x": 12, "y": 35 }, - "hideTimeOverride": true, "id": 69, "maxDataPoints": 100, "options": { @@ -1894,7 +1863,7 @@ "sort": "none" } }, - "pluginVersion": "10.4.0", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { @@ -1930,6 +1899,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", @@ -1970,7 +1940,7 @@ } ] }, - "unit": "bytes" + "unit": "binBps" }, "overrides": [] }, @@ -1993,14 +1963,14 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { "uid": "$DS" }, "editorMode": "code", - "expr": "cometbft_p2p_peer_receive_bytes_total{namespace=\"$namespace\", chain_id=\"$chain_id\", job=\"$instance\"}", + "expr": "rate(cometbft_p2p_peer_receive_bytes_total{namespace=\"$namespace\", chain_id=\"$chain_id\", job=\"$instance\"}[$__rate_interval])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{peer_id}}", @@ -2028,6 +1998,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", @@ -2068,7 +2039,7 @@ } ] }, - "unit": "bytes" + "unit": "binBps" }, "overrides": [] }, @@ -2091,14 +2062,14 @@ "sort": "none" } }, - "pluginVersion": "10.1.5", + "pluginVersion": "11.4.0", "targets": [ { "datasource": { "uid": "$DS" }, "editorMode": "code", - "expr": "cometbft_p2p_peer_send_bytes_total{namespace=\"$namespace\", chain_id=\"$chain_id\", job=\"$instance\"}", + "expr": "rate(cometbft_p2p_peer_send_bytes_total{namespace=\"$namespace\", chain_id=\"$chain_id\", job=\"$instance\"}[$__rate_interval]) ", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{peer_id}}", @@ -2110,7 +2081,9 @@ "type": "timeseries" } ], - "schemaVersion": 39, + "preload": false, + "refresh": "", + "schemaVersion": 40, "tags": [ "Blockchain" ], @@ -2118,26 +2091,20 @@ "list": [ { "current": { - "selected": false, "text": "default", "value": "default" }, - "hide": 0, "includeAll": false, "label": "Datasource", - "multi": false, "name": "DS", "options": [], "query": "prometheus", - "queryValue": "", "refresh": 1, "regex": "", - "skipUrlSync": false, "type": "datasource" }, { "current": { - "selected": false, "text": "sv-1", "value": "sv-1" }, @@ -2146,10 +2113,8 @@ "uid": "$DS" }, "definition": "label_values(cometbft_consensus_height,namespace)", - "hide": 0, "includeAll": false, "label": "namespace", - "multi": false, "name": "namespace", "options": [], "query": { @@ -2158,56 +2123,40 @@ }, "refresh": 2, "regex": "", - "skipUrlSync": false, "sort": 1, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" }, { "current": { - "selected": false, - "text": "cilr-0-stable", - "value": "cilr-0-stable" + "text": "cilr-4-0", + "value": "cilr-4-0" }, "datasource": { "type": "prometheus", "uid": "$DS" }, "definition": "label_values(cometbft_consensus_height, chain_id)", - "hide": 0, "includeAll": false, "label": "Chain ID", - "multi": false, "name": "chain_id", "options": [], "query": "label_values(cometbft_consensus_height, chain_id)", "refresh": 1, "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" }, { - "allValue": "", "current": { - "selected": false, - "text": "global-domain-0-cometbft-cometbft-rpc", - "value": "global-domain-0-cometbft-cometbft-rpc" + "text": "global-domain-4-cometbft-cometbft-rpc", + "value": "global-domain-4-cometbft-cometbft-rpc" }, "datasource": { "type": "prometheus", "uid": "$DS" }, "definition": "label_values(cometbft_consensus_height{chain_id=\"$chain_id\"},job)", - "hide": 0, "includeAll": false, "label": "Instance", - "multi": false, "name": "instance", "options": [], "query": { @@ -2216,47 +2165,19 @@ }, "refresh": 1, "regex": "", - "skipUrlSync": false, "sort": 5, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" } ] }, "time": { - "from": "now-2d", + "from": "now-6h", "to": "now" }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, + "timepicker": {}, "timezone": "", "title": "CometBFT", "uid": "UJyurCTWz", - "version": 1, + "version": 5, "weekStart": "" } diff --git a/cluster/pulumi/infra/grafana-dashboards/canton-network/global-sync-utilization.json b/cluster/pulumi/infra/grafana-dashboards/canton-network/global-sync-utilization.json new file mode 100644 index 00000000..0b7ab358 --- /dev/null +++ b/cluster/pulumi/infra/grafana-dashboards/canton-network/global-sync-utilization.json @@ -0,0 +1,256 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 7582, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "The absolute number of transactions on the global synchronizer that are not visible to the DSO, in a sliding window of 30 minutes. Note that currently this may be inaccurate (over-approximated) because any failed transaction is counted as a transaction not visible to the DSO.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.4.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "(sum(increase(daml_mediator_requests_total{namespace=~\"$namespace\"}[30m])) by (namespace) - sum(increase(splice_history_updates_transactions_total{namespace=~\"$namespace\"}[30m])) by (namespace))", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Transactions not seen by DSO (absolute)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "description": "The percentage of transactions on the global synchronizer that are not visible to the DSO, in a sliding window of 30 minutes. Note that currently this may be inaccurate (over-approximated) because any failed transaction is counted as a transaction not visible to the DSO.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.4.0", + "targets": [ + { + "editorMode": "code", + "expr": "(sum(increase(daml_mediator_requests_total{namespace=~\"$namespace\"}[30m])) by (namespace) - sum(increase(splice_history_updates_transactions_total{namespace=~\"$namespace\"}[30m])) by (namespace)) / (sum(increase(daml_mediator_requests_total{namespace=~\"$namespace\"}[30m])) by (namespace) > sum(increase(splice_history_updates_transactions_total{namespace=~\"$namespace\"}[30m])) by (namespace) or sum(increase(splice_history_updates_transactions_total{namespace=~\"$namespace\"}[30m])) by (namespace))", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Transaction not seen by DSO (percentage)", + "type": "timeseries" + } + ], + "preload": false, + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "All", + "value": "$__all" + }, + "definition": "label_values(daml_mediator_requests_total,namespace)", + "description": "", + "includeAll": true, + "label": "Namespace", + "name": "namespace", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(daml_mediator_requests_total,namespace)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": {}, + "timezone": "UTC", + "title": "Global Synchronizer Utilization", + "uid": "fe8wt04z620aof", + "version": 3, + "weekStart": "" +} diff --git a/daml/dars.lock b/daml/dars.lock index 5a92c35a..7fcc2df4 100644 --- a/daml/dars.lock +++ b/daml/dars.lock @@ -5,6 +5,7 @@ splice-amulet 0.1.3 0d89016d5a90eb8bced48bbac99e81c57781b3a36094b8d48b8e4389851e splice-amulet 0.1.4 a36ef8888fb44caae13d96341ce1fabd84fc9e2e7b209bbc3caabb48b6be1668 splice-amulet 0.1.5 b4867a47abbfa2d15482f22c9c50516f0af14036287f299342f5d336391e4997 splice-amulet 0.1.6 979ec710c3ae3a05cb44edf8461a9b4d7dd2053add95664f94fc89e5f18df80f +splice-amulet 0.1.7 4646d50cbdec6f088c98ae543da5c973d2d1be3363b9f32eb097d8fdc063ade7 splice-amulet-name-service 0.1.0 2598a415893cd496306499d4d0a29614621e0ef2ceeed55a63d3bdbb0f57830a splice-amulet-name-service 0.1.1 9e785f2ea6c2faea6bc5f1445482cafaff5a58acf4e83a3afc26b49b9dbce5d5 splice-amulet-name-service 0.1.2 711a2974d65e6ebd149704da75f3f71234798687ab895b92f066c865dbdeeabb @@ -12,12 +13,14 @@ splice-amulet-name-service 0.1.3 beb4b85f3f0cf36dfb93fc917d3ac218ee5d41b6e706047 splice-amulet-name-service 0.1.4 053c7f4c2a77312e7d465a4fa7dc8cb298754ad12c0c987a7c401bd724e65efc splice-amulet-name-service 0.1.5 6188c8b5f612278f988fc95c11e9742993ad3ac6ad0809f9af06ee9d366dc4a8 splice-amulet-name-service 0.1.6 a208aab2c4a248ab2eff352bd382f8b3bbadc92464123db587e8b359312a2f6c -splice-amulet-name-service-test 0.1.6 5124d0c961d22a244d22d04ff36ac15b5b78bba4b21a06e84a23cf113be1ef0f -splice-amulet-test 0.1.6 7b42a008f375cbdf58376d362c48b821ba1b4c7f70d907177bf3f5d01bb75a38 +splice-amulet-name-service 0.1.7 ba7806d9b2d593eac74a050161c54ae1325d170bf175cb66a9c1e5e5ffb88c3d +splice-amulet-name-service-test 0.1.7 c73004668d4676ffb8180e867d9e06471823bad0fc94787467ed0e2afdf78d16 +splice-amulet-test 0.1.7 b81ef9fd891e9f7574e566822fca73dfda629fc630592c5924bdf2965dd0dc98 splice-app-manager 0.1.0 e3605e0112595187ec963700d28f17fe042f3b80c862363e299003b9423a1844 splice-app-manager 0.1.1 e46903bc2e039daa4381f856a5c9fdc876eea41792e5b815e350b4a1afcd280f splice-dso-governance 0.1.0 7e0e82bdbe3941ebd13d029b86bb60640ddc9b7287012d6274194f26cd7b858c splice-dso-governance 0.1.1 332087889d9643fa24961edde7459a08d9edfb4fb737929cd4c79b952bc5819f +splice-dso-governance 0.1.10 1fa33994d8ae60d7839042ec8e0c86b5da2c725f1576a161fbf6d38e259f8c66 splice-dso-governance 0.1.2 4206e127be8b111ac84bd7f98bd9dbf03ed489f1642b46ab31a46ee6d688e7e8 splice-dso-governance 0.1.3 b0ae3cc03e418790305a3c15f761fe495572de5827f8d322fb8b96996b783c13 splice-dso-governance 0.1.4 dc24fd18b4d151cd1e0ff6bfb7438bafb2f50fe076d0f16f50565e60b153a0be @@ -26,7 +29,7 @@ splice-dso-governance 0.1.6 4e7653cfbf7ca249de4507aca9cd3b91060e5489042a522c589d splice-dso-governance 0.1.7 d406eba1132d464605f4dae3edf8cf5ecbbb34bd8edef0e047e7e526d328718c splice-dso-governance 0.1.8 1790a114f83d5f290261fae1e7e46fba75a861a3dd603c6b4ef6b67b49053948 splice-dso-governance 0.1.9 9ee83bfd872f91e659b8a8439c5b4eaf240bcf6f19698f884d7d7993ab48c401 -splice-dso-governance-test 0.1.9 dfb60854de99c4f6d4e9aa5bc2df37f3f178384883604a438ad1654bab3b8d8c +splice-dso-governance-test 0.1.11 87e171a350256144e29f8abdaca1d964b3a0cba3c5b0264d4ff649b77661aa91 splice-util 0.1.0 0f319b3bcc9a418836d58c86deae25b38d3f018f1b0c117456cd9011cface7f1 splice-util 0.1.1 00bf3632ca479d56e536096ca23bbc75d15084088ab5d12e4b31d6547d1df351 splice-validator-lifecycle 0.1.0 cef96fac957362f1fc097120bd13686cac7f84fbc8053afa994a1f9214d9570c @@ -39,6 +42,7 @@ splice-wallet 0.1.3 2c35bb4f5084ea66db59717d21750bfd64c43147ef5fd5166615092d592a splice-wallet 0.1.4 141dad2d33b6410b8e1c35a0c4f8f76cb691e4d9a4410ce89f33f373855317e1 splice-wallet 0.1.5 614b525a50c624062d851ce7df5bdb90ddfa0d6871c486cb6e2c7b694bfbce59 splice-wallet 0.1.6 ba51e944e430facce00c297c58f4769240402721de4a1d121705050f8e9be901 +splice-wallet 0.1.7 d9a91419b27aa27002a883334015a892c35075967b07008a446bc4b5073051ec splice-wallet-payments 0.1.0 50f762c0e3c94db34ccb4fb38e95c190479ee95f1aea4ebce4406a71d4e395e9 splice-wallet-payments 0.1.1 4ef1d8f6aba6f791311ff3c2322bc1220ed81fa7f125891d6d02726c6c7b787a splice-wallet-payments 0.1.2 775f5eb9c0249509adda5eb3ea4ee31bb953601168c18880df6f2ff09ec4298a @@ -46,7 +50,8 @@ splice-wallet-payments 0.1.3 b953b3729c81a55e598a364be7d0c0574750df3de12a7a1b53a splice-wallet-payments 0.1.4 12177f54873c1094ea169874ad0d7838383fd137f302d16356e93f28dfbc0fcc splice-wallet-payments 0.1.5 2177b7a579fe6d3d510c7bcda99d39ece104ae24cfd1b78ac5616990d2d6c675 splice-wallet-payments 0.1.6 6124379528eeb6fa17ecdab15577c29abb33d0c0d34dc5f2680a1ac4f49b1649 -splice-wallet-test 0.1.6 5ddb63a8f0874b31c5119abd65f5b32fc9a084c98571c6d902c243011a6e446e +splice-wallet-payments 0.1.7 4e3e0d9cdadf80f4bf8f3cd3660d5287c084c9a29f23c901aabce597d72fd467 +splice-wallet-test 0.1.7 48bc8460d3bf4367daa6f600e6cd945881c13c9dbe1665848300cf757734caaa splitwell 0.1.0 075c76de553ab88383a7c69de134afa82aacfdf8ea8fcfe8852c4b199c3b2669 splitwell 0.1.1 ccb1a0215053062202052e1a052f9214da3fdae5253a6d43e2e155ff4f57fe75 splitwell 0.1.2 778edd2c228c6b68198d4d033885b2d0dae7daaee55d7df3edd9dfdf1f10fbd0 @@ -54,4 +59,5 @@ splitwell 0.1.3 7cde068cde689584f86a2499689d5cb165264d96496721e24ac6fb909f770a58 splitwell 0.1.4 85557b86cd4f330f093915db1ea26eac5092de6b5ddae0690146f6059c89419b splitwell 0.1.5 a68e78774a7be655f5744c8ae0ac8b46d55ef6d1e7661bc27b9296154d56ac74 splitwell 0.1.6 872da0dd7986fd768930f85d6a7310a94a0ef924e7fbb7bb7a4e149f2b5feb74 -splitwell-test 0.1.6 22d1fe55b5419469e1a6b2a39c08d3ac5f49aaa876e65a2ce1b0c1937ad8474b \ No newline at end of file +splitwell 0.1.7 841d1c9c86b5c8f3a39059459ecd8febedf7703e18f117300bb0ebf4423db096 +splitwell-test 0.1.7 31fc8e7b62e87fb25d45bae8cd5b7b21b4dcdc8601db42d688a7e8730917adb9 \ No newline at end of file diff --git a/daml/dars/splice-amulet-0.1.7.dar b/daml/dars/splice-amulet-0.1.7.dar new file mode 100644 index 00000000..d2ab7850 Binary files /dev/null and b/daml/dars/splice-amulet-0.1.7.dar differ diff --git a/daml/dars/splice-amulet-name-service-0.1.7.dar b/daml/dars/splice-amulet-name-service-0.1.7.dar new file mode 100644 index 00000000..a417f2d6 Binary files /dev/null and b/daml/dars/splice-amulet-name-service-0.1.7.dar differ diff --git a/daml/dars/splice-dso-governance-0.1.10.dar b/daml/dars/splice-dso-governance-0.1.10.dar new file mode 100644 index 00000000..65e10f8f Binary files /dev/null and b/daml/dars/splice-dso-governance-0.1.10.dar differ diff --git a/daml/dars/splice-wallet-0.1.7.dar b/daml/dars/splice-wallet-0.1.7.dar new file mode 100644 index 00000000..6d38a684 Binary files /dev/null and b/daml/dars/splice-wallet-0.1.7.dar differ diff --git a/daml/dars/splice-wallet-payments-0.1.7.dar b/daml/dars/splice-wallet-payments-0.1.7.dar new file mode 100644 index 00000000..d159747f Binary files /dev/null and b/daml/dars/splice-wallet-payments-0.1.7.dar differ diff --git a/daml/dars/splitwell-0.1.7.dar b/daml/dars/splitwell-0.1.7.dar new file mode 100644 index 00000000..77bb4dfb Binary files /dev/null and b/daml/dars/splitwell-0.1.7.dar differ diff --git a/daml/splice-amulet-name-service-test/daml.yaml b/daml/splice-amulet-name-service-test/daml.yaml index 67d6b632..1124f991 100644 --- a/daml/splice-amulet-name-service-test/daml.yaml +++ b/daml/splice-amulet-name-service-test/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-amulet-name-service-test source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-amulet-name-service/daml.yaml b/daml/splice-amulet-name-service/daml.yaml index 34754744..421636af 100644 --- a/daml/splice-amulet-name-service/daml.yaml +++ b/daml/splice-amulet-name-service/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-amulet-name-service source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-amulet-test/daml.yaml b/daml/splice-amulet-test/daml.yaml index 39a967cd..2b27c85f 100644 --- a/daml/splice-amulet-test/daml.yaml +++ b/daml/splice-amulet-test/daml.yaml @@ -6,7 +6,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-amulet-test source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-amulet/daml.yaml b/daml/splice-amulet/daml.yaml index 655e9f20..2ec095c8 100644 --- a/daml/splice-amulet/daml.yaml +++ b/daml/splice-amulet/daml.yaml @@ -6,7 +6,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-amulet source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-amulet/daml/Splice/AmuletRules.daml b/daml/splice-amulet/daml/Splice/AmuletRules.daml index 7d586cd3..e0a191f2 100644 --- a/daml/splice-amulet/daml/Splice/AmuletRules.daml +++ b/daml/splice-amulet/daml/Splice/AmuletRules.daml @@ -125,7 +125,7 @@ template AmuletRules require "preapprovalExpiresAt is not in the past" (preapprovalExpiresAt > now) let configUsd = getValueAsOf now configSchedule (amuletPaid, _) <- computeTransferPreapprovalFee (preapprovalExpiresAt `subTime` now) configUsd context.context dso - transferResult <- chargeTransferPreapprovalFee validator amuletPaid inputs context dso + transferResult <- splitAndBurn validator amuletPaid inputs context.context dso proposalCid <- create ExternalPartySetupProposal with user validator @@ -148,7 +148,7 @@ template AmuletRules require "expiresAt is not in the past" (expiresAt > now) let configUsd = getValueAsOf now configSchedule (amuletPaid, _) <- computeTransferPreapprovalFee (expiresAt `subTime` now) configUsd context.context dso - transferResult <- chargeTransferPreapprovalFee provider amuletPaid inputs context dso + transferResult <- splitAndBurn provider amuletPaid inputs context.context dso transferPreapprovalCid <- create TransferPreapproval with receiver provider @@ -179,31 +179,11 @@ template AmuletRules case validateBuyMemberTrafficInputs configUsd synchronizerId trafficAmount of Left err -> throw (InvalidTransfer err) Right _ -> pure () + openRound <- fetchReferenceData (ForDso with dso) context.openMiningRound + let transferConfigAmulet = scaleFees (1.0 / openRound.amuletPrice) openRound.transferConfigUsd (trafficCostAmulet, trafficCostUsd) <- computeSynchronizerFees provider trafficAmount this context - let transfer = Transfer with - sender = provider - provider - inputs - outputs = [ TransferOutput with - receiver = dso - amount = trafficCostAmulet - receiverFeeRatio = 1.0 -- ensure the provider pays only the traffic cost - lock = None - ] - -- We don't issue any rewards as part of the transfer, as these are only for the burned fees. - rewardsConfig = RewardsIssuanceConfig with - issueAppRewards = False - issueValidatorRewards = False - transferResult <- executeTransfer rewardsConfig context dso transfer - let [TransferResultAmulet amuletCid] = transferResult.createdAmulets - -- burn the amulet created for the DSO party (using fetchAndArchive for extra safety) - void $ fetchAndArchive (ForOwner with dso; owner = dso) amuletCid - -- issue validator rewards over the whole burn - create ValidatorRewardCoupon with - dso - round = transferResult.round - user = provider - amount = trafficCostAmulet + -- We want to burn exactly trafficCostAmulet, and createFee is already burnt by the self-transfer itself, so we subtract the createFee from the amount we split off and burn explicitly. + transferResult <- splitAndBurn provider (trafficCostAmulet - transferConfigAmulet.createFee.fee) inputs context dso -- create a new MemberTraffic contract for the purchased traffic purchasedTraffic <- create MemberTraffic with dso @@ -1344,7 +1324,7 @@ template TransferPreapproval amuletRules <- fetchPublicReferenceData (ForDso dso) context.amuletRules (AmuletRules_Fetch dso) let configUsd = getValueAsOf now amuletRules.configSchedule (amuletPaid, _) <- computeTransferPreapprovalFee extension configUsd context.context dso - transferResult <- chargeTransferPreapprovalFee provider amuletPaid inputs context dso + transferResult <- splitAndBurn provider amuletPaid inputs context.context dso transferPreapprovalCid <- create this with lastRenewedAt = now expiresAt = newExpiresAt @@ -1401,34 +1381,38 @@ computeTransferPreapprovalFee duration amuletConfig context dso = do let feeAmulet = feeUsd / contextMiningRound.amuletPrice pure (feeAmulet, feeUsd) -chargeTransferPreapprovalFee : Party -> Decimal -> [TransferInput] -> PaymentTransferContext -> Party -> Update TransferResult -chargeTransferPreapprovalFee provider feeAmount inputs context dso = do - -- do not create activity records as part of the transfer, as we'll create them later +splitAndBurn : Party -> Decimal -> [TransferInput] -> TransferContext -> Party -> Update TransferResult +splitAndBurn sender amount inputs context dso = do +-- do not create activity records as part of the transfer. We create a validator activity record for the full burn below. let rewardsConfig = RewardsIssuanceConfig with issueAppRewards = False issueValidatorRewards = False - -- do a self-transfer to split the amulet - transferResult <- executeTransfer rewardsConfig context.context dso Transfer with - sender = provider - provider + transferResult <- executeTransfer rewardsConfig context dso Transfer with + sender + provider = sender inputs outputs = [ TransferOutput with - receiver = provider + receiver = sender receiverFeeRatio = 0.0 - amount = feeAmount + amount lock = None ] let [TransferResultAmulet amuletCid] = transferResult.createdAmulets -- burn the split amulet containing the fee amount - void $ fetchAndArchive (ForOwner with dso; owner = provider) amuletCid + amulet <- fetchAndArchive (ForOwner with dso; owner = sender) amuletCid -- create validator activity rewards over the whole burn. - -- this serves to incentivize the provider for creating the pre-approval and - -- enabling the receiver to interact with more entities on the network, - -- thereby contributing to increased network activity. create ValidatorRewardCoupon with dso round = transferResult.round - user = provider - amount = feeAmount + (sum transferResult.summary.outputFees) - pure transferResult + user = sender + amount = amount + sum transferResult.summary.outputFees + let amuletAsOfRoundZero = amulet.amount.initialAmount + amulet.amount.ratePerRound.rate * intToDecimal amulet.amount.createdAt.number + -- adjust the balance changes to account for the archival. This primarily matters for the tx log parsers in scan and the wallet. + return transferResult with + summary.balanceChanges = + Map.insertWith + (+) + sender + (BalanceChange (-amuletAsOfRoundZero) (- (amulet.amount.ratePerRound.rate))) + transferResult.summary.balanceChanges diff --git a/daml/splice-dso-governance-test/daml.yaml b/daml/splice-dso-governance-test/daml.yaml index 104923bd..e073c69b 100644 --- a/daml/splice-dso-governance-test/daml.yaml +++ b/daml/splice-dso-governance-test/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-dso-governance-test source: daml -version: 0.1.9 +version: 0.1.11 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-dso-governance/daml.yaml b/daml/splice-dso-governance/daml.yaml index 045e5fae..da0c75b6 100644 --- a/daml/splice-dso-governance/daml.yaml +++ b/daml/splice-dso-governance/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-dso-governance source: daml -version: 0.1.9 +version: 0.1.10 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-wallet-payments/daml.yaml b/daml/splice-wallet-payments/daml.yaml index bb2e6134..fa8b7df7 100644 --- a/daml/splice-wallet-payments/daml.yaml +++ b/daml/splice-wallet-payments/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-wallet-payments source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-wallet-test/daml.yaml b/daml/splice-wallet-test/daml.yaml index eec182f8..152517c5 100644 --- a/daml/splice-wallet-test/daml.yaml +++ b/daml/splice-wallet-test/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-wallet-test source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-wallet-test/daml/Splice/Scripts/TestWallet.daml b/daml/splice-wallet-test/daml/Splice/Scripts/TestWallet.daml index a67536d7..656e5fae 100644 --- a/daml/splice-wallet-test/daml/Splice/Scripts/TestWallet.daml +++ b/daml/splice-wallet-test/daml/Splice/Scripts/TestWallet.daml @@ -736,8 +736,9 @@ testBuyMemberTraffic = script do -- test that creating the initial traffic contract works before <- query @Amulet aliceValidator.primaryParty - COO_BuyMemberTraffic trafficCid1 <- executeAmuletOperation app aliceValidator $ + r <- executeAmuletOperation app aliceValidator $ CO_BuyMemberTraffic minTopupAmount testParticipantId synchronizerId migrationId (minutes 1) (Some topupStateCid) + COO_BuyMemberTraffic trafficCid1 <- pure r after <- query @Amulet aliceValidator.primaryParty before === after diff --git a/daml/splice-wallet/daml.yaml b/daml/splice-wallet/daml.yaml index 48c8927b..d4976237 100644 --- a/daml/splice-wallet/daml.yaml +++ b/daml/splice-wallet/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splice-wallet source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splitwell-test/daml.yaml b/daml/splitwell-test/daml.yaml index ca4c515b..0d542cce 100644 --- a/daml/splitwell-test/daml.yaml +++ b/daml/splitwell-test/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splitwell-test source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splitwell/daml.yaml b/daml/splitwell/daml.yaml index 6a2e3a2a..31a0bf88 100644 --- a/daml/splitwell/daml.yaml +++ b/daml/splitwell/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.0.0-snapshot.20240318.12913.0.v1c415c97 name: splitwell source: daml -version: 0.1.6 +version: 0.1.7 dependencies: - daml-prim - daml-stdlib diff --git a/nix/flake.lock b/nix/flake.lock index 5c3f273f..5bef566c 100644 --- a/nix/flake.lock +++ b/nix/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733749988, - "narHash": "sha256-+5qdtgXceqhK5ZR1YbP1fAUsweBIrhL38726oIEAtDs=", + "lastModified": 1736166416, + "narHash": "sha256-U47xeACNBpkSO6IcCm0XvahsVXpJXzjPIQG7TZlOToU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bc27f0fde01ce4e1bfec1ab122d72b7380278e68", + "rev": "b30f97d8c32d804d2d832ee837d0f1ca0695faa5", "type": "github" }, "original": { diff --git a/nix/overlays.nix b/nix/overlays.nix index 2d4d55e8..7e37a62a 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -14,8 +14,48 @@ cometbft_driver = super.callPackage ./cometbft-driver.nix {}; daml2js = super.callPackage ./daml2js.nix {}; python3 = super.python3.override { - packageOverrides = pySelf : pySuper : { - sphinx-reredirects = pySelf.callPackage ./sphinx-reredirects.nix { }; + packageOverrides = pySelf : pySuper : rec { + sphinx-reredirects = pySelf.callPackage ./sphinx-reredirects.nix { }; + # gsutil requires an older version of pyopenssl dependency + pyopenssl = pySuper.pyopenssl.overridePythonAttrs (old: rec { + version = "24.2.1"; + src = super.fetchFromGitHub { + owner = "pyca"; + repo = "pyopenssl"; + tag = version; + hash = "sha256-/TQnDWdycN4hQ7ZGvBhMJEZVafmL+0wy9eJ8hC6rfio="; + }; + # we remove the docs output because it fails to build and we don't need it + outputs = [ + "out" + "dev" + ]; + # tweaked to remove the sphinx hook to build docs + nativeBuildInputs = [ + super.openssl + ]; + }); + # downgraded to work with pyopenssl + cryptography = (pySuper.cryptography.override {}).overridePythonAttrs (old: rec { + pname = "cryptography"; + version = "43.0.1"; + src = pySuper.fetchPypi { + inherit pname version; + hash = "sha256-ID6Sp1cW2M+0kdxHx54X0NkgfM/8vLNfWY++RjrjRE0="; + }; + + cargoRoot = "src/rust"; + + cargoDeps = super.rustPlatform.fetchCargoTarball { + inherit src; + sourceRoot = "${pname}-${version}/${cargoRoot}"; + name = "${pname}-${version}"; + hash = "sha256-wiAHM0ucR1X7GunZX8V0Jk2Hsi+dVdGgDKqcYjSdD7Q="; + }; + }); + # downgraded together with cryptography. We can't just override it + # as it's not exposed in pythonpackages so we need to copy vectors.nix + cryptography-vectors = super.callPackage ./vectors.nix { buildPythonPackage = pySuper.buildPythonPackage; cryptography = pySelf.cryptography; flit-core = pySuper.flit-core; }; }; }; pre-commit = super.pre-commit.overrideAttrs (old: { diff --git a/nix/vectors.nix b/nix/vectors.nix new file mode 100644 index 00000000..4f296b03 --- /dev/null +++ b/nix/vectors.nix @@ -0,0 +1,38 @@ +{ + lib, + buildPythonPackage, + fetchPypi, + cryptography, + flit-core, +}: + +buildPythonPackage rec { + pname = "cryptography-vectors"; + # The test vectors must have the same version as the cryptography package + inherit (cryptography) version; + pyproject = true; + + src = fetchPypi { + pname = "cryptography_vectors"; + inherit version; + hash = "sha256-aKD8GP4nswnpM6KTpU8zVreKFMFSB+lsn/hWga8FCd4="; + }; + + nativeBuildInputs = [ flit-core ]; + + # No tests included + doCheck = false; + + pythonImportsCheck = [ "cryptography_vectors" ]; + + meta = with lib; { + description = "Test vectors for the cryptography package"; + homepage = "https://cryptography.io/en/latest/development/test-vectors/"; + downloadPage = "https://github.com/pyca/cryptography/tree/master/vectors"; + license = with licenses; [ + asl20 + bsd3 + ]; + maintainers = with maintainers; [ SuperSandro2000 ]; + }; +} diff --git a/project/Headers.scala b/project/Headers.scala index 6cc15cc2..e8b10d80 100644 --- a/project/Headers.scala +++ b/project/Headers.scala @@ -90,6 +90,7 @@ object Headers { Compile / headerSources := { val pySources = ( ((Compile / baseDirectory).value ** "*.py") --- + // TODO (#13695) directory moving/renaming ((Compile / baseDirectory).value ** "cn-svc-configs" ** "*") --- ((Compile / baseDirectory).value ** "node_modules" ** "*") ).get @@ -97,6 +98,7 @@ object Headers { val shSources = ( ((Compile / baseDirectory).value ** "*.sh") --- ((Compile / baseDirectory).value ** "node_modules" ** "*") --- + // TODO (#13695) directory moving/renaming ((Compile / baseDirectory).value ** "cn-svc-configs" ** "*") --- ((Compile / baseDirectory).value ** "community" ** "*") --- ((Compile / baseDirectory).value ** "*ts-client" ** "*") --- diff --git a/project/ignore-patterns/canton_log.ignore.txt b/project/ignore-patterns/canton_log.ignore.txt index 82536f04..1ac1b45a 100644 --- a/project/ignore-patterns/canton_log.ignore.txt +++ b/project/ignore-patterns/canton_log.ignore.txt @@ -28,12 +28,9 @@ HMAC256 JWT Validator is NOT recommended for production environments # Users are allocated by the validator app, and all apps are starting concurrently. PERMISSION_DENIED.*Could not resolve is_deactivated status for user -# TODO(#6839) Try to set things up in a way that doesn't produce this errors. # Using multiple auth configs for the long-running Canton instances produces the following warning # when authenticating using an auth config that is not the first in the list. Could not verify JWT token: The provided Algorithm doesn't match the one defined in the JWT's Header. -Couldn't get jwk from http: com.auth0.jwk.SigningKeyNotFoundException: No key found in https://canton-network-test.us.auth0.com/.well-known/jwks.json -Couldn't get jwk from http: com.auth0.jwk.NetworkException: Cannot obtain jwks from url http://127.0.0.1:9876/jwks # Ignore UNAUTHENTICATED errors logged during the invalid token rejection tests GrpcClientError: UNAUTHENTICATED/.*Request: Tap(13.37) @@ -90,6 +87,9 @@ Token refresh failed with Status.*UNAVAILABLE.*Health-check stream unexpectedly # TODO(#11018): Remove once Canton does not issue a warning for this expected condition INVALID_TRAFFIC_CONTROL_PURCHASED_MESSAGE.* signature threshold not reached +# Sequencers can issue this warning if SetTrafficPurchased requests occur at submission window boundaries (see #14746) +The traffic balance request submission timed out + # In ValidatorReonboardingIntegrationTest, importing the ACS on the new participant may lead to temporary ACS_COMMITMENT_MISMATCH errors. # The new participant can be both the sender or the counterParticipant in the error message. ACS_COMMITMENT_MISMATCH.*aliceValidatorLocalNewForValidatorReonboardingIT diff --git a/scripts/check-repo-names.sh b/scripts/check-repo-names.sh index 8508e9d4..c58bd280 100755 --- a/scripts/check-repo-names.sh +++ b/scripts/check-repo-names.sh @@ -32,11 +32,10 @@ function check_patterns_locally() { local exceptions=( '(\b|[`_])cn-docs' '@cn-load-tester\.com' - 'databaseName = "cn_apps"|"cn_apps_reonboard"' # TODO (#15709) rename database to splice_apps '^[^:]+V001__create_schema\.sql:' # TODO (#15491) avoiding changing hashes 'AUTH0_CN_MANAGEMENT_API_CLIENT_(ID|SECRET)|"dev" => ."AUTH0_CN"' # TODO (#15747) auth0 env names 'ans-web-ui\.yaml:.*name: splice-app-cns-ui-auth' # TODO (#15741) new secret - 'Headers.scala:.*"cn-svc-configs"' # TODO (#15742) references to missing project subdirectory + 'Headers.scala:.*"cn-svc-configs"' # TODO (#13695) directory moving/renaming 'istio-gateway/.*gateway\.yaml:.*credentialName: cn-' # TODO (#15745) TLS credential names in istio-gateway 'GcpConfig\.scala:' # cluster-specific '/da-cn-shared/cn-images|GOOGLE_CLOUD_PROJECT=da-cn-shared|"KMS_PROJECT_ID" -> "da-cn-shared"' # gcp diff --git a/scripts/scan-txlog/scan_txlog.py b/scripts/scan-txlog/scan_txlog.py index 7e07ae03..0e745225 100755 --- a/scripts/scan-txlog/scan_txlog.py +++ b/scripts/scan-txlog/scan_txlog.py @@ -1716,12 +1716,10 @@ def _txinfo(self, transaction, operation, message, parties=None): msg = message.split("\n", 1) round_flag = f":r{self.for_round}" if self.for_round else "" - LOG.info( - f"{transaction.record_time} {get_transaction_id(transaction)} ({operation}{round_flag}) - {msg[0]}" - ) - + full_log_message = f"{transaction.record_time} {get_transaction_id(transaction)} ({operation}{round_flag}) - {msg[0]}" if len(msg) > 1 and not self.args.hide_details: - LOG.info(textwrap.indent(msg[1], " ")) + full_log_message += "\n" + textwrap.indent(msg[1], " ") + LOG.info(full_log_message) return True