Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
// Covers the traffic fee with a wide margin, the fee itself depends on the amulet price.
private val tapAmount = 100_000.0

// The traffic discount the DSO registers the app-synchronizer at.
private val discount = BigDecimal("0.5")

// LocalNet runs the apps at their default polling interval, so a change takes a few rounds of
// automation to land.
private val automationTimeout = 2.minutes
Expand Down Expand Up @@ -137,7 +140,7 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
new DsoRules_RegisterSynchronizer(
appSynchronizerId.toProtoPrimitive,
operatorParty.toProtoPrimitive,
new GovernanceParameters(java.math.BigDecimal.ONE.setScale(10)),
new GovernanceParameters(discount.bigDecimal.setScale(10)),
)
)
),
Expand All @@ -156,6 +159,10 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
.value
}

clue("the registration carries the discount") {
BigDecimal(registration.payload.governanceParameters.discountFactor) shouldBe discount
}

clue("with a zero base rate the participant has no allowance of its own") {
eventually(automationTimeout) {
val state = trafficState()
Expand All @@ -173,14 +180,32 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn

val buyer = vc("providerValidatorClient").copy(token = Some(token)).getValidatorPartyId()

actAndCheck(automationTimeout)(
val (dedicatedPurchase, _) = actAndCheck(automationTimeout)(
"the participant buys traffic for the dedicated synchronizer on the global synchronizer",
buyTraffic(participant, buyer, appSynchronizerId, registration),
buyTraffic(participant, buyer, appSynchronizerId, Some(registration)),
)(
"the operator grants it on the dedicated synchronizer's sequencer",
_ => trafficState().extraTrafficPurchased.value shouldBe purchasedTraffic,
)

clue("the purchase costs the global synchronizer's price at the discount") {
val globalPurchase =
buyTraffic(participant, buyer, synchronizerId(participant, "global"), None)
// Allows for Daml rounding each step to ten decimal places.
BigDecimal(dedicatedPurchase.amuletPaid) shouldBe
(BigDecimal(globalPurchase.amuletPaid) * discount +- BigDecimal("0.000001"))
}

clue("a purchase for a synchronizer that is neither required nor registered is refused") {
val unregisteredSynchronizerId = SynchronizerId.tryFromString(
s"unregistered::${appSynchronizerId.namespace.toProtoPrimitive}"
)
assertThrowsAndLogsCommandFailures(
buyTraffic(participant, buyer, unregisteredSynchronizerId, None),
_.errorMessage should include("Unknown synchronizer provided"),
)
}

clue("the purchased traffic is drawn down by transacting on the dedicated synchronizer") {
val before = trafficState().extraTrafficConsumed.value
participant.health.ping(participant.id, synchronizerId = Some(appSynchronizerId))
Expand All @@ -195,8 +220,10 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
participant: ParticipantClientReference,
buyer: PartyId,
synchronizerId: SynchronizerId,
registration: ContractWithState[RegisteredSynchronizer.ContractId, RegisteredSynchronizer],
)(implicit env: FixtureParam): Unit = {
registration: Option[
ContractWithState[RegisteredSynchronizer.ContractId, RegisteredSynchronizer]
],
)(implicit env: FixtureParam): splice.amuletrules.AmuletRules_BuyMemberTrafficResult = {
val scan = scancl("scanClient")
val transferContext = scan.getTransferContextWithInstances(env.environment.clock.now)
val amuletRules = transferContext.amuletRules
Expand All @@ -220,7 +247,7 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
.amuletSum
.amulet

val _ = participant.ledger_api_extensions.commands.submitWithResult(
val purchase = participant.ledger_api_extensions.commands.submitWithResult(
ledgerApiUserId,
actAs = Seq(buyer),
readAs = Seq(buyer),
Expand All @@ -241,11 +268,12 @@ class LocalNetDedicatedSyncIntegrationTest extends IntegrationTestWithIsolatedEn
0L,
purchasedTraffic,
Some(scan.getDsoPartyId().toProtoPrimitive).toJava,
Some(registration.contractId).toJava,
registration.map(_.contractId).toJava,
),
disclosedContracts = DisclosedContracts
.forTesting(amuletRules, openMiningRound, registration)
.forTesting(amuletRules, (Seq[ContractWithState[?, ?]](openMiningRound) ++ registration)*)
.toLedgerApiDisclosedContracts,
)
purchase.exerciseResult
}
}
Loading