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

Feature/ledger flow updates #1417

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerAddressApproveFlex.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerAddressApproveStax.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerApproveFlex.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerApproveStax.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerWarningFlex.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "imageLedgerWarningStax.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
2 changes: 1 addition & 1 deletion novawallet/Common/Configs/ApplicationConfigs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ extension ApplicationConfig: ApplicationConfigProtocol {
}

var ledgerGuideURL: URL {
URL(string: "https://support.ledger.com/hc/en-us/articles/360019138694-Set-up-Bluetooth-connection")!
URL(string: "https://docs.novawallet.io/nova-wallet-wiki/wallet-management/hardware-wallets/ledger-devices")!
}

var ledgerMigrationURL: URL {
Expand Down
28 changes: 18 additions & 10 deletions novawallet/Common/Ledger/LedgerConnectionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ protocol LedgerConnectionManagerDelegate: AnyObject {
}

final class LedgerConnectionManager: NSObject {
private var centralManager: CBCentralManager?

@Atomic(defaultValue: [])
private var devices: [BluetoothLedgerDevice]
weak var delegate: LedgerConnectionManagerDelegate?

private var supportedDevices: [SupportedBluetoothDevice] = SupportedBluetoothDevice.ledgers
private var supportedDeviceUUIDs: [CBUUID] { supportedDevices.map(\.uuid) }
private var supportedDeviceNotifyUuids: [CBUUID] { supportedDevices.map(\.notifyUuid) }
let logger: LoggerProtocol

private let delegateQueue = DispatchQueue(label: "com.nova.wallet.ledger.connection." + UUID().uuidString)
private let supportedDevices: [CBUUID: SupportedBluetoothDevice] = SupportedBluetoothDevice.ledgers

weak var delegate: LedgerConnectionManagerDelegate?
private var centralManager: CBCentralManager?

let logger: LoggerProtocol
@Atomic(defaultValue: [])
private var devices: [BluetoothLedgerDevice]

private var supportedDeviceUUIDs: [CBUUID] { supportedDevices.values.map(\.uuid) }
private var supportedDeviceNotifyUuids: [CBUUID] { supportedDevices.values.map(\.notifyUuid) }

init(logger: LoggerProtocol) {
self.logger = logger
Expand All @@ -66,7 +66,15 @@ final class LedgerConnectionManager: NSObject {

private func didDiscoverDevice(_ peripheral: CBPeripheral) {
if bluetoothDevice(id: peripheral.identifier) == nil {
let device = BluetoothLedgerDevice(peripheral: peripheral)
let deviceModel: LedgerDeviceModel = peripheral.services?.compactMap {
supportedDevices[$0.uuid]?.model
}.first ?? .unknown

let device = BluetoothLedgerDevice(
peripheral: peripheral,
model: deviceModel
)

devices.append(device)
delegate?.ledgerConnection(manager: self, didDiscover: device)
}
Expand Down
39 changes: 30 additions & 9 deletions novawallet/Common/Ledger/LedgerDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ import CoreBluetooth
protocol LedgerDeviceProtocol {
var identifier: UUID { get }
var name: String { get }
var model: LedgerDeviceModel { get }
}

enum LedgerDeviceModel {
case nanoX
case stax
case flex
case unknown
}

final class BluetoothLedgerDevice: LedgerDeviceProtocol {
typealias WriteCommand = () -> Void

let peripheral: CBPeripheral
let model: LedgerDeviceModel

var name: String {
peripheral.name ?? "Unknown device"
Expand All @@ -28,48 +37,60 @@ final class BluetoothLedgerDevice: LedgerDeviceProtocol {

let transport = LedgerTransport()

init(peripheral: CBPeripheral) {
init(
peripheral: CBPeripheral,
model: LedgerDeviceModel
) {
self.peripheral = peripheral
self.model = model
}
}

struct SupportedBluetoothDevice {
let uuid: CBUUID
let notifyUuid: CBUUID
let writeUuid: CBUUID
let model: LedgerDeviceModel
}

/* We can find these and new devices here: https://github.com/LedgerHQ/device-sdk-ts/blob/develop/packages/device-management-kit/src/api/device-model/data/StaticDeviceModelDataSource.ts */
extension SupportedBluetoothDevice {
static var ledgers: [SupportedBluetoothDevice] {
[
ledgerNanoX,
ledgerStax,
ledgerFlex
static var ledgers: [CBUUID: SupportedBluetoothDevice] {
let nanoX = ledgerNanoX
let stax = ledgerStax
let flex = ledgerFlex

return [
nanoX.uuid: nanoX,
stax.uuid: stax,
flex.uuid: flex
]
}

static var ledgerNanoX: SupportedBluetoothDevice {
SupportedBluetoothDevice(
uuid: CBUUID(string: "13D63400-2C97-0004-0000-4C6564676572"),
notifyUuid: CBUUID(string: "13D63400-2C97-0004-0001-4C6564676572"),
writeUuid: CBUUID(string: "13D63400-2C97-0004-0002-4C6564676572")
writeUuid: CBUUID(string: "13D63400-2C97-0004-0002-4C6564676572"),
model: .nanoX
)
}

static var ledgerStax: SupportedBluetoothDevice {
SupportedBluetoothDevice(
uuid: CBUUID(string: "13D63400-2C97-6004-0000-4C6564676572"),
notifyUuid: CBUUID(string: "13D63400-2C97-6004-0001-4C6564676572"),
writeUuid: CBUUID(string: "13D63400-2C97-6004-0002-4C6564676572")
writeUuid: CBUUID(string: "13D63400-2C97-6004-0002-4C6564676572"),
model: .stax
)
}

static var ledgerFlex: SupportedBluetoothDevice {
SupportedBluetoothDevice(
uuid: CBUUID(string: "13D63400-2C97-3004-0000-4C6564676572"),
notifyUuid: CBUUID(string: "13D63400-2C97-3004-0001-4C6564676572"),
writeUuid: CBUUID(string: "13D63400-2C97-3004-0002-4C6564676572")
writeUuid: CBUUID(string: "13D63400-2C97-3004-0002-4C6564676572"),
model: .flex
)
}
}
2 changes: 1 addition & 1 deletion novawallet/Common/View/StackTable/StackActionCell.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit

final class StackActionCell: RowView<StackActionView>, StackTableViewCellProtocol {
var titleLabel: UILabel { rowContentView.titleLabel }
var titleLabel: UILabel { rowContentView.titleValueView.valueTop }
var imageView: UIImageView { rowContentView.iconImageView }
var detailsView: BorderedLabelView { rowContentView.detailsView }

Expand Down
24 changes: 12 additions & 12 deletions novawallet/Common/View/StackTable/StackActionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import UIKit
final class StackActionView: UIView {
let iconImageView = UIImageView()

let titleLabel: UILabel = {
let label = UILabel()
label.font = .regularSubheadline
label.textColor = R.color.colorTextPrimary()
return label
}()
let titleValueView: MultiValueView = .create { view in
view.valueTop.apply(style: .regularSubhedlinePrimary)
view.valueBottom.apply(style: .footnoteSecondary)
view.stackView.alignment = .leading
view.spacing = 2.0
}

var detailsView: BorderedLabelView {
internalDetailsView ?? setupDetailsView()
Expand Down Expand Up @@ -68,7 +68,7 @@ final class StackActionView: UIView {
view.snp.makeConstraints { make in
make.trailing.equalTo(disclosureIndicatorView.snp.leading).offset(-8)
make.centerY.equalToSuperview()
make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8)
make.leading.greaterThanOrEqualTo(titleValueView.snp.trailing).offset(8)
}

return view
Expand All @@ -82,8 +82,8 @@ final class StackActionView: UIView {
make.size.equalTo(iconSize)
}

addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
addSubview(titleValueView)
titleValueView.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(iconSize + titleOffset)
make.centerY.equalToSuperview()
}
Expand All @@ -92,14 +92,14 @@ final class StackActionView: UIView {
disclosureIndicatorView.snp.makeConstraints { make in
make.trailing.equalToSuperview()
make.centerY.equalToSuperview()
make.leading.greaterThanOrEqualTo(titleLabel.snp.trailing).offset(8)
make.leading.greaterThanOrEqualTo(titleValueView.snp.trailing).offset(8)
}

titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
titleValueView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
}

private func updateTitleLayout() {
titleLabel.snp.remakeConstraints { make in
titleValueView.snp.remakeConstraints { make in
make.leading.equalToSuperview().offset(iconSize + titleOffset)
make.centerY.equalToSuperview()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ final class ActionManageTableViewCell: UITableViewCell, ModalPickerCellProtocol
manageContentView.iconImageView.image = model.icon
}

manageContentView.titleLabel.textColor = textColor
manageContentView.titleValueView.valueTop.textColor = textColor

manageContentView.titleLabel.text = model.title
manageContentView.titleValueView.bind(
topValue: model.title,
bottomValue: model.subtitle
)
}
}
3 changes: 3 additions & 0 deletions novawallet/Common/ViewModel/ActionManageViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@ import UIKit
struct ActionManageViewModel {
let icon: UIImage?
let title: String
let subtitle: String?
let details: String?
let isDestructive: Bool
let allowsIconModification: Bool

init(
icon: UIImage? = nil,
title: String,
subtitle: String? = nil,
details: String? = nil,
isDestructive: Bool = false,
allowsIconModification: Bool = true
) {
self.icon = icon
self.title = title
self.subtitle = subtitle
self.details = details
self.isDestructive = isDestructive
self.allowsIconModification = allowsIconModification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ final class DAppOperationConfirmViewLayout: SCGenericActionLayoutView<UIStackVie

let transactionDetailsCell: StackActionCell = .create { view in
view.rowContentView.iconSize = 0
view.rowContentView.titleLabel.apply(style: .footnoteSecondary)
view.titleLabel.apply(style: .footnoteSecondary)
}

let rejectButton: TriangularedButton = .create { button in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ class WalletImportOptionsWireframe: ActionsManagePresentable {
let viewModels: [LocalizableResource<ActionManageViewModel>] = hwWalletOptions.map { option in
switch option {
case .paritySigner:
return LocalizableResource { locale in
LocalizableResource { locale in
ActionManageViewModel(
icon: ParitySignerType.legacy.iconForAction,
title: ParitySignerType.legacy.getName(for: locale),
details: nil
)
}
case .polkadotVault:
return LocalizableResource { locale in
LocalizableResource { locale in
ActionManageViewModel(
icon: ParitySignerType.vault.iconForAction,
title: ParitySignerType.vault.getName(for: locale),
Expand All @@ -67,16 +67,16 @@ class WalletImportOptionsWireframe: ActionsManagePresentable {
}
case .ledger:
if isLedgerGenericAvailable {
return LocalizableResource { locale in
LocalizableResource { locale in
ActionManageViewModel(
icon: R.image.iconLedgerActionWarning(),
title: R.string.localizable.commonLedgerNanoLegacy(preferredLanguages: locale.rLanguages),
title: R.string.localizable.commonLedgerLegacy(preferredLanguages: locale.rLanguages),
details: nil,
allowsIconModification: false
)
}
} else {
return LocalizableResource { locale in
LocalizableResource { locale in
ActionManageViewModel(
icon: R.image.iconLedgerAction(),
title: R.string.localizable.commonLedgerNanoX(preferredLanguages: locale.rLanguages),
Expand All @@ -85,10 +85,15 @@ class WalletImportOptionsWireframe: ActionsManagePresentable {
}
}
case .genericLedger:
return LocalizableResource { locale in
LocalizableResource { locale in
ActionManageViewModel(
icon: R.image.iconLedgerAction(),
title: R.string.localizable.commonLedgerNanoGeneric(preferredLanguages: locale.rLanguages),
subtitle: [
R.string.localizable.commonLedgerModelFlex(preferredLanguages: locale.rLanguages),
R.string.localizable.commonLedgerModelStax(preferredLanguages: locale.rLanguages),
R.string.localizable.commonLedgerModelNanoX(preferredLanguages: locale.rLanguages)
].joined(with: .commaSpace),
details: nil
)
}
Expand Down
Loading