Skip to content

Commit

Permalink
(ios) Add "swap-in addresses" view
Browse files Browse the repository at this point in the history
  • Loading branch information
robbiehanson committed Feb 19, 2024
1 parent a55bc15 commit d51c743
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 8 deletions.
4 changes: 4 additions & 0 deletions phoenix-ios/phoenix-ios.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
DC355E232A45FAF2008E8A8E /* NestedObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC355E222A45FAF2008E8A8E /* NestedObservableObject.swift */; };
DC355E252A45FDD3008E8A8E /* NoticeMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC355E242A45FDD3008E8A8E /* NoticeMonitor.swift */; };
DC370A892B7FBD7C0093C56F /* BtcAddrOptionsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC370A882B7FBD7C0093C56F /* BtcAddrOptionsSheet.swift */; };
DC370A8B2B7FFFC70093C56F /* SwapInAddresses.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC370A8A2B7FFFC70093C56F /* SwapInAddresses.swift */; };
DC384D81265C12B700131772 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC384D80265C12B700131772 /* Cache.swift */; };
DC384D83265C32F100131772 /* TextField+Verbatim.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC384D82265C32F100131772 /* TextField+Verbatim.swift */; };
DC39A2662A12C04D00F59E39 /* LiquidityPolicyHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC39A2652A12C04D00F59E39 /* LiquidityPolicyHelp.swift */; };
Expand Down Expand Up @@ -462,6 +463,7 @@
DC355E222A45FAF2008E8A8E /* NestedObservableObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedObservableObject.swift; sourceTree = "<group>"; };
DC355E242A45FDD3008E8A8E /* NoticeMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeMonitor.swift; sourceTree = "<group>"; };
DC370A882B7FBD7C0093C56F /* BtcAddrOptionsSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BtcAddrOptionsSheet.swift; sourceTree = "<group>"; };
DC370A8A2B7FFFC70093C56F /* SwapInAddresses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwapInAddresses.swift; sourceTree = "<group>"; };
DC384D7C265BE41900131772 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = fr; path = fr.lproj/about.html; sourceTree = "<group>"; };
DC384D80265C12B700131772 /* Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; };
DC384D82265C32F100131772 /* TextField+Verbatim.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextField+Verbatim.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1362,6 +1364,7 @@
DCFAEFC82A72F48700330088 /* SwapInWalletDetails.swift */,
DC43096D2A7953F400E28995 /* FinalWalletDetails.swift */,
DC43096F2A795F9900E28995 /* UtxoWrapper.swift */,
DC370A8A2B7FFFC70093C56F /* SwapInAddresses.swift */,
);
path = wallet;
sourceTree = "<group>";
Expand Down Expand Up @@ -1707,6 +1710,7 @@
DCBA371B2758076F00610EC8 /* SyncSeedManager.swift in Sources */,
DC39D4F12874DDF40030F18D /* View+If.swift in Sources */,
DCB62F492A5E09F900912A71 /* SpliceOutProblem.swift in Sources */,
DC370A8B2B7FFFC70093C56F /* SwapInAddresses.swift in Sources */,
53BEFD54160278C5E393E319 /* HomeView.swift in Sources */,
DCD1208728663F4A00EB39C5 /* TransactionsView.swift in Sources */,
DC118BFC27B4504B0080BBAC /* ScanView.swift in Sources */,
Expand Down
15 changes: 15 additions & 0 deletions phoenix-ios/phoenix-ios/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -13949,6 +13949,9 @@
},
"Legacy" : {

},
"Legacy descriptor" : {

},
"Legal" : {
"localizations" : {
Expand Down Expand Up @@ -19035,6 +19038,9 @@
}
}
}
},
"Public key" : {

},
"QR code" : {
"localizations" : {
Expand Down Expand Up @@ -22693,6 +22699,9 @@
},
"Support" : {
"comment" : "HomeView: Tools menu: Label"
},
"Swap addresses" : {

},
"Swap Fees" : {
"comment" : "Label in SummaryInfoGrid",
Expand Down Expand Up @@ -22816,6 +22825,9 @@
}
}
}
},
"Swap-in addresses" : {

},
"Swap-in wallet" : {
"comment" : "Navigation Bar Title",
Expand Down Expand Up @@ -22931,6 +22943,9 @@
}
}
}
},
"Taproot" : {

},
"Taproot (recommended)" : {

Expand Down
13 changes: 13 additions & 0 deletions phoenix-ios/phoenix-ios/officers/BusinessManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,19 @@ class BusinessManager {
}

}.store(in: &cancellables)

// Keep Prefs.shared.swapInAddressIndex up-to-date
Biz.business.peerManager.peerStatePublisher()
.flatMap { $0.swapInWallet.swapInAddressPublisher() }
.sink { (newInfo: Lightning_kmpSwapInWallet.SwapInAddressInfo?) in

if let newInfo {
if Prefs.shared.swapInAddressIndex < newInfo.index {
Prefs.shared.swapInAddressIndex = newInfo.index
}
}
}
.store(in: &cancellables)
}

func startTasks() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import SwiftUI
import PhoenixShared

fileprivate let filename = "SwapInAddresses"
#if DEBUG && true
fileprivate var log = LoggerFactory.shared.logger(filename, .trace)
#else
fileprivate var log = LoggerFactory.shared.logger(filename, .warning)
#endif

struct SwapInAddresses: View {

let swapInAddressPublisher = Biz.business.peerManager.peerStatePublisher().flatMap { $0.swapInWallet.swapInAddressPublisher()
}
@State var swapInAddressInfo: Lightning_kmpSwapInWallet.SwapInAddressInfo? = nil

@StateObject var toast = Toast()

@Environment(\.colorScheme) var colorScheme: ColorScheme

// --------------------------------------------------
// MARK: View Builders
// --------------------------------------------------

@ViewBuilder
var body: some View {

ZStack {
content()
toast.view()
}
.navigationTitle("Swap-in addresses")
.navigationBarTitleDisplayMode(.inline)
}

@ViewBuilder
func content() -> some View {

List {
section_taproot()
section_legacy()
}
.listStyle(.insetGrouped)
.listBackgroundColor(.primaryBackground)
.onReceive(swapInAddressPublisher) {
swapInAddressChanged($0)
}
}

@ViewBuilder
func section_taproot() -> some View {

Section {

let count = taprootAddressCount()
ForEach((0..<count).reversed(), id: \.self) { idx in

let address = taprootAddress(idx)
HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text(verbatim: "#\(idx)")
.lineLimit(1)
.foregroundColor(.secondary)
.padding(.trailing, 6)

Text(address)
.lineLimit(1)
.truncationMode(.middle)

Spacer(minLength: 6)

Button {
copyAddressToPasteboard(address)
} label: {
Image(systemName: "square.on.square")
}
}
}
} header: {
Text("Taproot")
}
}

@ViewBuilder
func section_legacy() -> some View {

Section {

let address = legacyAddress()
HStack(alignment: VerticalAlignment.center, spacing: 4) {
Text(address)
.lineLimit(1)
.truncationMode(.middle)

Button {
copyAddressToPasteboard(address)
} label: {
Image(systemName: "square.on.square")
}
}

} header: {
Text("Legacy")
}
}

// --------------------------------------------------
// MARK: View Helpers
// --------------------------------------------------

func taprootAddressCount() -> Int {

let lastIndex = swapInAddressInfo?.index ?? Prefs.shared.swapInAddressIndex
return lastIndex + 1
}

func taprootAddress(_ index: Int) -> String {

guard let keyManager = Biz.business.walletManager.keyManagerValue() else {
return "???"
}

return keyManager.swapInOnChainWallet
.getSwapInProtocol(addressIndex: Int32(index))
.address(chain: Biz.business.chain)
}

func legacyAddress() -> String {

guard let keyManager = Biz.business.walletManager.keyManagerValue() else {
return "???"
}

return keyManager.swapInOnChainWallet
.legacySwapInProtocol
.address(chain: Biz.business.chain)
}

// --------------------------------------------------
// MARK: Notifications
// --------------------------------------------------

func swapInAddressChanged(_ newInfo: Lightning_kmpSwapInWallet.SwapInAddressInfo?) {
log.trace("swapInAddressChanged()")

self.swapInAddressInfo = newInfo
}

// --------------------------------------------------
// MARK: Actions
// --------------------------------------------------

func copyAddressToPasteboard(_ address: String) -> Void {
log.trace("copyAddressToPasteboard()")

UIPasteboard.general.string = address
toast.pop(
NSLocalizedString("Copied to pasteboard!", comment: "Toast message"),
colorScheme: colorScheme.opposite,
style: .chrome
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fileprivate var log = LoggerFactory.shared.logger(filename, .warning)

fileprivate enum NavLinkTag: String {
case SwapInWalletDetails
case SwapInAddresses
case FinalWalletDetails
}

Expand Down Expand Up @@ -132,7 +133,12 @@ struct WalletInfoView: View {
navLink(.SwapInWalletDetails) {
subsection_swapInWallet_balance()
}
subsection_swapInWallet_legacyDescriptor()
subsection_swapInWallet_descriptor()
subsection_swapInWallet_publicKey()
navLink(.SwapInAddresses) {
subsection_swapInWallet_swapAddresses()
}

} header: {
subsection_swapInWallet_header()
Expand Down Expand Up @@ -175,6 +181,33 @@ struct WalletInfoView: View {
)
}

@ViewBuilder
func subsection_swapInWallet_legacyDescriptor() -> some View {

let keyManager = Biz.business.walletManager.keyManagerValue()
let descriptor = keyManager?.swapInOnChainWallet.legacyDescriptor ?? "?"

VStack(alignment: HorizontalAlignment.leading, spacing: 10) {

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text("Legacy descriptor")
.font(.headline.bold())
Spacer()
copyButton(descriptor)
}

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text(descriptor)
.lineLimit(1)
.font(.callout.weight(.light))
.foregroundColor(.secondary)
Spacer(minLength: 0)
invisibleImage()
}

} // </VStack>
}

@ViewBuilder
func subsection_swapInWallet_descriptor() -> some View {

Expand All @@ -192,7 +225,34 @@ struct WalletInfoView: View {

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text(descriptor)
.lineLimit(2)
.lineLimit(1)
.font(.callout.weight(.light))
.foregroundColor(.secondary)
Spacer(minLength: 0)
invisibleImage()
}

} // </VStack>
}

@ViewBuilder
func subsection_swapInWallet_publicKey() -> some View {

let keyManager = Biz.business.walletManager.keyManagerValue()
let pubKeyHex = keyManager?.swapInOnChainWallet.userPublicKey.toHex() ?? "?"

VStack(alignment: HorizontalAlignment.leading, spacing: 10) {

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text("Public key")
.font(.headline.bold())
Spacer()
copyButton(pubKeyHex)
}

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text(pubKeyHex)
.lineLimit(1)
.font(.callout.weight(.light))
.foregroundColor(.secondary)
Spacer(minLength: 0)
Expand All @@ -202,6 +262,19 @@ struct WalletInfoView: View {
} // </VStack>
}

@ViewBuilder
func subsection_swapInWallet_swapAddresses() -> some View {

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text("Swap addresses")
.font(.headline.bold())
Image(systemName: "list.bullet")
.padding(.leading, 8)
.foregroundColor(.secondary)
Spacer()
}
}

// --------------------------------------------------
// MARK: View Builders: FinalWallet
// --------------------------------------------------
Expand Down Expand Up @@ -310,7 +383,7 @@ struct WalletInfoView: View {

HStack(alignment: VerticalAlignment.center, spacing: 0) {
Text(xpub)
.lineLimit(2)
.lineLimit(1)
.font(.callout.weight(.light))
.foregroundColor(.secondary)
Spacer(minLength: 0)
Expand Down Expand Up @@ -375,6 +448,7 @@ struct WalletInfoView: View {

switch tag {
case .SwapInWalletDetails : SwapInWalletDetails(location: .embedded, popTo: popToWrapper)
case .SwapInAddresses : SwapInAddresses()
case .FinalWalletDetails : FinalWalletDetails()
}
}
Expand Down
Loading

0 comments on commit d51c743

Please sign in to comment.