From 25f5c982737cf22d0b9dc654a2b2eae812a1ee40 Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Wed, 23 Oct 2024 22:13:42 +0300 Subject: [PATCH 01/10] IOS-8316 IOS-8332 Add basic implementation blockchain --- .../Casper/CasperAddressService.swift | 74 +++++++++ .../Casper/CasperAddressUtils.swift | 149 ++++++++++++++++++ .../Casper/CasperExternalLinkProvider.swift | 34 ++++ .../Casper/CasperNetworkProvider.swift | 39 +++++ .../Casper/CasperWalletAssembly.swift | 27 ++++ .../Casper/CasperWalletManager.swift | 35 ++++ .../Casper/Network/CasperTarget.swift | 44 ++++++ .../API/TestnetAPINodeInfoProvider.swift | 6 +- .../Common/Address/AddressTypesConfig.swift | 3 +- BlockchainSdk/Common/Blockchain.swift | 13 +- .../Blockchain/Blockchain+AllCases.swift | 4 +- .../Derivations/DerivationConfigV1.swift | 2 + .../Derivations/DerivationConfigV2.swift | 2 + .../Derivations/DerivationConfigV3.swift | 2 + .../Factories/AddressServiceFactory.swift | 3 + .../EstimationFeeAddressFactory.swift | 3 + .../ExternalLinkProviderFactory.swift | 2 + BlockchainSdk/Extensions/Byte+.swift | 40 +++++ BlockchainSdk/Extensions/TWCoin+.swift | 3 +- BlockchainSdkTests/Casper/CasperTests.swift | 53 +++++++ .../Extensions/TWPublicKeyType+.swift | 3 +- .../ExchangeService/MercuryoService.swift | 3 +- .../ExchangeService/MoonPayService.swift | 2 + .../CustomTokenContractAddressConverter.swift | 3 +- ...TokenInteractionAvailabilityProvider.swift | 3 +- .../Services/TransactionParamsBuilder.swift | 3 +- TangemApp.xcodeproj/project.pbxproj | 82 +++++++++- .../xcshareddata/swiftpm/Package.resolved | 11 +- 28 files changed, 633 insertions(+), 15 deletions(-) create mode 100644 BlockchainSdk/Blockchains/Casper/CasperAddressService.swift create mode 100644 BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift create mode 100644 BlockchainSdk/Blockchains/Casper/CasperExternalLinkProvider.swift create mode 100644 BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift create mode 100644 BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift create mode 100644 BlockchainSdk/Blockchains/Casper/CasperWalletManager.swift create mode 100644 BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift create mode 100644 BlockchainSdk/Extensions/Byte+.swift create mode 100644 BlockchainSdkTests/Casper/CasperTests.swift diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift new file mode 100644 index 0000000000..8eeed61040 --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift @@ -0,0 +1,74 @@ +// +// CasperAddressService.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import TangemSdk + +public struct CasperAddressService { + // MARK: - Private Properties + + private let curve: EllipticCurve + + // MARK: - Init + + init(curve: EllipticCurve) { + self.curve = curve + } +} + +// MARK: - AddressProvider + +extension CasperAddressService: AddressProvider { + public func makeAddress(for publicKey: Wallet.PublicKey, with addressType: AddressType) throws -> Address { + guard let prefixAddresss = Constants.getAddressPrefix(curve: curve) else { + throw Error.unsupportedAddressPrefix + } + + let addressBytes = Data(hexString: prefixAddresss) + publicKey.blockchainKey + let address = try CasperAddressUtils().checksum(input: addressBytes) + return PlainAddress(value: address, publicKey: publicKey, type: addressType) + } +} + +// MARK: - AddressValidator + +extension CasperAddressService: AddressValidator { + public func validate(_ address: String) -> Bool { + return false + } +} + +// MARK: - Constants + +extension CasperAddressService { + enum Constants { + // ED25519 + static let prefixED25519 = "01" + static let lengthED25519 = 66 + + // SECP256K1 + static let prefixSECP256K1 = "02" + static let lengthSECP256K1 = 68 + + static func getAddressPrefix(curve: EllipticCurve) -> String? { + switch curve { + case .ed25519, .ed25519_slip0010: + return CasperAddressService.Constants.prefixED25519 + case .secp256k1: + return CasperAddressService.Constants.prefixSECP256K1 + default: + // Any curves not supported or will be added in the future + return nil + } + } + } + + enum Error: LocalizedError { + case unsupportedAddressPrefix + } +} diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift new file mode 100644 index 0000000000..238c0f0cb5 --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift @@ -0,0 +1,149 @@ +// +// CasperAddressUtils.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import Blake2 + +/* + https://github.com/casper-ecosystem/casper-js-sdk/blob/dev/src/lib/ChecksummedHex.ts + */ + +struct CasperAddressUtils { + + // Ed25519: encode([0x01]) + encode() + // or + // Secp256k1: encode([0x02]) + encode() + func checksum(input: Data) throws -> String { + let byteArray = input.bytes + + guard byteArray.count > 2, let first = byteArray.first else { + throw Error.failedSizeInputChecksum + } + + return try encode(input: [first]) + encode(input: Array(input.bytes[1.. [0x00, 0x01, 0x50, 0x05, 0xF0, 0x0F, ...] + private func bytesToNibbles(bytes: [UInt8]) -> [UInt8] { + let result: [UInt8] = bytes.reduce(into: [], { partialResult, byte in + partialResult.append((byte & 0xFF) >> 4) + partialResult.append(byte & 0x0F) + }) + + return result + } + + private func byteHash(bytes: [UInt8]) throws -> [UInt8] { + guard let hashData = try? Blake2b.hash(size: 32, data: bytes) else { + throw Error.failedHashBlake2b + } + return hashData.bytes + } + + private func encode(input: [UInt8]) throws -> String { + let inputNibbles = bytesToNibbles(bytes: input) + + print(inputNibbles.toHexString()) + + let hash = try byteHash(bytes: input) + + print(hash.toHexString()) + + // Separate bytes inside ByteArray to bits array + // E.g. [0x01, ...] -> [false, false, false, false, false, false, false, true, ...] + // E.g. [0xAA, ...] -> [true, false, true, false, true, false, true, false, ...] + let hashBits = hash.toBitArray().map { $0.boolValue } + + print(hashBits) + + var hashBitsValues = hashBits.makeIterator() + + print(hashBitsValues) + + let result: String = inputNibbles.reduce(into: "") { partialResult, nibbleByte in + let char = nibbleByte.hexString + + if char.range(of: "[^a-zA-Z0-9-]", options: .regularExpression) == nil, hashBitsValues.next() ?? false { + partialResult.append(char.lowercased()) + } else { + partialResult.append(char.uppercased()) + } + } + + print(result) + + return result + } +} + +extension CasperAddressUtils { + enum Constants { + static let regexEncodeByte = try! NSRegularExpression(pattern: "^[a-zA-Z()]") + } + + enum Error: LocalizedError { + case failedSizeInputChecksum + case failedHashBlake2b + } +} + +/* +/** + * @see Source + */ +object CasperAddressUtils { + // Ed25519: encode([0x01]) + encode() + // or + // Secp256k1: encode([0x02]) + encode() + fun ByteArray.checksum(): String = encode(byteArrayOf(first())) + encode(drop(1).toByteArray()) + + // Separate bytes inside ByteArray to nibbles + // E.g. [0x01, 0x55, 0xFF, ...] -> [0x00, 0x01, 0x50, 0x05, 0xF0, 0x0F, ...] + @Suppress("MagicNumber") + private fun bytesToNibbles(bytes: ByteArray): ByteArray = bytes + .flatMap { byte -> + listOf( + (byte.toInt() and 0xff shr 4).toByte(), + (byte.toInt() and 0x0f).toByte(), + ) + }.toByteArray() + + // Separate bytes inside ByteArray to bits array + // E.g. [0x01, ...] -> [false, false, false, false, false, false, false, true, ...] + // E.g. [0xAA, ...] -> [true, false, true, false, true, false, true, false, ...] + @Suppress("MagicNumber") + private fun ByteArray.toBitArray(): BooleanArray = this + .flatMap { byte -> + List(8) { i -> + byte.toInt() shr i and 0x01 == 0x01 + } + }.toBooleanArray() + + private fun byteHash(bytes: ByteArray): ByteArray = Blake2b.Blake2b256().digest(bytes) + + private fun encode(input: ByteArray): String { + val inputNibbles = bytesToNibbles(input) + val hash = byteHash(input) + val hashBits = hash.toBitArray() + val hashBitsValues = hashBits.iterator() + return inputNibbles.fold(StringBuilder()) { accum, nibble -> + val c = "%x".format(nibble) + + if (Regex("^[a-zA-Z()]+\$").matches(c) && hashBitsValues.hasNext() && hashBitsValues.next()) { + accum.append(c.uppercase()) + } else { + accum.append(c.lowercase()) + } + accum + }.toString() + } +} +*/ diff --git a/BlockchainSdk/Blockchains/Casper/CasperExternalLinkProvider.swift b/BlockchainSdk/Blockchains/Casper/CasperExternalLinkProvider.swift new file mode 100644 index 0000000000..73d7ac6d00 --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperExternalLinkProvider.swift @@ -0,0 +1,34 @@ +// +// CasperExternalLinkProvider.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +struct CasperExternalLinkProvider: ExternalLinkProvider { + var testnetFaucetURL: URL? { + URL(string: "https://testnet.cspr.live/tools/faucet") + } + + private let isTestnet: Bool + + private var baseExplorerUrl: String { + return isTestnet ? "https://testnet.cspr.live" : "https://cspr.live" + + } + + init(isTestnet: Bool) { + self.isTestnet = isTestnet + } + + func url(address: String, contractAddress: String?) -> URL? { + return URL(string: "\(baseExplorerUrl)/account/\(address)") + } + + func url(transaction hash: String) -> URL? { + return URL(string: "\(baseExplorerUrl)/deploy/\(hash)") + } +} diff --git a/BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift b/BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift new file mode 100644 index 0000000000..9fba71cd2a --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift @@ -0,0 +1,39 @@ +// +// CasperNetworkProvider.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Combine +import Foundation + +final class CasperNetworkProvider: HostProvider { + var host: String { + node.url.absoluteString + } + + private let node: NodeInfo + + // TODO: - + private let provider: NetworkProvider + + init( + node: NodeInfo, + configuration: NetworkProviderConfiguration + ) { + self.node = node + provider = NetworkProvider(configuration: configuration) + } + + // MARK: - Private Implementation + + private func requestPublisher(for target: FilecoinTarget.FilecoinTargetType) -> AnyPublisher { + provider.requestPublisher(CasperTarget(node: node)) + .filterSuccessfulStatusAndRedirectCodes() + .map(JSONRPC.Response.self) + .tryMap { try $0.result.get() } + .eraseToAnyPublisher() + } +} diff --git a/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift b/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift new file mode 100644 index 0000000000..b2637ded6c --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift @@ -0,0 +1,27 @@ +// +// CasperWalletAssembly.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation + +struct CasperWalletAssembly: WalletManagerAssembly { + func make(with input: WalletManagerAssemblyInput) throws -> WalletManager { + FilecoinWalletManager( + wallet: input.wallet, + networkService: FilecoinNetworkService( + providers: APIResolver(blockchain: input.blockchain, config: input.blockchainSdkConfig) + .resolveProviders(apiInfos: input.apiInfo) { nodeInfo, _ in + FilecoinNetworkProvider( + node: nodeInfo, + configuration: input.networkConfig + ) + } + ), + transactionBuilder: try FilecoinTransactionBuilder(publicKey: input.wallet.publicKey) + ) + } +} diff --git a/BlockchainSdk/Blockchains/Casper/CasperWalletManager.swift b/BlockchainSdk/Blockchains/Casper/CasperWalletManager.swift new file mode 100644 index 0000000000..b4c2ac824d --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/CasperWalletManager.swift @@ -0,0 +1,35 @@ +// +// CasperWalletManager.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import Combine + +class CasperWalletManager: BaseManager, WalletManager { + var currentHost: String { + // TODO: - https://tangem.atlassian.net/browse/IOS-8316 + "" + } + + var allowsFeeSelection: Bool { + false + } + + override func update(completion: @escaping (Result) -> Void) { + // TODO: - https://tangem.atlassian.net/browse/IOS-8316 + } + + func getFee(amount: Amount, destination: String) -> AnyPublisher<[Fee], any Error> { + // TODO: - https://tangem.atlassian.net/browse/IOS-8316 + return .anyFail(error: WalletError.empty) + } + + func send(_ transaction: Transaction, signer: any TransactionSigner) -> AnyPublisher { + // TODO: - https://tangem.atlassian.net/browse/IOS-8316 + return .anyFail(error: SendTxError(error: WalletError.empty)) + } +} diff --git a/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift b/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift new file mode 100644 index 0000000000..71d893fffe --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift @@ -0,0 +1,44 @@ +// +// CasperTarget.swift +// BlockchainSdk +// +// Created by skibinalexander on 22.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import Moya + +// TODO: - https://tangem.atlassian.net/browse/IOS-8316 +struct CasperTarget: TargetType { + + // MARK: - Properties + + let node: NodeInfo + + // MARK: - Init + + init(node: NodeInfo) { + self.node = node + } + + // MARK: - TargetType + + var baseURL: URL { + node.url + } + + var path: String { + "" + } + + var method: Moya.Method { + .post + } + + var task: Task { + .requestPlain + } + + var headers: [String : String]? +} diff --git a/BlockchainSdk/Common/API/TestnetAPINodeInfoProvider.swift b/BlockchainSdk/Common/API/TestnetAPINodeInfoProvider.swift index d1fdd19d0a..f65759f113 100644 --- a/BlockchainSdk/Common/API/TestnetAPINodeInfoProvider.swift +++ b/BlockchainSdk/Common/API/TestnetAPINodeInfoProvider.swift @@ -235,11 +235,15 @@ struct TestnetAPINodeInfoProvider { return [ .init(url: URL(string: "https://rpc.test.btcs.network")!) ] + case .casper: + return [ + .init(url: URL(string: "https://testnet.phantom-rpc.com/rpc")!) + ] // TODO: Refactor in IOS-6639 case .bitcoin, .litecoin, .disChain, .rsk, .bitcoinCash, .binance, .cardano, .xrp, .ducatus, .tezos, .dogecoin, .solana, .kusama, .dash, .gnosis, .terraV1, .terraV2, .cronos, .octa, .playa3ullGames, .radiant, .joystream, - .bittensor, .internetComputer, .filecoin, .energyWebX: + .bittensor, .internetComputer, .filecoin, .energyWebX, .casper: return nil } } diff --git a/BlockchainSdk/Common/Address/AddressTypesConfig.swift b/BlockchainSdk/Common/Address/AddressTypesConfig.swift index d4243aa619..8c1788595a 100644 --- a/BlockchainSdk/Common/Address/AddressTypesConfig.swift +++ b/BlockchainSdk/Common/Address/AddressTypesConfig.swift @@ -88,7 +88,8 @@ struct AddressTypesConfig { .sei, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: return [.default] } } diff --git a/BlockchainSdk/Common/Blockchain.swift b/BlockchainSdk/Common/Blockchain.swift index c9cb13666c..9e428539f1 100644 --- a/BlockchainSdk/Common/Blockchain.swift +++ b/BlockchainSdk/Common/Blockchain.swift @@ -90,6 +90,7 @@ public indirect enum Blockchain: Equatable, Hashable { /// Polkadot parachain case energyWebX(curve: EllipticCurve) case core(testnet: Bool) + case casper(testnet: Bool) public var isTestnet: Bool { switch self { @@ -133,7 +134,8 @@ public indirect enum Blockchain: Equatable, Hashable { .sei(let testnet), .kaspa(let testnet), .energyWebEVM(let testnet), - .core(let testnet): + .core(let testnet), + .casper(let testnet): return testnet case .litecoin, .ducatus, @@ -303,7 +305,7 @@ public indirect enum Blockchain: Equatable, Hashable { return 6 case .stellar: return 7 - case .solana, .ton, .bittensor, .sui: + case .solana, .ton, .bittensor, .sui, .casper: return 9 case .polkadot(_, let testnet): return testnet ? 12 : 10 @@ -459,6 +461,8 @@ public indirect enum Blockchain: Equatable, Hashable { return "EWT" case .core: return isTestnet ? "tCORE" : "CORE" + case .casper: + return "CSPR" } } @@ -951,6 +955,7 @@ extension Blockchain: Codable { case .energyWebEVM: return "energyWebEVM" case .energyWebX: return "energyWebX" case .core: return "core" + case .casper: return "casper" } } @@ -1285,6 +1290,8 @@ private extension Blockchain { case .network: return "core" case .coin: return "coredaoorg" } + case .casper: + return "casper" } } @@ -1399,6 +1406,8 @@ extension Blockchain { return SuiWalletAssembly() case .filecoin: return FilecoinWalletAssembly() + case .casper: + return CasperWalletAssembly() } } } diff --git a/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift b/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift index fcd8e74fa5..112be0ebbb 100644 --- a/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift +++ b/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift @@ -86,6 +86,7 @@ public extension Blockchain { case .energyWebEVM: break case .energyWebX: break case .core: break + case .casper: break // READ BELOW: // // Did you get a compilation error here? If so, add your new blockchain to the array below @@ -164,7 +165,8 @@ public extension Blockchain { .sei(testnet: false), .energyWebEVM(testnet: false), .energyWebX(curve: .ed25519_slip0010), - .core(testnet: false) + .core(testnet: false), + .casper(testnet: false), ] } } diff --git a/BlockchainSdk/Common/Derivations/DerivationConfigV1.swift b/BlockchainSdk/Common/Derivations/DerivationConfigV1.swift index 4362115dcd..7307cd10e0 100644 --- a/BlockchainSdk/Common/Derivations/DerivationConfigV1.swift +++ b/BlockchainSdk/Common/Derivations/DerivationConfigV1.swift @@ -143,6 +143,8 @@ public struct DerivationConfigV1: DerivationConfig { return "m/44'/246'/0'/0'/0'" case .core: return "m/44'/1116'/0'/0/0" + case .casper: + return "m/44'/506'/0'/0/0" } } } diff --git a/BlockchainSdk/Common/Derivations/DerivationConfigV2.swift b/BlockchainSdk/Common/Derivations/DerivationConfigV2.swift index 803558b301..d5f5438b74 100644 --- a/BlockchainSdk/Common/Derivations/DerivationConfigV2.swift +++ b/BlockchainSdk/Common/Derivations/DerivationConfigV2.swift @@ -128,6 +128,8 @@ public struct DerivationConfigV2: DerivationConfig { return "m/44'/461'/0'/0/0" case .energyWebX: return "m/44'/246'/0'/0'/0'" + case .casper: + return "m/44'/506'/0'/0/0" } } } diff --git a/BlockchainSdk/Common/Derivations/DerivationConfigV3.swift b/BlockchainSdk/Common/Derivations/DerivationConfigV3.swift index 322f1d695f..805ddb8d63 100644 --- a/BlockchainSdk/Common/Derivations/DerivationConfigV3.swift +++ b/BlockchainSdk/Common/Derivations/DerivationConfigV3.swift @@ -133,6 +133,8 @@ public struct DerivationConfigV3: DerivationConfig { return "m/44'/461'/0'/0/0" case .energyWebX: return "m/44'/246'/0'/0'/0'" + case .casper: + return "m/44'/506'/0'/0/0" } } } diff --git a/BlockchainSdk/Common/Factories/AddressServiceFactory.swift b/BlockchainSdk/Common/Factories/AddressServiceFactory.swift index 233b30fa6f..23c172753f 100644 --- a/BlockchainSdk/Common/Factories/AddressServiceFactory.swift +++ b/BlockchainSdk/Common/Factories/AddressServiceFactory.swift @@ -139,6 +139,9 @@ public struct AddressServiceFactory { return WalletCoreAddressService(blockchain: .filecoin) case .energyWebX(let curve): return PolkadotAddressService(network: .energyWebX(curve: curve)) + case .casper: + // We only support this type of curve + return CasperAddressService(curve: .secp256k1) } } } diff --git a/BlockchainSdk/Common/Factories/EstimationFeeAddressFactory.swift b/BlockchainSdk/Common/Factories/EstimationFeeAddressFactory.swift index dbd96bf47f..8cb67f0299 100644 --- a/BlockchainSdk/Common/Factories/EstimationFeeAddressFactory.swift +++ b/BlockchainSdk/Common/Factories/EstimationFeeAddressFactory.swift @@ -105,6 +105,9 @@ struct EstimationFeeAddressFactory { return "sei1lhjvds604fvac32j4eygpr820lyc82dlfv0ea4" case .energyWebX: return "5CogUCbb5PYYbEHhDVGDN6JRRYBkd4sFRVc4wwP8oy5Su34Z" + case .casper: + // TODO: - It is necessary to clarify + return "" } } } diff --git a/BlockchainSdk/Common/Factories/ExternalLinkProviderFactory.swift b/BlockchainSdk/Common/Factories/ExternalLinkProviderFactory.swift index a3e42f51dd..d09fd4163d 100644 --- a/BlockchainSdk/Common/Factories/ExternalLinkProviderFactory.swift +++ b/BlockchainSdk/Common/Factories/ExternalLinkProviderFactory.swift @@ -161,6 +161,8 @@ public struct ExternalLinkProviderFactory { return EnergyWebXExternalLinkProvider(isTestnet: isTestnet) case .core: return CoreExternalLinkProvider(isTestnet: isTestnet) + case .casper: + return CasperExternalLinkProvider(isTestnet: isTestnet) } } } diff --git a/BlockchainSdk/Extensions/Byte+.swift b/BlockchainSdk/Extensions/Byte+.swift new file mode 100644 index 0000000000..ed75c254bd --- /dev/null +++ b/BlockchainSdk/Extensions/Byte+.swift @@ -0,0 +1,40 @@ +// +// Byte+.swift +// BlockchainSdkTests +// +// Created by skibinalexander on 23.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import CryptoSwift + +extension Bit { + var boolValue: Bool { + self == .one + } +} + +extension UInt8 { + func toBits() -> [Bit] { + var byte = self + var bits = [Bit](repeating: .zero, count: 8) + for i in 0..<8 { + let currentBit = byte & 0x01 + if currentBit != 0 { + bits[i] = .one + } + + byte >>= 1 + } + + return bits + } +} + +extension Array where Element == UInt8 { + func toBitArray() -> [Bit] { + let arrayBits = self.map { $0.toBits() } + return arrayBits.reduce(into: []) { partialResult, bits in partialResult.append(contentsOf: bits) } + } +} diff --git a/BlockchainSdk/Extensions/TWCoin+.swift b/BlockchainSdk/Extensions/TWCoin+.swift index 9f7599f0fc..effe72a04f 100644 --- a/BlockchainSdk/Extensions/TWCoin+.swift +++ b/BlockchainSdk/Extensions/TWCoin+.swift @@ -123,7 +123,8 @@ extension CoinType { .blast, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: // Blockchains that are not in WalletCore yet return nil } diff --git a/BlockchainSdkTests/Casper/CasperTests.swift b/BlockchainSdkTests/Casper/CasperTests.swift new file mode 100644 index 0000000000..27b15aed99 --- /dev/null +++ b/BlockchainSdkTests/Casper/CasperTests.swift @@ -0,0 +1,53 @@ +// +// CasperTests.swift +// BlockchainSdkTests +// +// Created by skibinalexander on 23.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import TangemSdk +import XCTest + +@testable import BlockchainSdk + +final class CasperTests: XCTestCase { + + private let blockchain = Blockchain.casper(testnet: false) + + func testMakeAddressFromCorrectEd25519PublicKey() throws { + let walletPublicKey = Data(hexString: "98C07D7E72D89A681D7227A7AF8A6FD5F22FE0105C8741D55A95DF415454B82E") + let expectedAddress = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" + + let addressService = CasperAddressService(curve: .ed25519) + + try XCTAssertEqual(addressService.makeAddress(from: walletPublicKey).value, expectedAddress) + } + + func testValidateCorrectEd25519Address() { + let address = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" + + let addressService = CasperAddressService(curve: .ed25519) + + XCTAssertTrue(addressService.validate(address)) + } + + func testMakeAddressFromCorrectSecp256k1PublicKey() { + let walletPublicKey = Data(hexString: "021F997DFBBFD32817C0E110EAEE26BCBD2BB70B4640C515D9721C9664312EACD8") + let expectedAddress = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" + + let addressService = CasperAddressService(curve: .secp256k1) + + try XCTAssertEqual(addressService.makeAddress(from: walletPublicKey).value, expectedAddress) + } + + func testValidateCorrectSecp256k1Address() { + let address = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" + + let addressService = CasperAddressService(curve: .secp256k1) + + XCTAssertTrue(addressService.validate(address)) + } + +} diff --git a/BlockchainSdkTests/Extensions/TWPublicKeyType+.swift b/BlockchainSdkTests/Extensions/TWPublicKeyType+.swift index f027f9ee45..f88ac169d7 100644 --- a/BlockchainSdkTests/Extensions/TWPublicKeyType+.swift +++ b/BlockchainSdkTests/Extensions/TWPublicKeyType+.swift @@ -28,7 +28,8 @@ extension PublicKeyType { .radiant, .koinos, .filecoin, - .sei: + .sei, + .casper: self = PublicKeyType.secp256k1 case .ethereum, .bsc, diff --git a/Tangem/App/Services/ExchangeService/MercuryoService.swift b/Tangem/App/Services/ExchangeService/MercuryoService.swift index 73d3fdab8d..6ce2a9528a 100644 --- a/Tangem/App/Services/ExchangeService/MercuryoService.swift +++ b/Tangem/App/Services/ExchangeService/MercuryoService.swift @@ -282,7 +282,8 @@ private extension Blockchain { .sui, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: // Did you get a compilation error here? If so, check whether the network is supported at https://api.mercuryo.io/v1.6/lib/currencies return nil } diff --git a/Tangem/App/Services/ExchangeService/MoonPayService.swift b/Tangem/App/Services/ExchangeService/MoonPayService.swift index dd962a67ab..e43e0e8e52 100644 --- a/Tangem/App/Services/ExchangeService/MoonPayService.swift +++ b/Tangem/App/Services/ExchangeService/MoonPayService.swift @@ -390,6 +390,7 @@ private extension Blockchain { case .energyWebEVM: return nil case .energyWebX: return nil case .core: return nil + case .casper: return nil // Did you get a compilation error here? If so, check whether the network is supported at https://api.moonpay.com/v3/currencies } } @@ -470,6 +471,7 @@ private extension Blockchain { case .energyWebEVM: return nil case .energyWebX: return nil case .core: return nil + case .casper: return nil // Did you get a compilation error here? If so, check whether the network is supported at https://api.moonpay.com/v3/currencies } } diff --git a/Tangem/App/Utilities/CustomTokenContractAddressConverter.swift b/Tangem/App/Utilities/CustomTokenContractAddressConverter.swift index 988a49a87e..25ca84b988 100644 --- a/Tangem/App/Utilities/CustomTokenContractAddressConverter.swift +++ b/Tangem/App/Utilities/CustomTokenContractAddressConverter.swift @@ -105,7 +105,8 @@ struct CustomTokenContractAddressConverter { .sui, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: // Did you get a compilation error here? If so, check if the network supports multiple token contract address // formats (as Hedera does, for example) and add the appropriate conversion logic here if needed return originalAddress diff --git a/Tangem/App/Utilities/TokenInteractionAvailabilityProvider.swift b/Tangem/App/Utilities/TokenInteractionAvailabilityProvider.swift index 722e74a761..18abe0b065 100644 --- a/Tangem/App/Utilities/TokenInteractionAvailabilityProvider.swift +++ b/Tangem/App/Utilities/TokenInteractionAvailabilityProvider.swift @@ -104,7 +104,8 @@ struct TokenInteractionAvailabilityProvider { .sui, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: // Checking that we have at least one valid (non-empty) address // diff --git a/Tangem/Modules/Send/Services/TransactionParamsBuilder.swift b/Tangem/Modules/Send/Services/TransactionParamsBuilder.swift index 907e7321e1..d829b8cc2d 100644 --- a/Tangem/Modules/Send/Services/TransactionParamsBuilder.swift +++ b/Tangem/Modules/Send/Services/TransactionParamsBuilder.swift @@ -109,7 +109,8 @@ struct TransactionParamsBuilder { .sui, .energyWebEVM, .energyWebX, - .core: + .core, + .casper: throw TransactionParamsBuilderError.extraIdNotSupported } } diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index 6e929d01c7..7ca46e7ddb 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -52,6 +52,16 @@ 2D535E702A0CB4D20081EB76 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D535E6B2A0CB4D20081EB76 /* NotificationView.swift */; }; 2D535E722A0CB4D20081EB76 /* BottomSheetInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D535E6E2A0CB4D20081EB76 /* BottomSheetInfoView.swift */; }; 2D535E732A0CB4D20081EB76 /* BottomSheetInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D535E6F2A0CB4D20081EB76 /* BottomSheetInfoViewModel.swift */; }; + 2D554FA52CC761B5005C9C20 /* CasperWalletManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FA42CC761B5005C9C20 /* CasperWalletManager.swift */; }; + 2D554FA72CC761BF005C9C20 /* CasperWalletAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FA62CC761BF005C9C20 /* CasperWalletAssembly.swift */; }; + 2D554FAB2CC761D7005C9C20 /* CasperNetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FAA2CC761D7005C9C20 /* CasperNetworkProvider.swift */; }; + 2D554FAE2CC7735F005C9C20 /* CasperTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FAD2CC7735F005C9C20 /* CasperTarget.swift */; }; + 2D554FB02CC7797D005C9C20 /* CasperAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FAF2CC7797D005C9C20 /* CasperAddressService.swift */; }; + 2D554FB22CC79F0D005C9C20 /* CasperExternalLinkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FB12CC79F0D005C9C20 /* CasperExternalLinkProvider.swift */; }; + 2D554FB42CC82A6C005C9C20 /* CasperAddressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FB32CC82A6C005C9C20 /* CasperAddressUtils.swift */; }; + 2D554FB72CC82C23005C9C20 /* Blake2 in Frameworks */ = {isa = PBXBuildFile; productRef = 2D554FB62CC82C23005C9C20 /* Blake2 */; }; + 2D554FBD2CC8CD22005C9C20 /* CasperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FB92CC8CD1D005C9C20 /* CasperTests.swift */; }; + 2D554FC02CC9124C005C9C20 /* Byte+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D554FBE2CC8F4A6005C9C20 /* Byte+.swift */; }; 2D57CA862C3D0B0D0070D477 /* MarketsWalletDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D57CA852C3D0B0D0070D477 /* MarketsWalletDataSource.swift */; }; 2D57CA882C3D0BA30070D477 /* MarketsGeneratedAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D57CA872C3D0BA30070D477 /* MarketsGeneratedAddressView.swift */; }; 2D5DCA392BEA8584002D26AC /* WalletConnectCryptoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5DCA382BEA8584002D26AC /* WalletConnectCryptoProvider.swift */; }; @@ -2194,7 +2204,6 @@ DCAB5800295EE820005D0F4A /* AppLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCAB57FF295EE820005D0F4A /* AppLog.swift */; }; DCB616E52CB39AE100BE4481 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = DCB616E42CB39AE100BE4481 /* WalletConnect */; }; DCB616E72CB3A63800BE4481 /* ReownWalletKit in Frameworks */ = {isa = PBXBuildFile; productRef = DCB616E62CB3A63800BE4481 /* ReownWalletKit */; }; - DCB617762CB938AF00BE4481 /* ExpressProviderUpdateSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB617752CB938AF00BE4481 /* ExpressProviderUpdateSource.swift */; }; DCBAF6992A4AEEDD0029480A /* AnyWalletManagerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBAF6982A4AEEDD0029480A /* AnyWalletManagerFactory.swift */; }; DCBAF69B2A4AEF3C0029480A /* HDWalletManagerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBAF69A2A4AEF3C0029480A /* HDWalletManagerFactory.swift */; }; DCBAF69D2A4AF0500029480A /* SimpleWalletManagerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCBAF69C2A4AF0500029480A /* SimpleWalletManagerFactory.swift */; }; @@ -2978,6 +2987,15 @@ 2D535E6B2A0CB4D20081EB76 /* NotificationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = ""; }; 2D535E6E2A0CB4D20081EB76 /* BottomSheetInfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomSheetInfoView.swift; sourceTree = ""; }; 2D535E6F2A0CB4D20081EB76 /* BottomSheetInfoViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomSheetInfoViewModel.swift; sourceTree = ""; }; + 2D554FA42CC761B5005C9C20 /* CasperWalletManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperWalletManager.swift; sourceTree = ""; }; + 2D554FA62CC761BF005C9C20 /* CasperWalletAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperWalletAssembly.swift; sourceTree = ""; }; + 2D554FAA2CC761D7005C9C20 /* CasperNetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperNetworkProvider.swift; sourceTree = ""; }; + 2D554FAD2CC7735F005C9C20 /* CasperTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperTarget.swift; sourceTree = ""; }; + 2D554FAF2CC7797D005C9C20 /* CasperAddressService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressService.swift; sourceTree = ""; }; + 2D554FB12CC79F0D005C9C20 /* CasperExternalLinkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperExternalLinkProvider.swift; sourceTree = ""; }; + 2D554FB32CC82A6C005C9C20 /* CasperAddressUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressUtils.swift; sourceTree = ""; }; + 2D554FB92CC8CD1D005C9C20 /* CasperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperTests.swift; sourceTree = ""; }; + 2D554FBE2CC8F4A6005C9C20 /* Byte+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Byte+.swift"; sourceTree = ""; }; 2D57CA852C3D0B0D0070D477 /* MarketsWalletDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketsWalletDataSource.swift; sourceTree = ""; }; 2D57CA872C3D0BA30070D477 /* MarketsGeneratedAddressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketsGeneratedAddressView.swift; sourceTree = ""; }; 2D5DCA382BEA8584002D26AC /* WalletConnectCryptoProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletConnectCryptoProvider.swift; sourceTree = ""; }; @@ -5853,6 +5871,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2D554FB72CC82C23005C9C20 /* Blake2 in Frameworks */, B68E1F992CBC453E0043E598 /* IcpKit in Frameworks */, B68E1F8A2CBC44910043E598 /* Hedera in Frameworks */, B62D34472CBC51D400C2460E /* SwiftCBOR in Frameworks */, @@ -6026,6 +6045,36 @@ path = BottomSheetInfoView; sourceTree = ""; }; + 2D554FA32CC76188005C9C20 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D554FAF2CC7797D005C9C20 /* CasperAddressService.swift */, + 2D554FB32CC82A6C005C9C20 /* CasperAddressUtils.swift */, + 2D554FB12CC79F0D005C9C20 /* CasperExternalLinkProvider.swift */, + 2D554FAA2CC761D7005C9C20 /* CasperNetworkProvider.swift */, + 2D554FA62CC761BF005C9C20 /* CasperWalletAssembly.swift */, + 2D554FA42CC761B5005C9C20 /* CasperWalletManager.swift */, + 2D554FAC2CC7734D005C9C20 /* Network */, + ); + path = Casper; + sourceTree = ""; + }; + 2D554FAC2CC7734D005C9C20 /* Network */ = { + isa = PBXGroup; + children = ( + 2D554FAD2CC7735F005C9C20 /* CasperTarget.swift */, + ); + path = Network; + sourceTree = ""; + }; + 2D554FB82CC8CD0D005C9C20 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D554FB92CC8CD1D005C9C20 /* CasperTests.swift */, + ); + path = Casper; + sourceTree = ""; + }; 2D5DCC2B2C3309F1000EE379 /* TokensNetworkSelector */ = { isa = PBXGroup; children = ( @@ -10143,6 +10192,7 @@ B62D3C592CBC79D900C2460E /* Bitcoin */, B62D3C612CBC79D900C2460E /* BitcoinCash */, B62D3C7F2CBC79D900C2460E /* Cardano */, + 2D554FA32CC76188005C9C20 /* Casper */, B62D3C922CBC79D900C2460E /* Chia */, B62D3CA42CBC79D900C2460E /* Cosmos */, B62D3CA92CBC79D900C2460E /* Dash */, @@ -10648,11 +10698,10 @@ B62D3F942CBC79DA00C2460E /* Extensions */ = { isa = PBXGroup; children = ( - B62D3F762CBC79DA00C2460E /* Bech32 */, - B62D3F7A2CBC79DA00C2460E /* Moya+Combine */, B62D3F7B2CBC79DA00C2460E /* AnyPublisher+Async.swift */, B62D3F7C2CBC79DA00C2460E /* BigUInt+.swift */, B62D3F7D2CBC79DA00C2460E /* Bundle+.swift */, + 2D554FBE2CC8F4A6005C9C20 /* Byte+.swift */, B62D3F7E2CBC79DA00C2460E /* CBOR+.swift */, B62D3F7F2CBC79DA00C2460E /* Collection+.swift */, B62D3F802CBC79DA00C2460E /* Data+.swift */, @@ -10675,6 +10724,8 @@ B62D3F912CBC79DA00C2460E /* TWPublicKey+.swift */, B62D3F922CBC79DA00C2460E /* Uint64+.swift */, B62D3F932CBC79DA00C2460E /* URL+.swift */, + B62D3F762CBC79DA00C2460E /* Bech32 */, + B62D3F7A2CBC79DA00C2460E /* Moya+Combine */, ); path = Extensions; sourceTree = ""; @@ -11193,6 +11244,7 @@ B62D430D2CBC79E200C2460E /* Aptos */, B62D43172CBC79E300C2460E /* Bitcoin */, B62D432B2CBC79E300C2460E /* Cardano */, + 2D554FB82CC8CD0D005C9C20 /* Casper */, B62D432F2CBC79E400C2460E /* Chia */, B62D42F92CBC79E100C2460E /* Common */, B62D43132CBC79E300C2460E /* Cosmos */, @@ -14804,6 +14856,7 @@ B62D34462CBC51D400C2460E /* SwiftCBOR */, B62D344C2CBC675600C2460E /* stellarsdk */, B62D344F2CBC67D500C2460E /* AnyCodable */, + 2D554FB62CC82C23005C9C20 /* Blake2 */, ); productName = BlockchainSdk; productReference = B68E1F652CBC44050043E598 /* BlockchainSdk.framework */; @@ -15047,6 +15100,7 @@ B62D34452CBC51D400C2460E /* XCRemoteSwiftPackageReference "SwiftCBOR" */, B62D344B2CBC675600C2460E /* XCRemoteSwiftPackageReference "stellar-ios-mac-sdk" */, B62D344E2CBC67D500C2460E /* XCRemoteSwiftPackageReference "AnyCodable" */, + 2D554FB52CC82C23005C9C20 /* XCRemoteSwiftPackageReference "Blake2.swift" */, ); productRefGroup = 5D3F77C324BF56D800E8695B /* Products */; projectDirPath = ""; @@ -17380,6 +17434,7 @@ B62D403E2CBC79DA00C2460E /* AdaliteNetworkProvider.swift in Sources */, B62D41222CBC79DA00C2460E /* KoinosExternalLinkProvider.swift in Sources */, B62D425D2CBC79DB00C2460E /* BlockchainSdkDependencies.swift in Sources */, + 2D554FAB2CC761D7005C9C20 /* CasperNetworkProvider.swift in Sources */, B62D414D2CBC79DA00C2460E /* PolkadotTransaction.swift in Sources */, B62D42D92CBC79DB00C2460E /* String+.swift in Sources */, B62D42712CBC79DB00C2460E /* BitcoinTransactionFeeCalculator.swift in Sources */, @@ -17447,6 +17502,7 @@ B62D3FA12CBC79DA00C2460E /* AlgorandResponse+TransactionHistory.swift in Sources */, B62D42BC2CBC79DB00C2460E /* Wallet.swift in Sources */, B62D40892CBC79DA00C2460E /* ABIEncoder.swift in Sources */, + 2D554FB22CC79F0D005C9C20 /* CasperExternalLinkProvider.swift in Sources */, B62D41952CBC79DA00C2460E /* StellarExternalLinkProvider.swift in Sources */, B62D40AA2CBC79DA00C2460E /* DisChainExternalLinkProvider.swift in Sources */, B62D42082CBC79DB00C2460E /* XRPHistoricalTransaction.swift in Sources */, @@ -17612,6 +17668,7 @@ B62D41422CBC79DA00C2460E /* NEARNetworkService.swift in Sources */, B62D40102CBC79DA00C2460E /* OP_2OVER.swift in Sources */, B62D40A62CBC79DA00C2460E /* BSCExternalLinkProvider.swift in Sources */, + 2D554FC02CC9124C005C9C20 /* Byte+.swift in Sources */, B62D42A02CBC79DB00C2460E /* BaseManager.swift in Sources */, B62D421C2CBC79DB00C2460E /* XRPExternalLinkProvider.swift in Sources */, B62D41942CBC79DA00C2460E /* StellarAddressService.swift in Sources */, @@ -17633,6 +17690,7 @@ B62D40542CBC79DA00C2460E /* Chia+Int64.swift in Sources */, B62D406D2CBC79DA00C2460E /* CosmosRestProvider.swift in Sources */, B62D3FCD2CBC79DA00C2460E /* OP_ADD.swift in Sources */, + 2D554FA72CC761BF005C9C20 /* CasperWalletAssembly.swift in Sources */, B62D40E62CBC79DA00C2460E /* HederaNetworkResult.TransactionInfo.swift in Sources */, B62D428A2CBC79DB00C2460E /* TronTransactionHistoryProvider.swift in Sources */, B62D41922CBC79DA00C2460E /* SolanaWalletAssembly.swift in Sources */, @@ -17695,12 +17753,14 @@ B62D41D02CBC79DB00C2460E /* vote_asset_contract.pb.swift in Sources */, B62D42642CBC79DB00C2460E /* WalletFactory.swift in Sources */, B62D3FED2CBC79DA00C2460E /* OP_CHECKSIGVERIFY.swift in Sources */, + 2D554FB02CC7797D005C9C20 /* CasperAddressService.swift in Sources */, B62D40E02CBC79DA00C2460E /* HederaNetworkResult.AccountHbarBalance.swift in Sources */, B62D41562CBC79DA00C2460E /* SubscanAPIResult.ExtrinsicsList.swift in Sources */, B62D42492CBC79DB00C2460E /* DwellirAPIResolver.swift in Sources */, B62D3FF72CBC79DA00C2460E /* OP_NOP.swift in Sources */, B62D3FB12CBC79DA00C2460E /* AptosNetworkProvider.swift in Sources */, B62D40492CBC79DA00C2460E /* CardanoAssetFilter.swift in Sources */, + 2D554FA52CC761B5005C9C20 /* CasperWalletManager.swift in Sources */, B62D42632CBC79DB00C2460E /* TransactionHistoryProviderFactory.swift in Sources */, B62D426C2CBC79DB00C2460E /* MaximumAmountRestrictable.swift in Sources */, B62D40362CBC79DA00C2460E /* BitcoinCashNetworkService.swift in Sources */, @@ -17890,6 +17950,7 @@ B62D41E52CBC79DB00C2460E /* TronWalletManager.swift in Sources */, B62D41442CBC79DA00C2460E /* NEARAddressService.swift in Sources */, B62D421F2CBC79DB00C2460E /* XrpResponse.swift in Sources */, + 2D554FB42CC82A6C005C9C20 /* CasperAddressUtils.swift in Sources */, B62D42D82CBC79DB00C2460E /* Sequence+.swift in Sources */, B62D40262CBC79DA00C2460E /* OpCodeFactory.swift in Sources */, B62D3FBF2CBC79DA00C2460E /* BinanceWalletManager.swift in Sources */, @@ -18046,6 +18107,7 @@ B62D40F82CBC79DA00C2460E /* ICPNetworkService.swift in Sources */, B62D40D92CBC79DA00C2460E /* FilecoinWalletManager.swift in Sources */, B62D41052CBC79DA00C2460E /* KaspaAPIResolver.swift in Sources */, + 2D554FAE2CC7735F005C9C20 /* CasperTarget.swift in Sources */, B62D41802CBC79DA00C2460E /* RavencoinNetworkProvider.swift in Sources */, B62D42482CBC79DB00C2460E /* APIResolver.swift in Sources */, B62D42692CBC79DB00C2460E /* CardanoTransferRestrictable.swift in Sources */, @@ -18150,6 +18212,7 @@ B62D435E2CBC79E400C2460E /* KoinosTransactionBuilderTests.swift in Sources */, B62D43672CBC79E400C2460E /* XCTAssert+.swift in Sources */, B62D43402CBC79E400C2460E /* AddressTests.swift in Sources */, + 2D554FBD2CC8CD22005C9C20 /* CasperTests.swift in Sources */, B62D43482CBC79E400C2460E /* TransactionSizeTesterUtility.swift in Sources */, B62D435F2CBC79E400C2460E /* KoinosWalletManagerTests.swift in Sources */, B62D434B2CBC79E400C2460E /* BlockchainCodingKeyTests.swift in Sources */, @@ -25838,6 +25901,14 @@ minimumVersion = 1.1.0; }; }; + 2D554FB52CC82C23005C9C20 /* XCRemoteSwiftPackageReference "Blake2.swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/tesseract-one/Blake2.swift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.2.0; + }; + }; B0B11A062C787FE70018A2A6 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/gonzalezreal/swift-markdown-ui"; @@ -25971,6 +26042,11 @@ package = 0ABC61132C410AFD00065EBA /* XCRemoteSwiftPackageReference "tweetnacl-swiftwrap" */; productName = TweetNacl; }; + 2D554FB62CC82C23005C9C20 /* Blake2 */ = { + isa = XCSwiftPackageProductDependency; + package = 2D554FB52CC82C23005C9C20 /* XCRemoteSwiftPackageReference "Blake2.swift" */; + productName = Blake2; + }; B0B11A072C787FE70018A2A6 /* MarkdownUI */ = { isa = XCSwiftPackageProductDependency; package = B0B11A062C787FE70018A2A6 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */; diff --git a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved index e32cbce5cd..0fcbdbf6bf 100644 --- a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "4e1b69c9c30f370afdaa78e05da89f70ae6c42d2fd2679b81d83f0e75a92937a", + "originHash" : "f9d3700ee836f1f7a8ded2f7e98a15a7155ef6acb3b115c4f3291b9b8f046f19", "pins" : [ { "identity" : "anyasyncsequence", @@ -37,6 +37,15 @@ "version" : "5.3.0" } }, + { + "identity" : "blake2.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tesseract-one/Blake2.swift.git", + "state" : { + "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", + "version" : "0.2.0" + } + }, { "identity" : "cryptoswift", "kind" : "remoteSourceControl", From e8fd34afec4442b4a2c8d8133eeb3088ec4a8caa Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Fri, 25 Oct 2024 12:03:06 +0300 Subject: [PATCH 02/10] IOS-8332 Make correct flow make address for casper --- .../Casper/CasperAddressService.swift | 9 ++- .../Casper/CasperAddressUtils.swift | 74 ++--------------- .../{ => Network}/CasperNetworkProvider.swift | 2 +- .../Casper/Network/CasperTarget.swift | 6 ++ TangemApp.xcodeproj/project.pbxproj | 81 ++++++++++++++++++- .../xcshareddata/swiftpm/Package.resolved | 11 ++- 6 files changed, 109 insertions(+), 74 deletions(-) rename BlockchainSdk/Blockchains/Casper/{ => Network}/CasperNetworkProvider.swift (88%) diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift index 8eeed61040..4d3bbb3fad 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift @@ -39,7 +39,14 @@ extension CasperAddressService: AddressProvider { extension CasperAddressService: AddressValidator { public func validate(_ address: String) -> Bool { - return false + let isCorrectEd25519Address = address.count == Constants.lengthED25519 && address.hasPrefix(Constants.prefixED25519) + let isCorrectSecp256k1Address = address.count == Constants.lengthSECP256K1 && address.hasPrefix(Constants.prefixSECP256K1) + + guard isCorrectEd25519Address || isCorrectSecp256k1Address else { + return false + } + + return true } } diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift index 238c0f0cb5..4047544475 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift @@ -50,43 +50,32 @@ struct CasperAddressUtils { private func encode(input: [UInt8]) throws -> String { let inputNibbles = bytesToNibbles(bytes: input) - - print(inputNibbles.toHexString()) - let hash = try byteHash(bytes: input) - print(hash.toHexString()) - // Separate bytes inside ByteArray to bits array // E.g. [0x01, ...] -> [false, false, false, false, false, false, false, true, ...] // E.g. [0xAA, ...] -> [true, false, true, false, true, false, true, false, ...] let hashBits = hash.toBitArray().map { $0.boolValue } - print(hashBits) - var hashBitsValues = hashBits.makeIterator() - print(hashBitsValues) - let result: String = inputNibbles.reduce(into: "") { partialResult, nibbleByte in - let char = nibbleByte.hexString + let char = String(format: "%X", nibbleByte) - if char.range(of: "[^a-zA-Z0-9-]", options: .regularExpression) == nil, hashBitsValues.next() ?? false { - partialResult.append(char.lowercased()) - } else { + if char.range(of: Constants.regexEncodeByte, options: .regularExpression) != nil, hashBitsValues.next() ?? false { partialResult.append(char.uppercased()) + } else { + partialResult.append(char.lowercased()) } } - print(result) - return result } } extension CasperAddressUtils { enum Constants { - static let regexEncodeByte = try! NSRegularExpression(pattern: "^[a-zA-Z()]") + static let regexEncodeByte = "^[a-zA-Z()]+" } enum Error: LocalizedError { @@ -94,56 +83,3 @@ extension CasperAddressUtils { case failedHashBlake2b } } - -/* -/** - * @see Source - */ -object CasperAddressUtils { - // Ed25519: encode([0x01]) + encode() - // or - // Secp256k1: encode([0x02]) + encode() - fun ByteArray.checksum(): String = encode(byteArrayOf(first())) + encode(drop(1).toByteArray()) - - // Separate bytes inside ByteArray to nibbles - // E.g. [0x01, 0x55, 0xFF, ...] -> [0x00, 0x01, 0x50, 0x05, 0xF0, 0x0F, ...] - @Suppress("MagicNumber") - private fun bytesToNibbles(bytes: ByteArray): ByteArray = bytes - .flatMap { byte -> - listOf( - (byte.toInt() and 0xff shr 4).toByte(), - (byte.toInt() and 0x0f).toByte(), - ) - }.toByteArray() - - // Separate bytes inside ByteArray to bits array - // E.g. [0x01, ...] -> [false, false, false, false, false, false, false, true, ...] - // E.g. [0xAA, ...] -> [true, false, true, false, true, false, true, false, ...] - @Suppress("MagicNumber") - private fun ByteArray.toBitArray(): BooleanArray = this - .flatMap { byte -> - List(8) { i -> - byte.toInt() shr i and 0x01 == 0x01 - } - }.toBooleanArray() - - private fun byteHash(bytes: ByteArray): ByteArray = Blake2b.Blake2b256().digest(bytes) - - private fun encode(input: ByteArray): String { - val inputNibbles = bytesToNibbles(input) - val hash = byteHash(input) - val hashBits = hash.toBitArray() - val hashBitsValues = hashBits.iterator() - return inputNibbles.fold(StringBuilder()) { accum, nibble -> - val c = "%x".format(nibble) - - if (Regex("^[a-zA-Z()]+\$").matches(c) && hashBitsValues.hasNext() && hashBitsValues.next()) { - accum.append(c.uppercase()) - } else { - accum.append(c.lowercase()) - } - accum - }.toString() - } -} -*/ diff --git a/BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift b/BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift similarity index 88% rename from BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift rename to BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift index 9fba71cd2a..8c0a82e6c5 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperNetworkProvider.swift +++ b/BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift @@ -29,7 +29,7 @@ final class CasperNetworkProvider: HostProvider { // MARK: - Private Implementation - private func requestPublisher(for target: FilecoinTarget.FilecoinTargetType) -> AnyPublisher { + private func requestPublisher(for target: CasperTarget.TargetType) -> AnyPublisher { provider.requestPublisher(CasperTarget(node: node)) .filterSuccessfulStatusAndRedirectCodes() .map(JSONRPC.Response.self) diff --git a/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift b/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift index 71d893fffe..b5841cfa68 100644 --- a/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift +++ b/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift @@ -42,3 +42,9 @@ struct CasperTarget: TargetType { var headers: [String : String]? } + +// MARK: - TargetType + +extension CasperTarget { + enum TargetType {} +} diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index 5fe931400f..10b918a2a5 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -67,6 +67,16 @@ 2D61671E2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61671D2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift */; }; 2D6167202C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61671F2C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift */; }; 2D6167222C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6167212C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift */; }; + 2D66B6FE2CCAB074009EDD04 /* CasperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D66B6FC2CCAB074009EDD04 /* CasperTests.swift */; }; + 2D66B7012CCAB27A009EDD04 /* Blake2 in Frameworks */ = {isa = PBXBuildFile; productRef = 2D66B7002CCAB27A009EDD04 /* Blake2 */; }; + 2D66B7032CCAB2CD009EDD04 /* Byte+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D66B7022CCAB2CD009EDD04 /* Byte+.swift */; }; + 2D6BFF152CCAAE7D001BBAC4 /* CasperTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF0C2CCAAE7D001BBAC4 /* CasperTarget.swift */; }; + 2D6BFF162CCAAE7D001BBAC4 /* CasperAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF0E2CCAAE7D001BBAC4 /* CasperAddressService.swift */; }; + 2D6BFF172CCAAE7D001BBAC4 /* CasperAddressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF0F2CCAAE7D001BBAC4 /* CasperAddressUtils.swift */; }; + 2D6BFF182CCAAE7D001BBAC4 /* CasperExternalLinkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF102CCAAE7D001BBAC4 /* CasperExternalLinkProvider.swift */; }; + 2D6BFF192CCAAE7D001BBAC4 /* CasperNetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF112CCAAE7D001BBAC4 /* CasperNetworkProvider.swift */; }; + 2D6BFF1A2CCAAE7D001BBAC4 /* CasperWalletAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF122CCAAE7D001BBAC4 /* CasperWalletAssembly.swift */; }; + 2D6BFF1B2CCAAE7D001BBAC4 /* CasperWalletManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6BFF132CCAAE7D001BBAC4 /* CasperWalletManager.swift */; }; 2D70C61D2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D70C61B2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift */; }; 2DA8AB122A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA8AB112A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift */; }; 2DB3614B2C14FBAB00BB1D38 /* SegmentedPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3614A2C14FBAB00BB1D38 /* SegmentedPickerView.swift */; }; @@ -2985,6 +2995,15 @@ 2D61671D2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokensNetworkRoutable.swift; sourceTree = ""; }; 2D61671F2C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinator.swift; sourceTree = ""; }; 2D6167212C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinatorView.swift; sourceTree = ""; }; + 2D66B6FC2CCAB074009EDD04 /* CasperTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperTests.swift; sourceTree = ""; }; + 2D66B7022CCAB2CD009EDD04 /* Byte+.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Byte+.swift"; sourceTree = ""; }; + 2D6BFF0C2CCAAE7D001BBAC4 /* CasperTarget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperTarget.swift; sourceTree = ""; }; + 2D6BFF0E2CCAAE7D001BBAC4 /* CasperAddressService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperAddressService.swift; sourceTree = ""; }; + 2D6BFF0F2CCAAE7D001BBAC4 /* CasperAddressUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperAddressUtils.swift; sourceTree = ""; }; + 2D6BFF102CCAAE7D001BBAC4 /* CasperExternalLinkProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperExternalLinkProvider.swift; sourceTree = ""; }; + 2D6BFF112CCAAE7D001BBAC4 /* CasperNetworkProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperNetworkProvider.swift; sourceTree = ""; }; + 2D6BFF122CCAAE7D001BBAC4 /* CasperWalletAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperWalletAssembly.swift; sourceTree = ""; }; + 2D6BFF132CCAAE7D001BBAC4 /* CasperWalletManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CasperWalletManager.swift; sourceTree = ""; }; 2D70C61B2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketsAddCustomItemView.swift; sourceTree = ""; }; 2D788E7F2ADD657000E0884B /* WalletSelectorViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletSelectorViewModel.swift; sourceTree = ""; }; 2D788E822ADD657000E0884B /* WalletSelectorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletSelectorView.swift; sourceTree = ""; }; @@ -5857,6 +5876,7 @@ B6C0D3F62CBDC552001113ED /* BinanceChain in Frameworks */, B68E1F962CBC451D0043E598 /* ScaleCodec in Frameworks */, B62D34502CBC67D500C2460E /* AnyCodable in Frameworks */, + 2D66B7012CCAB27A009EDD04 /* Blake2 in Frameworks */, B68E1F8D2CBC44AA0043E598 /* CryptoSwift in Frameworks */, B6C0D3F42CBDC543001113ED /* Moya in Frameworks */, B68E1F932CBC44FF0043E598 /* TonSwift in Frameworks */, @@ -6039,6 +6059,36 @@ path = WalletSelectorItemView; sourceTree = ""; }; + 2D66B6FD2CCAB074009EDD04 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D66B6FC2CCAB074009EDD04 /* CasperTests.swift */, + ); + path = Casper; + sourceTree = ""; + }; + 2D6BFF0D2CCAAE7D001BBAC4 /* Network */ = { + isa = PBXGroup; + children = ( + 2D6BFF112CCAAE7D001BBAC4 /* CasperNetworkProvider.swift */, + 2D6BFF0C2CCAAE7D001BBAC4 /* CasperTarget.swift */, + ); + path = Network; + sourceTree = ""; + }; + 2D6BFF142CCAAE7D001BBAC4 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D6BFF0D2CCAAE7D001BBAC4 /* Network */, + 2D6BFF0E2CCAAE7D001BBAC4 /* CasperAddressService.swift */, + 2D6BFF0F2CCAAE7D001BBAC4 /* CasperAddressUtils.swift */, + 2D6BFF102CCAAE7D001BBAC4 /* CasperExternalLinkProvider.swift */, + 2D6BFF122CCAAE7D001BBAC4 /* CasperWalletAssembly.swift */, + 2D6BFF132CCAAE7D001BBAC4 /* CasperWalletManager.swift */, + ); + path = Casper; + sourceTree = ""; + }; 2D788E7E2ADD657000E0884B /* WalletSelector */ = { isa = PBXGroup; children = ( @@ -10131,6 +10181,7 @@ B62D3C592CBC79D900C2460E /* Bitcoin */, B62D3C612CBC79D900C2460E /* BitcoinCash */, B62D3C7F2CBC79D900C2460E /* Cardano */, + 2D6BFF142CCAAE7D001BBAC4 /* Casper */, B62D3C922CBC79D900C2460E /* Chia */, B62D3CA42CBC79D900C2460E /* Cosmos */, B62D3CA92CBC79D900C2460E /* Dash */, @@ -10636,11 +10687,10 @@ B62D3F942CBC79DA00C2460E /* Extensions */ = { isa = PBXGroup; children = ( - B62D3F762CBC79DA00C2460E /* Bech32 */, - B62D3F7A2CBC79DA00C2460E /* Moya+Combine */, B62D3F7B2CBC79DA00C2460E /* AnyPublisher+Async.swift */, B62D3F7C2CBC79DA00C2460E /* BigUInt+.swift */, B62D3F7D2CBC79DA00C2460E /* Bundle+.swift */, + 2D66B7022CCAB2CD009EDD04 /* Byte+.swift */, B62D3F7E2CBC79DA00C2460E /* CBOR+.swift */, B62D3F7F2CBC79DA00C2460E /* Collection+.swift */, B62D3F802CBC79DA00C2460E /* Data+.swift */, @@ -10663,6 +10713,8 @@ B62D3F912CBC79DA00C2460E /* TWPublicKey+.swift */, B62D3F922CBC79DA00C2460E /* Uint64+.swift */, B62D3F932CBC79DA00C2460E /* URL+.swift */, + B62D3F762CBC79DA00C2460E /* Bech32 */, + B62D3F7A2CBC79DA00C2460E /* Moya+Combine */, ); path = Extensions; sourceTree = ""; @@ -11181,6 +11233,7 @@ B62D430D2CBC79E200C2460E /* Aptos */, B62D43172CBC79E300C2460E /* Bitcoin */, B62D432B2CBC79E300C2460E /* Cardano */, + 2D66B6FD2CCAB074009EDD04 /* Casper */, B62D432F2CBC79E400C2460E /* Chia */, B62D42F92CBC79E100C2460E /* Common */, B62D43132CBC79E300C2460E /* Cosmos */, @@ -14780,6 +14833,7 @@ B6C0D3F32CBDC543001113ED /* Moya */, B6C0D3F52CBDC552001113ED /* BinanceChain */, B6C0D3F82CBDC5A3001113ED /* SwiftyJSON */, + 2D66B7002CCAB27A009EDD04 /* Blake2 */, ); productName = BlockchainSdk; productReference = B68E1F652CBC44050043E598 /* BlockchainSdk.framework */; @@ -14992,6 +15046,7 @@ B6C0D3F02CBDC52D001113ED /* XCRemoteSwiftPackageReference "Moya" */, B6C0D3F72CBDC5A3001113ED /* XCRemoteSwiftPackageReference "SwiftyJSON" */, B62C16772CBE095A00522683 /* XCRemoteSwiftPackageReference "Alamofire" */, + 2D66B6FF2CCAB27A009EDD04 /* XCRemoteSwiftPackageReference "Blake2.swift" */, ); productRefGroup = 5D3F77C324BF56D800E8695B /* Products */; projectDirPath = ""; @@ -17259,6 +17314,7 @@ B62D402C2CBC79DA00C2460E /* BitcoinExternalLinkProvider.swift in Sources */, B62D40282CBC79DA00C2460E /* ScriptChunkHelper.swift in Sources */, B62D41B42CBC79DB00C2460E /* TezosTransactionBuilder.swift in Sources */, + 2D6BFF1B2CCAAE7D001BBAC4 /* CasperWalletManager.swift in Sources */, B62D41212CBC79DA00C2460E /* KoinosAPIResolver.swift in Sources */, B62D40112CBC79DA00C2460E /* OP_2ROT.swift in Sources */, B62D40212CBC79DA00C2460E /* OP_EXAMPLE.swift in Sources */, @@ -17292,6 +17348,7 @@ B62D422B2CBC79DB00C2460E /* BlockBookResponses.swift in Sources */, B62D3F982CBC79DA00C2460E /* AlgorandTransactionParams.swift in Sources */, B62D3FB32CBC79DA00C2460E /* AptosAddressService.swift in Sources */, + 2D6BFF162CCAAE7D001BBAC4 /* CasperAddressService.swift in Sources */, B62D40612CBC79DA00C2460E /* ChiaTransactionBuilder.swift in Sources */, B62D40B32CBC79DA00C2460E /* MantaExternalLinkProvider.swift in Sources */, B62D42232CBC79DB00C2460E /* XRPWalletAssembly.swift in Sources */, @@ -17407,6 +17464,7 @@ B62D40DB2CBC79DA00C2460E /* HederaAccountInfo.swift in Sources */, B62D42AF2CBC79DB00C2460E /* FeeResourceType.swift in Sources */, B62D41402CBC79DA00C2460E /* NEARNetworkResult.TransactionStatus.swift in Sources */, + 2D6BFF1A2CCAAE7D001BBAC4 /* CasperWalletAssembly.swift in Sources */, B62D41272CBC79DA00C2460E /* LitecoinNetworkParams.swift in Sources */, B62D40422CBC79DA00C2460E /* RosettaData.swift in Sources */, B62D3FBE2CBC79DA00C2460E /* BinanceWalletAssembly.swift in Sources */, @@ -17427,6 +17485,7 @@ B62D42372CBC79DB00C2460E /* ElectrumDTO.swift in Sources */, B62D402E2CBC79DA00C2460E /* BitcoinModels.swift in Sources */, B62D40F92CBC79DA00C2460E /* ICPProviderTarget.swift in Sources */, + 2D6BFF152CCAAE7D001BBAC4 /* CasperTarget.swift in Sources */, B62D42742CBC79DB00C2460E /* TransactionFeeProvider.swift in Sources */, B62D42CB2CBC79DB00C2460E /* Data+.swift in Sources */, B62D42112CBC79DB00C2460E /* SigningAlgorithm.swift in Sources */, @@ -17516,6 +17575,7 @@ B62D42352CBC79DB00C2460E /* BlockcypherTarget.swift in Sources */, B62D418C2CBC79DA00C2460E /* SolanaFeeParameters.swift in Sources */, B62D41422CBC79DA00C2460E /* NEARNetworkService.swift in Sources */, + 2D66B7032CCAB2CD009EDD04 /* Byte+.swift in Sources */, B62D40102CBC79DA00C2460E /* OP_2OVER.swift in Sources */, B62D40A62CBC79DA00C2460E /* BSCExternalLinkProvider.swift in Sources */, B62D42A02CBC79DB00C2460E /* BaseManager.swift in Sources */, @@ -17662,6 +17722,7 @@ B62D3FAD2CBC79DA00C2460E /* AptosFeeParams.swift in Sources */, B62D41162CBC79DA00C2460E /* KoinosNetworkService.swift in Sources */, B62D42272CBC79DB00C2460E /* BlockBookConfig.swift in Sources */, + 2D6BFF182CCAAE7D001BBAC4 /* CasperExternalLinkProvider.swift in Sources */, B62D423C2CBC79DB00C2460E /* Address.swift in Sources */, B62D42BA2CBC79DB00C2460E /* TransactionSendResult.swift in Sources */, B62D41EE2CBC79DB00C2460E /* VeChainNetworkParams.TransactionStatus.swift in Sources */, @@ -17823,6 +17884,7 @@ B62D42562CBC79DB00C2460E /* DerivationConfigV2.swift in Sources */, B62D42662CBC79DB00C2460E /* ExistentialDepositProvider.swift in Sources */, B62D41C92CBC79DB00C2460E /* common.pb.swift in Sources */, + 2D6BFF192CCAAE7D001BBAC4 /* CasperNetworkProvider.swift in Sources */, B62D3FF62CBC79DA00C2460E /* OP_IF.swift in Sources */, B62D428D2CBC79DB00C2460E /* BlockBookTransactionHistoryTotalPageCountExtractor.swift in Sources */, B62D41872CBC79DA00C2460E /* SolanaAddressService.swift in Sources */, @@ -17855,6 +17917,7 @@ B62D410E2CBC79DA00C2460E /* KoinosDTOMapper.swift in Sources */, B62D40452CBC79DA00C2460E /* RosettaTarget.swift in Sources */, B62D3FAE2CBC79DA00C2460E /* AptosTransactionInfo.swift in Sources */, + 2D6BFF172CCAAE7D001BBAC4 /* CasperAddressUtils.swift in Sources */, B62D40952CBC79DA00C2460E /* EthereumNetworkProvider.swift in Sources */, B62D42822CBC79DB00C2460E /* EthereumTransactionHistoryMapper.swift in Sources */, B62D41CA2CBC79DB00C2460E /* exchange_contract.pb.swift in Sources */, @@ -18056,6 +18119,7 @@ B62D435E2CBC79E400C2460E /* KoinosTransactionBuilderTests.swift in Sources */, B62D43672CBC79E400C2460E /* XCTAssert+.swift in Sources */, B62D43402CBC79E400C2460E /* AddressTests.swift in Sources */, + 2D66B6FE2CCAB074009EDD04 /* CasperTests.swift in Sources */, B62D43482CBC79E400C2460E /* TransactionSizeTesterUtility.swift in Sources */, B62D435F2CBC79E400C2460E /* KoinosWalletManagerTests.swift in Sources */, B62D434B2CBC79E400C2460E /* BlockchainCodingKeyTests.swift in Sources */, @@ -24618,6 +24682,14 @@ minimumVersion = 1.1.0; }; }; + 2D66B6FF2CCAB27A009EDD04 /* XCRemoteSwiftPackageReference "Blake2.swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/tesseract-one/Blake2.swift.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.2.0; + }; + }; B0B11A062C787FE70018A2A6 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/gonzalezreal/swift-markdown-ui"; @@ -24783,6 +24855,11 @@ package = 0ABC61132C410AFD00065EBA /* XCRemoteSwiftPackageReference "tweetnacl-swiftwrap" */; productName = TweetNacl; }; + 2D66B7002CCAB27A009EDD04 /* Blake2 */ = { + isa = XCSwiftPackageProductDependency; + package = 2D66B6FF2CCAB27A009EDD04 /* XCRemoteSwiftPackageReference "Blake2.swift" */; + productName = Blake2; + }; B0B11A072C787FE70018A2A6 /* MarkdownUI */ = { isa = XCSwiftPackageProductDependency; package = B0B11A062C787FE70018A2A6 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */; diff --git a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7d0bac80d3..787c39eb96 100644 --- a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "02f9726bb29f3b4a5b80be95a438cf6549b3f8295494cffb8be5ea7f235aed48", + "originHash" : "2128558e1d1243c6cc9ff15d560f477124f9ab89eb2561c6fb3404169a8ee99e", "pins" : [ { "identity" : "alamofire", @@ -46,6 +46,15 @@ "version" : "5.3.0" } }, + { + "identity" : "blake2.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tesseract-one/Blake2.swift.git", + "state" : { + "revision" : "29c55c8fe42d6661e5a32cc5bbbad1fff64fd01e", + "version" : "0.2.0" + } + }, { "identity" : "cryptoswift", "kind" : "remoteSourceControl", From 33199a7fea992ceead5679525db6168584935a17 Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 29 Oct 2024 19:47:43 +0300 Subject: [PATCH 03/10] IOS-8332 Make merge with last develop --- .../Casper/CasperAddressUtils.swift | 3 +- .../Casper/CasperWalletAssembly.swift | 14 +- BlockchainSdk/Common/Blockchain.swift | 4 +- TangemApp.xcodeproj/project.pbxproj | 79 ++- .../xcshareddata/swiftpm/Package.resolved | 483 ++++++++++++++++++ 5 files changed, 548 insertions(+), 35 deletions(-) create mode 100644 TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift index 23dcefe483..3a61942e3a 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressUtils.swift @@ -7,7 +7,6 @@ // import Foundation -import Blake2 /* https://github.com/casper-ecosystem/casper-js-sdk/blob/dev/src/lib/ChecksummedHex.ts @@ -41,7 +40,7 @@ struct CasperAddressUtils { } private func byteHash(bytes: [UInt8]) throws -> [UInt8] { - guard let hashData = try? Blake2b.hash(size: 32, data: bytes) else { + guard let hashData = Data(bytes).hashBlake2b(outputLength: 32) else { throw Error.failedHashBlake2b } return hashData.bytes diff --git a/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift b/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift index b2637ded6c..906cafac57 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperWalletAssembly.swift @@ -10,18 +10,6 @@ import Foundation struct CasperWalletAssembly: WalletManagerAssembly { func make(with input: WalletManagerAssemblyInput) throws -> WalletManager { - FilecoinWalletManager( - wallet: input.wallet, - networkService: FilecoinNetworkService( - providers: APIResolver(blockchain: input.blockchain, config: input.blockchainSdkConfig) - .resolveProviders(apiInfos: input.apiInfo) { nodeInfo, _ in - FilecoinNetworkProvider( - node: nodeInfo, - configuration: input.networkConfig - ) - } - ), - transactionBuilder: try FilecoinTransactionBuilder(publicKey: input.wallet.publicKey) - ) + CasperWalletManager(wallet: input.wallet) } } diff --git a/BlockchainSdk/Common/Blockchain.swift b/BlockchainSdk/Common/Blockchain.swift index 4455a769a7..5da785dcdb 100644 --- a/BlockchainSdk/Common/Blockchain.swift +++ b/BlockchainSdk/Common/Blockchain.swift @@ -91,6 +91,7 @@ public indirect enum Blockchain: Equatable, Hashable { /// Polkadot parachain case energyWebX(curve: EllipticCurve) case core(testnet: Bool) + case casper(testnet: Bool) public var isTestnet: Bool { switch self { @@ -134,7 +135,8 @@ public indirect enum Blockchain: Equatable, Hashable { .sei(let testnet), .kaspa(let testnet), .energyWebEVM(let testnet), - .core(let testnet): + .core(let testnet), + .casper(let testnet): return testnet case .litecoin, .ducatus, diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index 2c982b7abf..dd36df8276 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -65,6 +65,15 @@ 2D61671E2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61671D2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift */; }; 2D6167202C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D61671F2C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift */; }; 2D6167222C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D6167212C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift */; }; + 2D616FEC2CD1414000581EA6 /* CasperNetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */; }; + 2D616FED2CD1414000581EA6 /* CasperWalletManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FEA2CD1414000581EA6 /* CasperWalletManager.swift */; }; + 2D616FEE2CD1414000581EA6 /* CasperAddressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */; }; + 2D616FEF2CD1414000581EA6 /* CasperAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */; }; + 2D616FF02CD1414000581EA6 /* CasperExternalLinkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE82CD1414000581EA6 /* CasperExternalLinkProvider.swift */; }; + 2D616FF12CD1414000581EA6 /* CasperWalletAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE92CD1414000581EA6 /* CasperWalletAssembly.swift */; }; + 2D616FF22CD1414000581EA6 /* CasperTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE42CD1414000581EA6 /* CasperTarget.swift */; }; + 2D616FF42CD1421000581EA6 /* Byte+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FF32CD1421000581EA6 /* Byte+.swift */; }; + 2D616FF72CD142BE00581EA6 /* CasperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FF52CD142BE00581EA6 /* CasperTests.swift */; }; 2D70C61D2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D70C61B2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift */; }; 2DA8AB122A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA8AB112A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift */; }; 2DB3614B2C14FBAB00BB1D38 /* SegmentedPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3614A2C14FBAB00BB1D38 /* SegmentedPickerView.swift */; }; @@ -2707,10 +2716,6 @@ EFD68F392CC3D7DE00693C97 /* ExpressDTO+Swap.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F382CC3D7DB00693C97 /* ExpressDTO+Swap.swift */; }; EFD68F3B2CC3D7E600693C97 /* ExpressDTO+Onramp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F3A2CC3D7E300693C97 /* ExpressDTO+Onramp.swift */; }; EFD68F3F2CC3E5C700693C97 /* OnrampRedirectSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F3E2CC3E5C600693C97 /* OnrampRedirectSettings.swift */; }; - EFD68F302CC2D02500693C97 /* OnrampCountryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F2F2CC2D02300693C97 /* OnrampCountryView.swift */; }; - EFD68F322CC2D04500693C97 /* OnrampCountryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F312CC2D04400693C97 /* OnrampCountryViewModel.swift */; }; - EFD68F342CC2D29C00693C97 /* OnrampCountryRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F332CC2D29700693C97 /* OnrampCountryRoutable.swift */; }; - EFD68F372CC2F58900693C97 /* OnrampIdentityMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFD68F362CC2F58000693C97 /* OnrampIdentityMock.swift */; }; EFDD6EDD2CBCF3EA00804205 /* ExpressProviderUpdateSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFDD6EDC2CBCF3EA00804205 /* ExpressProviderUpdateSource.swift */; }; EFE1812B292E30C00072D80C /* SupportChatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C9FCB92869CC3E00FDE63E /* SupportChatViewModel.swift */; }; EFE1812C292E30DF0072D80C /* OnboardingCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0E1565126B97F8C005B33E4 /* OnboardingCardView.swift */; }; @@ -3002,6 +3007,15 @@ 2D61671D2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokensNetworkRoutable.swift; sourceTree = ""; }; 2D61671F2C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinator.swift; sourceTree = ""; }; 2D6167212C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinatorView.swift; sourceTree = ""; }; + 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperNetworkProvider.swift; sourceTree = ""; }; + 2D616FE42CD1414000581EA6 /* CasperTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperTarget.swift; sourceTree = ""; }; + 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressService.swift; sourceTree = ""; }; + 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressUtils.swift; sourceTree = ""; }; + 2D616FE82CD1414000581EA6 /* CasperExternalLinkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperExternalLinkProvider.swift; sourceTree = ""; }; + 2D616FE92CD1414000581EA6 /* CasperWalletAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperWalletAssembly.swift; sourceTree = ""; }; + 2D616FEA2CD1414000581EA6 /* CasperWalletManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperWalletManager.swift; sourceTree = ""; }; + 2D616FF32CD1421000581EA6 /* Byte+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Byte+.swift"; sourceTree = ""; }; + 2D616FF52CD142BE00581EA6 /* CasperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperTests.swift; sourceTree = ""; }; 2D70C61B2B21E90A00BD1DAB /* MarketsAddCustomItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarketsAddCustomItemView.swift; sourceTree = ""; }; 2D788E7F2ADD657000E0884B /* WalletSelectorViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletSelectorViewModel.swift; sourceTree = ""; }; 2D788E822ADD657000E0884B /* WalletSelectorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletSelectorView.swift; sourceTree = ""; }; @@ -5694,10 +5708,6 @@ EFD68F382CC3D7DB00693C97 /* ExpressDTO+Swap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ExpressDTO+Swap.swift"; sourceTree = ""; }; EFD68F3A2CC3D7E300693C97 /* ExpressDTO+Onramp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ExpressDTO+Onramp.swift"; sourceTree = ""; }; EFD68F3E2CC3E5C600693C97 /* OnrampRedirectSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampRedirectSettings.swift; sourceTree = ""; }; - EFD68F2F2CC2D02300693C97 /* OnrampCountryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampCountryView.swift; sourceTree = ""; }; - EFD68F312CC2D04400693C97 /* OnrampCountryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampCountryViewModel.swift; sourceTree = ""; }; - EFD68F332CC2D29700693C97 /* OnrampCountryRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampCountryRoutable.swift; sourceTree = ""; }; - EFD68F362CC2F58000693C97 /* OnrampIdentityMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampIdentityMock.swift; sourceTree = ""; }; EFDD6EDC2CBCF3EA00804205 /* ExpressProviderUpdateSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpressProviderUpdateSource.swift; sourceTree = ""; }; EFE255F52C3D79BB00B17DAC /* BSDKTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BSDKTransaction.swift; path = Tangem/Common/BlockchainSDK/BSDKTransaction.swift; sourceTree = SOURCE_ROOT; }; EFE255F92C3D8C7C00B17DAC /* SendQRCodeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendQRCodeService.swift; sourceTree = ""; }; @@ -6024,6 +6034,36 @@ path = WalletSelectorItemView; sourceTree = ""; }; + 2D616FE52CD1414000581EA6 /* Network */ = { + isa = PBXGroup; + children = ( + 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */, + 2D616FE42CD1414000581EA6 /* CasperTarget.swift */, + ); + path = Network; + sourceTree = ""; + }; + 2D616FEB2CD1414000581EA6 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D616FE52CD1414000581EA6 /* Network */, + 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */, + 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */, + 2D616FE82CD1414000581EA6 /* CasperExternalLinkProvider.swift */, + 2D616FE92CD1414000581EA6 /* CasperWalletAssembly.swift */, + 2D616FEA2CD1414000581EA6 /* CasperWalletManager.swift */, + ); + path = Casper; + sourceTree = ""; + }; + 2D616FF62CD142BE00581EA6 /* Casper */ = { + isa = PBXGroup; + children = ( + 2D616FF52CD142BE00581EA6 /* CasperTests.swift */, + ); + path = Casper; + sourceTree = ""; + }; 2D788E7E2ADD657000E0884B /* WalletSelector */ = { isa = PBXGroup; children = ( @@ -10124,6 +10164,7 @@ B62D3C592CBC79D900C2460E /* Bitcoin */, B62D3C612CBC79D900C2460E /* BitcoinCash */, B62D3C7F2CBC79D900C2460E /* Cardano */, + 2D616FEB2CD1414000581EA6 /* Casper */, B62D3C922CBC79D900C2460E /* Chia */, B62D3CA42CBC79D900C2460E /* Cosmos */, B62D3CA92CBC79D900C2460E /* Dash */, @@ -10631,6 +10672,7 @@ B62D3F762CBC79DA00C2460E /* Bech32 */, B62D3F7A2CBC79DA00C2460E /* Moya+Combine */, B62D3F7B2CBC79DA00C2460E /* AnyPublisher+Async.swift */, + 2D616FF32CD1421000581EA6 /* Byte+.swift */, B62D3F7C2CBC79DA00C2460E /* BigUInt+.swift */, B62D3F7D2CBC79DA00C2460E /* Bundle+.swift */, B62D3F7E2CBC79DA00C2460E /* CBOR+.swift */, @@ -11175,6 +11217,7 @@ B62D430D2CBC79E200C2460E /* Aptos */, B62D43172CBC79E300C2460E /* Bitcoin */, B62D432B2CBC79E300C2460E /* Cardano */, + 2D616FF62CD142BE00581EA6 /* Casper */, B62D432F2CBC79E400C2460E /* Chia */, B62D42F92CBC79E100C2460E /* Common */, B62D43132CBC79E300C2460E /* Cosmos */, @@ -13943,9 +13986,6 @@ EF9E29F52B4F0CCF00418559 /* Manager */ = { isa = PBXGroup; children = ( - EF1399752CBD0A9F00AC9E2B /* OnrampProviderManager */, - EF49C06A2CAD8A730062AF06 /* OnrampRepository */, - EF49C05A2CAD70230062AF06 /* OnrampManager */, EF25610F2CC6A2CD00D3C16A /* OnrampStorage */, EF1399752CBD0A9F00AC9E2B /* OnrampProviderManager */, EF49C06A2CAD8A730062AF06 /* OnrampRepository */, @@ -14481,14 +14521,6 @@ path = Onramp; sourceTree = ""; }; - EFD68F352CC2F57900693C97 /* Onramp */ = { - isa = PBXGroup; - children = ( - EFD68F362CC2F58000693C97 /* OnrampIdentityMock.swift */, - ); - path = Onramp; - sourceTree = ""; - }; EFE23AC9292CB84600A3C554 /* IconView */ = { isa = PBXGroup; children = ( @@ -17087,6 +17119,13 @@ B62D42802CBC79DB00C2460E /* AlgorandTransactionHistoryMapper.swift in Sources */, B62D403A2CBC79DA00C2460E /* AdaliteBalanceResponseDTO.swift in Sources */, B62D40382CBC79DA00C2460E /* BitcoinCashWalletAssembly.swift in Sources */, + 2D616FEC2CD1414000581EA6 /* CasperNetworkProvider.swift in Sources */, + 2D616FED2CD1414000581EA6 /* CasperWalletManager.swift in Sources */, + 2D616FEE2CD1414000581EA6 /* CasperAddressUtils.swift in Sources */, + 2D616FEF2CD1414000581EA6 /* CasperAddressService.swift in Sources */, + 2D616FF02CD1414000581EA6 /* CasperExternalLinkProvider.swift in Sources */, + 2D616FF12CD1414000581EA6 /* CasperWalletAssembly.swift in Sources */, + 2D616FF22CD1414000581EA6 /* CasperTarget.swift in Sources */, B62D42C82CBC79DB00C2460E /* Bundle+.swift in Sources */, B62D420B2CBC79DB00C2460E /* XRPTransaction.swift in Sources */, B62D41CC2CBC79DB00C2460E /* proposal_contract.pb.swift in Sources */, @@ -17402,6 +17441,7 @@ B62D408E2CBC79DA00C2460E /* TokenBalanceERC20TokenMethod.swift in Sources */, B62D40A32CBC79DA00C2460E /* AvalancheExternalLinkProvider.swift in Sources */, B62D3FFA2CBC79DA00C2460E /* OP_VER.swift in Sources */, + 2D616FF42CD1421000581EA6 /* Byte+.swift in Sources */, B62D425A2CBC79DB00C2460E /* JSONRPC.swift in Sources */, B62D42352CBC79DB00C2460E /* BlockcypherTarget.swift in Sources */, B62D418C2CBC79DA00C2460E /* SolanaFeeParameters.swift in Sources */, @@ -17945,6 +17985,7 @@ B62D435E2CBC79E400C2460E /* KoinosTransactionBuilderTests.swift in Sources */, B62D43672CBC79E400C2460E /* XCTAssert+.swift in Sources */, B62D43402CBC79E400C2460E /* AddressTests.swift in Sources */, + 2D616FF72CD142BE00581EA6 /* CasperTests.swift in Sources */, B62D43482CBC79E400C2460E /* TransactionSizeTesterUtility.swift in Sources */, B62D435F2CBC79E400C2460E /* KoinosWalletManagerTests.swift in Sources */, B62D434B2CBC79E400C2460E /* BlockchainCodingKeyTests.swift in Sources */, diff --git a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000000..800687ca63 --- /dev/null +++ b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,483 @@ +{ + "originHash" : "279320f6fd232b7bb4b2b24520941724ff8087e6be3fcae17ffa02b6129981e1", + "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire.git", + "state" : { + "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a", + "version" : "5.9.1" + } + }, + { + "identity" : "anyasyncsequence", + "kind" : "remoteSourceControl", + "location" : "https://github.com/vsanthanam/AnyAsyncSequence.git", + "state" : { + "revision" : "9fee8443252bb25e191b0b3b03a006aabac44088", + "version" : "1.0.2" + } + }, + { + "identity" : "anycodable", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Flight-School/AnyCodable.git", + "state" : { + "revision" : "862808b2070cd908cb04f9aafe7de83d35f81b05", + "version" : "0.6.7" + } + }, + { + "identity" : "base32", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Jarema/Base32.git", + "state" : { + "revision" : "7f723a2e55f1c76e7c79263aebf89dbfcd58e77d", + "version" : "0.10.2" + } + }, + { + "identity" : "bigint", + "kind" : "remoteSourceControl", + "location" : "https://github.com/attaswift/BigInt", + "state" : { + "revision" : "0ed110f7555c34ff468e72e1686e59721f2b0da6", + "version" : "5.3.0" + } + }, + { + "identity" : "bitcoincore", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/bitcoincore.git", + "state" : { + "revision" : "c00b5c60ab9560acee8309f39620fabfde32b518", + "version" : "0.0.21" + } + }, + { + "identity" : "cryptoswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", + "state" : { + "revision" : "7892a123f7e8d0fe62f9f03728b17bbd4f94df5c", + "version" : "1.8.1" + } + }, + { + "identity" : "dgcharts", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/DGCharts", + "state" : { + "revision" : "a2c1aa43650995d5139ad9e3ad4fd9c93d41776d", + "version" : "5.1.0-tangem3" + } + }, + { + "identity" : "float16", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SusanDoggie/Float16.git", + "state" : { + "revision" : "936ae66adccf1c91bcaeeb9c0cddde78a13695c3", + "version" : "1.1.1" + } + }, + { + "identity" : "grpc-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/grpc-swift.git", + "state" : { + "revision" : "db2f35c1a02e6480afe936949f6e739576cad622", + "version" : "1.21.0-tangem2" + } + }, + { + "identity" : "hedera-sdk-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/hedera-sdk-swift.git", + "state" : { + "revision" : "601ed82daac59bbd0050073adea057c20bcd73ef", + "version" : "0.26.0-tangem4" + } + }, + { + "identity" : "icpkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/IcpKit.git", + "state" : { + "revision" : "48d906f7a3eca66dd4cbc239f21fd829dfc9decf", + "version" : "0.1.2-tangem4" + } + }, + { + "identity" : "moya", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Moya/Moya.git", + "state" : { + "revision" : "c263811c1f3dbf002be9bd83107f7cdc38992b26", + "version" : "15.0.3" + } + }, + { + "identity" : "networkimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/NetworkImage", + "state" : { + "revision" : "7aff8d1b31148d32c5933d75557d42f6323ee3d1", + "version" : "6.0.0" + } + }, + { + "identity" : "potentcodables", + "kind" : "remoteSourceControl", + "location" : "https://github.com/outfoxx/PotentCodables.git", + "state" : { + "revision" : "660e33e84e00b9bf07bd41dd99ff800600e435e7", + "version" : "3.5.0" + } + }, + { + "identity" : "qrcode", + "kind" : "remoteSourceControl", + "location" : "https://github.com/WalletConnect/QRCode", + "state" : { + "revision" : "263f280d2c8144adfb0b6676109846cfc8dd552b", + "version" : "14.3.1" + } + }, + { + "identity" : "reactiveswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveCocoa/ReactiveSwift.git", + "state" : { + "revision" : "c43bae3dac73fdd3cb906bd5a1914686ca71ed3c", + "version" : "6.7.0" + } + }, + { + "identity" : "regex", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sharplet/Regex.git", + "state" : { + "revision" : "76c2b73d4281d77fc3118391877efd1bf972f515", + "version" : "2.1.1" + } + }, + { + "identity" : "reown-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/reown-com/reown-swift.git", + "state" : { + "revision" : "8c1a43e28358a30dc03367dca2f38476f1573ece", + "version" : "1.0.4" + } + }, + { + "identity" : "rxswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ReactiveX/RxSwift.git", + "state" : { + "revision" : "c7c7d2cf50a3211fe2843f76869c698e4e417930", + "version" : "6.8.0" + } + }, + { + "identity" : "scalecodec.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tesseract-one/ScaleCodec.swift", + "state" : { + "revision" : "bd39b2d68d87126a61b62a071ee4c065e2a1fe30", + "version" : "0.2.1" + } + }, + { + "identity" : "secp256k1.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GigaBitcoin/secp256k1.swift.git", + "state" : { + "revision" : "1a14e189def5eaa92f839afdd2faad8e43b61a6e", + "version" : "0.12.2" + } + }, + { + "identity" : "solana.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/Solana.Swift.git", + "state" : { + "revision" : "54f15e1afd87e14b45c848a71030cab6798451ec", + "version" : "1.2.0-tangem12" + } + }, + { + "identity" : "starscream", + "kind" : "remoteSourceControl", + "location" : "https://github.com/daltoniam/Starscream.git", + "state" : { + "revision" : "c6bfd1af48efcc9a9ad203665db12375ba6b145a", + "version" : "4.0.8" + } + }, + { + "identity" : "stellar-ios-mac-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Soneso/stellar-ios-mac-sdk.git", + "state" : { + "revision" : "952762a66ca49e0e28ba14a8dc5dbb72da361a95", + "version" : "2.5.4" + } + }, + { + "identity" : "swift-asn1", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-asn1.git", + "state" : { + "revision" : "eb11d30c1de3b896f55aefdb3745dd5e7e1f319f", + "version" : "0.3.0" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "d029d9d39c87bed85b1c50adee7c41795261a192", + "version" : "1.0.6" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types", + "state" : { + "revision" : "12358d55a3824bd5fed310b999ea8cf83a9a1a65", + "version" : "1.0.3" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", + "version" : "1.5.4" + } + }, + { + "identity" : "swift-markdown-ui", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/swift-markdown-ui", + "state" : { + "revision" : "55441810c0f678c78ed7e2ebd46dde89228e02fc", + "version" : "2.4.0" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "635b2589494c97e48c62514bc8b37ced762e0a62", + "version" : "2.63.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "363da63c1966405764f380c627409b2f9d9e710b", + "version" : "1.21.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "0904bf0feb5122b7e5c3f15db7df0eabe623dd87", + "version" : "1.30.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "7c381eb6083542b124a6c18fae742f55001dc2b5", + "version" : "2.26.0" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "6cbe0ed2b394f21ab0d46b9f0c50c6be964968ce", + "version" : "1.20.1" + } + }, + { + "identity" : "swift-numberkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/objecthub/swift-numberkit.git", + "state" : { + "revision" : "0f9c918dcea73f6ff4ff762b8e83a0991ca668d9", + "version" : "2.4.2" + } + }, + { + "identity" : "swift-numerics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-numerics", + "state" : { + "revision" : "0a5bc04095a675662cf24757cc0640aa2204253b", + "version" : "1.0.2" + } + }, + { + "identity" : "swift-protobuf-binaries", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/swift-protobuf-binaries.git", + "state" : { + "revision" : "594a9b8c47df13087ee0a1f25dbc64173604d0e9", + "version" : "1.25.2-tangem3" + } + }, + { + "identity" : "swift-qrcode-generator", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/swift-qrcode-generator", + "state" : { + "revision" : "5ca09b6a2ad190f94aa3d6ddef45b187f8c0343b", + "version" : "1.0.3" + } + }, + { + "identity" : "swift-sodium", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jedisct1/swift-sodium.git", + "state" : { + "revision" : "4f9164a0a2c9a6a7ff53a2833d54a5c79c957342", + "version" : "0.9.1" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5", + "version" : "1.3.2" + } + }, + { + "identity" : "swiftbinancechain", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/SwiftBinanceChain.git", + "state" : { + "revision" : "beaa96aee991b744c6f0e48b19238767e89a22d2", + "version" : "0.0.13" + } + }, + { + "identity" : "swiftcbor", + "kind" : "remoteSourceControl", + "location" : "https://github.com/valpackett/SwiftCBOR.git", + "state" : { + "revision" : "98a59c305cca5c5367c3422d5e127661d4e76e24", + "version" : "0.4.5" + } + }, + { + "identity" : "swiftdate", + "kind" : "remoteSourceControl", + "location" : "https://github.com/malcommac/SwiftDate", + "state" : { + "revision" : "5d943224c3bb173e6ecf27295611615eba90c80e", + "version" : "7.0.0" + } + }, + { + "identity" : "swiftimagereadwrite", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dagronf/SwiftImageReadWrite", + "state" : { + "revision" : "5596407d1cf61b953b8e658fa8636a471df3c509", + "version" : "1.1.6" + } + }, + { + "identity" : "swiftyjson", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/SwiftyJSON.git", + "state" : { + "revision" : "acff55ab1a8b138a49477ff523287b18833fc1a0", + "version" : "5.0.1-tangem1" + } + }, + { + "identity" : "tangem-sdk-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Tangem/tangem-sdk-ios.git", + "state" : { + "revision" : "eedb44b085adc47b876fc2f292dd6dbc2547108c", + "version" : "3.11.0" + } + }, + { + "identity" : "ton-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/ton-swift.git", + "state" : { + "revision" : "723cfeb8da0ea024158b4274fced8a1891bff88e", + "version" : "1.0.10-tangem3" + } + }, + { + "identity" : "tweetnacl-swiftwrap", + "kind" : "remoteSourceControl", + "location" : "https://github.com/bitmark-inc/tweetnacl-swiftwrap.git", + "state" : { + "revision" : "f8fd111642bf2336b11ef9ea828510693106e954", + "version" : "1.1.0" + } + }, + { + "identity" : "wallet-core-binaries-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tangem/wallet-core-binaries-ios.git", + "state" : { + "revision" : "954aa903bcf3899b9bb99267ff847f7967f12327", + "version" : "4.0.46-tangem3.1" + } + }, + { + "identity" : "wallet-mobile-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/MobileWalletProtocol/wallet-mobile-sdk", + "state" : { + "revision" : "84b3d3f25a2e3b140ec12bb0d22c35b58f817d44", + "version" : "1.0.0" + } + }, + { + "identity" : "zipfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weichsel/ZIPFoundation.git", + "state" : { + "revision" : "b979e8b52c7ae7f3f39fa0182e738e9e7257eb78", + "version" : "0.9.18" + } + } + ], + "version" : 3 +} From 0290eb323326a17f5a65b42a53028784c431249b Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Mon, 4 Nov 2024 10:42:01 +0300 Subject: [PATCH 04/10] IOS-8332 Refactor casper address tests --- BlockchainSdk/Common/Blockchain.swift | 5 ++-- BlockchainSdkTests/Common/AddressTests.swift | 28 +++++++++++++++++++ .../xcshareddata/swiftpm/Package.resolved | 3 +- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/BlockchainSdk/Common/Blockchain.swift b/BlockchainSdk/Common/Blockchain.swift index e597f9b1ec..9770a16a9a 100644 --- a/BlockchainSdk/Common/Blockchain.swift +++ b/BlockchainSdk/Common/Blockchain.swift @@ -967,7 +967,7 @@ extension Blockchain: Codable { case .energyWebX: return "energyWebX" case .core: return "core" case .canxium: return "canxium" - case .casper: return "casper" + case .casper: return "casper-network" } } @@ -1065,6 +1065,7 @@ extension Blockchain: Codable { case "energyWebX": self = .energyWebX(curve: curve) case "core": self = .core(testnet: isTestnet) case "canxium": self = .canxium + case "casper-network": self = .casper(testnet: isTestnet) default: throw BlockchainSdkError.decodingFailed } @@ -1308,7 +1309,7 @@ private extension Blockchain { case .canxium: return "canxium" case .casper: - return "casper" + return "casper-network" } } diff --git a/BlockchainSdkTests/Common/AddressTests.swift b/BlockchainSdkTests/Common/AddressTests.swift index 973f2a9970..63d70406cd 100644 --- a/BlockchainSdkTests/Common/AddressTests.swift +++ b/BlockchainSdkTests/Common/AddressTests.swift @@ -1310,4 +1310,32 @@ class AddressesTests: XCTestCase { XCTAssertTrue(addressService.validate("f7b1299849420e082bbdd9de92cb36e0645e7870513a6eb833d5449a88799699")) } + + func testCasperAddressGeneration() throws { + let blockchain = Blockchain.casper(testnet: false) + + let ed25519WalletPublicKey = Data(hexString: "98C07D7E72D89A681D7227A7AF8A6FD5F22FE0105C8741D55A95DF415454B82E") + let ed25519ExpectedAddress = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" + + let ed25519AddressService = CasperAddressService(curve: .ed25519) + + try XCTAssertEqual(ed25519AddressService.makeAddress(from: ed25519WalletPublicKey).value, ed25519ExpectedAddress) + + let secp256k1WalletPublicKey = Data(hexString: "021F997DFBBFD32817C0E110EAEE26BCBD2BB70B4640C515D9721C9664312EACD8") + let secp256k1ExpectedAddress = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" + + let secp256k1AddressService = CasperAddressService(curve: .secp256k1) + + try XCTAssertEqual(secp256k1AddressService.makeAddress(from: secp256k1WalletPublicKey).value, secp256k1ExpectedAddress) + } + + func testCasperAddressValidation() { + let ed25519Address = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" + let ed25519AddressService = CasperAddressService(curve: .ed25519) + + let secp256k1Address = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" + let secp256k1AddressService = CasperAddressService(curve: .secp256k1) + + XCTAssertTrue(secp256k1AddressService.validate(secp256k1Address)) + } } diff --git a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0d24db4a94..cf56bf68e7 100644 --- a/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/TangemApp.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -429,8 +429,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Tangem/tangem-sdk-ios.git", "state" : { - "revision" : "eedb44b085adc47b876fc2f292dd6dbc2547108c", - "version" : "3.11.0" + "revision" : "f490a80f2156067a9b1c6f24974aaaab316e8639" } }, { From b4f27061192f5e1eb8e59cb2b47d914fa6fede5d Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Mon, 4 Nov 2024 10:45:46 +0300 Subject: [PATCH 05/10] IOS-8332 Remove non actual tests --- BlockchainSdkTests/Casper/CasperTests.swift | 34 --------------------- 1 file changed, 34 deletions(-) diff --git a/BlockchainSdkTests/Casper/CasperTests.swift b/BlockchainSdkTests/Casper/CasperTests.swift index 5b5e0228d5..8e7089ddb7 100644 --- a/BlockchainSdkTests/Casper/CasperTests.swift +++ b/BlockchainSdkTests/Casper/CasperTests.swift @@ -13,38 +13,4 @@ import XCTest final class CasperTests: XCTestCase { private let blockchain = Blockchain.casper(testnet: false) - - func testMakeAddressFromCorrectEd25519PublicKey() throws { - let walletPublicKey = Data(hexString: "98C07D7E72D89A681D7227A7AF8A6FD5F22FE0105C8741D55A95DF415454B82E") - let expectedAddress = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" - - let addressService = CasperAddressService(curve: .ed25519) - - try XCTAssertEqual(addressService.makeAddress(from: walletPublicKey).value, expectedAddress) - } - - func testValidateCorrectEd25519Address() { - let address = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" - - let addressService = CasperAddressService(curve: .ed25519) - - XCTAssertTrue(addressService.validate(address)) - } - - func testMakeAddressFromCorrectSecp256k1PublicKey() { - let walletPublicKey = Data(hexString: "021F997DFBBFD32817C0E110EAEE26BCBD2BB70B4640C515D9721C9664312EACD8") - let expectedAddress = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" - - let addressService = CasperAddressService(curve: .secp256k1) - - try XCTAssertEqual(addressService.makeAddress(from: walletPublicKey).value, expectedAddress) - } - - func testValidateCorrectSecp256k1Address() { - let address = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" - - let addressService = CasperAddressService(curve: .secp256k1) - - XCTAssertTrue(addressService.validate(address)) - } } From 4a17d695e5305ca16ae8600fd9aeb96c7a58b177 Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 5 Nov 2024 10:55:35 +0300 Subject: [PATCH 06/10] IOS-8332 Completed changes for review --- .../Casper/CasperAddressService.swift | 46 ++++++++--------- .../Casper/Common/CasperConstants.swift | 32 ++++++++++++ .../Network/CasperNetworkProvider.swift | 38 -------------- .../Casper/Network/CasperTarget.swift | 49 ------------------- BlockchainSdkTests/Casper/CasperTests.swift | 2 + BlockchainSdkTests/Common/AddressTests.swift | 2 + TangemApp.xcodeproj/project.pbxproj | 48 +++++------------- 7 files changed, 68 insertions(+), 149 deletions(-) create mode 100644 BlockchainSdk/Blockchains/Casper/Common/CasperConstants.swift delete mode 100644 BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift delete mode 100644 BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift index 22fc8c7fc6..fae20657c2 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift @@ -25,7 +25,7 @@ public struct CasperAddressService { extension CasperAddressService: AddressProvider { public func makeAddress(for publicKey: Wallet.PublicKey, with addressType: AddressType) throws -> Address { - guard let prefixAddresss = Constants.getAddressPrefix(curve: curve) else { + guard let prefixAddresss = CasperConstants.getAddressPrefix(curve: curve) else { throw Error.unsupportedAddressPrefix } @@ -39,43 +39,37 @@ extension CasperAddressService: AddressProvider { extension CasperAddressService: AddressValidator { public func validate(_ address: String) -> Bool { - let isCorrectEd25519Address = address.count == Constants.lengthED25519 && address.hasPrefix(Constants.prefixED25519) - let isCorrectSecp256k1Address = address.count == Constants.lengthSECP256K1 && address.hasPrefix(Constants.prefixSECP256K1) + let isCorrectEd25519Address = address.count == CasperConstants.lengthED25519 && address.hasPrefix(CasperConstants.prefixED25519) + let isCorrectSecp256k1Address = address.count == CasperConstants.lengthSECP256K1 && address.hasPrefix(CasperConstants.prefixSECP256K1) guard isCorrectEd25519Address || isCorrectSecp256k1Address else { return false } - return true + if address.isSameCase() { + return true + } + + do { + return try address == CasperAddressUtils().checksum(input: Data(hexString: address)) + } catch { + return false + } } } // MARK: - Constants extension CasperAddressService { - enum Constants { - // ED25519 - static let prefixED25519 = "01" - static let lengthED25519 = 66 - - // SECP256K1 - static let prefixSECP256K1 = "02" - static let lengthSECP256K1 = 68 - - static func getAddressPrefix(curve: EllipticCurve) -> String? { - switch curve { - case .ed25519, .ed25519_slip0010: - return CasperAddressService.Constants.prefixED25519 - case .secp256k1: - return CasperAddressService.Constants.prefixSECP256K1 - default: - // Any curves not supported or will be added in the future - return nil - } - } - } - enum Error: LocalizedError { case unsupportedAddressPrefix } } + +// MARK: - Helpers + +extension String { + func isSameCase() -> Bool { + lowercased() == self || uppercased() == self + } +} diff --git a/BlockchainSdk/Blockchains/Casper/Common/CasperConstants.swift b/BlockchainSdk/Blockchains/Casper/Common/CasperConstants.swift new file mode 100644 index 0000000000..9fb3bc21de --- /dev/null +++ b/BlockchainSdk/Blockchains/Casper/Common/CasperConstants.swift @@ -0,0 +1,32 @@ +// +// CasperConstants.swift +// BlockchainSdk +// +// Created by Alexander Skibin on 29.10.2024. +// Copyright © 2024 Tangem AG. All rights reserved. +// + +import Foundation +import TangemSdk + +enum CasperConstants { + // ED25519 + static let prefixED25519 = "01" + static let lengthED25519 = 66 + + // SECP256K1 + static let prefixSECP256K1 = "02" + static let lengthSECP256K1 = 68 + + static func getAddressPrefix(curve: EllipticCurve) -> String? { + switch curve { + case .ed25519, .ed25519_slip0010: + return CasperConstants.prefixED25519 + case .secp256k1: + return CasperConstants.prefixSECP256K1 + default: + // Any curves not supported or will be added in the future + return nil + } + } +} diff --git a/BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift b/BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift deleted file mode 100644 index 3026b41076..0000000000 --- a/BlockchainSdk/Blockchains/Casper/Network/CasperNetworkProvider.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// CasperNetworkProvider.swift -// BlockchainSdk -// -// Created by skibinalexander on 22.10.2024. -// Copyright © 2024 Tangem AG. All rights reserved. -// - -import Combine -import Foundation - -final class CasperNetworkProvider: HostProvider { - var host: String { - node.url.absoluteString - } - - private let node: NodeInfo - - private let provider: NetworkProvider - - init( - node: NodeInfo, - configuration: NetworkProviderConfiguration - ) { - self.node = node - provider = NetworkProvider(configuration: configuration) - } - - // MARK: - Private Implementation - - private func requestPublisher(for target: CasperTarget.TargetType) -> AnyPublisher { - provider.requestPublisher(CasperTarget(node: node)) - .filterSuccessfulStatusAndRedirectCodes() - .map(JSONRPC.Response.self) - .tryMap { try $0.result.get() } - .eraseToAnyPublisher() - } -} diff --git a/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift b/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift deleted file mode 100644 index 5e191990ea..0000000000 --- a/BlockchainSdk/Blockchains/Casper/Network/CasperTarget.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// CasperTarget.swift -// BlockchainSdk -// -// Created by skibinalexander on 22.10.2024. -// Copyright © 2024 Tangem AG. All rights reserved. -// - -import Foundation -import Moya - -// TODO: - https://tangem.atlassian.net/browse/IOS-8316 -struct CasperTarget: TargetType { - // MARK: - Properties - - let node: NodeInfo - - // MARK: - Init - - init(node: NodeInfo) { - self.node = node - } - - // MARK: - TargetType - - var baseURL: URL { - node.url - } - - var path: String { - "" - } - - var method: Moya.Method { - .post - } - - var task: Task { - .requestPlain - } - - var headers: [String: String]? -} - -// MARK: - TargetType - -extension CasperTarget { - enum TargetType {} -} diff --git a/BlockchainSdkTests/Casper/CasperTests.swift b/BlockchainSdkTests/Casper/CasperTests.swift index 8e7089ddb7..4d45fa7077 100644 --- a/BlockchainSdkTests/Casper/CasperTests.swift +++ b/BlockchainSdkTests/Casper/CasperTests.swift @@ -13,4 +13,6 @@ import XCTest final class CasperTests: XCTestCase { private let blockchain = Blockchain.casper(testnet: false) + + // TODO: - https://tangem.atlassian.net/browse/IOS-8318 } diff --git a/BlockchainSdkTests/Common/AddressTests.swift b/BlockchainSdkTests/Common/AddressTests.swift index 63d70406cd..7c6333c4c0 100644 --- a/BlockchainSdkTests/Common/AddressTests.swift +++ b/BlockchainSdkTests/Common/AddressTests.swift @@ -1333,6 +1333,8 @@ class AddressesTests: XCTestCase { let ed25519Address = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" let ed25519AddressService = CasperAddressService(curve: .ed25519) + XCTAssertTrue(ed25519AddressService.validate(ed25519Address)) + let secp256k1Address = "02021f997DfbbFd32817C0E110EAeE26BCbD2BB70b4640C515D9721c9664312eaCd8" let secp256k1AddressService = CasperAddressService(curve: .secp256k1) diff --git a/TangemApp.xcodeproj/project.pbxproj b/TangemApp.xcodeproj/project.pbxproj index b340b6df83..b72285de91 100644 --- a/TangemApp.xcodeproj/project.pbxproj +++ b/TangemApp.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 2D1400CA2C43F79F00B75A42 /* MarketsPortfolioContextActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1400C82C43F4FD00B75A42 /* MarketsPortfolioContextActions.swift */; }; 2D1400CE2C44090400B75A42 /* MarketsPortfolioContainerRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1400CD2C44090400B75A42 /* MarketsPortfolioContainerRoutable.swift */; }; 2D1400D22C4425B300B75A42 /* MarketsTokenDetailsPortfolioCoordinatorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1400D12C4425B300B75A42 /* MarketsTokenDetailsPortfolioCoordinatorFactory.swift */; }; + 2D1B27122CDA025A0066F484 /* CasperConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1B27112CDA025A0066F484 /* CasperConstants.swift */; }; 2D1BB3682C07421C008392F7 /* MarketsTokenModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1BB3672C07421C008392F7 /* MarketsTokenModel.swift */; }; 2D1BB36A2C074534008392F7 /* MarketsDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1BB3692C074534008392F7 /* MarketsDTO.swift */; }; 2D1BB36C2C0745ED008392F7 /* MarketsListOrderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D1BB36B2C0745ED008392F7 /* MarketsListOrderType.swift */; }; @@ -73,8 +74,6 @@ 2DA57BC12CD650E900C890DF /* CasperAddressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */; }; 2DA57BC22CD650E900C890DF /* CasperWalletManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FEA2CD1414000581EA6 /* CasperWalletManager.swift */; }; 2DA57BC32CD650E900C890DF /* CasperAddressService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */; }; - 2DA57BC42CD650F100C890DF /* CasperTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE42CD1414000581EA6 /* CasperTarget.swift */; }; - 2DA57BC52CD650F100C890DF /* CasperNetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */; }; 2DA8AB122A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA8AB112A433BDB00C75D85 /* Analytics+BlockchainExceptionHandler.swift */; }; 2DB3614B2C14FBAB00BB1D38 /* SegmentedPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3614A2C14FBAB00BB1D38 /* SegmentedPickerView.swift */; }; 2DB3614D2C14FBF500BB1D38 /* SegmentedPickerView+EnviromentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB3614C2C14FBF500BB1D38 /* SegmentedPickerView+EnviromentValues.swift */; }; @@ -2500,12 +2499,6 @@ EF8BE6BD2CCA994F001FBA2B /* OnrampRedirectDataRequestItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6BC2CCA9941001FBA2B /* OnrampRedirectDataRequestItem.swift */; }; EF8BE6C02CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6BF2CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift */; }; EF8BE6C42CCB95D7001FBA2B /* OnrampRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6C32CCB95D7001FBA2B /* OnrampRoutable.swift */; }; - EF8BE6B02CCA71E3001FBA2B /* CommonOnrampProviderManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6AF2CCA71E0001FBA2B /* CommonOnrampProviderManager.swift */; }; - EF8BE6B32CCA8800001FBA2B /* OnrampDataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6B22CCA87FE001FBA2B /* OnrampDataRepository.swift */; }; - EF8BE6BB2CCA98CB001FBA2B /* OnrampPairRequestItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6BA2CCA98CA001FBA2B /* OnrampPairRequestItem.swift */; }; - EF8BE6BD2CCA994F001FBA2B /* OnrampRedirectDataRequestItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6BC2CCA9941001FBA2B /* OnrampRedirectDataRequestItem.swift */; }; - EF8BE6C02CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6BF2CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift */; }; - EF8BE6C42CCB95D7001FBA2B /* OnrampRoutable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8BE6C32CCB95D7001FBA2B /* OnrampRoutable.swift */; }; EF8D780F2981458500B67418 /* UserTokenListManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8D780E2981458500B67418 /* UserTokenListManagerMock.swift */; }; EF8DBCDD2C060A03009072CF /* StakingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8DBCDC2C060A03009072CF /* StakingManager.swift */; }; EF8DBCE02C060CCE009072CF /* StakingDependenciesFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF8DBCDF2C060CCE009072CF /* StakingDependenciesFactory.swift */; }; @@ -3003,6 +2996,7 @@ 2D1400C82C43F4FD00B75A42 /* MarketsPortfolioContextActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsPortfolioContextActions.swift; sourceTree = ""; }; 2D1400CD2C44090400B75A42 /* MarketsPortfolioContainerRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsPortfolioContainerRoutable.swift; sourceTree = ""; }; 2D1400D12C4425B300B75A42 /* MarketsTokenDetailsPortfolioCoordinatorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenDetailsPortfolioCoordinatorFactory.swift; sourceTree = ""; }; + 2D1B27112CDA025A0066F484 /* CasperConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperConstants.swift; sourceTree = ""; }; 2D1BB3672C07421C008392F7 /* MarketsTokenModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenModel.swift; sourceTree = ""; }; 2D1BB3692C074534008392F7 /* MarketsDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsDTO.swift; sourceTree = ""; }; 2D1BB36B2C0745ED008392F7 /* MarketsListOrderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsListOrderType.swift; sourceTree = ""; }; @@ -3037,8 +3031,6 @@ 2D61671D2C7632F9006FCEA6 /* MarketsTokensNetworkRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokensNetworkRoutable.swift; sourceTree = ""; }; 2D61671F2C763500006FCEA6 /* MarketsTokenNetworkSelectorCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinator.swift; sourceTree = ""; }; 2D6167212C763505006FCEA6 /* MarketsTokenNetworkSelectorCoordinatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketsTokenNetworkSelectorCoordinatorView.swift; sourceTree = ""; }; - 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperNetworkProvider.swift; sourceTree = ""; }; - 2D616FE42CD1414000581EA6 /* CasperTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperTarget.swift; sourceTree = ""; }; 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressService.swift; sourceTree = ""; }; 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperAddressUtils.swift; sourceTree = ""; }; 2D616FE82CD1414000581EA6 /* CasperExternalLinkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CasperExternalLinkProvider.swift; sourceTree = ""; }; @@ -5517,12 +5509,6 @@ EF8BE6BC2CCA9941001FBA2B /* OnrampRedirectDataRequestItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampRedirectDataRequestItem.swift; sourceTree = ""; }; EF8BE6BF2CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonOnrampDataRepository.swift; sourceTree = ""; }; EF8BE6C32CCB95D7001FBA2B /* OnrampRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampRoutable.swift; sourceTree = ""; }; - EF8BE6AF2CCA71E0001FBA2B /* CommonOnrampProviderManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonOnrampProviderManager.swift; sourceTree = ""; }; - EF8BE6B22CCA87FE001FBA2B /* OnrampDataRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampDataRepository.swift; sourceTree = ""; }; - EF8BE6BA2CCA98CA001FBA2B /* OnrampPairRequestItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampPairRequestItem.swift; sourceTree = ""; }; - EF8BE6BC2CCA9941001FBA2B /* OnrampRedirectDataRequestItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampRedirectDataRequestItem.swift; sourceTree = ""; }; - EF8BE6BF2CCA9CC3001FBA2B /* CommonOnrampDataRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonOnrampDataRepository.swift; sourceTree = ""; }; - EF8BE6C32CCB95D7001FBA2B /* OnrampRoutable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnrampRoutable.swift; sourceTree = ""; }; EF8D780E2981458500B67418 /* UserTokenListManagerMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTokenListManagerMock.swift; sourceTree = ""; }; EF8DBCDC2C060A03009072CF /* StakingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingManager.swift; sourceTree = ""; }; EF8DBCDF2C060CCE009072CF /* StakingDependenciesFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StakingDependenciesFactory.swift; sourceTree = ""; }; @@ -5993,6 +5979,14 @@ path = Common; sourceTree = ""; }; + 2D1B27102CDA024F0066F484 /* Common */ = { + isa = PBXGroup; + children = ( + 2D1B27112CDA025A0066F484 /* CasperConstants.swift */, + ); + path = Common; + sourceTree = ""; + }; 2D1BB3662C074207008392F7 /* Markets */ = { isa = PBXGroup; children = ( @@ -6094,20 +6088,10 @@ path = WalletSelectorItemView; sourceTree = ""; }; - 2D616FE52CD1414000581EA6 /* Network */ = { - isa = PBXGroup; - children = ( - 2D616FE32CD1414000581EA6 /* CasperNetworkProvider.swift */, - 2D616FE42CD1414000581EA6 /* CasperTarget.swift */, - ); - path = Network; - sourceTree = ""; - }; 2D616FEB2CD1414000581EA6 /* Casper */ = { isa = PBXGroup; children = ( - 2DA57BB92CD64D8000C890DF /* Common */, - 2D616FE52CD1414000581EA6 /* Network */, + 2D1B27102CDA024F0066F484 /* Common */, 2D616FE62CD1414000581EA6 /* CasperAddressService.swift */, 2D616FE72CD1414000581EA6 /* CasperAddressUtils.swift */, 2D616FE82CD1414000581EA6 /* CasperExternalLinkProvider.swift */, @@ -6136,13 +6120,6 @@ path = WalletSelector; sourceTree = ""; }; - 2DA57BB92CD64D8000C890DF /* Common */ = { - isa = PBXGroup; - children = ( - ); - path = Common; - sourceTree = ""; - }; 2DADFF9E2C98A9F30029F390 /* Tooltip */ = { isa = PBXGroup; children = ( @@ -17375,8 +17352,6 @@ B62D42A32CBC79DB00C2460E /* BlockchainSdkConfig.swift in Sources */, B62D41572CBC79DA00C2460E /* SubscanAPIResult.swift in Sources */, B62D406C2CBC79DA00C2460E /* CosmosProtoMessage.pb.swift in Sources */, - 2DA57BC42CD650F100C890DF /* CasperTarget.swift in Sources */, - 2DA57BC52CD650F100C890DF /* CasperNetworkProvider.swift in Sources */, B62D41492CBC79DA00C2460E /* NEARTransactionParams.swift in Sources */, B62D40AD2CBC79DA00C2460E /* EthereumPoWExternalLinkProvider.swift in Sources */, B62D40C12CBC79DA00C2460E /* EVMSmartContractInteractor.swift in Sources */, @@ -17680,6 +17655,7 @@ B62D42D42CBC79DB00C2460E /* Moya+.swift in Sources */, B62D40702CBC79DA00C2460E /* CosmosTransactionBuilder.swift in Sources */, B62D41972CBC79DA00C2460E /* StellarNetworkService.swift in Sources */, + 2D1B27122CDA025A0066F484 /* CasperConstants.swift in Sources */, B62D42912CBC79DB00C2460E /* TransactionHistoryProvider.swift in Sources */, B62D3FD92CBC79DA00C2460E /* OP_MUL.swift in Sources */, B62D40312CBC79DA00C2460E /* BitcoinWalletAssembly.swift in Sources */, From 5afc7439c30d6b1813e398464f218d9009656324 Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 5 Nov 2024 10:58:31 +0300 Subject: [PATCH 07/10] IOS-8332 Refactor --- BlockchainSdk/Blockchains/Casper/CasperAddressService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift index fae20657c2..55fe98e141 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift @@ -68,7 +68,7 @@ extension CasperAddressService { // MARK: - Helpers -extension String { +fileprivate extension String { func isSameCase() -> Bool { lowercased() == self || uppercased() == self } From 67f96e8115137bc948b20c536f17ef84b82da85f Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 5 Nov 2024 17:00:14 +0300 Subject: [PATCH 08/10] IOS-8332 Add casper curve as parameter --- .../Blockchains/Casper/CasperAddressService.swift | 2 +- BlockchainSdk/Common/Blockchain.swift | 14 ++++++++------ .../Common/Blockchain/Blockchain+AllCases.swift | 2 +- .../Common/Factories/AddressServiceFactory.swift | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift index 55fe98e141..abb3ccb0ae 100644 --- a/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift +++ b/BlockchainSdk/Blockchains/Casper/CasperAddressService.swift @@ -68,7 +68,7 @@ extension CasperAddressService { // MARK: - Helpers -fileprivate extension String { +private extension String { func isSameCase() -> Bool { lowercased() == self || uppercased() == self } diff --git a/BlockchainSdk/Common/Blockchain.swift b/BlockchainSdk/Common/Blockchain.swift index 9770a16a9a..be60fb09c0 100644 --- a/BlockchainSdk/Common/Blockchain.swift +++ b/BlockchainSdk/Common/Blockchain.swift @@ -92,7 +92,7 @@ public indirect enum Blockchain: Equatable, Hashable { case energyWebX(curve: EllipticCurve) case core(testnet: Bool) case canxium - case casper(testnet: Bool) + case casper(curve: EllipticCurve, testnet: Bool) public var isTestnet: Bool { switch self { @@ -136,8 +136,7 @@ public indirect enum Blockchain: Equatable, Hashable { .sei(let testnet), .kaspa(let testnet), .energyWebEVM(let testnet), - .core(let testnet), - .casper(let testnet): + .core(let testnet): return testnet case .litecoin, .ducatus, @@ -172,7 +171,9 @@ public indirect enum Blockchain: Equatable, Hashable { .algorand(_, let testnet), .aptos(_, let testnet), .shibarium(let testnet), - .sui(_, let testnet): + .sui(_, let testnet), + .casper(_, let testnet) + : return testnet } } @@ -196,7 +197,8 @@ public indirect enum Blockchain: Equatable, Hashable { .hedera(let curve, _), .bittensor(let curve), .sui(let curve, _), - .energyWebX(let curve): + .energyWebX(let curve), + .casper(let curve, _): return curve case .chia: return .bls12381_G2_AUG @@ -1065,7 +1067,7 @@ extension Blockchain: Codable { case "energyWebX": self = .energyWebX(curve: curve) case "core": self = .core(testnet: isTestnet) case "canxium": self = .canxium - case "casper-network": self = .casper(testnet: isTestnet) + case "casper-network": self = .casper(curve: curve, testnet: isTestnet) default: throw BlockchainSdkError.decodingFailed } diff --git a/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift b/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift index 9482ef6263..7b8894897d 100644 --- a/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift +++ b/BlockchainSdk/Common/Blockchain/Blockchain+AllCases.swift @@ -168,7 +168,7 @@ public extension Blockchain { .energyWebX(curve: .ed25519_slip0010), .core(testnet: false), .canxium, - .casper(testnet: false), + .casper(curve: .secp256k1, testnet: false), ] } } diff --git a/BlockchainSdk/Common/Factories/AddressServiceFactory.swift b/BlockchainSdk/Common/Factories/AddressServiceFactory.swift index 251f78b131..0c742d9395 100644 --- a/BlockchainSdk/Common/Factories/AddressServiceFactory.swift +++ b/BlockchainSdk/Common/Factories/AddressServiceFactory.swift @@ -140,9 +140,9 @@ public struct AddressServiceFactory { return WalletCoreAddressService(blockchain: .filecoin) case .energyWebX(let curve): return PolkadotAddressService(network: .energyWebX(curve: curve)) - case .casper: + case .casper(let curve, _): // We only support this type of curve - return CasperAddressService(curve: .secp256k1) + return CasperAddressService(curve: curve) } } } From 2069d470e813c97709d7a0b1b99999eee48e57ea Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 5 Nov 2024 19:23:16 +0300 Subject: [PATCH 09/10] IOS-8332 Fix tests --- BlockchainSdkTests/Common/AddressTests.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/BlockchainSdkTests/Common/AddressTests.swift b/BlockchainSdkTests/Common/AddressTests.swift index 7c6333c4c0..b9b600ec5d 100644 --- a/BlockchainSdkTests/Common/AddressTests.swift +++ b/BlockchainSdkTests/Common/AddressTests.swift @@ -1312,8 +1312,6 @@ class AddressesTests: XCTestCase { } func testCasperAddressGeneration() throws { - let blockchain = Blockchain.casper(testnet: false) - let ed25519WalletPublicKey = Data(hexString: "98C07D7E72D89A681D7227A7AF8A6FD5F22FE0105C8741D55A95DF415454B82E") let ed25519ExpectedAddress = "0198c07D7e72D89A681d7227a7Af8A6fd5F22fe0105c8741d55A95dF415454b82E" From f59687810048f2775cc57c6f9d8f91364402f0d6 Mon Sep 17 00:00:00 2001 From: Skibin Alexander Date: Tue, 5 Nov 2024 19:49:14 +0300 Subject: [PATCH 10/10] IOS-8332 Fix tests --- BlockchainSdk/Extensions/Byte+.swift | 3 +-- BlockchainSdkTests/Casper/CasperTests.swift | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/BlockchainSdk/Extensions/Byte+.swift b/BlockchainSdk/Extensions/Byte+.swift index fd72f23bfa..cbf47a0ea3 100644 --- a/BlockchainSdk/Extensions/Byte+.swift +++ b/BlockchainSdk/Extensions/Byte+.swift @@ -34,7 +34,6 @@ extension UInt8 { extension Array where Element == UInt8 { func toBitArray() -> [Bit] { - let arrayBits = map { $0.toBits() } - return arrayBits.reduce(into: []) { partialResult, bits in partialResult.append(contentsOf: bits) } + flatMap { $0.toBits() } } } diff --git a/BlockchainSdkTests/Casper/CasperTests.swift b/BlockchainSdkTests/Casper/CasperTests.swift index 4d45fa7077..34174ff6d4 100644 --- a/BlockchainSdkTests/Casper/CasperTests.swift +++ b/BlockchainSdkTests/Casper/CasperTests.swift @@ -12,7 +12,7 @@ import XCTest @testable import BlockchainSdk final class CasperTests: XCTestCase { - private let blockchain = Blockchain.casper(testnet: false) + private let blockchain = Blockchain.casper(curve: .secp256k1, testnet: false) // TODO: - https://tangem.atlassian.net/browse/IOS-8318 }