Skip to content

Commit

Permalink
- bug fix: baking rewards index out of bounds for new users
Browse files Browse the repository at this point in the history
- add another unit test case to cover this
  • Loading branch information
simonmcl committed Jun 26, 2024
1 parent 40d7e18 commit f1b5a0c
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Sources/KukaiCoreSwift/Clients/TzKTClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ public class TzKTClient {
var estimatedNextReward: RewardDetails? = nil

// Check if we have enough rewards to bring us up to the current cycle
guard currentDelegatorRewards.count > TzKTClient.numberOfFutureCyclesReturned,
guard TzKTClient.numberOfFutureCyclesReturned >= 0,
currentDelegatorRewards.count > TzKTClient.numberOfFutureCyclesReturned,
let currentBakerConfig = bakerConfigs[delegate.address],
let inProgresCycleBakerConfig = bakerConfigs[currentDelegatorRewards[TzKTClient.numberOfFutureCyclesReturned].baker.address] else {

Expand Down
28 changes: 28 additions & 0 deletions Tests/KukaiCoreSwiftTests/Clients/TzKTClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,34 @@ class TzKTClientTests: XCTestCase {
wait(for: [expectation], timeout: 120)
}

func testEstimateRewardsNone() {
let expectation = XCTestExpectation(description: "tzkt-testEstimateRewardsNone")
let delegate = TzKTAccountDelegate(alias: "Teztillery", address: "tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4", active: true)

MockConstants.shared.tzktClient.estimateLastAndNextReward(forAddress: "tz1ckwbvP7pdTLS1aAe6YPoiKpG2d8ENU8Ac", delegate: delegate) { result in
switch result {
case .success(let rewards):
XCTAssert(rewards.previousReward == nil, rewards.previousReward?.amount.description ?? "")

XCTAssert(rewards.estimatedPreviousReward == nil, rewards.estimatedPreviousReward?.amount.normalisedRepresentation ?? "")

XCTAssert(rewards.estimatedNextReward?.amount.normalisedRepresentation == "0", rewards.estimatedNextReward?.amount.normalisedRepresentation ?? "")
XCTAssert(rewards.estimatedNextReward?.fee.description == "0.0499", rewards.estimatedNextReward?.fee.description ?? "")
XCTAssert(rewards.estimatedNextReward?.cycle.description == "745", rewards.estimatedNextReward?.cycle.description ?? "")
XCTAssert(rewards.estimatedNextReward?.bakerAlias == "Teztillery", rewards.estimatedNextReward?.bakerAlias ?? "")

XCTAssert(rewards.moreThan1CycleBetweenPreiousAndNext() == false)

case .failure(let error):
XCTFail("Error: \(error)")
}

expectation.fulfill()
}

wait(for: [expectation], timeout: 120)
}

func testBakers() {
let expectation = XCTestExpectation(description: "tzkt-bakers")

Expand Down
18 changes: 18 additions & 0 deletions Tests/KukaiCoreSwiftTests/MockConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ public struct MockConstants {
var tzktDelegatorRewardsNoPreviousURL = tzktURL.appendingPathComponent("v1/rewards/delegators/tz1iv8r8UUCEZK5gqpLPnMPzP4VRJBJUdGgr")
tzktDelegatorRewardsNoPreviousURL.appendQueryItem(name: "limit", value: 25)

var tzktDelegatorRewardsNoneURL = tzktURL.appendingPathComponent("v1/rewards/delegators/tz1ckwbvP7pdTLS1aAe6YPoiKpG2d8ENU8Ac")
tzktDelegatorRewardsNoneURL.appendQueryItem(name: "limit", value: 25)

var bakingBadConfigURL1 = bakingBadURL.appendingPathComponent("v2/bakers/tz1fwnfJNgiDACshK9avfRfFbMaXrs3ghoJa")
bakingBadConfigURL1.appendQueryItem(name: "configs", value: "true")

Expand All @@ -105,6 +108,9 @@ public struct MockConstants {
var bakingBadConfigURL4 = bakingBadURL.appendingPathComponent("v2/bakers/tz1aRoaRhSpRYvFdyvgWLL6TGyRoGF51wDjM")
bakingBadConfigURL4.appendQueryItem(name: "configs", value: "true")

var bakingBadConfigURL5 = bakingBadURL.appendingPathComponent("v2/bakers/tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4")
bakingBadConfigURL5.appendQueryItem(name: "configs", value: "true")

var tzktsuggestURL1 = tzktURL.appendingPathComponent("v1/suggest/accounts/Bake Nug Payouts")
tzktsuggestURL1.appendQueryItem(name: "limit", value: 1)

Expand All @@ -117,6 +123,9 @@ public struct MockConstants {
var tzktsuggestURL4 = tzktURL.appendingPathComponent("v1/suggest/accounts/Baking Benjamins Payouts")
tzktsuggestURL4.appendQueryItem(name: "limit", value: 1)

var tzktsuggestURL5 = tzktURL.appendingPathComponent("v1/suggest/accounts/Teztillery Payouts")
tzktsuggestURL5.appendQueryItem(name: "limit", value: 1)

var tzktLastBakerRewardURL = tzktURL.appendingPathComponent("v1/accounts/tz1Ue76bLW7boAcJEZf2kSGcamdBKVi4Kpss/operations")
tzktLastBakerRewardURL.appendQueryItem(name: "limit", value: 1)
tzktLastBakerRewardURL.appendQueryItem(name: "type", value: "transaction")
Expand All @@ -137,6 +146,11 @@ public struct MockConstants {
tzktLastBakerRewardURL4.appendQueryItem(name: "type", value: "transaction")
tzktLastBakerRewardURL4.appendQueryItem(name: "sender.in", value: "tz1ZgkTFmiwddPXGbs4yc6NWdH4gELW7wsnv,tz1ShireJgwr8ag5dETMY4RNqkXeu1YgyDYC")

var tzktLastBakerRewardURL5 = tzktURL.appendingPathComponent("v1/accounts/tz1ckwbvP7pdTLS1aAe6YPoiKpG2d8ENU8Ac/operations")
tzktLastBakerRewardURL5.appendQueryItem(name: "limit", value: 1)
tzktLastBakerRewardURL5.appendQueryItem(name: "type", value: "transaction")
tzktLastBakerRewardURL5.appendQueryItem(name: "sender.in", value: "tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4")

var tzktDelegatesURL = tzktURL.appendingPathComponent("v1/delegates")
tzktDelegatesURL.appendQueryItem(name: "select.values", value: "address,alias,balance,stakingBalance")
tzktDelegatesURL.appendQueryItem(name: "active", value: "true")
Expand Down Expand Up @@ -191,18 +205,22 @@ public struct MockConstants {
tzktCyclesURL: (MockConstants.jsonStub(fromFilename: "tzkt_cycles"), MockConstants.http200),
tzktDelegatorRewardsURL: (MockConstants.jsonStub(fromFilename: "tzkt_delegator-rewards"), MockConstants.http200),
tzktDelegatorRewardsNoPreviousURL: (MockConstants.jsonStub(fromFilename: "tzkt_delegator-rewards-no-previous"), MockConstants.http200),
tzktDelegatorRewardsNoneURL: (MockConstants.jsonStub(fromFilename: "tzkt_delegator-rewards-none"), MockConstants.http200),
bakingBadConfigURL1: (MockConstants.jsonStub(fromFilename: "tzkt_baker-config-tz1fwnfJNgiDACshK9avfRfFbMaXrs3ghoJa"), MockConstants.http200),
bakingBadConfigURL2: (MockConstants.jsonStub(fromFilename: "tzkt_baker-config-tz1ZgkTFmiwddPXGbs4yc6NWdH4gELW7wsnv"), MockConstants.http200),
bakingBadConfigURL3: (MockConstants.jsonStub(fromFilename: "tzkt_baker-config-tz1S5WxdZR5f9NzsPXhr7L9L1vrEb5spZFur"), MockConstants.http200),
bakingBadConfigURL4: (MockConstants.jsonStub(fromFilename: "tzkt_baker-config-tz1aRoaRhSpRYvFdyvgWLL6TGyRoGF51wDjM"), MockConstants.http200),
bakingBadConfigURL5: (MockConstants.jsonStub(fromFilename: "tzkt_baker-config-tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4"), MockConstants.http200),
tzktsuggestURL1: (MockConstants.jsonStub(fromFilename: "tzkt_suggest-bake-nug"), MockConstants.http200),
tzktsuggestURL2: (MockConstants.jsonStub(fromFilename: "tzkt_suggest-the-shire"), MockConstants.http200),
tzktsuggestURL3: (MockConstants.jsonStub(fromFilename: "tzkt_suggest-the-shire_updated"), MockConstants.http200),
tzktsuggestURL4: (MockConstants.jsonStub(fromFilename: "tzkt_suggest-baking-benjamins"), MockConstants.http200),
tzktsuggestURL5: (MockConstants.jsonStub(fromFilename: "tzkt_suggest-teztillery"), MockConstants.http200),
tzktLastBakerRewardURL: (MockConstants.jsonStub(fromFilename: "tzkt_last-baker-payment"), MockConstants.http200),
tzktLastBakerRewardURL2: (MockConstants.jsonStub(fromFilename: "tzkt_last-baker-payment"), MockConstants.http200),
tzktLastBakerRewardURL3: (MockConstants.jsonStub(fromFilename: "tzkt_last-baker-payment_updated"), MockConstants.http200),
tzktLastBakerRewardURL4: (MockConstants.jsonStub(fromFilename: "tzkt_last-baker-payment_updated"), MockConstants.http200),
tzktLastBakerRewardURL5: (MockConstants.jsonStub(fromFilename: "tzkt_last-baker-payment_updated"), MockConstants.http200),
tzktDelegatesURL: (MockConstants.jsonStub(fromFilename: "tzkt_ghostnet-bakers"), MockConstants.http200),

// Media proxy
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"address": "tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4",
"name": "Teztillery",
"logo": "https://services.tzkt.io/v1/avatars/tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4",
"balance": 2187.553015,
"stakingBalance": 10120.963766,
"stakingCapacity": 11897.932014,
"maxStakingBalance": 11897.932014,
"freeSpace": 3098.9606940000003,
"fee": 0.0499,
"minDelegation": 10,
"payoutDelay": 1,
"payoutPeriod": 1,
"openForDelegation": true,
"estimatedRoi": 0.05916,
"serviceType": "tezos_only",
"serviceHealth": "active",
"payoutTiming": "no_data",
"payoutAccuracy": "no_data",
"insuranceCoverage": 0
}
106 changes: 106 additions & 0 deletions Tests/KukaiCoreSwiftTests/Stubs/tzkt_delegator-rewards-none.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
[
{
"cycle": 752,
"delegatedBalance": 730253,
"stakedBalance": 0,
"baker": {
"alias": "Teztillery",
"address": "tz1bdTgmF8pzBH9chtJptsjjrh5UfSXp1SQ4"
},
"bakingPower": 0,
"totalBakingPower": 378988343190364,
"bakerDelegatedBalance": 335560569,
"externalDelegatedBalance": 7535104289,
"bakerStakedBalance": 1321992446,
"externalStakedBalance": 0,
"expectedBlocks": 0,
"expectedEndorsements": 0,
"futureBlocks": 0,
"futureBlockRewards": 0,
"blocks": 0,
"blockRewardsDelegated": 0,
"blockRewardsStakedOwn": 0,
"blockRewardsStakedEdge": 0,
"blockRewardsStakedShared": 0,
"missedBlocks": 0,
"missedBlockRewards": 0,
"futureEndorsements": 0,
"futureEndorsementRewards": 0,
"endorsements": 0,
"endorsementRewardsDelegated": 0,
"endorsementRewardsStakedOwn": 0,
"endorsementRewardsStakedEdge": 0,
"endorsementRewardsStakedShared": 0,
"missedEndorsements": 0,
"missedEndorsementRewards": 0,
"blockFees": 0,
"missedBlockFees": 0,
"doubleBakingRewards": 0,
"doubleBakingLostStaked": 0,
"doubleBakingLostUnstaked": 0,
"doubleBakingLostExternalStaked": 0,
"doubleBakingLostExternalUnstaked": 0,
"doubleEndorsingRewards": 0,
"doubleEndorsingLostStaked": 0,
"doubleEndorsingLostUnstaked": 0,
"doubleEndorsingLostExternalStaked": 0,
"doubleEndorsingLostExternalUnstaked": 0,
"doublePreendorsingRewards": 0,
"doublePreendorsingLostStaked": 0,
"doublePreendorsingLostUnstaked": 0,
"doublePreendorsingLostExternalStaked": 0,
"doublePreendorsingLostExternalUnstaked": 0,
"vdfRevelationRewardsDelegated": 0,
"vdfRevelationRewardsStakedOwn": 0,
"vdfRevelationRewardsStakedEdge": 0,
"vdfRevelationRewardsStakedShared": 0,
"nonceRevelationRewardsDelegated": 0,
"nonceRevelationRewardsStakedOwn": 0,
"nonceRevelationRewardsStakedEdge": 0,
"nonceRevelationRewardsStakedShared": 0,
"nonceRevelationLosses": 0,
"blockRewardsLiquid": 0,
"endorsementRewardsLiquid": 0,
"nonceRevelationRewardsLiquid": 0,
"vdfRevelationRewardsLiquid": 0,
"revelationRewards": 0,
"revelationLosses": 0,
"doublePreendorsingLosses": 0,
"doubleEndorsingLosses": 0,
"doubleBakingLosses": 0,
"endorsementRewards": 0,
"blockRewards": 0,
"stakingBalance": 9192657304,
"activeStake": 0,
"selectedStake": 378988343190364,
"balance": 730253,
"ownBlocks": 0,
"extraBlocks": 0,
"missedOwnBlocks": 0,
"missedExtraBlocks": 0,
"uncoveredOwnBlocks": 0,
"uncoveredExtraBlocks": 0,
"uncoveredEndorsements": 0,
"ownBlockRewards": 0,
"extraBlockRewards": 0,
"missedOwnBlockRewards": 0,
"missedExtraBlockRewards": 0,
"uncoveredOwnBlockRewards": 0,
"uncoveredExtraBlockRewards": 0,
"uncoveredEndorsementRewards": 0,
"ownBlockFees": 0,
"extraBlockFees": 0,
"missedOwnBlockFees": 0,
"missedExtraBlockFees": 0,
"uncoveredOwnBlockFees": 0,
"uncoveredExtraBlockFees": 0,
"doubleBakingLostDeposits": 0,
"doubleBakingLostRewards": 0,
"doubleBakingLostFees": 0,
"doubleEndorsingLostDeposits": 0,
"doubleEndorsingLostRewards": 0,
"doubleEndorsingLostFees": 0,
"revelationLostRewards": 0,
"revelationLostFees": 0
}
]
6 changes: 6 additions & 0 deletions Tests/KukaiCoreSwiftTests/Stubs/tzkt_suggest-teztillery.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"alias": "Tezex Bakery Payouts",
"address": "tz1cBvEkYWV7RjTkd2kEcMPLwP62pqivXNEi"
}
]

0 comments on commit f1b5a0c

Please sign in to comment.