Skip to content

Commit

Permalink
Profile - Third-Party deposits (#680)
Browse files Browse the repository at this point in the history
  • Loading branch information
GhenadieVP committed Aug 22, 2023
1 parent c35f978 commit 345bd1c
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
"description" : "computer unit test",
"id" : "BABE1442-3C98-41FF-AFB0-D0F5829B020D"
},
"snapshotVersion" : 43
"snapshotVersion" : 44
},
"networks" : [
{
Expand Down Expand Up @@ -272,6 +272,13 @@
}
}
}
},
"onLedgerSettings": {
"thirdPartyDeposits": {
"depositRule": "acceptAll",
"assetsExceptionList": [],
"depositorsAllowList": []
}
}
},
{
Expand Down Expand Up @@ -334,6 +341,37 @@
}
}
}
},
"onLedgerSettings": {
"thirdPartyDeposits": {
"depositRule": "acceptKnown",
"assetsExceptionList": [
{
"address": {
"discriminator": "resourceAddress",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"
},
"exceptionRule": "allow"
},
{
"address" : {
"discriminator": "nonFungibleGlobalID",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#1#"
},
"exceptionRule": "deny"
},
],
"depositorsAllowList": [
{
"discriminator": "resourceAddress",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"
},
{
"discriminator": "nonFungibleGlobalID",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#2#"
},
]
}
}
},
{
Expand Down Expand Up @@ -396,8 +434,39 @@
}
}
}
},
"onLedgerSettings": {
"thirdPartyDeposits": {
"depositRule": "denyAll",
"assetsExceptionList": [
{
"address": {
"discriminator": "resourceAddress",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"
},
"exceptionRule": "deny"
},
{
"address" : {
"discriminator": "nonFungibleGlobalID",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#1#"
},
"exceptionRule": "allow"
},
],
"depositorsAllowList": [
{
"discriminator": "resourceAddress",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"
},
{
"discriminator": "nonFungibleGlobalID",
"value": "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#2#"
},
]
}
}
}
},
],
"authorizedDapps" : [
{
Expand Down
4 changes: 4 additions & 0 deletions Sources/Profile/Entity/Account.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ extension Profile.Network {
/// A required non empty display name, used by presentation layer and sent to Dapps when requested.
public var displayName: NonEmpty<String>

/// The on ledger synced settings for this account
public var onLedgerSettings: OnLedgerSettings

public init(
networkID: NetworkID,
address: EntityAddress,
Expand All @@ -78,6 +81,7 @@ extension Profile.Network {
self.address = address
self.securityState = securityState
self.appearanceID = extraProperties.appearanceID
self.onLedgerSettings = .default
self.displayName = displayName
}
}
Expand Down
133 changes: 133 additions & 0 deletions Sources/Profile/Entity/OnLedgerSettings/Account+OnLedgerSettings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import EngineKit
import Prelude

// MARK: - Profile.Network.Account.OnLedgerSettings
extension Profile.Network.Account {
public struct OnLedgerSettings: Hashable, Sendable, Codable {
/// Controls the ability of third-parties to deposit into this account
public var thirdPartyDeposits: ThirdPartyDeposits

public init(thirdPartyDeposits: ThirdPartyDeposits) {
self.thirdPartyDeposits = thirdPartyDeposits
}

/// The default value for newly created accounts.
/// After the account is created the OnLedgerSettings will be updated either by User or by syncing with the Ledger.
public static let `default` = Self(thirdPartyDeposits: .default)
}
}

// MARK: - Profile.Network.Account.OnLedgerSettings.ThirdPartyDeposits
extension Profile.Network.Account.OnLedgerSettings {
public struct ThirdPartyDeposits: Hashable, Sendable, Codable {
/// The general deposit rule to apply
public enum DepositRule: String, Hashable, Sendable, Codable, CaseIterable {
case acceptAll
case acceptKnown
case denyAll
}

/// The addresses that can be added as exception to the `DepositRule`
public enum DepositAddress: Hashable, Sendable, Codable {
case resourceAddress(ResourceAddress)
case nonFungibleGlobalID(NonFungibleGlobalId)
}

/// The exception kind for deposit address
public enum DepositAddressExceptionRule: String, Hashable, Sendable, Codable, CaseIterable {
/// A resource can always be deposited in to the account by third-parties
case allow
/// A resource can never be deposited in to the account by third-parties
case deny
}

/// The specific Asset exception rule
public struct AssetException: Hashable, Sendable, Codable {
public let address: DepositAddress
public let exceptionRule: DepositAddressExceptionRule

public init(address: DepositAddress, exceptionRule: DepositAddressExceptionRule) {
self.address = address
self.exceptionRule = exceptionRule
}
}

/// Controls the ability of thir-parties to deposit into this account
public var depositRule: DepositRule

/// Denies or allows third-party deposits of specific assets by ignoring the `depositMode`
public var assetsExceptionList: OrderedSet<AssetException>

/// Allows certain third-party depositors to deposit assets freely.
/// Note: There is no `deny` counterpart for this.
public var depositorsAllowList: OrderedSet<DepositAddress>

public init(
depositRule: DepositRule,
assetsExceptionList: OrderedSet<AssetException>,
depositorsAllowList: OrderedSet<DepositAddress>
) {
self.depositRule = depositRule
self.assetsExceptionList = assetsExceptionList
self.depositorsAllowList = depositorsAllowList
}

/// On Ledger default is `acceptAll` for deposit mode and empty lists
public static let `default` = Self(depositRule: .acceptAll, assetsExceptionList: [], depositorsAllowList: [])
}
}

/// Override default Hashable conformance to use only the Address for hashing and comparison,
/// assuring that there is only one exception rule for a given Address in the Set.
extension Profile.Network.Account.OnLedgerSettings.ThirdPartyDeposits.AssetException {
public func hash(into hasher: inout Hasher) {
hasher.combine(address)
}

public static func == (lhs: Self, rhs: Self) -> Bool {
lhs.address == rhs.address
}
}

extension Profile.Network.Account.OnLedgerSettings.ThirdPartyDeposits.DepositAddress {
private enum CodingKeys: String, CodingKey {
case discriminator
case value
}

enum Discriminator: String, Sendable, Hashable, CustomStringConvertible, Codable {
case resourceAddress, nonFungibleGlobalID

public var description: String {
rawValue
}
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

let discriminator = try container.decode(Discriminator.self, forKey: .discriminator)
let value = try container.decode(String.self, forKey: .value)

switch discriminator {
case .resourceAddress:
self = try .resourceAddress(.init(validatingAddress: value))
case .nonFungibleGlobalID:
self = try .nonFungibleGlobalID(.init(nonFungibleGlobalId: value))
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

switch self {
case let .resourceAddress(address):
try container.encode(Discriminator.resourceAddress, forKey: .discriminator)
try container.encode(address.address, forKey: .value)

case let .nonFungibleGlobalID(id):
try container.encode(Discriminator.nonFungibleGlobalID, forKey: .discriminator)
try container.encode(id.asStr(), forKey: .value)
}
}
}
3 changes: 2 additions & 1 deletion Sources/Profile/Snapshot/ProfileSnapshot+Header.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ extension ProfileSnapshot.Header.Version {
/// - 40: Changed Persona data/field format
/// - 41: Nickname is not optional
/// - 42: Change counter to not be factor source based.
public static let minimum: Self = 43
/// - 44: Added OnLedgerSettings
public static let minimum: Self = 44
}

extension ProfileSnapshot.Header {
Expand Down
66 changes: 66 additions & 0 deletions Tests/ProfileTests/ProfileTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,16 @@ final class ProfileTests: TestCase {
"account_tdx_21_12ya9jylskaa6gdrfr8nvve3pfc6wyhyw7eg83fwlc7fv2w0eanumcd"
)

XCTAssertEqual(
network.accounts[0].onLedgerSettings,
.init(thirdPartyDeposits: .init(
depositRule: .acceptAll,
assetsExceptionList: [],
depositorsAllowList: []
)
)
)

// Account 1
XCTAssertEqual(
network.accounts[1].publicKey()?.compressedData.hex(),
Expand All @@ -539,6 +549,34 @@ final class ProfileTests: TestCase {
"account_tdx_21_12xg7tf7aup8lrxkvug0vzatntzww0c6jnntyj6yd4eg5920kpxpzvt"
)

XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.depositRule, .acceptKnown
)

XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[0].address,
.resourceAddress(.init(stringLiteral: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"))
)
XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[0].exceptionRule, .allow
)

XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[1].address,
try .nonFungibleGlobalID(.init(nonFungibleGlobalId: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#1#"))
)
XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[1].exceptionRule, .deny
)

XCTAssertEqual(
network.accounts[1].onLedgerSettings.thirdPartyDeposits.depositorsAllowList,
try [
.resourceAddress(.init(stringLiteral: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder")),
.nonFungibleGlobalID(.init(nonFungibleGlobalId: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#2#")),
]
)

// Account 2
XCTAssertEqual(
network.accounts[2].publicKey()?.compressedData.hex(),
Expand All @@ -554,6 +592,34 @@ final class ProfileTests: TestCase {
"account_tdx_21_12yth59wfyl8e4axupym0c96g9heuf5j06lv2lgc2cuapzlmj6alzzn"
)

XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.depositRule, .denyAll
)

XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[0].address,
.resourceAddress(.init(stringLiteral: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder"))
)
XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[0].exceptionRule, .deny
)

XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[1].address,
try .nonFungibleGlobalID(.init(nonFungibleGlobalId: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#1#"))
)
XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.assetsExceptionList[1].exceptionRule, .allow
)

XCTAssertEqual(
network.accounts[2].onLedgerSettings.thirdPartyDeposits.depositorsAllowList,
try [
.resourceAddress(.init(stringLiteral: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder")),
.nonFungibleGlobalID(.init(nonFungibleGlobalId: "resource_tdx_21_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxsmgder:#2#")),
]
)

// Persona 0
XCTAssertEqual(
network.personas[0].publicKey()?.compressedData.hex(),
Expand Down

0 comments on commit 345bd1c

Please sign in to comment.