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

Deposit instruction based on deposit rules #877

Merged
Show file tree
Hide file tree
Changes from 5 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
12 changes: 12 additions & 0 deletions RadixWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,7 @@
832880692AE664C30014FBF3 /* EntityFlag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832880682AE664C30014FBF3 /* EntityFlag.swift */; };
8328806C2AE6725F0014FBF3 /* AccountPreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8328806B2AE6725F0014FBF3 /* AccountPreferencesTests.swift */; };
83D0B5692AE01EDE0048DCBE /* RadixEngineToolkitError+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83D0B5682AE01EDE0048DCBE /* RadixEngineToolkitError+Description.swift */; };
83EE47502AF027DF00155F03 /* AssetTransferDepositRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83EE474F2AF027DF00155F03 /* AssetTransferDepositRuleTests.swift */; };
E62BB7632AEA856300D46DAC /* ImportMnemonicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E62BB7622AEA856300D46DAC /* ImportMnemonicTests.swift */; };
E6390FB32AE6C3E200B4DEE2 /* ProfileStore+OverlayWindowClient+Alert+OwnershipConflict.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6390FB22AE6C3E200B4DEE2 /* ProfileStore+OverlayWindowClient+Alert+OwnershipConflict.swift */; };
E63D123D2ADD1FC00001CBB1 /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = E63D123C2ADD1FC00001CBB1 /* SwiftUIIntrospect */; };
Expand Down Expand Up @@ -2401,6 +2402,7 @@
832880682AE664C30014FBF3 /* EntityFlag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityFlag.swift; sourceTree = "<group>"; };
8328806B2AE6725F0014FBF3 /* AccountPreferencesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountPreferencesTests.swift; sourceTree = "<group>"; };
83D0B5682AE01EDE0048DCBE /* RadixEngineToolkitError+Description.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RadixEngineToolkitError+Description.swift"; sourceTree = "<group>"; };
83EE474F2AF027DF00155F03 /* AssetTransferDepositRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetTransferDepositRuleTests.swift; sourceTree = "<group>"; };
E62BB7622AEA856300D46DAC /* ImportMnemonicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportMnemonicTests.swift; sourceTree = "<group>"; };
E6390FB22AE6C3E200B4DEE2 /* ProfileStore+OverlayWindowClient+Alert+OwnershipConflict.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileStore+OverlayWindowClient+Alert+OwnershipConflict.swift"; sourceTree = "<group>"; };
E67F14442AE029BA00738BE1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6667,6 +6669,14 @@
path = AccountPreferencesTests;
sourceTree = "<group>";
};
83EE474E2AF027CE00155F03 /* AssetTransferTests */ = {
isa = PBXGroup;
children = (
83EE474F2AF027DF00155F03 /* AssetTransferDepositRuleTests.swift */,
);
path = AssetTransferTests;
sourceTree = "<group>";
};
E63D123B2ADD1FC00001CBB1 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -6766,6 +6776,7 @@
E6DBA2732ADEBFB200A38425 /* Features */ = {
isa = PBXGroup;
children = (
83EE474E2AF027CE00155F03 /* AssetTransferTests */,
830EA9DE2AEB8201004C8051 /* AccountAndPersonaHidingTests */,
8328806A2AE6724B0014FBF3 /* AccountPreferencesTests */,
E6DBA2782ADEBFB200A38425 /* SettingsFeatureTests */,
Expand Down Expand Up @@ -7507,6 +7518,7 @@
E6DBA3732ADEBFB300A38425 /* ROLAClientTests.swift in Sources */,
E6DBA31F2ADEBFB300A38425 /* RadixConnectCustomData.swift in Sources */,
E6DBA34B2ADEBFB300A38425 /* SLIP10TestHelpers.swift in Sources */,
83EE47502AF027DF00155F03 /* AssetTransferDepositRuleTests.swift in Sources */,
E6DBA3462ADEBFB300A38425 /* DataToHexStringTests.swift in Sources */,
E6DBA38B2ADEC0CB00A38425 /* SLIP10TestVectorsHelper.swift in Sources */,
E6DBA3572ADEBFB300A38425 /* SLIP10InterfaceTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ extension OnLedgerEntitiesClient {
)

let filteredFungibleResources = fungibleResources.filter { resource in
!poolUnitResources.fungibleResourceAddresses.contains(resource.resourceAddress.address)
!poolUnitResources.fungibleResourceAddresses.contains(resource.resourceAddress)
}

let filteredNonFungibleResources = nonFungibleResources.filter { resource in
!poolUnitResources.nonFungibleResourceAddresses.contains(resource.resourceAddress.address)
!poolUnitResources.nonFungibleResourceAddresses.contains(resource.resourceAddress)
}

return await .init(
Expand All @@ -70,7 +70,7 @@ extension OnLedgerEntitiesClient {
metadata: .init(item.explicitMetadata),
fungibleResources: filteredFungibleResources.sorted(),
nonFungibleResources: filteredNonFungibleResources.sorted(),
poolUnitResources: poolUnitResources.nonEmpty
poolUnitResources: poolUnitResources
)
}

Expand Down Expand Up @@ -304,10 +304,6 @@ extension OnLedgerEntitiesClient {
}

let amount = try RETDecimal(value: vault.amount)
guard amount > 0 else {
return nil
}

return try .init(
resourceAddress: .init(validatingAddress: vaultAggregated.resourceAddress),
atLedgerState: ledgerState,
Expand All @@ -327,10 +323,6 @@ extension OnLedgerEntitiesClient {
return nil
}

guard vault.totalCount > 0 else {
return nil
}

return try .init(
resourceAddress: .init(validatingAddress: vaultAggregated.resourceAddress),
atLedgerState: ledgerState,
Expand Down Expand Up @@ -472,7 +464,7 @@ extension OnLedgerEntitiesClient {
}

extension OnLedgerEntity.Account.PoolUnitResources {
var nonEmpty: OnLedgerEntity.Account.PoolUnitResources {
var nonEmptyVaults: OnLedgerEntity.Account.PoolUnitResources {
let stakes = radixNetworkStakes.compactMap { stake in
let stakeUnitResource: OnLedgerEntity.OwnedFungibleResource? = {
guard let stakeUnitResource = stake.stakeUnitResource, stakeUnitResource.amount > 0 else {
Expand Down Expand Up @@ -502,6 +494,34 @@ extension OnLedgerEntity.Account.PoolUnitResources {
}
}

extension [OnLedgerEntity.OwnedNonFungibleResource] {
public var nonEmptyVaults: [OnLedgerEntity.OwnedNonFungibleResource] {
filter { $0.nonFungibleIdsCount > 0 }
}
}

extension OnLedgerEntity.OwnedFungibleResources {
public var nonEmptyVaults: OnLedgerEntity.OwnedFungibleResources {
.init(
xrdResource: xrdResource.flatMap { $0.amount > 0 ? $0 : nil },
nonXrdResources: nonXrdResources.filter { $0.amount > 0 }
)
}
}

extension OnLedgerEntity.Account {
public var nonEmptyVaults: OnLedgerEntity.Account {
.init(
address: address,
atLedgerState: atLedgerState,
metadata: metadata,
fungibleResources: fungibleResources.nonEmptyVaults,
nonFungibleResources: nonFungibleResources.nonEmptyVaults,
poolUnitResources: poolUnitResources.nonEmptyVaults
)
}
}

extension OnLedgerEntitiesClient {
public struct OwnedStakeDetails: Hashable, Sendable {
public let validator: OnLedgerEntity.Validator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,15 +374,15 @@ extension Address {
extension OnLedgerEntity.Account.PoolUnitResources {
// The fungible resources used to build up the pool units.
// Will be used to filter out those from the general fungible resources list.
var fungibleResourceAddresses: [String] {
radixNetworkStakes.compactMap(\.stakeUnitResource?.resourceAddress.address) +
poolUnits.map(\.resource.resourceAddress.address)
var fungibleResourceAddresses: [ResourceAddress] {
GhenadieVP marked this conversation as resolved.
Show resolved Hide resolved
radixNetworkStakes.compactMap(\.stakeUnitResource?.resourceAddress) +
poolUnits.map(\.resource.resourceAddress)
}

// The non fungible resources used to build up the pool units.
// Will be used to filter out those from the general fungible resources list.
var nonFungibleResourceAddresses: [String] {
radixNetworkStakes.compactMap(\.stakeClaimResource?.resourceAddress.address)
var nonFungibleResourceAddresses: [ResourceAddress] {
radixNetworkStakes.compactMap(\.stakeClaimResource?.resourceAddress)
}
}

Expand Down
19 changes: 19 additions & 0 deletions RadixWallet/Core/SharedModels/Assets/OnLedgerEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,22 @@ extension [OnLedgerEntity.NonFungibleToken.NFTData] {
self[.claimAmount]?.decimal
}
}

extension OnLedgerEntity.Account {
public var allFungibleResourceAddresses: [ResourceAddress] {
fungibleResources.xrdResource.asArray(\.resourceAddress) + fungibleResources.nonXrdResources.map(\.resourceAddress)
}

public var allResourceAddresses: Set<ResourceAddress> {
Set(
allFungibleResourceAddresses
+ nonFungibleResources.map(\.resourceAddress)
+ poolUnitResources.fungibleResourceAddresses
+ poolUnitResources.nonFungibleResourceAddresses
)
}

public func hasResource(_ resourceAddress: ResourceAddress) -> Bool {
allResourceAddresses.contains(resourceAddress)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ extension AccountList {
guard !Task.isCancelled else {
return
}
await send(.internal(.accountPortfolioUpdate(accountPortfolio)))
await send(.internal(.accountPortfolioUpdate(accountPortfolio.nonEmptyVaults)))
}
}
case .backUpMnemonic:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ extension AssetTransfer {

try await instructionForDepositing(
bucket: bucket,
resource: resource.address,
into: account.recipient
)
}
Expand All @@ -221,6 +222,7 @@ extension AssetTransfer {

try await instructionForDepositing(
bucket: bucket,
resource: resource.address,
into: account.recipient
)
}
Expand All @@ -232,30 +234,79 @@ extension AssetTransfer {

func instructionForDepositing(
bucket: ManifestBuilderBucket,
resource: ResourceAddress,
into receivingAccount: ReceivingAccount.State.Account
) async throws -> ManifestBuilder.InstructionsChain.Instruction {
@Dependency(\.userDefaultsClient) var userDefaultsClient
@Dependency(\.secureStorageClient) var secureStorageClient
let isUserAccount = receivingAccount.isUserAccount
// TODO: Temporary revert of checking if the receiving account is a ledger account
let isSoftwareAccount = true // !receivingAccount.isLedgerAccount
let recipientAddress = receivingAccount.address
let userHasAccessToMnemonic = if let deviceFactorSourceID = receivingAccount.left?.deviceFactorSourceID {
await secureStorageClient.containsMnemonicIdentifiedByFactorSourceID(deviceFactorSourceID)
} else { false }

guard isUserAccount, isSoftwareAccount, userHasAccessToMnemonic else {
if case let .left(userAccount) = receivingAccount {
@Dependency(\.secureStorageClient) var secureStorageClient
// TODO: Temporary revert of checking if the receiving account is a ledger account
let isSoftwareAccount = true // !receivingAccount.isLedgerAccount
GhenadieVP marked this conversation as resolved.
Show resolved Hide resolved
let userHasAccessToMnemonic = userAccount.deviceFactorSourceID.map { deviceFactorSourceID in
secureStorageClient.containsMnemonicIdentifiedByFactorSourceID(deviceFactorSourceID)
} ?? false

let needsSignatureForDepositing = await needsSignatureForDepositting(into: userAccount, resource: resource)

if needsSignatureForDepositing, isSoftwareAccount, userHasAccessToMnemonic {
return try ManifestBuilder.accountDeposit(
recipientAddress.intoEngine(),
bucket
)
} else {
return try ManifestBuilder.accountTryDepositOrAbort(
recipientAddress.intoEngine(),
nil,
bucket
)
}
} else {
return try ManifestBuilder.accountTryDepositOrAbort(
recipientAddress.intoEngine(),
nil,
bucket
)
}
}

return try ManifestBuilder.accountDeposit(
recipientAddress.intoEngine(),
bucket
)
/// Determines if depositting the resource into an account requires the addition of a signature
func needsSignatureForDepositting(into receivingAccount: Profile.Network.Account, resource resourceAddress: ResourceAddress) async -> Bool {
let depositSettings = receivingAccount.onLedgerSettings.thirdPartyDeposits
let resourceException = depositSettings.assetsExceptionList.first { $0.address == resourceAddress }?.exceptionRule

switch (depositSettings.depositRule, resourceException) {
// AcceptAll
case (.acceptAll, .none):
return false
case (.acceptAll, .allow):
return false
case (.acceptAll, .deny):
return true

// Accept Known
case (.acceptKnown, .allow):
return false
case (.acceptKnown, .none):
// Check if the resource is known to the account
@Dependency(\.onLedgerEntitiesClient) var onLedgerEntitiesClient
let hasResource = await (try? onLedgerEntitiesClient
.getAccount(receivingAccount.address)
.hasResource(resourceAddress)
) ?? false

return !hasResource
case (.acceptKnown, .deny):
return true

// DenyAll
case (.denyAll, .none):
return true
case (.denyAll, .allow):
return false
case (.denyAll, .deny):
return true
}
}

extension AssetTransfer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public struct AssetsView: Sendable, FeatureReducer {
return .run { [address = state.account.address, mode = state.mode] send in
for try await portfolio in await accountPortfoliosClient.portfolioForAccount(address).debounce(for: .seconds(0.1)) {
guard !Task.isCancelled else { return }
await send(.internal(.resourcesStateUpdated(createResourcesState(from: portfolio, mode: mode))))
await send(.internal(.resourcesStateUpdated(createResourcesState(from: portfolio.nonEmptyVaults, mode: mode))))
}
} catch: { error, _ in
loggerGlobal.error("AssetsView portfolioForAccount failed: \(error)")
Expand Down
Loading
Loading