diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect-Package.xcscheme
index 14b8eeb45..058e64dd2 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect-Package.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/WalletConnect-Package.xcscheme
@@ -482,6 +482,48 @@
ReferencedContainer = "container:">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Bool {
// Override point for customization after application launch.
+
return true
}
diff --git a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountInteractor.swift b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountInteractor.swift
index d861b6ceb..ce02d82c9 100644
--- a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountInteractor.swift
+++ b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountInteractor.swift
@@ -6,7 +6,10 @@ import WalletConnectSign
struct AccountDetails {
let chain: String
let methods: [String]
- let account: String
+ let address: String
+ var account: String {
+ "\(chain):\(address)"
+ }
}
diff --git a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountPresenter.swift b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountPresenter.swift
index e89ea8a8e..09c318daf 100644
--- a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountPresenter.swift
+++ b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountPresenter.swift
@@ -70,7 +70,7 @@ final class SessionAccountPresenter: ObservableObject {
}
func copyUri() {
- UIPasteboard.general.string = sessionAccount.account
+ UIPasteboard.general.string = sessionAccount.address
}
}
@@ -128,17 +128,17 @@ extension SessionAccountPresenter.Errors: LocalizedError {
// MARK: - Transaction Stub
private enum Stub {
struct Transaction: Codable {
- let from, to, data, gas: String
+ let from, to, data, gasLimit: String
let gasPrice, value, nonce: String
}
static let tx = [Transaction(from: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
to: "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83",
- data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
- gas: "0x76c0",
- gasPrice: "0x9184e72a000",
- value: "0x9184e72a",
- nonce: "0x117")]
+ data: "0x",
+ gasLimit: "0x5208",
+ gasPrice: "0x013e3d2ed4",
+ value: "0x00",
+ nonce: "0x09")]
static let eth_signTypedData = """
{
"types": {
diff --git a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountView.swift b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountView.swift
index 939a9edb6..247bc800a 100644
--- a/Example/DApp/Modules/Sign/SessionAccount/SessionAccountView.swift
+++ b/Example/DApp/Modules/Sign/SessionAccount/SessionAccountView.swift
@@ -16,7 +16,7 @@ struct SessionAccountView: View {
ScrollView {
VStack(spacing: 12) {
networkView(title: String(presenter.sessionAccount.chain.split(separator: ":").first ?? ""))
- accountView(address: presenter.sessionAccount.account)
+ accountView(address: presenter.sessionAccount.address)
methodsView(methods: presenter.sessionAccount.methods)
Spacer()
diff --git a/Example/DApp/Modules/Sign/SignPresenter.swift b/Example/DApp/Modules/Sign/SignPresenter.swift
index 0b2e86e7d..86f10339b 100644
--- a/Example/DApp/Modules/Sign/SignPresenter.swift
+++ b/Example/DApp/Modules/Sign/SignPresenter.swift
@@ -169,6 +169,13 @@ extension SignPresenter {
}
.store(in: &subscriptions)
+ Sign.instance.sessionSettlePublisher
+ .receive(on: DispatchQueue.main)
+ .sink { [unowned self] _ in
+ self.getSession()
+ }
+ .store(in: &subscriptions)
+
Sign.instance.authResponsePublisher
.receive(on: DispatchQueue.main)
.sink { [unowned self] response in
@@ -227,7 +234,7 @@ extension SignPresenter {
AccountDetails(
chain: account.blockchainIdentifier,
methods: Array(namespace.methods),
- account: account.address
+ address: account.address
)
)
}
diff --git a/Example/DApp/Modules/Sign/SignView.swift b/Example/DApp/Modules/Sign/SignView.swift
index 03b4003a9..b080ee2eb 100644
--- a/Example/DApp/Modules/Sign/SignView.swift
+++ b/Example/DApp/Modules/Sign/SignView.swift
@@ -96,7 +96,7 @@ struct SignView: View {
.padding(12)
} else {
VStack {
- ForEach(presenter.accountsDetails, id: \.chain) { account in
+ ForEach(presenter.accountsDetails, id: \.account) { account in
Button {
presenter.presentSessionAccount(sessionAccount: account)
} label: {
diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj
index 2447d9efa..29561390d 100644
--- a/Example/ExampleApp.xcodeproj/project.pbxproj
+++ b/Example/ExampleApp.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 61DAC4AB2C65897800BAF3F8 /* YttriumWrapper in Frameworks */ = {isa = PBXBuildFile; productRef = 61DAC4AA2C65897800BAF3F8 /* YttriumWrapper */; };
767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */; };
84310D05298BC980000C15B6 /* MainInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84310D04298BC980000C15B6 /* MainInteractor.swift */; };
8439CB89293F658E00F2F2E2 /* PushMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8439CB88293F658E00F2F2E2 /* PushMessage.swift */; };
@@ -27,6 +28,7 @@
84733CD32C1C2A4B001B2850 /* AlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AEC2502B4D42C100E27A5B /* AlertPresenter.swift */; };
84733CD42C1C2C24001B2850 /* ProfilingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50B6A372B06697B00162B01 /* ProfilingService.swift */; };
84733CD52C1C2CEB001B2850 /* InputConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C56EE25D293F56D6004840D1 /* InputConfig.swift */; };
+ 84733CDA2C258BDB001B2850 /* AccountMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84733CD92C258BDB001B2850 /* AccountMock.swift */; };
847BD1D62989492500076C90 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D12989492500076C90 /* MainViewController.swift */; };
847BD1D82989492500076C90 /* MainModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D32989492500076C90 /* MainModule.swift */; };
847BD1D92989492500076C90 /* MainPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847BD1D42989492500076C90 /* MainPresenter.swift */; };
@@ -408,6 +410,7 @@
846E35A32C0065B600E63DF4 /* ConfigPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigPresenter.swift; sourceTree = ""; };
846E35A52C0065C100E63DF4 /* ConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigView.swift; sourceTree = ""; };
846E35A72C006C5600E63DF4 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
+ 84733CD92C258BDB001B2850 /* AccountMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountMock.swift; sourceTree = ""; };
847BD1D12989492500076C90 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; };
847BD1D32989492500076C90 /* MainModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainModule.swift; sourceTree = ""; };
847BD1D42989492500076C90 /* MainPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainPresenter.swift; sourceTree = ""; };
@@ -763,6 +766,7 @@
A59D25EE2AB3672700D7EA3A /* AsyncButton in Frameworks */,
C5133A78294125CC00A8314C /* Web3 in Frameworks */,
C5B2F7052970573D000DBA0E /* SolanaSwift in Frameworks */,
+ 61DAC4AB2C65897800BAF3F8 /* YttriumWrapper in Frameworks */,
8487A9462A836C3F0003D5AF /* Sentry in Frameworks */,
C55D349929630D440004314A /* Web3Wallet in Frameworks */,
C56EE255293F569A004840D1 /* Starscream in Frameworks */,
@@ -1438,6 +1442,7 @@
isa = PBXGroup;
children = (
A5D610CC2AB3592F00C20083 /* ListingsSertice */,
+ 84733CD92C258BDB001B2850 /* AccountMock.swift */,
);
path = BusinessLayer;
sourceTree = "";
@@ -2068,6 +2073,7 @@
C54C248F2AEB1B5600DA4BF6 /* WalletConnectRouter */,
84AEC2532B4D43CD00E27A5B /* SwiftMessages */,
84F391F92BA87CEB00FDC20A /* Web3ModalUI */,
+ 61DAC4AA2C65897800BAF3F8 /* YttriumWrapper */,
);
productName = ChatWallet;
productReference = C56EE21B293F55ED004840D1 /* WalletApp.app */;
@@ -2495,6 +2501,7 @@
C5B2F6F729705293000DBA0E /* SessionRequestRouter.swift in Sources */,
C56EE24F293F566D004840D1 /* WalletView.swift in Sources */,
C55D34B22965FB750004314A /* SessionProposalView.swift in Sources */,
+ 84733CDA2C258BDB001B2850 /* AccountMock.swift in Sources */,
C56EE248293F566D004840D1 /* ScanQR.swift in Sources */,
847BD1EB298A87AB00076C90 /* SubscriptionsViewModel.swift in Sources */,
C55D349B2965BC2F0004314A /* TagsView.swift in Sources */,
@@ -3324,6 +3331,10 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
+ 61DAC4AA2C65897800BAF3F8 /* YttriumWrapper */ = {
+ isa = XCSwiftPackageProductDependency;
+ productName = YttriumWrapper;
+ };
844749FC29B9E6B2005F520B /* WalletConnectNetworking */ = {
isa = XCSwiftPackageProductDependency;
productName = WalletConnectNetworking;
diff --git a/Example/Shared/Signer/Signer.swift b/Example/Shared/Signer/Signer.swift
index 3091c6c98..819c909dd 100644
--- a/Example/Shared/Signer/Signer.swift
+++ b/Example/Shared/Signer/Signer.swift
@@ -1,6 +1,7 @@
import Foundation
import Commons
import WalletConnectSign
+import YttriumWrapper
final class Signer {
enum Errors: Error {
@@ -9,7 +10,39 @@ final class Signer {
private init() {}
- static func sign(request: Request, importAccount: ImportAccount) throws -> AnyCodable {
+ static func sign(request: Request, importAccount: ImportAccount) async throws -> AnyCodable {
+ if try await didRequestSmartAccount(request) {
+ return try await signWithSmartAccount(request: request)
+ } else {
+ return try signWithEOA(request: request, importAccount: importAccount)
+ }
+ }
+
+
+ private static func didRequestSmartAccount(_ request: Request) async throws -> Bool {
+ // Attempt to decode params for transaction requests encapsulated in an array of dictionaries
+ if let paramsArray = try? request.params.get([AnyCodable].self),
+ let firstParam = paramsArray.first?.value as? [String: Any],
+ let account = firstParam["from"] as? String {
+ let smartAccountAddress = try await SmartAccount.instance.getAddress()
+ return account.lowercased() == smartAccountAddress.lowercased()
+ }
+
+ // Attempt to decode params for signing message requests
+ if let paramsArray = try? request.params.get([AnyCodable].self) {
+ if request.method == "personal_sign" || request.method == "eth_signTypedData" {
+ // Typically, the account address is the second parameter for personal_sign and eth_signTypedData
+ if paramsArray.count > 1,
+ let account = paramsArray[1].value as? String {
+ let smartAccountAddress = try await SmartAccount.instance.getAddress()
+ return account.lowercased() == smartAccountAddress.lowercased()
+ }
+ }
+ }
+
+ return false
+ }
+ private static func signWithEOA(request: Request, importAccount: ImportAccount) throws -> AnyCodable {
let signer = ETHSigner(importAccount: importAccount)
switch request.method {
@@ -24,11 +57,41 @@ final class Signer {
case "solana_signTransaction":
return SOLSigner.signTransaction(request.params)
-
+
default:
throw Signer.Errors.notImplemented
}
}
+
+
+ private static func signWithSmartAccount(request: Request) async throws -> AnyCodable {
+ switch request.method {
+ case "personal_sign":
+ let params = try request.params.get([String].self)
+ let message = params[0]
+ let signed = try SmartAccount.mockInstance.signMessage(message)
+ return AnyCodable(signed)
+
+ case "eth_signTypedData":
+ let params = try request.params.get([String].self)
+ let message = params[0]
+ let signed = try SmartAccount.mockInstance.signMessage(message)
+ return AnyCodable(signed)
+
+ case "eth_sendTransaction":
+ let params = try request.params.get([YttriumWrapper.Transaction].self)
+ let transaction = params[0]
+ let result = try await SmartAccount.mockInstance.sendTransaction(transaction)
+ return AnyCodable(result)
+
+ // case "wallet_sendCalls":
+ // let transactions =
+ // return try await SmartAccount.mockInstance.sendBatchTransaction(<#T##batch: [Transaction]##[Transaction]#>)
+
+ default:
+ throw Signer.Errors.notImplemented
+ }
+ }
}
extension Signer.Errors: LocalizedError {
@@ -38,3 +101,4 @@ extension Signer.Errors: LocalizedError {
}
}
}
+
diff --git a/Example/WalletApp/ApplicationLayer/AppDelegate.swift b/Example/WalletApp/ApplicationLayer/AppDelegate.swift
index f2f961b36..0c125d80f 100644
--- a/Example/WalletApp/ApplicationLayer/AppDelegate.swift
+++ b/Example/WalletApp/ApplicationLayer/AppDelegate.swift
@@ -8,6 +8,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
+ SmartAccount.configure(entryPoint: "", chainId: 11155111)
return true
}
diff --git a/Example/WalletApp/BusinessLayer/AccountMock.swift b/Example/WalletApp/BusinessLayer/AccountMock.swift
new file mode 100644
index 000000000..f28bf893b
--- /dev/null
+++ b/Example/WalletApp/BusinessLayer/AccountMock.swift
@@ -0,0 +1,101 @@
+import Foundation
+import YttriumWrapper
+import WalletConnectUtils
+
+class AccountClientMock: YttriumWrapper.AccountClientProtocol {
+
+ var onSign: OnSign?
+
+ var chainId: Int
+
+ required init(entryPoint: String, chainId: Int, onSign: OnSign?) {
+ self.chainId = chainId
+ self.onSign = onSign
+ }
+
+ // prepares UserOp
+ func sendTransaction(_ transaction: YttriumWrapper.Transaction) async throws -> String {
+ guard let onSign = onSign else {
+ fatalError("Error - onSign closure must be set before calling signMessage")
+ }
+ let _ = onSign("UserOp")
+ return "txHash"
+ }
+
+ func sendBatchTransaction(_ batch: [YttriumWrapper.Transaction]) async throws -> String {
+ return "userOpReceipt"
+ }
+
+ func getAddress() async throws -> String {
+ return "0xF4D7560648F1252FD7501863355AEaBfb9d3b7c3"
+ }
+
+ func getAccount() async throws -> Account {
+ let chain = try Blockchain(namespace: "eip155", reference: chainId)
+ let address = try await getAddress()
+ return try Account(blockchain: chain, accountAddress: address)
+ }
+
+ func signMessage(_ message: String) throws -> String {
+ guard let onSign = onSign else {
+ fatalError("Error - onSign closure must be set before calling signMessage")
+ }
+ return try! onSign(message).get()
+ }
+}
+
+extension YttriumWrapper.AccountClient {
+
+ func getAccount() async throws -> Account {
+ let chain = try Blockchain(namespace: "eip155", reference: chainId)
+ let address = try await getAddress()
+ return try Account(blockchain: chain, accountAddress: address)
+ }
+}
+
+class SmartAccount {
+ static var mockInstance: AccountClientMock = {
+ guard let config = SmartAccount.config else {
+ fatalError("Error - you must call SmartAccount.configure(entryPoint:chainId:onSign:) before accessing the shared instance.")
+ }
+ return AccountClientMock(
+ entryPoint: config.entryPoint,
+ chainId: config.chainId,
+ onSign: config.onSign
+ )
+ }()
+
+ static var instance: AccountClient = {
+ guard let config = SmartAccount.config else {
+ fatalError("Error - you must call SmartAccount.configure(entryPoint:chainId:onSign:) before accessing the shared instance.")
+ }
+ return AccountClient(
+ entryPoint: config.entryPoint,
+ chainId: config.chainId,
+ onSign: config.onSign
+ )
+ }()
+
+ private static var config: Config?
+
+ private init() {}
+
+ struct Config {
+ let entryPoint: String
+ let chainId: Int
+ var onSign: OnSign?
+ }
+
+ /// SmartAccount instance config method
+ /// - Parameters:
+ /// - entryPoint: Entry point
+ /// - chainId: Chain ID
+ /// - onSign: Closure for signing messages (optional)
+ static public func configure(
+ entryPoint: String,
+ chainId: Int,
+ onSign: OnSign? = nil
+ ) {
+ SmartAccount.config = Config(entryPoint: entryPoint, chainId: chainId, onSign: onSign)
+ }
+}
diff --git a/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift
index d2186d935..d2534dffb 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/Main/MainModule.swift
@@ -1,4 +1,5 @@
import SwiftUI
+import Web3
final class MainModule {
@discardableResult
@@ -8,8 +9,39 @@ final class MainModule {
let presenter = MainPresenter(router: router, interactor: interactor, importAccount: importAccount, pushRegisterer: app.pushRegisterer, configurationService: app.configurationService)
let viewController = MainViewController(presenter: presenter)
+ configureSmartAccountOnSign(importAccount: importAccount)
router.viewController = viewController
return viewController
}
+
+ static func configureSmartAccountOnSign(importAccount: ImportAccount) {
+ SmartAccount.instance.onSign = { messageToSign in
+ func dataToHash(_ data: Data) -> Bytes {
+ let prefix = "\u{19}Ethereum Signed Message:\n"
+ let prefixData = (prefix + String(data.count)).data(using: .utf8)!
+ let prefixedMessageData = prefixData + data
+ return .init(hex: prefixedMessageData.toHexString())
+ }
+
+ let prvKey = try! EthereumPrivateKey(hexPrivateKey: importAccount.privateKey)
+
+ // Determine if the message is hex-encoded or plain text
+ let dataToSign: Bytes
+ if messageToSign.hasPrefix("0x") {
+ // Hex-encoded message, remove "0x" and convert
+ let messageData = Data(hex: String(messageToSign.dropFirst(2)))
+ dataToSign = dataToHash(messageData)
+ } else {
+ // Plain text message, convert directly to data
+ let messageData = Data(messageToSign.utf8)
+ dataToSign = dataToHash(messageData)
+ }
+
+ // Sign the data
+ let (v, r, s) = try! prvKey.sign(message: .init(Data(dataToSign)))
+ let result = "0x" + r.toHexString() + s.toHexString() + String(v + 27, radix: 16)
+ return .success(result)
+ }
+ }
}
diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift
index ceeef4bc2..155192e9e 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalInteractor.swift
@@ -4,7 +4,7 @@ import Web3Wallet
import WalletConnectRouter
final class SessionProposalInteractor {
- func approve(proposal: Session.Proposal, account: Account) async throws -> Bool {
+ func approve(proposal: Session.Proposal, EOAAccount: Account, smartAccount: Account) async throws -> Bool {
// Following properties are used to support all the required and optional namespaces for the testing purposes
let supportedMethods = Set(proposal.requiredNamespaces.flatMap { $0.value.methods } + (proposal.optionalNamespaces?.flatMap { $0.value.methods } ?? []))
let supportedEvents = Set(proposal.requiredNamespaces.flatMap { $0.value.events } + (proposal.optionalNamespaces?.flatMap { $0.value.events } ?? []))
@@ -13,7 +13,9 @@ final class SessionProposalInteractor {
let supportedOptionalChains = proposal.optionalNamespaces?["eip155"]?.chains ?? []
var supportedChains = supportedRequiredChains + supportedOptionalChains
- let supportedAccounts = Array(supportedChains).map { Account(blockchain: $0, address: account.address)! }
+ var supportedAccounts = Array(supportedChains).map { Account(blockchain: $0, address: EOAAccount.address)! }
+
+ supportedAccounts.append(smartAccount)
/* Use only supported values for production. I.e:
let supportedMethods = ["eth_signTransaction", "personal_sign", "eth_signTypedData", "eth_sendTransaction", "eth_sign"]
diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift
index e494039a2..8381e4c4d 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/SessionProposal/SessionProposalPresenter.swift
@@ -36,7 +36,8 @@ final class SessionProposalPresenter: ObservableObject {
func onApprove() async throws {
do {
ActivityIndicatorManager.shared.start()
- let showConnected = try await interactor.approve(proposal: sessionProposal, account: importAccount.account)
+ let smartAccount = try await SmartAccount.instance.getAccount()
+ let showConnected = try await interactor.approve(proposal: sessionProposal, EOAAccount: importAccount.account, smartAccount: smartAccount)
showConnected ? showConnectedSheet.toggle() : router.dismiss()
ActivityIndicatorManager.shared.stop()
} catch {
diff --git a/Example/WalletApp/PresentationLayer/Wallet/SessionRequest/SessionRequestInteractor.swift b/Example/WalletApp/PresentationLayer/Wallet/SessionRequest/SessionRequestInteractor.swift
index edc2ed4df..93335feaa 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/SessionRequest/SessionRequestInteractor.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/SessionRequest/SessionRequestInteractor.swift
@@ -6,7 +6,7 @@ import WalletConnectRouter
final class SessionRequestInteractor {
func respondSessionRequest(sessionRequest: Request, importAccount: ImportAccount) async throws -> Bool {
do {
- let result = try Signer.sign(request: sessionRequest, importAccount: importAccount)
+ let result = try await Signer.sign(request: sessionRequest, importAccount: importAccount)
try await Web3Wallet.instance.respond(
topic: sessionRequest.topic,
requestId: sessionRequest.id,
diff --git a/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsPresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsPresenter.swift
index 87a048768..6be579ffa 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsPresenter.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsPresenter.swift
@@ -8,16 +8,37 @@ final class SettingsPresenter: ObservableObject {
private let interactor: SettingsInteractor
private let router: SettingsRouter
private let accountStorage: AccountStorage
-
private var disposeBag = Set()
+ @Published var smartAccount: String = "Loading..."
init(interactor: SettingsInteractor, router: SettingsRouter, accountStorage: AccountStorage) {
defer { setupInitialState() }
self.interactor = interactor
self.router = router
self.accountStorage = accountStorage
+ fetchSmartAccount()
+
+ }
+
+ func fetchSmartAccount() {
+ Task {
+ do {
+ let smartAccount = try await getSmartAccount()
+ DispatchQueue.main.async {
+ self.smartAccount = smartAccount
+ }
+ } catch {
+ DispatchQueue.main.async {
+ self.smartAccount = "Failed to load"
+ }
+ print("Failed to get smart account: \(error)")
+ }
+ }
}
+ private func getSmartAccount() async throws -> String {
+ return try await SmartAccount.instance.getAccount().absoluteString
+ }
var account: String {
guard let importAccount = accountStorage.importAccount else { return .empty }
diff --git a/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsView.swift b/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsView.swift
index 73a5fdbcd..d4547b3c6 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsView.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/Settings/SettingsView.swift
@@ -3,9 +3,7 @@ import AsyncButton
import Web3ModalUI
struct SettingsView: View {
-
@EnvironmentObject var viewModel: SettingsPresenter
-
@State private var copyAlert: Bool = false
var body: some View {
@@ -16,6 +14,7 @@ struct SettingsView: View {
Group {
header(title: "Account")
row(title: "CAIP-10", subtitle: viewModel.account)
+ row(title: "Smart Account", subtitle: viewModel.smartAccount)
row(title: "Private key", subtitle: viewModel.privateKey)
}
.padding(.horizontal, 20)
@@ -108,10 +107,10 @@ struct SettingsView: View {
}
func separator() -> some View {
- Rectangle()
- .foregroundColor(.Foreground100.opacity(0.05))
- .frame(maxWidth: .infinity)
- .frame(height: 1)
- .padding(.top, 8)
+ Rectangle()
+ .foregroundColor(.Foreground100.opacity(0.05))
+ .frame(maxWidth: .infinity)
+ .frame(height: 1)
+ .padding(.top, 8)
}
}
diff --git a/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomePresenter.swift b/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomePresenter.swift
index f97cfe29f..c5480c919 100644
--- a/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomePresenter.swift
+++ b/Example/WalletApp/PresentationLayer/Wallet/Welcome/WelcomePresenter.swift
@@ -24,9 +24,9 @@ final class WelcomePresenter: ObservableObject {
func onImport() {
guard let account = ImportAccount(input: input)
else { return input = .empty }
-
importAccount(account)
}
+
}
// MARK: Private functions
diff --git a/Package.swift b/Package.swift
index b255c6b99..6031d73a0 100644
--- a/Package.swift
+++ b/Package.swift
@@ -43,10 +43,14 @@ let package = Package(
.library(
name: "WalletConnectIdentity",
targets: ["WalletConnectIdentity"]),
+ .library(
+ name: "YttriumWrapper",
+ targets: ["YttriumWrapper"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
- .package(url: "https://github.com/WalletConnect/QRCode", from: "14.3.1")
+ .package(url: "https://github.com/WalletConnect/QRCode", from: "14.3.1"),
+ .package(path: "../yttrium")
],
targets: [
.target(
@@ -136,6 +140,13 @@ let package = Package(
.process("Resources/PrivacyInfo.xcprivacy"),
]
),
+ .target(
+ name: "YttriumWrapper",
+ dependencies: [
+ .productItem(name: "Yttrium", package: "yttrium")
+ ],
+ path: "Sources/YttriumWrapper"
+ ),
.testTarget(
name: "WalletConnectSignTests",
dependencies: ["WalletConnectSign", "WalletConnectUtils", "TestingUtils", "WalletConnectVerify"]),
diff --git a/README.md b/README.md
index e07ccaa25..2048a8dce 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Wallet Connect v.2 - Swift
+# WalletConnect v.2 - Swift


@@ -58,4 +58,4 @@ Apache 2.0
## Guides
-- [Artifacts sometimes not available in Actions -> Build name -> Artifacts?](./docs/guides/downloading_artifacts.md)
\ No newline at end of file
+- [Artifacts sometimes not available in Actions -> Build name -> Artifacts?](./docs/guides/downloading_artifacts.md)
diff --git a/Sources/WalletConnectUtils/Account.swift b/Sources/WalletConnectUtils/Account.swift
index 7d5c2cbee..eb1b7615d 100644
--- a/Sources/WalletConnectUtils/Account.swift
+++ b/Sources/WalletConnectUtils/Account.swift
@@ -11,7 +11,9 @@
[CAIP-10]:https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md
*/
public struct Account: Equatable, Hashable {
-
+ public enum Errors: Error {
+ case invalidInitFormat
+ }
/// A blockchain namespace. Usually describes an ecosystem or standard.
public let namespace: String
@@ -71,6 +73,13 @@ public struct Account: Equatable, Hashable {
public init?(blockchain: Blockchain, address: String) {
self.init("\(blockchain.absoluteString):\(address)")
}
+
+ public init(blockchain: Blockchain, accountAddress: String) throws {
+ guard let instance = Self("\(blockchain.absoluteString):\(accountAddress)") else {
+ throw Errors.invalidInitFormat
+ }
+ self = instance
+ }
}
extension Account: LosslessStringConvertible {
diff --git a/Sources/WalletConnectUtils/Blockchain.swift b/Sources/WalletConnectUtils/Blockchain.swift
index 8d920f01d..9e839bdb9 100644
--- a/Sources/WalletConnectUtils/Blockchain.swift
+++ b/Sources/WalletConnectUtils/Blockchain.swift
@@ -9,7 +9,9 @@
[CAIP-2]:https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md
*/
public struct Blockchain: Equatable, Hashable {
-
+ public enum Errors: Error {
+ case invalidInitFormat
+ }
/// A blockchain namespace. Usually describes an ecosystem or standard.
public let namespace: String
@@ -43,6 +45,13 @@ public struct Blockchain: Equatable, Hashable {
public init?(namespace: String, reference: String) {
self.init("\(namespace):\(reference)")
}
+
+ public init(namespace: String, reference: Int) throws {
+ guard let instance = Self("\(namespace):\(reference)") else {
+ throw Errors.invalidInitFormat
+ }
+ self = instance
+ }
}
extension Blockchain: LosslessStringConvertible {
diff --git a/Sources/YttriumWrapper/YttriumWrapper.swift b/Sources/YttriumWrapper/YttriumWrapper.swift
new file mode 100644
index 000000000..d7d761cd4
--- /dev/null
+++ b/Sources/YttriumWrapper/YttriumWrapper.swift
@@ -0,0 +1,3 @@
+import Foundation
+
+@_exported import Yttrium