Skip to content

Commit

Permalink
[Wallet] Edit session namespaces (#231)
Browse files Browse the repository at this point in the history
* Edit session namespaces UI

* Update namespace error handling

* Pending requests

* Show SessionRequest Screen

* Reload SessionDetails on request respond

* Unused import removed
  • Loading branch information
flypaper0 committed May 25, 2022
1 parent 03d69f9 commit bb6b5f9
Show file tree
Hide file tree
Showing 13 changed files with 384 additions and 277 deletions.
2 changes: 1 addition & 1 deletion Example/DApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
name: "Swift Dapp",
description: "a description",
url: "wallet.connect",
icons: ["https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"])
icons: ["https://avatars.githubusercontent.com/u/37784886"])
Auth.configure(Auth.Config(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a"))
Auth.instance.sessionDeletePublisher
.receive(on: DispatchQueue.main)
Expand Down
28 changes: 20 additions & 8 deletions Example/ExampleApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84494387278D9C1B00CC26BB /* UIAlertController.swift */; };
844943A1278EC49700CC26BB /* Web3 in Frameworks */ = {isa = PBXBuildFile; productRef = 844943A0278EC49700CC26BB /* Web3 */; };
8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFB274F98A10081F94C /* RequestViewController.swift */; };
8460DD002750D6F50081F94C /* SessionDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DCFF2750D6F50081F94C /* SessionDetailsViewController.swift */; };
8460DD022750D7020081F94C /* SessionDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8460DD012750D7020081F94C /* SessionDetailsView.swift */; };
84CE641F27981DED00142511 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE641E27981DED00142511 /* AppDelegate.swift */; };
84CE642127981DED00142511 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE642027981DED00142511 /* SceneDelegate.swift */; };
84CE642827981DF000142511 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84CE642727981DF000142511 /* Assets.xcassets */; };
Expand All @@ -49,6 +47,11 @@
84CE647027A2CD6B00142511 /* WalletTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CE646F27A2CD6B00142511 /* WalletTests.swift */; };
84F568C2279582D200D0A289 /* Signer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F568C1279582D200D0A289 /* Signer.swift */; };
84F568C42795832A00D0A289 /* EthereumTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F568C32795832A00D0A289 /* EthereumTransaction.swift */; };
A5A4FC56283CBB7800BBEC1E /* SessionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC55283CBB7800BBEC1E /* SessionDetailView.swift */; };
A5A4FC58283CBB9F00BBEC1E /* SessionDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC57283CBB9F00BBEC1E /* SessionDetailViewModel.swift */; };
A5A4FC5A283CC08600BBEC1E /* SessionNamespaceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC59283CC08600BBEC1E /* SessionNamespaceViewModel.swift */; };
A5A4FC5C283D1F6700BBEC1E /* SessionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC5B283D1F6700BBEC1E /* SessionDetailViewController.swift */; };
A5A4FC5E283D23CA00BBEC1E /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A4FC5D283D23CA00BBEC1E /* Array.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -102,8 +105,6 @@
76B6E39E2807A3B6004DF775 /* WalletViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewController.swift; sourceTree = "<group>"; };
84494387278D9C1B00CC26BB /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = "<group>"; };
8460DCFB274F98A10081F94C /* RequestViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestViewController.swift; sourceTree = "<group>"; };
8460DCFF2750D6F50081F94C /* SessionDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDetailsViewController.swift; sourceTree = "<group>"; };
8460DD012750D7020081F94C /* SessionDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDetailsView.swift; sourceTree = "<group>"; };
84CE641C27981DED00142511 /* DApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
84CE641E27981DED00142511 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
84CE642027981DED00142511 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
Expand All @@ -124,6 +125,11 @@
84CE646F27A2CD6B00142511 /* WalletTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletTests.swift; sourceTree = "<group>"; };
84F568C1279582D200D0A289 /* Signer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signer.swift; sourceTree = "<group>"; };
84F568C32795832A00D0A289 /* EthereumTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumTransaction.swift; sourceTree = "<group>"; };
A5A4FC55283CBB7800BBEC1E /* SessionDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDetailView.swift; sourceTree = "<group>"; };
A5A4FC57283CBB9F00BBEC1E /* SessionDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDetailViewModel.swift; sourceTree = "<group>"; };
A5A4FC59283CC08600BBEC1E /* SessionNamespaceViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionNamespaceViewModel.swift; sourceTree = "<group>"; };
A5A4FC5B283D1F6700BBEC1E /* SessionDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDetailViewController.swift; sourceTree = "<group>"; };
A5A4FC5D283D23CA00BBEC1E /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -179,6 +185,7 @@
children = (
761C64A526FCB0AA004239D1 /* SessionInfo.swift */,
84F568C32795832A00D0A289 /* EthereumTransaction.swift */,
A5A4FC5D283D23CA00BBEC1E /* Array.swift */,
84F568C1279582D200D0A289 /* Signer.swift */,
765056262821989600F9AE79 /* Color+Extension.swift */,
84494387278D9C1B00CC26BB /* UIAlertController.swift */,
Expand Down Expand Up @@ -261,8 +268,10 @@
8460DCFE2750D6DF0081F94C /* SessionDetails */ = {
isa = PBXGroup;
children = (
8460DCFF2750D6F50081F94C /* SessionDetailsViewController.swift */,
8460DD012750D7020081F94C /* SessionDetailsView.swift */,
A5A4FC55283CBB7800BBEC1E /* SessionDetailView.swift */,
A5A4FC5B283D1F6700BBEC1E /* SessionDetailViewController.swift */,
A5A4FC57283CBB9F00BBEC1E /* SessionDetailViewModel.swift */,
A5A4FC59283CC08600BBEC1E /* SessionNamespaceViewModel.swift */,
);
path = SessionDetails;
sourceTree = "<group>";
Expand Down Expand Up @@ -512,22 +521,25 @@
765056272821989600F9AE79 /* Color+Extension.swift in Sources */,
76235E8D28202043004ED0AA /* RequestView.swift in Sources */,
8460DCFC274F98A10081F94C /* RequestViewController.swift in Sources */,
8460DD002750D6F50081F94C /* SessionDetailsViewController.swift in Sources */,
76744CF926FE4D7400B77ED9 /* ActiveSessionCell.swift in Sources */,
764E1D4026F8D3FC00A1FB15 /* AppDelegate.swift in Sources */,
761C64A626FCB0AA004239D1 /* SessionInfo.swift in Sources */,
A5A4FC5E283D23CA00BBEC1E /* Array.swift in Sources */,
76235E8B28201C9C004ED0AA /* Utilities.swift in Sources */,
76744CF726FE4D5400B77ED9 /* ActiveSessionItem.swift in Sources */,
A5A4FC5A283CC08600BBEC1E /* SessionNamespaceViewModel.swift in Sources */,
764E1D4226F8D3FC00A1FB15 /* SceneDelegate.swift in Sources */,
84F568C2279582D200D0A289 /* Signer.swift in Sources */,
A5A4FC56283CBB7800BBEC1E /* SessionDetailView.swift in Sources */,
7600223B2819FC0B0011DD38 /* ProposalView.swift in Sources */,
761248172819F9E600CB6D48 /* WalletView.swift in Sources */,
8460DD022750D7020081F94C /* SessionDetailsView.swift in Sources */,
A5A4FC58283CBB9F00BBEC1E /* SessionDetailViewModel.swift in Sources */,
76B6E39F2807A3B6004DF775 /* WalletViewController.swift in Sources */,
764E1D5A26F8DF1B00A1FB15 /* ScannerViewController.swift in Sources */,
760022392819FBF90011DD38 /* ProposalViewController.swift in Sources */,
84494388278D9C1B00CC26BB /* UIAlertController.swift in Sources */,
84F568C42795832A00D0A289 /* EthereumTransaction.swift in Sources */,
A5A4FC5C283D1F6700BBEC1E /* SessionDetailViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion Example/ExampleApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
name: "Example Wallet",
description: "wallet description",
url: "example.wallet",
icons: ["https://gblobscdn.gitbook.com/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media"])
icons: ["https://avatars.githubusercontent.com/u/37784886"])
Auth.configure(Auth.Config(metadata: metadata, projectId: "8ba9ee138960775e5231b70cc5ef1c3a"))

guard let windowScene = (scene as? UIWindowScene) else { return }
Expand Down
138 changes: 138 additions & 0 deletions Example/ExampleApp/SessionDetails/SessionDetailView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import SwiftUI
import WalletConnectAuth

struct SessionDetailView: View {

@ObservedObject var viewModel: SessionDetailViewModel

var didPressSessionRequest: ((Request) -> Void)?

var body: some View {
List {
Section { headerView() }

ForEach(viewModel.chains, id: \.self) { chain in
Section(header: header(chain: chain)) {
if let namespace = viewModel.namespace(for: chain) {

if namespace.accounts.isNotEmpty {
accountSection(chain: chain, namespace: namespace)
}

if namespace.methods.isNotEmpty {
methodsSection(chain: chain, namespace: namespace)
}

if namespace.events.isNotEmpty {
methodsSection(chain: chain, namespace: namespace)
}
}
}
}

if viewModel.requests.isNotEmpty {
requestsSection()
}
}
.listStyle(.insetGrouped)
}
}

private extension SessionDetailView {

func accountSection(chain: String, namespace: SessionNamespaceViewModel) -> some View {
Section(header: headerRow("Accounts")) {
ForEach(namespace.accounts, id: \.self) { account in
plainRow(account.absoluteString)
}
.onDelete { indices in Task {
await viewModel.remove(field: .accounts, at: indices, for: chain)
}}
}
}

func methodsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View {
Section(header: headerRow("Methods")) {
ForEach(namespace.methods, id: \.self) { method in
plainRow(method)
}
.onDelete { indices in Task {
await viewModel.remove(field: .methods, at: indices, for: chain)
}}
}
}

func eventsSection(chain: String, namespace: SessionNamespaceViewModel) -> some View {
Section(header: headerRow("Events")) {
ForEach(namespace.events, id: \.self) { event in
plainRow(event)
}
.onDelete { indices in Task {
await viewModel.remove(field: .events, at: indices, for: chain)
}}
}
}

func requestsSection() -> some View {
Section(header: Text("Pending requests")) {
ForEach(viewModel.requests, id: \.method) { request in
Button(action: { didPressSessionRequest?(request) }) {
plainRow(request.method)
}
}
}
}

func headerView() -> some View {
VStack(spacing: 12.0) {
AsyncImage(url: viewModel.peerIconURL) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(Circle())
} placeholder: {
ProgressView().progressViewStyle(.circular)
}
.frame(width: 64, height: 64)
.frame(maxWidth: .infinity)

Text(viewModel.peerName)
.font(.headline)

VStack {
Text(viewModel.peerDescription)
Text(viewModel.peerURL)
}
.font(.footnote)
.foregroundColor(.secondaryLabel)

Button("Ping") {
viewModel.ping()
}
.buttonStyle(BorderedProminentButtonStyle())
}
.background(Color(.systemGroupedBackground))
.listRowInsets(EdgeInsets())
}

func headerRow(_ text: String) -> some View {
return Text(text)
.font(.footnote)
.foregroundColor(.secondaryLabel)
}

func plainRow(_ text: String) -> some View {
return Text(text)
.font(.body)
}

func header(chain: String) -> some View {
HStack {
Text(chain)
Spacer()
Button("Delete") { Task {
await viewModel.remove(field: .chain, for: chain)
}}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import UIKit
import SwiftUI
import WalletConnectAuth
import WalletConnectUtils

final class SessionDetailViewController: UIHostingController<SessionDetailView> {

private let viewModel: SessionDetailViewModel

init(session: Session, client: Auth) {
self.viewModel = SessionDetailViewModel(session: session, client: client)
super.init(rootView: SessionDetailView(viewModel: viewModel))

rootView.didPressSessionRequest = { [weak self] request in
self?.showSessionRequest(request)
}
}

func reload() {
viewModel.objectWillChange.send()
}

private func showSessionRequest(_ request: Request) {
let viewController = RequestViewController(request)
viewController.onSign = { [unowned self] in
let result = Signer.signEth(request: request)
let response = JSONRPCResponse<AnyCodable>(id: request.id, result: result)
Auth.instance.respond(topic: request.topic, response: .response(response))
reload()
}
viewController.onReject = { [unowned self] in
Auth.instance.respond(
topic: request.topic,
response: .error(JSONRPCErrorResponse(
id: request.id,
error: JSONRPCErrorResponse.Error(code: 0, message: ""))
)
)
reload()
}
present(viewController, animated: true)
}

@MainActor required dynamic init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Loading

0 comments on commit bb6b5f9

Please sign in to comment.