Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(crowdnode): v20 APY calculation #639

Merged
merged 21 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
94bf1b8
Merge pull request #548 from dashpay/release/6.3.3
tikhop May 11, 2023
55983c3
Merge pull request #551 from dashpay/release/7.0.0
tikhop May 21, 2023
880eb43
Merge pull request #563 from dashpay/release/7.0.1
pankcuf Jul 8, 2023
54d66c0
Merge pull request #576 from dashpay/release/7.0.2
pankcuf Jul 25, 2023
041c682
chore: Merge pull request #582 from dashpay/release/7.0.3
tikhop Aug 3, 2023
e88493f
chore: Merge pull request #587 from dashpay/release/7.0.4
tikhop Aug 12, 2023
065d73d
Merge pull request #596 from dashpay/release/7.0.5
tikhop Aug 30, 2023
a3c5acf
chore: bump up version 7.1.0 (+ set disconnect reason for DashSync's …
pankcuf Sep 26, 2023
81694ed
Merge pull request #607 from dashpay/release/7.1.0
pankcuf Oct 4, 2023
c87d590
Merge branch 'master' into release/8.0.0
pankcuf Dec 8, 2023
b6866bc
chore: disable Uphold and Coinbase
Syn-McJ Dec 11, 2023
d01b36d
chore: don't start CoinbaseObjcWrapper
Syn-McJ Dec 11, 2023
86cd675
Merge pull request #635 from Syn-McJ/chore/disable-coinbase-uphold
pankcuf Dec 11, 2023
d365959
fix: count HPMN as 4 virtual masternodes
Syn-McJ Dec 18, 2023
b3d5528
Merge branch 'release/8.0.0' into fix/crowdnode-apy
Syn-McJ Dec 19, 2023
15333d6
test: virtual masternodes
Syn-McJ Dec 19, 2023
052bbe9
fix: coinbase crash
Syn-McJ Jan 18, 2024
855ee00
fix: CrowdNode APY calculation
Syn-McJ Jan 19, 2024
b54bd6e
Merge branch 'develop' into fix/crowdnode-apy
Syn-McJ Jan 23, 2024
db01fe3
Merge branch 'develop' into fix/crowdnode-apy
Syn-McJ Jan 23, 2024
8fa8e50
chore: cleanup
Syn-McJ Jan 23, 2024
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
2 changes: 1 addition & 1 deletion DashSyncCurrentCommit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
71d2f9578544a48331ffa09edc748b3ed8766b97
def9c768c36fcc1436f7e7185693369405977e61
30 changes: 18 additions & 12 deletions DashWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@
75889B792AD2A04900C17F5D /* CoinJoinInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75889B752AD296E700C17F5D /* CoinJoinInfoViewController.swift */; };
75889B7F2AD2D7F800C17F5D /* CoinJoin.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 75889B812AD2D7F800C17F5D /* CoinJoin.storyboard */; };
75889B892AD2DF0200C17F5D /* CoinJoin.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 75889B812AD2D7F800C17F5D /* CoinJoin.storyboard */; };
759C8F9F2B593589004B1305 /* CrowdNodeAPYView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759C8F9E2B593589004B1305 /* CrowdNodeAPYView.swift */; };
759C8FA02B593589004B1305 /* CrowdNodeAPYView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759C8F9E2B593589004B1305 /* CrowdNodeAPYView.swift */; };
75A664D82B09F1EA007EFD16 /* VotingInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A664D72B09F1EA007EFD16 /* VotingInfoViewController.swift */; };
75A8C1652AE5726B0042256E /* UsernameRequestsDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A8C1632AE5725C0042256E /* UsernameRequestsDAO.swift */; };
75A8C1672AE5734A0042256E /* UsernameRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75A8C1662AE5734A0042256E /* UsernameRequest.swift */; };
Expand Down Expand Up @@ -2444,6 +2446,7 @@
75889B802AD2D7F800C17F5D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/CoinJoin.storyboard; sourceTree = "<group>"; };
759816E519357D6F005060EA /* BRBubbleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BRBubbleView.h; sourceTree = "<group>"; };
759816E619357D6F005060EA /* BRBubbleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BRBubbleView.m; sourceTree = "<group>"; };
759C8F9E2B593589004B1305 /* CrowdNodeAPYView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrowdNodeAPYView.swift; sourceTree = "<group>"; };
75A664D72B09F1EA007EFD16 /* VotingInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VotingInfoViewController.swift; sourceTree = "<group>"; };
75A8C1632AE5725C0042256E /* UsernameRequestsDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameRequestsDAO.swift; sourceTree = "<group>"; };
75A8C1662AE5734A0042256E /* UsernameRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UsernameRequest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5074,6 +5077,7 @@
isa = PBXGroup;
children = (
47083B3429893E2C0010AF71 /* Tx Cell */,
759C8F9E2B593589004B1305 /* CrowdNodeAPYView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -8746,6 +8750,7 @@
C9F42FB229DD5141001BC549 /* BackupInfoViewController.swift in Sources */,
47C6E6E5291A68B6003FEDF2 /* AppliedFiltersView.swift in Sources */,
2A7A7BAE234770C900451078 /* DWCaptureSessionManager.m in Sources */,
759C8F9F2B593589004B1305 /* CrowdNodeAPYView.swift in Sources */,
C94D982E2A544E8E00F3BEE1 /* UIButton+Dash.swift in Sources */,
C956AF2B2A5CC97F002FAB75 /* ConfirmPaymentModel.swift in Sources */,
2A11F59F2194BD6200E7B563 /* DWDataMigrationManager.m in Sources */,
Expand Down Expand Up @@ -9054,6 +9059,7 @@
C9D2C6FB2A320AA000D15901 /* TxReclassifyTransactionsWhereToChangeViewController.swift in Sources */,
C9D2C6FC2A320AA000D15901 /* DWLocalCurrencyViewController.m in Sources */,
C9D2C6FD2A320AA000D15901 /* BadgeView.swift in Sources */,
759C8FA02B593589004B1305 /* CrowdNodeAPYView.swift in Sources */,
C943B5162A40A54600AF23C5 /* DWCreateInvitationButton.m in Sources */,
C9D2C6FE2A320AA000D15901 /* HomeHeaderView.swift in Sources */,
C9D2C6FF2A320AA000D15901 /* ProgressView.swift in Sources */,
Expand Down Expand Up @@ -10087,7 +10093,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = dashwallet/dashwallet.entitlements;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
Expand Down Expand Up @@ -10217,7 +10223,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = dashwallet/dashwallet.entitlements;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
Expand Down Expand Up @@ -10423,7 +10429,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
IBSC_MODULE = WatchApp_Extension;
Expand All @@ -10445,7 +10451,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
IBSC_MODULE = WatchApp_Extension;
Expand All @@ -10465,7 +10471,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = C98AA93FF5283EC6405BCE4B /* Pods-WatchApp Extension.debug.xcconfig */;
buildSettings = {
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "";
Expand All @@ -10492,7 +10498,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = CE02413EF0C60B1D1EDE6457 /* Pods-WatchApp Extension.release.xcconfig */;
buildSettings = {
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "";
Expand Down Expand Up @@ -11204,7 +11210,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = dashwallet/dashwallet.entitlements;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
Expand Down Expand Up @@ -11405,7 +11411,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
IBSC_MODULE = WatchApp_Extension;
Expand All @@ -11425,7 +11431,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 556B5EBEBAEA571D74FF69A3 /* Pods-WatchApp Extension.testflight.xcconfig */;
buildSettings = {
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "";
Expand Down Expand Up @@ -11524,7 +11530,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = dashwallet/dashwallet.entitlements;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
Expand Down Expand Up @@ -11713,7 +11719,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
EXCLUDED_ARCHS = "";
IBSC_MODULE = WatchApp_Extension;
Expand All @@ -11733,7 +11739,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 29B232FD70BA2EDF87F86A56 /* Pods-WatchApp Extension.testnet.xcconfig */;
buildSettings = {
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 44RJ69WHFF;
ENABLE_BITCODE = NO;
EXCLUDED_ARCHS = "";
Expand Down
21 changes: 18 additions & 3 deletions DashWallet/Sources/Categories/DSChain+DashWallet.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#import "DSMasternodeManager.h"
#import "NSDate+Utils.h"
#import <objc/runtime.h>
#import "DSSimplifiedMasternodeEntry.h"


NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -89,13 +91,25 @@ - (NSNumber *_Nullable)calculateMasternodeAPY {
return nil;

DSMasternodeList *masternodeList = self.chainManager.masternodeManager.currentMasternodeList;

if (masternodeList.validMasternodeCount == 0)
return nil;

NSInteger virtualMNCount = 0;

for (DSSimplifiedMasternodeEntry *entry in masternodeList.simplifiedMasternodeEntries) {
if (entry.isValid) {
if (entry.type == 1) { // HPMN
virtualMNCount += 4;
} else {
virtualMNCount += 1;
}
}
}

return [self calculateMasternodeAPYWithHeight:self.lastTerminalBlock.height
prevDifficultyTarget:self.lastTerminalBlock.target
masternodeCount:masternodeList.validMasternodeCount];
masternodeCount:virtualMNCount];
}

- (NSNumber *)calculateMasternodeAPYWithHeight:(uint64_t)height prevDifficultyTarget:(uint32_t)difficulty masternodeCount:(uint64_t)mnCount {
Expand Down Expand Up @@ -237,7 +251,8 @@ - (uint64_t)calculateblockInflationWithHeight:(uint64_t)height nPrevBits:(uint32
}

// Hard fork to reduce the block reward by 10 extra percent (allowing budget/superblocks)
uint64_t nSuperblockPart = (nPrevHeight > [self budgetPaymentsStartBlock]) ? nSubsidy / 10 : 0;
uint64_t treasuryPart = [self isCore20ActiveAtHeight:nPrevHeight] ? 20 : 10; // parts per 100, 20 is 20%
uint64_t nSuperblockPart = (nPrevHeight > [self budgetPaymentsStartBlock]) ? (nSubsidy * treasuryPart) / 100 : 0;

return fSuperblockPartOnly ? nSuperblockPart : nSubsidy - nSuperblockPart;
}
Expand Down
15 changes: 13 additions & 2 deletions DashWallet/Sources/Models/CrowdNode/CrowdNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ public final class CrowdNode {
private(set) var isOnlineStateRestored = false
var showNotificationOnResult = false

let masternodeAPY: Double
let crowdnodeAPY: Double
var masternodeAPY: Double
var crowdnodeAPY: Double

public static let shared: CrowdNode = .init()

Expand Down Expand Up @@ -188,6 +188,7 @@ extension CrowdNode {
}

DSLogger.log("restoring CrowdNode state")
checkAPY()
signUpState = SignUpState.notStarted
validatePrefs()

Expand Down Expand Up @@ -298,6 +299,16 @@ extension CrowdNode {
balance = 0
prefs.resetUserDefaults()
}

private func checkAPY() {
let chain = DWEnvironment.sharedInstance().currentChain

if let apy = chain.calculateMasternodeAPY()?.doubleValue {
masternodeAPY = apy
crowdnodeAPY = masternodeAPY * 0.85
chain.apy = NSNumber(value: apy)
}
}
}

// MARK: Signup
Expand Down
80 changes: 80 additions & 0 deletions DashWallet/Sources/UI/CrowdNode/Views/CrowdNodeAPYView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// Created by tkhp, Andrei Ashikhmin
// Copyright © 2024 Dash Core Group. All rights reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import UIKit

@objc(DWCrowdNodeAPYView)
class CrowdNodeAPYView: UIView {

override init(frame: CGRect) {
super.init(frame: frame)
addCrowdNodeAPYLabel()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric, height: 24.0)
}

private func addCrowdNodeAPYLabel() {
let systemGreen = UIColor(red: 98.0 / 255.0, green: 182.0 / 255.0, blue: 125.0 / 255.0, alpha: 1.0)

let apyStackView = UIStackView()
apyStackView.translatesAutoresizingMaskIntoConstraints = false
apyStackView.axis = .horizontal
apyStackView.spacing = 4
apyStackView.backgroundColor = systemGreen.withAlphaComponent(0.1)
apyStackView.layer.cornerRadius = 6.0
apyStackView.layer.masksToBounds = true
apyStackView.layoutMargins = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 8)
apyStackView.isLayoutMarginsRelativeArrangement = true
addSubview(apyStackView)

let iconImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 14, height: 14))
iconImageView.contentMode = .center
iconImageView.image = UIImage(named: "image.crowdnode.apy")
apyStackView.addArrangedSubview(iconImageView)

let apiLabel = UILabel()
apiLabel.textColor = systemGreen
apiLabel.font = UIFont.systemFont(ofSize: 11, weight: .semibold)
apiLabel.text = String.localizedStringWithFormat(NSLocalizedString("Current APY = %@", comment: "CrowdNode"), apy)
apyStackView.addArrangedSubview(apiLabel)

NSLayoutConstraint.activate([
apyStackView.topAnchor.constraint(equalTo: topAnchor),
apyStackView.bottomAnchor.constraint(equalTo: bottomAnchor),
apyStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
apyStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
apyStackView.heightAnchor.constraint(equalToConstant: 24.0)
])
}

private var apy: String {
let apyValue = DWEnvironment.sharedInstance().apy.doubleValue * 0.85

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .percent
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2
numberFormatter.multiplier = 1
return numberFormatter.string(from: NSNumber(value: apyValue)) ?? ""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@

#import "DWEnvironment.h"
#import "DWUIKit.h"
#import "dashwallet-Swift.h"

@interface DWCrowdNodeAPYView : UIView

@end

@interface DWExploreTestnetContentsView ()
@end
Expand Down Expand Up @@ -273,66 +271,3 @@ - (void)addContent:(UIView *)view {
[_contentStack addArrangedSubview:view];
}
@end


@implementation DWCrowdNodeAPYView

- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self addCrowdNodeAPYLabel];
}

return self;
}

- (CGSize)intrinsicContentSize {
return CGSizeMake(UIViewNoIntrinsicMetric, 24.0f);
}

- (void)addCrowdNodeAPYLabel {
UIColor *systemGreen = [UIColor colorWithRed:98.0 / 255.0 green:182.0 / 255.0 blue:125.0 / 255.0 alpha:1.0];

UIStackView *apyStackView = [UIStackView new];
apyStackView.translatesAutoresizingMaskIntoConstraints = NO;
apyStackView.axis = UILayoutConstraintAxisHorizontal;
apyStackView.spacing = 4;
apyStackView.backgroundColor = [systemGreen colorWithAlphaComponent:0.1];
apyStackView.layer.cornerRadius = 6.0;
apyStackView.layer.masksToBounds = YES;
apyStackView.layoutMargins = UIEdgeInsetsMake(0, 8, 0, 8);
apyStackView.layoutMarginsRelativeArrangement = YES;
[self addSubview:apyStackView];

UIImageView *iconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 14, 14)];
iconImageView.contentMode = UIViewContentModeCenter;
[iconImageView setImage:[UIImage imageNamed:@"image.crowdnode.apy"]];
[apyStackView addArrangedSubview:iconImageView];

UILabel *apiLabel = [[UILabel alloc] init];
apiLabel.textColor = systemGreen;
apiLabel.font = [UIFont systemFontOfSize:11 weight:UIFontWeightSemibold];
apiLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Current APY = %@", @"Crowdnode"), [self apy]];
[apyStackView addArrangedSubview:apiLabel];

[NSLayoutConstraint activateConstraints:@[
[apyStackView.topAnchor constraintEqualToAnchor:self.topAnchor],
[apyStackView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[apyStackView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[apyStackView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
[apyStackView.heightAnchor constraintEqualToConstant:24.0f],
]];
}

- (NSString *)apy {
double apyValue = [DWEnvironment sharedInstance].apy.doubleValue * 0.85;

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterPercentStyle;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 2;
numberFormatter.multiplier = @(1);
return [numberFormatter stringFromNumber:@(apyValue)];
}

@end
Loading
Loading