Add Solana.swift

This commit is contained in:
Ivan Grachev 2022-05-03 20:02:21 +03:00
parent 73ae9f2df0
commit efc65ad4f7
2 changed files with 369 additions and 73 deletions

View File

@ -0,0 +1,290 @@
// Copyright © 2022 Tokenary. All rights reserved.
import Foundation
import WalletCore
class Solana {
enum SendTransactionError: Error {
case blockhashNotFound, unknown
}
private enum Method: String {
case sendTransaction, simulateTransaction, getLatestBlockhash
}
private struct SendTransactionResponse: Codable {
let result: String?
private let error: Error?
var blockhashNotFound: Bool {
return error?.data.err == "BlockhashNotFound"
}
private struct Error: Codable {
let data: Data
struct Data: Codable {
let err: String
}
}
}
private struct LatestBlockhashResponse: Codable {
let result: Result
struct Result: Codable {
let value: Value
struct Value: Codable {
let blockhash: String
}
}
}
static let shared = Solana()
private let urlSession = URLSession(configuration: .default)
private let rpcURL = URL(string: "https://api.mainnet-beta.solana.com")!
private init() {}
func sign(message: String, asHex: Bool) -> String? {
let digest = asHex ? Data(hex: message) : Base58.decodeNoCheck(string: message)
guard let digest = digest else { return nil }
let words = ""
let password = ""
guard let key = StoredKey.importHDWallet(mnemonic: words, name: "", password: Data(password.utf8), coin: .solana),
let phantomPrivateKey = key.wallet(password: Data(password.utf8))?.getKey(coin: .solana, derivationPath: "m/44'/501'/0'/0'") else { return nil }
if let data = phantomPrivateKey.sign(digest: digest, curve: CoinType.solana.curve) {
return Base58.encodeNoCheck(data: data)
} else {
return nil
}
}
func signAndSendTransaction(retryCount: Int = 0, message: String, options: [String: Any]?, completion: @escaping (Result<String, SendTransactionError>) -> Void) {
guard retryCount < 3,
let signed = sign(message: message, asHex: false),
let raw = compileTransactionData(message: message, signature: signed, simulation: false) else {
completion(.failure(.unknown))
return
}
sendTransaction(signed: raw, options: options) { [weak self] result in
switch result {
case let .success(result):
completion(.success(result))
case let .failure(sendTransactionError):
switch sendTransactionError {
case .unknown:
completion(.failure(.unknown))
case .blockhashNotFound:
self?.updateBlockhash(message: message) { updatedMessage in
if let updatedMessage = updatedMessage {
self?.signAndSendTransaction(message: updatedMessage, options: options, completion: completion)
} else {
completion(.failure(.unknown))
}
}
}
}
}
}
// MARK: - Private
private func createRequest(method: Method, parameters: [Any]? = nil) -> URLRequest {
var request = URLRequest(url: rpcURL)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
var dict: [String: Any] = [
"method": method.rawValue,
"id": 1,
"jsonrpc": "2.0"
]
if let parameters = parameters {
dict["params"] = parameters
}
request.httpBody = try? JSONSerialization.data(withJSONObject: dict, options: .fragmentsAllowed)
return request
}
private func getLatestBlockhash(completion: @escaping (String?) -> Void) {
let request = createRequest(method: .getLatestBlockhash)
let dataTask = urlSession.dataTask(with: request) { data, _, _ in
DispatchQueue.main.async {
if let data = data,
let response = try? JSONDecoder().decode(LatestBlockhashResponse.self, from: data) {
completion(response.result.value.blockhash)
} else {
completion(nil)
}
}
}
dataTask.resume()
}
private func sendTransaction(signed: String, options: [String: Any]?, completion: @escaping (Result<String, SendTransactionError>) -> Void) {
var parameters: [Any] = [signed]
if let options = options {
parameters.append(options)
}
let request = createRequest(method: .sendTransaction, parameters: parameters)
let dataTask = urlSession.dataTask(with: request) { data, _, _ in
DispatchQueue.main.async {
if let data = data,
let response = try? JSONDecoder().decode(SendTransactionResponse.self, from: data) {
if let result = response.result {
completion(.success(result))
} else {
completion(.failure(response.blockhashNotFound ? .blockhashNotFound : .unknown))
}
} else {
completion(.failure(.unknown))
}
}
}
dataTask.resume()
}
private func simulateTransaction(serializedMessage: String, signature: String, publicKey: String, completion: @escaping (Any?) -> Void) {
guard let message = compileTransactionData(message: serializedMessage, signature: signature, simulation: true) else {
completion(nil)
return
}
let configuration: [String: Any] = ["accounts": ["encoding": "jsonParsed", "addresses": [publicKey]]]
let request = createRequest(method: .simulateTransaction, parameters: [message, configuration])
let dataTask = urlSession.dataTask(with: request) { data, _, _ in
DispatchQueue.main.async {
if let data = data {
let raw = try? JSONSerialization.jsonObject(with: data)
completion(raw)
} else {
completion(nil)
}
}
}
dataTask.resume()
}
private func compileTransactionData(message: String, signature: String, simulation: Bool) -> String? {
guard let messageData = Base58.decodeNoCheck(string: message),
let signatureData = Base58.decodeNoCheck(string: signature) else { return nil }
let numberOfSignatures = messageData.requiredSignaturesCount
let placeholderSignature = Data(repeating: 0, count: 64)
var result = Data()
let encodedSignatureLength = Data.encodeLength(numberOfSignatures)
result = encodedSignatureLength + (simulation ? placeholderSignature : signatureData)
for _ in 0..<(numberOfSignatures - 1) {
result += placeholderSignature
}
result += messageData
return Base58.encodeNoCheck(data: result)
}
private func updateBlockhash(message: String, completion: @escaping (String?) -> Void) {
guard var data = Base58.decodeNoCheck(string: message) else {
completion(nil)
return
}
getLatestBlockhash { blockhash in
guard let blockhash = blockhash,
let numRequiredSignatures = data.popFirst(),
let numReadonlySignedAccounts = data.popFirst(),
let numReadonlyUnsignedAccounts = data.popFirst(),
let blockhashData = Base58.decodeNoCheck(string: blockhash) else {
completion(nil)
return
}
let numberOfBytes = 32
let accountCount = data.decodeLength()
let blockhashStartIndex = data.index(data.startIndex, offsetBy: numberOfBytes * accountCount)
let blockhashEndIndex = data.index(blockhashStartIndex, offsetBy: numberOfBytes)
data.replaceSubrange(blockhashStartIndex..<blockhashEndIndex, with: blockhashData)
data = Data.encodeLength(accountCount) + data
data = Data([numRequiredSignatures, numReadonlySignedAccounts, numReadonlyUnsignedAccounts]) + data
completion(Base58.encodeNoCheck(data: data))
}
}
}
// https://github.com/p2p-org/solana-swift/blob/main/Sources/SolanaSwift/Extensions/Data%2BExtensions.swift
private extension Data {
var requiredSignaturesCount: Int {
if let first = first {
return Int(first)
} else {
return 0
}
}
var decodedLength: Int {
var len = 0
var size = 0
var bytes = self
while true {
guard let elem = bytes.first else { break }
bytes = bytes.dropFirst()
len = len | ((Int(elem) & 0x7f) << (size * 7))
size += 1
if Int16(elem) & 0x80 == 0 {
break
}
}
return len
}
mutating func decodeLength() -> Int {
var len = 0
var size = 0
while true {
guard let elem = bytes.first else { break }
_ = popFirst()
len = len | ((Int(elem) & 0x7f) << (size * 7))
size += 1
if Int16(elem) & 0x80 == 0 {
break
}
}
return len
}
static func encodeLength(_ len: Int) -> Data {
encodeLength(UInt(len))
}
private static func encodeLength(_ len: UInt) -> Data {
var remLen = len
var bytes = Data()
while true {
var elem = remLen & 0x7f
remLen = remLen >> 7
if remLen == 0 {
bytes.append(UInt8(elem))
break
} else {
elem = elem | 0x80
bytes.append(UInt8(elem))
}
}
return bytes
}
}

View File

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0A35995B64EBF9C1B79FFADF /* Pods_Tokenary_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE9E1A64A4B68CD2CC762C5C /* Pods_Tokenary_iOS.framework */; };
0D059AD226C2796200EE3023 /* ApprovalSubject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D059AD126C2796200EE3023 /* ApprovalSubject.swift */; };
0DC850E726B73A5900809E82 /* AuthenticationReason.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC850E626B73A5900809E82 /* AuthenticationReason.swift */; };
2C03D1D2269B407900EF10EA /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C03D1D1269B407900EF10EA /* NetworkMonitor.swift */; };
@ -64,6 +63,8 @@
2C264BEB27B6B50700234393 /* DappRequestProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C264BEA27B6B50700234393 /* DappRequestProcessor.swift */; };
2C264BEC27B6B50700234393 /* DappRequestProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C264BEA27B6B50700234393 /* DappRequestProcessor.swift */; };
2C3B7F022756A08600931264 /* Identifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3B7F012756A08600931264 /* Identifiers.swift */; };
2C40379428199110004C7263 /* Solana.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C40379328199110004C7263 /* Solana.swift */; };
2C40379528199110004C7263 /* Solana.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C40379328199110004C7263 /* Solana.swift */; };
2C40709027667A6600AB3D55 /* MultilineLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C40708E27667A6600AB3D55 /* MultilineLabelTableViewCell.swift */; };
2C40709127667A6600AB3D55 /* MultilineLabelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2C40708F27667A6600AB3D55 /* MultilineLabelTableViewCell.xib */; };
2C40709427667A8600AB3D55 /* ImageWithLabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C40709227667A8600AB3D55 /* ImageWithLabelTableViewCell.swift */; };
@ -188,7 +189,8 @@
2CF255BA275A749300AE54B9 /* ApproveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CF255B9275A749300AE54B9 /* ApproveViewController.swift */; };
2CFDDF4C2765416F00F89019 /* macos-specific-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 2CFDDF4B2765416F00F89019 /* macos-specific-content.js */; };
2CFDDF4E2765417E00F89019 /* ios-specific-content.js in Resources */ = {isa = PBXBuildFile; fileRef = 2CFDDF4D2765417D00F89019 /* ios-specific-content.js */; };
9CF0E61C7E25270AFD7B66BC /* Pods_Tokenary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 748E4E402F96890CD86451CD /* Pods_Tokenary.framework */; };
C45E534A4BF2FA3DBC9116B3 /* Pods_Tokenary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DFFD1CBABB76153BE61BCD1 /* Pods_Tokenary.framework */; };
C5AD3358DE1CE6481703BCDB /* Pods_Tokenary_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACC67B61D954CA785C669AB /* Pods_Tokenary_iOS.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -236,6 +238,7 @@
/* Begin PBXFileReference section */
0D059AD126C2796200EE3023 /* ApprovalSubject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApprovalSubject.swift; sourceTree = "<group>"; };
0DC850E626B73A5900809E82 /* AuthenticationReason.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationReason.swift; sourceTree = "<group>"; };
2608F6615C03FAE4CC2FADB5 /* Pods-Tokenary.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary.debug.xcconfig"; path = "Target Support Files/Pods-Tokenary/Pods-Tokenary.debug.xcconfig"; sourceTree = "<group>"; };
2C03D1D1269B407900EF10EA /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
2C03D1D4269B428C00EF10EA /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
2C09CB9F273979C1009AD39B /* Safari macOS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Safari macOS.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -267,6 +270,7 @@
2C264BE527B5AC6800234393 /* TezosResponseToExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TezosResponseToExtension.swift; sourceTree = "<group>"; };
2C264BEA27B6B50700234393 /* DappRequestProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DappRequestProcessor.swift; sourceTree = "<group>"; };
2C3B7F012756A08600931264 /* Identifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identifiers.swift; sourceTree = "<group>"; };
2C40379328199110004C7263 /* Solana.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Solana.swift; sourceTree = "<group>"; };
2C40708E27667A6600AB3D55 /* MultilineLabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLabelTableViewCell.swift; sourceTree = "<group>"; };
2C40708F27667A6600AB3D55 /* MultilineLabelTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MultilineLabelTableViewCell.xib; sourceTree = "<group>"; };
2C40709227667A8600AB3D55 /* ImageWithLabelTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageWithLabelTableViewCell.swift; sourceTree = "<group>"; };
@ -365,12 +369,11 @@
2CF255B9275A749300AE54B9 /* ApproveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApproveViewController.swift; sourceTree = "<group>"; };
2CFDDF4B2765416F00F89019 /* macos-specific-content.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "macos-specific-content.js"; sourceTree = "<group>"; };
2CFDDF4D2765417D00F89019 /* ios-specific-content.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "ios-specific-content.js"; sourceTree = "<group>"; };
3A44A6AD75AD00A8147D51C9 /* Pods-Tokenary iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary iOS.release.xcconfig"; path = "Target Support Files/Pods-Tokenary iOS/Pods-Tokenary iOS.release.xcconfig"; sourceTree = "<group>"; };
748E4E402F96890CD86451CD /* Pods_Tokenary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tokenary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
79196256009C6E698EB7AA59 /* Pods-Tokenary.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary.release.xcconfig"; path = "Target Support Files/Pods-Tokenary/Pods-Tokenary.release.xcconfig"; sourceTree = "<group>"; };
79E83B47DE0EB9BC8AC9B236 /* Pods-Tokenary iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary iOS.debug.xcconfig"; path = "Target Support Files/Pods-Tokenary iOS/Pods-Tokenary iOS.debug.xcconfig"; sourceTree = "<group>"; };
9FB2D4E7F11F60183689311C /* Pods-Tokenary.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary.debug.xcconfig"; path = "Target Support Files/Pods-Tokenary/Pods-Tokenary.debug.xcconfig"; sourceTree = "<group>"; };
BE9E1A64A4B68CD2CC762C5C /* Pods_Tokenary_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tokenary_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4DCD96CD3888DB031C72F842 /* Pods-Tokenary.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary.release.xcconfig"; path = "Target Support Files/Pods-Tokenary/Pods-Tokenary.release.xcconfig"; sourceTree = "<group>"; };
561742E845857C54DFB9F896 /* Pods-Tokenary iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary iOS.release.xcconfig"; path = "Target Support Files/Pods-Tokenary iOS/Pods-Tokenary iOS.release.xcconfig"; sourceTree = "<group>"; };
8DFFD1CBABB76153BE61BCD1 /* Pods_Tokenary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tokenary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AACC67B61D954CA785C669AB /* Pods_Tokenary_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tokenary_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BEF328B0641A53F7D2AE18A7 /* Pods-Tokenary iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tokenary iOS.debug.xcconfig"; path = "Target Support Files/Pods-Tokenary iOS/Pods-Tokenary iOS.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -385,7 +388,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9CF0E61C7E25270AFD7B66BC /* Pods_Tokenary.framework in Frameworks */,
C45E534A4BF2FA3DBC9116B3 /* Pods_Tokenary.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -393,7 +396,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0A35995B64EBF9C1B79FFADF /* Pods_Tokenary_iOS.framework in Frameworks */,
C5AD3358DE1CE6481703BCDB /* Pods_Tokenary_iOS.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -422,6 +425,15 @@
path = Models;
sourceTree = "<group>";
};
26E4798B40DBB530BCE4677E /* Frameworks */ = {
isa = PBXGroup;
children = (
8DFFD1CBABB76153BE61BCD1 /* Pods_Tokenary.framework */,
AACC67B61D954CA785C669AB /* Pods_Tokenary_iOS.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
2C09CBA0273979C1009AD39B /* Safari macOS */ = {
isa = PBXGroup;
children = (
@ -454,7 +466,7 @@
2C5FF98A26C8567D00B32ACC /* Screensaver */,
2C19953D2674C4B900A8E370 /* Products */,
FB5786212D81829B0FADBD25 /* Pods */,
3C02E73226D93B28BA7E14DD /* Frameworks */,
26E4798B40DBB530BCE4677E /* Frameworks */,
);
sourceTree = "<group>";
};
@ -781,6 +793,7 @@
children = (
2C03D1D1269B407900EF10EA /* NetworkMonitor.swift */,
2C264BEA27B6B50700234393 /* DappRequestProcessor.swift */,
2C40379328199110004C7263 /* Solana.swift */,
2CAA412426C7CD93009F3535 /* ReviewRequester.swift */,
2C901C4C268A033100D0926A /* GasService.swift */,
2CC0CDBD2692027E0072922A /* PriceService.swift */,
@ -809,22 +822,13 @@
path = Screens;
sourceTree = "<group>";
};
3C02E73226D93B28BA7E14DD /* Frameworks */ = {
isa = PBXGroup;
children = (
748E4E402F96890CD86451CD /* Pods_Tokenary.framework */,
BE9E1A64A4B68CD2CC762C5C /* Pods_Tokenary_iOS.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
FB5786212D81829B0FADBD25 /* Pods */ = {
isa = PBXGroup;
children = (
9FB2D4E7F11F60183689311C /* Pods-Tokenary.debug.xcconfig */,
79196256009C6E698EB7AA59 /* Pods-Tokenary.release.xcconfig */,
79E83B47DE0EB9BC8AC9B236 /* Pods-Tokenary iOS.debug.xcconfig */,
3A44A6AD75AD00A8147D51C9 /* Pods-Tokenary iOS.release.xcconfig */,
2608F6615C03FAE4CC2FADB5 /* Pods-Tokenary.debug.xcconfig */,
4DCD96CD3888DB031C72F842 /* Pods-Tokenary.release.xcconfig */,
BEF328B0641A53F7D2AE18A7 /* Pods-Tokenary iOS.debug.xcconfig */,
561742E845857C54DFB9F896 /* Pods-Tokenary iOS.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -865,13 +869,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 2C19954C2674C4BA00A8E370 /* Build configuration list for PBXNativeTarget "Tokenary" */;
buildPhases = (
032A6C803438BB662CB91D5C /* [CP] Check Pods Manifest.lock */,
32E2F132C9F0D04B9DD910D3 /* [CP] Check Pods Manifest.lock */,
2C1995382674C4B900A8E370 /* Sources */,
2C1995392674C4B900A8E370 /* Frameworks */,
2C19953A2674C4B900A8E370 /* Resources */,
2C1995512674C6A100A8E370 /* ShellScript */,
2C09CBB8273979C1009AD39B /* Embed App Extensions */,
E992E558A2E6E14778576867 /* [CP] Embed Pods Frameworks */,
3D316E6296010EB641655C38 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -887,13 +891,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 2C5FF98026C84F7C00B32ACC /* Build configuration list for PBXNativeTarget "Tokenary iOS" */;
buildPhases = (
9283FF1ED099C56D5CD4C47F /* [CP] Check Pods Manifest.lock */,
DCCA30A739CF7344417CDED3 /* [CP] Check Pods Manifest.lock */,
2C5FF96B26C84F7B00B32ACC /* Sources */,
2C5FF96C26C84F7B00B32ACC /* Frameworks */,
2C5FF96D26C84F7B00B32ACC /* Resources */,
2CC8C59D27678D4B0083FB1B /* ShellScript */,
2CCEB84627594E2A00768473 /* Embed App Extensions */,
3D6DA0588EFAC21D933260AA /* [CP] Embed Pods Frameworks */,
D86A5B8303DF5C648C914004 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -1055,28 +1059,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
032A6C803438BB662CB91D5C /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Tokenary-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
2C1995512674C6A100A8E370 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -1147,7 +1129,46 @@
shellPath = /bin/sh;
shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\n\nif which swiftlint; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
3D6DA0588EFAC21D933260AA /* [CP] Embed Pods Frameworks */ = {
32E2F132C9F0D04B9DD910D3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Tokenary-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3D316E6296010EB641655C38 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
D86A5B8303DF5C648C914004 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -1164,7 +1185,7 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tokenary iOS/Pods-Tokenary iOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9283FF1ED099C56D5CD4C47F /* [CP] Check Pods Manifest.lock */ = {
DCCA30A739CF7344417CDED3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -1186,23 +1207,6 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E992E558A2E6E14778576867 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tokenary/Pods-Tokenary-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -1288,6 +1292,7 @@
2C264BDC27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */,
2C03D1D5269B428C00EF10EA /* Notification.swift in Sources */,
2C1995562674D0F300A8E370 /* Ethereum.swift in Sources */,
2C40379428199110004C7263 /* Solana.swift in Sources */,
2C8A09DF267579EA00993638 /* AccountsListViewController.swift in Sources */,
2C917429267D2A6E00049075 /* Keychain.swift in Sources */,
);
@ -1341,6 +1346,7 @@
2CF2559C275A477F00AE54B9 /* ApprovalSubject.swift in Sources */,
2C264BE727B5AC6800234393 /* TezosResponseToExtension.swift in Sources */,
2C264BD627B5806200234393 /* Web3Provider.swift in Sources */,
2C40379528199110004C7263 /* Solana.swift in Sources */,
2CE0594427640EB40042D844 /* ExtensionBridge.swift in Sources */,
2CF255B1275A4A1800AE54B9 /* ResponseToExtension.swift in Sources */,
2CF2559B275A46E700AE54B9 /* AuthenticationReason.swift in Sources */,
@ -1619,7 +1625,7 @@
};
2C19954D2674C4BA00A8E370 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9FB2D4E7F11F60183689311C /* Pods-Tokenary.debug.xcconfig */;
baseConfigurationReference = 2608F6615C03FAE4CC2FADB5 /* Pods-Tokenary.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@ -1647,7 +1653,7 @@
};
2C19954E2674C4BA00A8E370 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 79196256009C6E698EB7AA59 /* Pods-Tokenary.release.xcconfig */;
baseConfigurationReference = 4DCD96CD3888DB031C72F842 /* Pods-Tokenary.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@ -1675,7 +1681,7 @@
};
2C5FF98126C84F7C00B32ACC /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 79E83B47DE0EB9BC8AC9B236 /* Pods-Tokenary iOS.debug.xcconfig */;
baseConfigurationReference = BEF328B0641A53F7D2AE18A7 /* Pods-Tokenary iOS.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@ -1701,7 +1707,7 @@
};
2C5FF98226C84F7C00B32ACC /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3A44A6AD75AD00A8147D51C9 /* Pods-Tokenary iOS.release.xcconfig */;
baseConfigurationReference = 561742E845857C54DFB9F896 /* Pods-Tokenary iOS.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;