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

7.8.0 Add staking proxy support #971

Merged
merged 82 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
5df275e
add layout
lynx56 Jan 9, 2024
aa172b9
add subscription
lynx56 Jan 10, 2024
f4480e9
Merge branch 'base/proxy' into feature/setup-staking-proxy
lynx56 Jan 10, 2024
54cd582
refactor
lynx56 Jan 11, 2024
0393ebc
remove tests
lynx56 Jan 11, 2024
e4012e2
PR fixes
lynx56 Jan 11, 2024
44a99cc
Merge branch 'feature/add-staking-proxy' into feature/setup-staking-p…
lynx56 Jan 11, 2024
757731e
init
lynx56 Jan 12, 2024
4ed20fa
fix coding
lynx56 Jan 15, 2024
e92ccce
fix accountId
lynx56 Jan 15, 2024
58c9e77
PR fixes
lynx56 Jan 15, 2024
33a6d87
Merge branch 'base/proxy' into feature/setup-staking-proxy
lynx56 Jan 15, 2024
a3582a6
bugfix
lynx56 Jan 15, 2024
65eae53
Merge branch 'feature/setup-staking-proxy' into feature/setup-staking…
lynx56 Jan 15, 2024
05b49f2
add yourwallets, w3name
lynx56 Jan 16, 2024
279b9b0
add error handling, add constants
lynx56 Jan 16, 2024
4eef7e7
cleanup
lynx56 Jan 16, 2024
32b1142
bugfix
lynx56 Jan 16, 2024
4876dc5
bugfixes, fix address icon
lynx56 Jan 17, 2024
ec647b5
add watchonly in filter
lynx56 Jan 17, 2024
e7ff5c1
init
lynx56 Jan 17, 2024
4c6b562
bugfixes
lynx56 Jan 17, 2024
0f1b5cc
buildfix
lynx56 Jan 17, 2024
d48dbb0
remove tests
lynx56 Jan 17, 2024
00b531a
init
lynx56 Jan 18, 2024
220a830
remove tests
lynx56 Jan 18, 2024
1b091bc
add error handling
lynx56 Jan 18, 2024
65e2b1f
fix warning
lynx56 Jan 19, 2024
7206dad
PR fixes
lynx56 Jan 19, 2024
8a5aa0c
PR fixes
lynx56 Jan 19, 2024
bb6bcb5
rollback validation
lynx56 Jan 19, 2024
088b2ac
PR fixes
lynx56 Jan 19, 2024
540021d
Merge branch 'feature/setup-staking-proxy-logic' into feature/setup-s…
lynx56 Jan 19, 2024
b4adaba
Merge branch 'feature/setup-staking-proxy-confirm' into feature/setup…
lynx56 Jan 19, 2024
12b9235
init
lynx56 Jan 19, 2024
83df0e5
add validations
lynx56 Jan 22, 2024
97e427b
separate add and remove interactors
lynx56 Jan 22, 2024
93a1abb
deposit is optional
lynx56 Jan 22, 2024
69ab283
bugfix interactor setup
lynx56 Jan 22, 2024
992350b
separate add and remove presenters
lynx56 Jan 22, 2024
965bd81
fix type
lynx56 Jan 22, 2024
ae63f45
Merge pull request #935 from novasamatech/feature/setup-staking-proxy
ERussel Jan 23, 2024
2d99b98
Merge pull request #937 from novasamatech/feature/setup-staking-proxy…
ERussel Jan 23, 2024
8856b84
Merge pull request #939 from novasamatech/feature/setup-staking-proxy…
ERussel Jan 23, 2024
3cfdd56
Merge pull request #941 from novasamatech/feature/setup-staking-proxies
ERussel Jan 23, 2024
5d25836
Merge pull request #947 from novasamatech/feature/setup-staking-proxy…
ERussel Jan 23, 2024
0416d3c
Merge pull request #948 from novasamatech/feature/setup-staking-proxy…
ERussel Jan 23, 2024
2b49844
Merge branch 'fix/extrinsic-splitter' into feature/add-staking-proxy
ERussel Jan 23, 2024
55c65ed
fix conflicts
ERussel Jan 23, 2024
1dd500d
Merge branch 'feature/add-staking-proxy' into feature/setup-staking-r…
lynx56 Jan 23, 2024
df7dbd8
rearrange
lynx56 Jan 23, 2024
cb19cd3
remove unused files
lynx56 Jan 23, 2024
adf3e28
cleanup
lynx56 Jan 23, 2024
551725c
bugdix
lynx56 Jan 23, 2024
1d0f055
Proxy: controller alert (#953)
lynx56 Jan 25, 2024
9484eb7
Merge pull request #950 from novasamatech/feature/setup-staking-revok…
ERussel Jan 25, 2024
4eca8a2
bugfixes
lynx56 Jan 29, 2024
8a032fd
fix tests
lynx56 Jan 29, 2024
1fdc800
init
lynx56 Jan 30, 2024
5c6e99f
add validation
lynx56 Jan 30, 2024
2bd4424
refactor
lynx56 Jan 31, 2024
49c3b23
PR fixes
lynx56 Jan 31, 2024
f8876ed
typo
lynx56 Jan 31, 2024
78c3bf2
buildfix
lynx56 Jan 31, 2024
40bf821
bugfix
lynx56 Jan 31, 2024
42e26e3
Merge pull request #959 from novasamatech/feature/proxy-sync-at-block
ERussel Jan 31, 2024
cd97019
Merge pull request #960 from novasamatech/fix/proxy-bugfixes
ERussel Jan 31, 2024
af2a4ac
init
lynx56 Feb 2, 2024
753d666
Merge pull request #963 from novasamatech/fix/controller-account
ERussel Feb 5, 2024
9ec01a4
fix merge conflicts
ERussel Feb 5, 2024
f1589fe
Merge pull request #966 from novasamatech/feature/add-staking-proxy
ERussel Feb 5, 2024
2c55389
enable proxieds on add staking proxy
ERussel Feb 7, 2024
385d118
fix duplicated proxy validation
ERussel Feb 7, 2024
ca4727c
fix active stakers parsing when nil
ERussel Feb 7, 2024
034959c
fix texts
ERussel Feb 7, 2024
b32b471
sync localization
ERussel Feb 7, 2024
46518d9
fix links open logic
ERussel Feb 7, 2024
26abb8a
fix formating
ERussel Feb 7, 2024
98cd0eb
Merge pull request #968 from novasamatech/fix/add-staking-proxy-bugs
ERussel Feb 7, 2024
543ea15
display full amount for total balance
ERussel Feb 7, 2024
992dbc4
fix crash on DApp browser when address prefix too large
ERussel Feb 7, 2024
4a2c152
Merge pull request #969 from novasamatech/feature/display-whole-total…
ERussel Feb 7, 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
246 changes: 226 additions & 20 deletions novawallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions novawallet/Assets.xcassets/iconDelete.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "delete.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ protocol StakingLocalSubscriptionFactoryProtocol {
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedBagListNode>

func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition>
}

final class StakingLocalSubscriptionFactory: SubstrateLocalSubscriptionFactory,
Expand Down Expand Up @@ -355,4 +360,25 @@ final class StakingLocalSubscriptionFactory: SubstrateLocalSubscriptionFactory,

return provider
}

func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition> {
clearIfNeeded()

let codingPath = Proxy.proxyList
let localKey = try LocalStorageKeyFactory().createFromStoragePath(
codingPath,
accountId: accountId,
chainId: chainId
)

return try getDataProvider(
for: localKey,
chainId: chainId,
storageCodingPath: codingPath,
shouldUseFallback: false
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ typealias DecodedBondedPool = ChainStorageDecodedItem<NominationPools.BondedPool
typealias DecodedRewardPool = ChainStorageDecodedItem<NominationPools.RewardPool>
typealias DecodedSubPools = ChainStorageDecodedItem<NominationPools.SubPools>
typealias DecodedPoolId = ChainStorageDecodedItem<StringScaleMapper<NominationPools.PoolId>>
typealias DecodedProxyDefinition = ChainStorageDecodedItem<ProxyDefinition>
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import RobinHood

protocol ProxyListLocalSubscriptionHandler {
func handleAllProxies(result: Result<[DataProviderChange<ProxyAccountModel>], Error>)
func handleProxies(
result: Result<ProxyDefinition?, Error>,
accountId: AccountId,
chainId: ChainModel.Id
)
}

extension ProxyListLocalSubscriptionHandler {
func handleAllProxies(result _: Result<[DataProviderChange<ProxyAccountModel>], Error>) {}
func handleProxies(
result _: Result<ProxyDefinition?, Error>,
accountId _: AccountId,
chainId _: ChainModel.Id
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,40 @@ import RobinHood

protocol ProxyListLocalSubscriptionFactoryProtocol {
func getProxyListProvider() throws -> StreamableProvider<ProxyAccountModel>
func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition>
}

final class ProxyListLocalSubscriptionFactory: BaseLocalSubscriptionFactory {
static let shared = ProxyListLocalSubscriptionFactory(
chainRegistry: ChainRegistryFacade.sharedRegistry,
streamableProviderFactory: SubstrateDataProviderFactory(
facade: SubstrateDataStorageFacade.shared,
operationManager: OperationManagerFacade.sharedManager,
logger: Logger.shared
),
storageFacade: UserDataStorageFacade.shared,
operationManager: OperationManager(operationQueue: OperationManagerFacade.sharedDefaultQueue),
operationManager: OperationManagerFacade.sharedManager,
logger: Logger.shared
)

let chainRegistry: ChainRegistryProtocol
let streamableProviderFactory: SubstrateDataProviderFactoryProtocol
let storageFacade: StorageFacadeProtocol
let operationManager: OperationManagerProtocol
let logger: LoggerProtocol

init(
chainRegistry: ChainRegistryProtocol,
streamableProviderFactory: SubstrateDataProviderFactoryProtocol,
storageFacade: StorageFacadeProtocol,
operationManager: OperationManagerProtocol,
logger: LoggerProtocol
) {
self.chainRegistry = chainRegistry
self.streamableProviderFactory = streamableProviderFactory
self.storageFacade = storageFacade
self.operationManager = operationManager
self.logger = logger
Expand Down Expand Up @@ -64,4 +80,54 @@ extension ProxyListLocalSubscriptionFactory: ProxyListLocalSubscriptionFactoryPr

return provider
}

func getProxyListProvider(
for accountId: AccountId,
chainId: ChainModel.Id
) throws -> AnyDataProvider<DecodedProxyDefinition> {
clearIfNeeded()

let codingPath = Proxy.proxyList
let localKey = try LocalStorageKeyFactory().createFromStoragePath(
codingPath,
accountId: accountId,
chainId: chainId
)

if let dataProvider = getProvider(for: localKey) as? DataProvider<DecodedProxyDefinition> {
return AnyDataProvider(dataProvider)
}

guard let runtimeCodingProvider = chainRegistry.getRuntimeProvider(for: chainId) else {
throw ChainRegistryError.runtimeMetadaUnavailable
}

let repository = InMemoryDataProviderRepository<DecodedProxyDefinition>()

let streamableProvider = streamableProviderFactory.createStorageProvider(for: localKey)
let fallback = StorageProviderSourceFallback<ProxyDefinition>.init(
usesRuntimeFallback: false,
missingEntryStrategy: .defaultValue(nil)
)
let trigger = DataProviderProxyTrigger()
let source: StorageProviderSource<ProxyDefinition> = StorageProviderSource(
itemIdentifier: localKey,
possibleCodingPaths: [codingPath],
runtimeService: runtimeCodingProvider,
provider: streamableProvider,
trigger: trigger,
fallback: fallback,
operationManager: operationManager
)

let dataProvider = DataProvider(
source: AnyDataProviderSource(source),
repository: AnyDataProviderRepository(repository),
updateTrigger: trigger
)

saveProvider(dataProvider, for: localKey)

return AnyDataProvider(dataProvider)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ protocol ProxyListLocalStorageSubscriber where Self: AnyObject {
var proxyListLocalSubscriptionHandler: ProxyListLocalSubscriptionHandler { get }

func subscribeAllProxies() -> StreamableProvider<ProxyAccountModel>?

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id,
modifyInternalList: @escaping (ProxyDefinition) -> ProxyDefinition
) -> AnyDataProvider<DecodedProxyDefinition>?
}

extension ProxyListLocalStorageSubscriber {
Expand Down Expand Up @@ -42,6 +48,54 @@ extension ProxyListLocalStorageSubscriber {

return provider
}

func subscribeProxies(
for accountId: AccountId,
chainId: ChainModel.Id,
modifyInternalList: @escaping (ProxyDefinition) -> ProxyDefinition
) -> AnyDataProvider<DecodedProxyDefinition>? {
guard let provider = try? proxyListLocalSubscriptionFactory.getProxyListProvider(
for: accountId,
chainId: chainId
) else {
return nil
}

let updateClosure = { [weak self] (changes: [DataProviderChange<DecodedProxyDefinition>]) in
let proxies = changes.reduceToLastChange()?.item.map { modifyInternalList($0) } ?? nil

self?.proxyListLocalSubscriptionHandler.handleProxies(
result: .success(proxies),
accountId: accountId,
chainId: chainId
)
return
}

let failureClosure = { [weak self] (error: Error) in
self?.proxyListLocalSubscriptionHandler.handleProxies(
result: .failure(error),
accountId: accountId,
chainId: chainId
)
return
}

let options = DataProviderObserverOptions(
alwaysNotifyOnRefresh: false,
waitsInProgressSyncOnAdd: false
)

provider.addObserver(
self,
deliverOn: .main,
executing: updateClosure,
failing: failureClosure,
options: options
)

return provider
}
}

extension ProxyListLocalStorageSubscriber where Self: ProxyListLocalSubscriptionHandler {
Expand Down
63 changes: 41 additions & 22 deletions novawallet/Common/Helpers/AssetBalanceFormatterFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ protocol AssetBalanceFormatterFactoryProtocol {

func createAssetPriceFormatter(for info: AssetBalanceDisplayInfo) -> LocalizableResource<TokenFormatter>

func createTotalPriceFormatter(for info: AssetBalanceDisplayInfo) -> LocalizableResource<TokenFormatter>

func createInputTokenFormatter(
for info: AssetBalanceDisplayInfo
) -> LocalizableResource<TokenFormatter>
Expand All @@ -40,12 +42,14 @@ class AssetBalanceFormatterFactory {
private func createTokenFormatterCommon(
for info: AssetBalanceDisplayInfo,
roundingMode: NumberFormatter.RoundingMode,
preferredPrecisionOffset: UInt8 = 0
preferredPrecisionOffset: UInt8 = 0,
usesSuffixForBigNumbers: Bool = true
) -> LocalizableResource<TokenFormatter> {
let formatter = createCompoundFormatter(
for: info.displayPrecision,
roundingMode: roundingMode,
prefferedPrecisionOffset: preferredPrecisionOffset
prefferedPrecisionOffset: preferredPrecisionOffset,
usesSuffixForBigNumber: usesSuffixForBigNumbers
)

let tokenFormatter = TokenFormatter(
Expand All @@ -65,9 +69,10 @@ class AssetBalanceFormatterFactory {
private func createCompoundFormatter(
for preferredPrecision: UInt16,
roundingMode: NumberFormatter.RoundingMode = .down,
prefferedPrecisionOffset: UInt8 = 0
prefferedPrecisionOffset: UInt8 = 0,
usesSuffixForBigNumber: Bool = true
) -> LocalizableDecimalFormatting {
let abbreviations: [BigNumberAbbreviation] = [
var abbreviations: [BigNumberAbbreviation] = [
BigNumberAbbreviation(
threshold: 0,
divisor: 1.0,
Expand All @@ -93,27 +98,32 @@ class AssetBalanceFormatterFactory {
divisor: 1.0,
suffix: "",
formatter: nil
),
BigNumberAbbreviation(
threshold: 1_000_000,
divisor: 1_000_000.0,
suffix: "M",
formatter: nil
),
BigNumberAbbreviation(
threshold: 1_000_000_000,
divisor: 1_000_000_000.0,
suffix: "B",
formatter: nil
),
BigNumberAbbreviation(
threshold: 1_000_000_000_000,
divisor: 1_000_000_000_000.0,
suffix: "T",
formatter: nil
)
]

if usesSuffixForBigNumber {
abbreviations.append(contentsOf: [
BigNumberAbbreviation(
threshold: 1_000_000,
divisor: 1_000_000.0,
suffix: "M",
formatter: nil
),
BigNumberAbbreviation(
threshold: 1_000_000_000,
divisor: 1_000_000_000.0,
suffix: "B",
formatter: nil
),
BigNumberAbbreviation(
threshold: 1_000_000_000_000,
divisor: 1_000_000_000_000.0,
suffix: "T",
formatter: nil
)
])
}

return BigNumberFormatter(
abbreviations: abbreviations,
precision: 2,
Expand Down Expand Up @@ -154,6 +164,15 @@ extension AssetBalanceFormatterFactory: AssetBalanceFormatterFactoryProtocol {
createTokenFormatterCommon(for: info, roundingMode: .down, preferredPrecisionOffset: 2)
}

func createTotalPriceFormatter(for info: AssetBalanceDisplayInfo) -> LocalizableResource<TokenFormatter> {
createTokenFormatterCommon(
for: info,
roundingMode: .down,
preferredPrecisionOffset: 2,
usesSuffixForBigNumbers: false
)
}

func createInputTokenFormatter(
for info: AssetBalanceDisplayInfo
) -> LocalizableResource<TokenFormatter> {
Expand Down
5 changes: 5 additions & 0 deletions novawallet/Common/Helpers/ChainAccountFetching.swift
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,11 @@ extension MetaAccountModel {

return chainAccount.proxy
}

func address(for chainAsset: ChainAsset) throws -> AccountAddress? {
let request = chainAsset.chain.accountRequest()
return try fetch(for: request)?.toAddress()
}
}

extension ChainModel {
Expand Down
9 changes: 9 additions & 0 deletions novawallet/Common/Model/AssetBalance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ struct AssetBalance: Equatable {
)
}

func regularTransferrableBalance() -> BigUInt {
Self.transferrableBalance(
from: freeInPlank,
frozen: frozenInPlank,
reserved: reservedInPlank,
mode: .regular
)
}

static func transferrableBalance(
from free: BigUInt,
frozen: BigUInt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ enum SubqueryMultistaking {
}

struct StatsResponse: Decodable {
let activeStakers: SubqueryNodes<ActiveStaker>
let activeStakers: SubqueryNodes<ActiveStaker>?
let stakingApies: SubqueryNodes<Apy>
let rewards: SubqueryAggregates<AccumulatedReward>
let slashes: SubqueryAggregates<AccumulatedReward>
let rewards: SubqueryAggregates<AccumulatedReward>?
let slashes: SubqueryAggregates<AccumulatedReward>?
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ extension SubqueryMultistakingOperationFactory: MultistakingOffchainOperationFac
do {
let query = try buildQuery(for: request)
let operation = createOperation(for: query) { (result: SubqueryMultistaking.StatsResponse) in
let activeStakers = result.activeStakers.groupByNetworkAccountStaking()
let rewards = result.rewards.groupByNetworkStaking()
let slashes = result.slashes.groupByNetworkStaking()
let activeStakers = result.activeStakers?.groupByNetworkAccountStaking() ?? [:]
let rewards = result.rewards?.groupByNetworkStaking() ?? [:]
let slashes = result.slashes?.groupByNetworkStaking() ?? [:]

let stateFilterByNetworkStaking = request.stateFilters.groupByNetworkStaking()

Expand Down
Loading
Loading