├── .gitignore ├── ApiParser ├── Package.swift ├── README.md └── Sources │ └── ApiParser │ ├── CodeGenerator.swift │ ├── Settings.swift │ ├── TypeConverter.swift │ └── main.swift ├── LICENSE ├── Package.swift ├── README.md ├── Sources ├── CTonSDK │ ├── module.modulemap │ └── shim.h └── EverscaleClientSwift │ ├── Abi │ ├── Abi.swift │ └── AbiTypes.swift │ ├── Binding │ ├── Binding.swift │ ├── BindingStore.swift │ └── BindingTypes.swift │ ├── Boc │ ├── Boc.swift │ └── BocTypes.swift │ ├── Client │ ├── Client.swift │ └── ClientTypes.swift │ ├── Crypto │ ├── Crypto.swift │ └── CryptoTypes.swift │ ├── Debot │ ├── Debot.swift │ └── DebotTypes.swift │ ├── Extensions │ ├── FileReader.swift │ ├── Helpers.swift │ └── SimpleEnv.swift │ ├── Net │ ├── Net.swift │ └── NetTypes.swift │ ├── Processing │ ├── Processing.swift │ └── ProcessingTypes.swift │ ├── Proofs │ ├── Proofs.swift │ └── ProofsTypes.swift │ ├── Tvm │ ├── Tvm.swift │ └── TvmTypes.swift │ └── Utils │ ├── Utils.swift │ └── UtilsTypes.swift ├── Tests ├── EverscaleClientSwiftTests │ ├── AbiTests.swift │ ├── BindingTests.swift │ ├── BocTests.swift │ ├── ClientTests.swift │ ├── CryptoTests.swift │ ├── ErrorsTests.swift │ ├── Fixtures │ │ └── abi │ │ │ ├── Events.abi.json │ │ │ ├── Events.tvc │ │ │ ├── Giver.abi.json │ │ │ ├── GiverNodeSE.abi.json │ │ │ ├── GiverNodeSE_v2.abi.json │ │ │ ├── GiverNodeSE_v2.keys.json │ │ │ ├── GiverV2.abi.json │ │ │ ├── GiverV2.tvc │ │ │ ├── GiverWallet.abi.json │ │ │ ├── Hello.abi.json │ │ │ ├── Hello.tvc │ │ │ ├── LimitWallet.abi.json │ │ │ ├── LimitWallet.tvc │ │ │ ├── Piggy.abi.json │ │ │ ├── Piggy.tvc │ │ │ ├── SetcodeMultisigWallet2.abi.json │ │ │ ├── SetcodeMultisigWallet2.tvc │ │ │ ├── Subscription.abi.json │ │ │ ├── Subscription.tvc │ │ │ ├── Wallet.abi.json │ │ │ ├── Wallet.tvc │ │ │ ├── helloDebot.abi.json │ │ │ ├── helloDebot.png │ │ │ ├── helloDebot.sol │ │ │ ├── helloDebot.tvc │ │ │ ├── tda.abi.json │ │ │ ├── tda.tvc │ │ │ ├── tdb.abi.json │ │ │ ├── tdb.tvc │ │ │ ├── testDebot.abi.json │ │ │ ├── testDebot.tvc │ │ │ ├── testDebot2.abi.json │ │ │ ├── testDebot2.tvc │ │ │ ├── testDebot3.abi.json │ │ │ ├── testDebot3.sol │ │ │ ├── testDebot3.tvc │ │ │ ├── testDebot4.abi.json │ │ │ ├── testDebot4.tvc │ │ │ ├── testDebot5.abi.json │ │ │ ├── testDebot5.tvc │ │ │ ├── testDebot6.abi.json │ │ │ ├── testDebot6.sol │ │ │ ├── testDebot6.tvc │ │ │ ├── testDebot7.abi.json │ │ │ ├── testDebot7.sol │ │ │ ├── testDebot7.tvc │ │ │ ├── testDebot8.abi.json │ │ │ ├── testDebot8.sol │ │ │ ├── testDebot8.tvc │ │ │ ├── testDebotTarget.abi.json │ │ │ └── testDebotTarget.tvc │ ├── Helpers.swift │ ├── NetTests.swift │ ├── ProcessingTests.swift │ ├── TvmTests.swift │ └── UtilsTests.swift └── LinuxMain.swift ├── api_generate.sh └── scripts ├── install_rust.sh └── install_tonsdk.sh /.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | xcuserdata 4 | *.xcodeproj 5 | DerivedData/ 6 | .DS_Store 7 | .swiftpm 8 | db.sqlite 9 | .env* 10 | Keys/* 11 | !Keys/.gitkeep 12 | Package.resolved 13 | TON-SDK/* 14 | dependencies/* 15 | api.json -------------------------------------------------------------------------------- /ApiParser/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:6.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ApiParser", 8 | platforms: [ 9 | .macOS(SupportedPlatform.MacOSVersion.v10_13) 10 | ], 11 | products: [ 12 | .executable(name: "ApiParser", targets: ["ApiParser"]) 13 | ], 14 | dependencies: [ 15 | .package(url: "https://github.com/nerzh/swift-regular-expression.git", .upToNextMajor(from: "0.2.4")), 16 | .package(url: "https://github.com/apple/swift-argument-parser", .upToNextMinor(from: "0.4.3")), 17 | .package(url: "https://github.com/nerzh/SwiftFileUtils", .upToNextMinor(from: "1.3.0")), 18 | ], 19 | targets: [ 20 | .executableTarget( 21 | name: "ApiParser", 22 | dependencies: [ 23 | .product(name: "SwiftRegularExpression", package: "swift-regular-expression"), 24 | .product(name: "ArgumentParser", package: "swift-argument-parser"), 25 | .product(name: "FileUtils", package: "SwiftFileUtils"), 26 | ]), 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /ApiParser/README.md: -------------------------------------------------------------------------------- 1 | # Api Parser For Everscale Swift Client [Swift Everscale SDK](https://github.com/nerzh/everscale-client-swift) 2 | 3 | ### Update SDK 4 | 5 | ```bash 6 | cd everscale-client-swift 7 | ``` 8 | ```bash 9 | bash api_generate.sh 10 | ``` 11 | -------------------------------------------------------------------------------- /ApiParser/Sources/ApiParser/Settings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 08.05.2021. 6 | // 7 | 8 | import Foundation 9 | 10 | let libPrefix: String = "TSDK" 11 | let libEnumPostfix: String = "EnumTypes" 12 | let defaultEnumParents: [String] = ["String", "Codable"] 13 | let defaultStructTypeParents: [String] = ["Codable"] 14 | -------------------------------------------------------------------------------- /ApiParser/Sources/ApiParser/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 04.05.2021. 6 | // 7 | 8 | import ArgumentParser 9 | import FileUtils 10 | import Foundation 11 | import SwiftRegularExpression 12 | 13 | struct ApiParser: ParsableCommand { 14 | 15 | @Argument(help: "Path to api json file.") 16 | var pathToApiFile: String 17 | 18 | mutating func run() throws { 19 | let api = try SDKApi.init(pathToApiFile) 20 | let sdkSwiftModel = api.convertToSwift() 21 | let generator = CodeGenerator(swiftApi: sdkSwiftModel) 22 | generator.generate() 23 | try changeReadMeSDKVersion(sdkSwiftModel) 24 | } 25 | 26 | private func changeReadMeSDKVersion(_ sdkSwiftModel: SDKSwiftApi) throws { 27 | let readMePath: String = "./../README.md" 28 | let readMeURL: URL = URL(fileURLWithPath: readMePath) 29 | var fileText: String = try FileUtils.readFile(readMeURL) 30 | fileText.replaceSelf(#"VERSION-.+?-orange"#, "VERSION-\(sdkSwiftModel.version)-orange") 31 | try FileUtils.writeFile(to: readMeURL, fileText.data(using: .utf8)) 32 | } 33 | } 34 | 35 | ApiParser.main() 36 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:6.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "EverscaleClientSwift", 8 | platforms: [ 9 | .macOS(SupportedPlatform.MacOSVersion.v12), 10 | .iOS(SupportedPlatform.IOSVersion.v13) 11 | ], 12 | products: [ 13 | .library(name: "EverscaleClientSwift", targets: ["EverscaleClientSwift"]), 14 | ], 15 | dependencies: [ 16 | .package(url: "https://github.com/nerzh/swift-regular-expression.git", .upToNextMajor(from: "0.2.4")), 17 | .package(url: "https://github.com/nerzh/SwiftFileUtils", .upToNextMajor(from: "1.3.0")), 18 | .package(url: "https://github.com/bytehubio/BigInt", exact: "5.3.0"), 19 | .package(url: "https://github.com/nerzh/swift-extensions-pack", .upToNextMajor(from: "2.0.0")), 20 | ], 21 | targets: [ 22 | .systemLibrary(name: "CTonSDK", pkgConfig: "libton_client"), 23 | .target( 24 | name: "EverscaleClientSwift", 25 | dependencies: [ 26 | .byName(name: "CTonSDK"), 27 | .product(name: "SwiftRegularExpression", package: "swift-regular-expression"), 28 | .product(name: "BigInt", package: "BigInt"), 29 | .product(name: "SwiftExtensionsPack", package: "swift-extensions-pack"), 30 | ]), 31 | .testTarget( 32 | name: "EverscaleClientSwiftTests", 33 | dependencies: [ 34 | .product(name: "SwiftRegularExpression", package: "swift-regular-expression"), 35 | .byName(name: "EverscaleClientSwift"), 36 | .product(name: "FileUtils", package: "SwiftFileUtils"), 37 | .product(name: "BigInt", package: "BigInt"), 38 | .product(name: "SwiftExtensionsPack", package: "swift-extensions-pack"), 39 | ]), 40 | ] 41 | ) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift Client for TVM SDK (everscale, venom, gosh) 2 | 3 | 10 | 11 | [![SPM](https://img.shields.io/badge/swift-package%20manager-green)](https://swift.org/package-manager/) 12 | [![SPM](https://img.shields.io/badge/SDK%20VERSION-1.49.2-orange)](https://github.com/tonlabs/ever-sdk) 13 | 14 | Swift is a strongly typed language that has long been used not only for iOS development. Apple is actively promoting it to new platforms and today it can be used for almost any task. Thanks to this, this implementation provides the work of TVM (toncoin, everscale, venom, gosh) SDK on many platforms at once, including the native one for mobile phones. Let me remind you that swift can also be built for android. 15 | 16 | | OS | Result | 17 | | ----------- | ----------- | 18 | | MacOS | ✅ | 19 | | Linux | ✅ | 20 | | iOS | ✅ | 21 | | Windows | Soon | 22 | 23 | ## Get api keys and TVM endpoints: 24 | 25 | You need to get an API-KEY here [https://dashboard.evercloud.dev](https://dashboard.evercloud.dev) 26 | 27 | 28 | ## Usage 29 | 30 | All requests are async 31 | 32 | ```swift 33 | import EverscaleClientSwift 34 | 35 | var config: TSDKClientConfig = .init() 36 | config.network = TSDKNetworkConfig(endpoints: ["https://net.ton.dev"]) 37 | let client: TSDKClientModule = .init(config: config) 38 | 39 | // Crypto 40 | client.crypto.factorize(TSDKParamsOfFactorize(composite: "17ED48941A08F981")) { (response) in 41 | print(response.result?.factors) 42 | } 43 | 44 | // Boc 45 | let payload: TSDKParamsOfParse = .init(boc: "te6ccgEBAQEAWAAAq2n+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzSsG8DgAAAAAjuOu9NAL7BxYpA") 46 | client.boc.parse_message(payload) { (response) in 47 | if let result = response.result, let parsed: [String: Any] = result.parsed.toDictionary() { 48 | print(parsed["id"]) 49 | print(parsed["src"]) 50 | print(parsed["dst"]) 51 | } 52 | } 53 | ``` 54 | 55 | ## Errors 56 | 57 | ```swift 58 | client.crypto.factorize(TSDKParamsOfFactorize(composite: "17ED48941A08F981")) { (response) in 59 | if let error = response.error { 60 | print(error.data.toJSON()) 61 | print(error.code) 62 | } 63 | } 64 | ``` 65 | 66 | ## Setup TONSDK For Linux and MacOS 67 | 68 | ### Install sdk with bash script 69 | 70 | 0. This download SDK to current dirrectory, compile it and add library symlinks to your system 71 | ```sh 72 | cd everscale-client-swift 73 | ``` 74 | 75 | 1. For install or update the SDK version simply by running these command 76 | ```sh 77 | bash scripts/install_tonsdk.sh 78 | ``` 79 | 80 | ### Manual install sdk ( if you have any problem with script install_tonsdk.sh ) 81 | 82 |
83 | SPOILER: Manual installation 84 | 85 | 0. Install Rust to your OS 86 | 1. git clone https://github.com/tonlabs/ever-sdk 87 | 2. cd ./SDK 88 | 3. cargo update 89 | 4. cargo build --release 90 | 5. copy or create symlink of dynamic library 91 | __macOS :__ 92 | **./SDK/target/release/libton_client.dylib** 93 | to 94 | **/usr/local/lib/libton_client.dylib** 95 | 96 | __Linux :__ 97 | **./SDK/target/release/libton_client.so** 98 | to 99 | **/usr/lib/libton_client.so** 100 | 6. Create pkgConfig file : 101 | 102 | __macOS :__ 103 | **/usr/local/lib/pkgconfig/libton_client.pc** 104 | 105 | ```bash 106 | 107 | prefix=/usr/local 108 | exec_prefix=${prefix} 109 | includedir=${prefix}/include 110 | libdir=${exec_prefix}/lib 111 | 112 | Name: ton_client 113 | Description: ton_client 114 | Version: 1.0.0 115 | Cflags: -I${includedir} 116 | Libs: -L${libdir} -lton_client 117 | 118 | ``` 119 | __Linux:__ 120 | **/usr/lib/pkgconfig/libton_client.pc** 121 | 122 | ```bash 123 | prefix=/usr 124 | exec_prefix=${prefix} 125 | includedir=${prefix}/include 126 | libdir=${exec_prefix}/lib 127 | 128 | Name: ton_client 129 | Description: ton_client 130 | Version: 1.0.0 131 | Cflags: -I${includedir} 132 | Libs: -L${libdir} -lton_client 133 | ``` 134 | 7. Copy or create symlink of file 135 | **/SDK/ton_client/client/tonclient.h** 136 | to 137 | __MacOS:__ 138 | **/usr/local/include/tonclient.h** 139 | __Linux:__ 140 | **/usr/include/tonclient.h** 141 | 142 |
143 | 144 | ## Setup TONSDK For iOS 145 | 146 | 0. Install Rust 147 | 148 | ```bash 149 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh || true && \ 150 | source ~/.profile 151 | ``` 152 | 153 | 1. Install "cargo lipo" 154 | 155 | ```bash 156 | rustup target add aarch64-apple-ios x86_64-apple-ios || true && \ 157 | cargo install cargo-lipo 158 | ``` 159 | 160 | 2. Build SDK for iOS 161 | 162 | **Go to your project folder and:** 163 | 164 | ```bash 165 | git clone https://github.com/tonlabs/SDK.git || true && \ 166 | cd ./SDK 167 | ``` 168 | 169 | ```bash 170 | git pull --ff-only || true && \ 171 | cargo update || true && \ 172 | cargo lipo --release 173 | ``` 174 | ⚠️ Wait installation 175 | 176 | 3. In xcode __File > Add files to "Name Your Project"__ navigate to ./SDK/ton_client/tonclient.h 177 | 178 | 4. Create bridge. In xcode __File > New > File__, select Header File, set name for example **Tonclient-Bridging-Header.h** 179 | 180 | and add 181 | 182 | __#include __ 183 | 184 | __#import "tonclient.h"__ 185 | 186 | like this: 187 | 188 | ```C 189 | #ifndef Tonclient_Bridging_Header_h 190 | #define Tonclient_Bridging_Header_h 191 | 192 | #include 193 | #import "tonclient.h" 194 | 195 | #endif 196 | ``` 197 | 5. Add path to Tonclient-Bridging-Header.h **$(PROJECT_DIR)/Tonclient-Bridging-Header.h** 198 | 199 | 200 | ![](https://user-images.githubusercontent.com/10519803/101789966-9591bc80-3b0a-11eb-8918-1adf36130617.png) 201 | 202 | 6. Add path to search for libraries ( path to directory withlibton_client.a ) **$(PROJECT_DIR)/SDK/target/universal/release** 203 | 204 | 205 | ![](https://user-images.githubusercontent.com/10519803/101791171-e524b800-3b0b-11eb-98fa-29b7a50c3b67.png) 206 | 207 | 7. __File > Swift Packages > Add Package Dependency__ **https://github.com/nerzh/ton-client-swift** 208 | 209 | 210 | ![](https://user-images.githubusercontent.com/10519803/101791238-fa99e200-3b0b-11eb-99f3-8e8120c57e96.png) 211 | 212 | 8. Build project ... 213 | 214 | ## Tests 215 | ### If you use Xcode for Test 216 | 217 | Please, set custom working directory to project folder for your xcode scheme. This is necessary for the relative path "./" to this library folders. 218 | You may change it with the xcode edit scheme menu __Product > Scheme > Edit Scheme__ menu __Run__ submenu __Options__ enable checkbox "Use custom directory" and add custom working directory. 219 | 220 | Or if above variant not available, then inside file path_to_this_library/.swiftpm/xcode/xcshareddata/xcschemes/TonClientSwift.xcscheme 221 | set to tag __"LaunchAction"__ absolute path to this library with options: 222 | **useCustomWorkingDirectory = "YES"** 223 | **customWorkingDirectory = "/path_to_this_library"** 224 | 225 | 226 | ### Tests 227 | 228 | 1. inside root directory of everscale-client-swift create **.env.debug** file with 229 | NET TON DEV 230 | ``` 231 | server_address=https://net.ton.dev 232 | giver_address=0:653b9a6452c7a982c6dc92b2da9eba832ade1c467699ebb3b43dca6d77b780dd 233 | giver_abi_name=Giver 234 | giver_function=grant 235 | ``` 236 | **Optional:** Install locale NodeSE for tests if you needed: 237 | - launch docker 238 | - docker run -d --name local-node -p 80:80 tonlabs/local-node 239 | nodeSE will start on localhost:80 240 | ``` 241 | server_address=http://localhost:80 242 | giver_abi_name=GiverNodeSE_v2 243 | giver_amount=10000000000 244 | ``` 245 | 246 | 2. Run Tests 247 | __MacOS:__ 248 | Run Tests inside Xcode 249 | __Linux:__ 250 | swift test --generate-linuxmain 251 | swift test --enable-test-discovery 252 | 253 | ### Update SDK 254 | 255 | ```bash 256 | cd everscale-client-swift 257 | ``` 258 | ```bash 259 | bash api_generate.sh 260 | ``` 261 | -------------------------------------------------------------------------------- /Sources/CTonSDK/module.modulemap: -------------------------------------------------------------------------------- 1 | module CTonSDK { 2 | header "shim.h" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Sources/CTonSDK/shim.h: -------------------------------------------------------------------------------- 1 | #ifndef shim_h 2 | #define shim_h 3 | #include "stdbool.h" 4 | #include "tonclient.h" 5 | #endif 6 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Binding/Binding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleh Hudeichuk on 18.10.2020. 3 | // 4 | 5 | import Foundation 6 | import CTonSDK 7 | import SwiftExtensionsPack 8 | 9 | public protocol TSDKBindingPrtcl { 10 | 11 | var context: UInt32 { get } 12 | static func convertToTSDKString(_ string: String, _ handler: (_ tsdkString: tc_string_data_t) throws -> Void) throws 13 | static func convertFromTSDKString(_ tsdkString: tc_string_data_t) throws -> String 14 | static func convertTSDKStringPointerToString(_ tsdkStringPointer: OpaquePointer) throws -> String 15 | static func convertTSDKStringToDictionary(_ tsdkString: tc_string_data_t) throws -> [String: Any]? 16 | static func convertTSDKStringPointerToDictionary(_ tsdkStringPointer: OpaquePointer) throws -> [String: Any]? 17 | } 18 | 19 | 20 | // MARK: Binding Helpers 21 | 22 | public final class TSDKBindingModule: TSDKBindingPrtcl { 23 | 24 | public var context: UInt32 = .init() 25 | 26 | public init(config: TSDKClientConfig = TSDKClientConfig()) throws { 27 | self.context = try createContext(config: config) 28 | } 29 | 30 | public static func convertToTSDKString(_ string: String, _ handler: (_ tsdkString: tc_string_data_t) throws -> Void) throws { 31 | try string.getPointer { (ptr: UnsafePointer, len: Int) in 32 | try handler(tc_string_data_t.init(content: ptr, len: UInt32(len))) 33 | } 34 | } 35 | 36 | public static func convertFromTSDKString(_ tsdkString: tc_string_data_t) throws -> String { 37 | let data = Data(bytes: tsdkString.content, count: Int(tsdkString.len)) 38 | guard let s = String(data: data, encoding: .utf8) else { 39 | throw TSDKClientError.init(code: 0, message: "convertFromTSDKString NOT VALID") 40 | } 41 | return s 42 | } 43 | 44 | public static func convertTSDKStringPointerToString(_ tsdkStringPointer: OpaquePointer) -> String { 45 | let tsdkString: tc_string_data_t = tc_read_string(tsdkStringPointer) 46 | defer { tc_destroy_string(tsdkStringPointer) } 47 | return String(cString: UnsafeRawPointer(tsdkString.content).bindMemory(to: CChar.self, capacity: Int(tsdkString.len))) 48 | } 49 | 50 | public static func convertTSDKStringPointerToDictionary(_ tsdkStringPointer: OpaquePointer) -> [String: Any]? { 51 | let string: String = convertTSDKStringPointerToString(tsdkStringPointer) 52 | return string.toDictionary() 53 | } 54 | 55 | public static func convertTSDKStringToDictionary(_ tsdkString: tc_string_data_t) throws -> [String: Any]? { 56 | let string: String = try convertFromTSDKString(tsdkString) 57 | return string.toDictionary() 58 | } 59 | 60 | private func createContext(config: TSDKClientConfig) throws -> UInt32 { 61 | var contextId: UInt32 = .init() 62 | let json: String = config.toJson ?? "{}" 63 | try Self.convertToTSDKString(json) { config in 64 | let ctx: OpaquePointer = tc_create_context(config) 65 | let contextResponse: TSDKContextResponse = try Self.convertFromTSDKString(tc_read_string(ctx)).toModel(TSDKContextResponse.self) 66 | defer { tc_destroy_string(ctx) } 67 | if let context = contextResponse.result { 68 | contextId = context 69 | } else { 70 | fatalError(contextResponse.error.debugDescription) 71 | } 72 | } 73 | return contextId 74 | } 75 | 76 | public func destroyContext() { 77 | tc_destroy_context(context) 78 | } 79 | 80 | public func requestLibraryAsync(_ methodName: String, 81 | _ payload: Encodable = "", 82 | _ requestHandler: @escaping @Sendable (_ requestId: UInt32, 83 | _ stringResponse: String, 84 | _ responseType: TSDKBindingResponseType, 85 | _ finished: Bool) throws -> Void 86 | ) throws { 87 | try Self.convertToTSDKString(methodName) { [weak self] tsdkMethodName in 88 | guard let self = self else { return } 89 | let payload = payload.toJson ?? "" 90 | try Self.convertToTSDKString(payload) { tsdkPayload in 91 | let requestId: UInt32 = BindingStore.generate_request_id() 92 | BindingStore.addResponseHandler(requestId, requestHandler) 93 | tc_request(self.context, 94 | tsdkMethodName, 95 | tsdkPayload, 96 | requestId 97 | ) { (requestId: UInt32, params: tc_string_data_t, responseType: UInt32, finished: Bool) in 98 | let responseHandler = BindingStore.getResponseHandler(requestId) 99 | do { 100 | let swiftString: String = try TSDKBindingModule.convertFromTSDKString(params) 101 | let responseType: TSDKBindingResponseType = (TSDKBindingResponseType.init(rawValue: responseType) ?? .unknown)! 102 | 103 | try responseHandler?(requestId, swiftString, responseType, finished) 104 | if finished || responseType == .responseError { 105 | BindingStore.deleteResponseHandler(requestId) 106 | } 107 | } catch { 108 | BindingStore.deleteResponseHandler(requestId) 109 | try? responseHandler?( 110 | requestId, 111 | [ 112 | "code": 0, 113 | "message": String(describing: error), 114 | "data": ([:] as [String: Any]).toAnyValue() 115 | ].toAnyValue().toJSON(), 116 | .responseError, 117 | true) 118 | } 119 | } 120 | } 121 | } 122 | } 123 | 124 | public func requestLibraryAsyncAwait(_ methodName: String, 125 | _ payload: Encodable = "", 126 | _ requestHandler: @escaping @Sendable (_ requestId: UInt32, 127 | _ stringResponse: String, 128 | _ responseType: TSDKBindingResponseType, 129 | _ finished: Bool) throws -> Void 130 | ) throws { 131 | try Self.convertToTSDKString(methodName) { [weak self] tsdkMethodName in 132 | guard let self = self else { return } 133 | let payload = payload.toJson ?? "" 134 | try Self.convertToTSDKString(payload) { tsdkPayload in 135 | let requestId: UInt32 = BindingStore.generate_request_id() 136 | BindingStore.addResponseHandler(requestId, requestHandler) 137 | tc_request(self.context, 138 | tsdkMethodName, 139 | tsdkPayload, 140 | requestId 141 | ) { (requestId: UInt32, params: tc_string_data_t, responseType: UInt32, finished: Bool) in 142 | let responseHandler = BindingStore.getResponseHandler(requestId) 143 | do { 144 | let swiftString: String = try TSDKBindingModule.convertFromTSDKString(params) 145 | let responseType: TSDKBindingResponseType = (TSDKBindingResponseType.init(rawValue: responseType) ?? .unknown)! 146 | 147 | if !swiftString.isEmpty { 148 | BindingStore.setCompleteResponse(requestId, 149 | (requestId: requestId, 150 | stringResponse: swiftString, 151 | responseType: responseType, 152 | finished: true)) 153 | } 154 | 155 | if finished || responseType == .responseError { 156 | BindingStore.deleteResponseHandler(requestId) 157 | let response: BindingStore.RawResponse = try BindingStore.getCompleteResponse(requestId) 158 | try responseHandler?(response.requestId, response.stringResponse, response.responseType, response.finished) 159 | BindingStore.deleteCompleteResponse(requestId) 160 | } 161 | } catch { 162 | BindingStore.deleteResponseHandler(requestId) 163 | BindingStore.deleteCompleteResponse(requestId) 164 | try? responseHandler?( 165 | requestId, 166 | [ 167 | "code": 0, 168 | "message": String(describing: error), 169 | "data": ([:] as [String: Any]).toAnyValue() 170 | ].toAnyValue().toJSON(), 171 | .responseError, 172 | true) 173 | } 174 | } 175 | } 176 | } 177 | } 178 | 179 | deinit { 180 | #if DEBUG 181 | print("destroyContext()") 182 | #endif 183 | destroyContext() 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Binding/BindingStore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 19.10.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | public final class BindingStore: @unchecked Sendable { 11 | 12 | nonisolated(unsafe) private static var requsetId: UInt32 = .init() 13 | private static let requestLock: NSLock = .init() 14 | private static let asyncResponseLock: NSLock = .init() 15 | nonisolated(unsafe) public static var responses: [UInt32: (_ requestId: UInt32, 16 | _ stringResponse: String, 17 | _ responseType: TSDKBindingResponseType, 18 | _ finished: Bool) throws -> Void] = .init() 19 | 20 | /// BECAUSE SDK METHODS LIKE PROCESS MESSAGE RETURNED TWO RESPONSE 21 | /// FIRST REAL RESPONSE AND LAST EMPTY STRING WITH STATUS FINISHED 22 | public typealias RawResponse = (requestId: UInt32, 23 | stringResponse: String, 24 | responseType: TSDKBindingResponseType, 25 | finished: Bool) 26 | nonisolated(unsafe) public static var completeResponses: [UInt32: RawResponse] = [:] 27 | nonisolated(unsafe) public static var completeResponsesLock: NSLock = .init() 28 | 29 | public class func setCompleteResponse(_ id: UInt32, _ response: RawResponse) { 30 | completeResponsesLock.lock() 31 | defer { completeResponsesLock.unlock() } 32 | completeResponses[id] = response 33 | } 34 | 35 | public class func getCompleteResponse(_ id: UInt32) throws -> RawResponse { 36 | completeResponsesLock.lock() 37 | defer { completeResponsesLock.unlock() } 38 | guard let result = completeResponses[id] else { throw TSDKClientError("\(id) not found") } 39 | return result 40 | } 41 | 42 | public class func deleteCompleteResponse(_ id: UInt32) { 43 | completeResponsesLock.lock() 44 | defer { completeResponsesLock.unlock() } 45 | completeResponses[id] = nil 46 | } 47 | 48 | public class func addResponseHandler(_ requestId: UInt32, 49 | _ response: @escaping @Sendable (_ requestId: UInt32, 50 | _ stringResponse: String, 51 | _ responseType: TSDKBindingResponseType, 52 | _ finished: Bool) throws -> Void 53 | ) { 54 | asyncResponseLock.lock() 55 | responses[requestId] = response 56 | asyncResponseLock.unlock() 57 | } 58 | 59 | public class func getResponseHandler(_ requestId: UInt32) -> ((_ requestId: UInt32, 60 | _ stringResponse: String, 61 | _ responseType: TSDKBindingResponseType, 62 | _ finished: Bool) throws -> Void)? { 63 | asyncResponseLock.lock() 64 | defer { asyncResponseLock.unlock() } 65 | return responses[requestId] 66 | } 67 | 68 | public class func deleteResponseHandler(_ requestId: UInt32) { 69 | asyncResponseLock.lock() 70 | defer { asyncResponseLock.unlock() } 71 | responses[requestId] = nil 72 | } 73 | 74 | public class func generate_request_id() -> UInt32 { 75 | requestLock.lock() 76 | defer { requestLock.unlock() } 77 | if requsetId == UInt32.max { 78 | requsetId = 0 79 | } 80 | requsetId += 1 81 | return requsetId 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Binding/BindingTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleh Hudeichuk on 18.10.2020. 3 | // 4 | 5 | import Foundation 6 | import SwiftExtensionsPack 7 | 8 | public struct TSDKContextResponse: Codable { 9 | public var result: UInt32? 10 | public var error: AnyValue? 11 | } 12 | 13 | public struct TSDKBindingRequest { 14 | public var result: (_ result: TSDKResult?) -> Void 15 | public var error: (_ error: TSDKError?) -> Void 16 | public var customHandler: (_ params: TSDKCustom?) -> Void 17 | } 18 | 19 | public enum TSDKBindingResponseType: UInt32 { 20 | case responseSuccess = 0 21 | case responseError = 1 22 | case responseNop = 2 23 | case responseCustom = 100 24 | case unknown 25 | } 26 | 27 | public struct TSDKNoneResult: Codable, Sendable {} 28 | 29 | public struct TSDKDefault: Codable { 30 | public var result: AnyValue? 31 | public var error: AnyValue? 32 | public var data: AnyValue? 33 | public var message: AnyValue? 34 | public var code: AnyValue? 35 | 36 | public init(result: AnyValue? = nil, error: AnyValue? = nil, data: AnyValue? = nil, message: AnyValue? = nil, code: AnyValue? = nil) { 37 | self.result = result 38 | self.error = error 39 | self.data = data 40 | self.message = message 41 | self.code = code 42 | } 43 | } 44 | 45 | public struct TSDKBindingResponse { 46 | public var result: TSDKResult? 47 | public var error: TSDKError? 48 | public var dappError: TSDKError? 49 | public var finished: Bool = false 50 | public var requestId: UInt32 = 0 51 | public var rawResponse: String = .init() 52 | 53 | public init(result: TSDKResult? = nil, 54 | error: TSDKError? = nil, 55 | dappError: TSDKError? = nil, 56 | finished: Bool = false, 57 | requestId: UInt32 = 0, 58 | rawResponse: String = .init() 59 | ) { 60 | self.result = result 61 | self.error = error 62 | self.dappError = dappError 63 | self.finished = finished 64 | self.requestId = requestId 65 | self.rawResponse = rawResponse 66 | } 67 | 68 | public mutating func update(_ requestId: UInt32, 69 | _ rawResponse: String, 70 | _ responseType: TSDKBindingResponseType, 71 | _ finished: Bool 72 | ) { 73 | self.finished = finished 74 | self.requestId = requestId 75 | self.rawResponse = rawResponse 76 | 77 | switch responseType { 78 | case .responseSuccess: 79 | result = rawResponse.toModel(TSDKResult.self) 80 | case .responseError: 81 | error = rawResponse.toModel(TSDKError.self) 82 | Log.warn(error ?? "RESPONSE TYPE ERROR, BUT ERROR IS NIL") 83 | case .responseCustom: 84 | result = rawResponse.toModel(TSDKResult.self) 85 | case .responseNop: 86 | result = rawResponse.toModel(TSDKResult.self) 87 | default: 88 | dappError = rawResponse.toModel(TSDKError.self) 89 | Log.warn(error ?? "responseType NOT FOUND and dappError not parsed. Raw Response\n\(rawResponse)") 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Client/Client.swift: -------------------------------------------------------------------------------- 1 | public final class TSDKClientModule { 2 | 3 | private var binding: TSDKBindingModule 4 | public let module: String = "client" 5 | public let config: TSDKClientConfig 6 | public var crypto: TSDKCryptoModule 7 | public var abi: TSDKAbiModule 8 | public var boc: TSDKBocModule 9 | public var processing: TSDKProcessingModule 10 | public var utils: TSDKUtilsModule 11 | public var tvm: TSDKTvmModule 12 | public var net: TSDKNetModule 13 | public var debot: TSDKDebotModule 14 | public var proofs: TSDKProofsModule 15 | 16 | public init(config: TSDKClientConfig) throws { 17 | self.config = config 18 | self.binding = try TSDKBindingModule(config: config) 19 | self.crypto = TSDKCryptoModule(binding: binding) 20 | self.abi = TSDKAbiModule(binding: binding) 21 | self.boc = TSDKBocModule(binding: binding) 22 | self.processing = TSDKProcessingModule(binding: binding) 23 | self.utils = TSDKUtilsModule(binding: binding) 24 | self.tvm = TSDKTvmModule(binding: binding) 25 | self.net = TSDKNetModule(binding: binding) 26 | self.debot = TSDKDebotModule(binding: binding) 27 | self.proofs = TSDKProofsModule(binding: binding) 28 | } 29 | 30 | /// Returns Core Library API reference 31 | public func get_api_reference(_ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 32 | ) throws { 33 | let method: String = "get_api_reference" 34 | try binding.requestLibraryAsync(methodName(module, method), "") { (requestId, params, responseType, finished) in 35 | var response: TSDKBindingResponse = .init() 36 | response.update(requestId, params, responseType, finished) 37 | try handler(response) 38 | } 39 | } 40 | 41 | /// Returns Core Library API reference 42 | @available(iOS 13, *) 43 | @available(macOS 12, *) 44 | public func get_api_reference() async throws -> TSDKResultOfGetApiReference { 45 | try await withCheckedThrowingContinuation { continuation in 46 | do { 47 | let method: String = "get_api_reference" 48 | try binding.requestLibraryAsyncAwait(methodName(module, method), "") { (requestId, params, responseType, finished) in 49 | var response: TSDKBindingResponse = .init() 50 | response.update(requestId, params, responseType, finished) 51 | if let error = response.error { 52 | continuation.resume(throwing: error) 53 | } else if let result = response.result { 54 | continuation.resume(returning: result) 55 | } else { 56 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 57 | } 58 | } 59 | } catch { 60 | continuation.resume(throwing: error) 61 | } 62 | } 63 | } 64 | 65 | /// Returns Core Library version 66 | public func version(_ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 67 | ) throws { 68 | let method: String = "version" 69 | try binding.requestLibraryAsync(methodName(module, method), "") { (requestId, params, responseType, finished) in 70 | var response: TSDKBindingResponse = .init() 71 | response.update(requestId, params, responseType, finished) 72 | try handler(response) 73 | } 74 | } 75 | 76 | /// Returns Core Library version 77 | @available(iOS 13, *) 78 | @available(macOS 12, *) 79 | public func version() async throws -> TSDKResultOfVersion { 80 | try await withCheckedThrowingContinuation { continuation in 81 | do { 82 | let method: String = "version" 83 | try binding.requestLibraryAsyncAwait(methodName(module, method), "") { (requestId, params, responseType, finished) in 84 | var response: TSDKBindingResponse = .init() 85 | response.update(requestId, params, responseType, finished) 86 | if let error = response.error { 87 | continuation.resume(throwing: error) 88 | } else if let result = response.result { 89 | continuation.resume(returning: result) 90 | } else { 91 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 92 | } 93 | } 94 | } catch { 95 | continuation.resume(throwing: error) 96 | } 97 | } 98 | } 99 | 100 | /// Returns Core Library API reference 101 | public func config(_ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 102 | ) throws { 103 | let method: String = "config" 104 | try binding.requestLibraryAsync(methodName(module, method), "") { (requestId, params, responseType, finished) in 105 | var response: TSDKBindingResponse = .init() 106 | response.update(requestId, params, responseType, finished) 107 | try handler(response) 108 | } 109 | } 110 | 111 | /// Returns Core Library API reference 112 | @available(iOS 13, *) 113 | @available(macOS 12, *) 114 | public func config() async throws -> TSDKClientConfig { 115 | try await withCheckedThrowingContinuation { continuation in 116 | do { 117 | let method: String = "config" 118 | try binding.requestLibraryAsyncAwait(methodName(module, method), "") { (requestId, params, responseType, finished) in 119 | var response: TSDKBindingResponse = .init() 120 | response.update(requestId, params, responseType, finished) 121 | if let error = response.error { 122 | continuation.resume(throwing: error) 123 | } else if let result = response.result { 124 | continuation.resume(returning: result) 125 | } else { 126 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 127 | } 128 | } 129 | } catch { 130 | continuation.resume(throwing: error) 131 | } 132 | } 133 | } 134 | 135 | /// Returns detailed information about this build. 136 | public func build_info(_ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 137 | ) throws { 138 | let method: String = "build_info" 139 | try binding.requestLibraryAsync(methodName(module, method), "") { (requestId, params, responseType, finished) in 140 | var response: TSDKBindingResponse = .init() 141 | response.update(requestId, params, responseType, finished) 142 | try handler(response) 143 | } 144 | } 145 | 146 | /// Returns detailed information about this build. 147 | @available(iOS 13, *) 148 | @available(macOS 12, *) 149 | public func build_info() async throws -> TSDKResultOfBuildInfo { 150 | try await withCheckedThrowingContinuation { continuation in 151 | do { 152 | let method: String = "build_info" 153 | try binding.requestLibraryAsyncAwait(methodName(module, method), "") { (requestId, params, responseType, finished) in 154 | var response: TSDKBindingResponse = .init() 155 | response.update(requestId, params, responseType, finished) 156 | if let error = response.error { 157 | continuation.resume(throwing: error) 158 | } else if let result = response.result { 159 | continuation.resume(returning: result) 160 | } else { 161 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 162 | } 163 | } 164 | } catch { 165 | continuation.resume(throwing: error) 166 | } 167 | } 168 | } 169 | 170 | /// Resolves application request processing result 171 | public func resolve_app_request(_ payload: TSDKParamsOfResolveAppRequest, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 172 | ) throws { 173 | let method: String = "resolve_app_request" 174 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 175 | var response: TSDKBindingResponse = .init() 176 | response.update(requestId, params, responseType, finished) 177 | try handler(response) 178 | } 179 | } 180 | 181 | /// Resolves application request processing result 182 | @available(iOS 13, *) 183 | @available(macOS 12, *) 184 | public func resolve_app_request(_ payload: TSDKParamsOfResolveAppRequest) async throws -> TSDKNoneResult { 185 | try await withCheckedThrowingContinuation { continuation in 186 | do { 187 | let method: String = "resolve_app_request" 188 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 189 | var response: TSDKBindingResponse = .init() 190 | response.update(requestId, params, responseType, finished) 191 | if let error = response.error { 192 | continuation.resume(throwing: error) 193 | } else if let result = response.result { 194 | continuation.resume(returning: result) 195 | } else { 196 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 197 | } 198 | } 199 | } catch { 200 | continuation.resume(throwing: error) 201 | } 202 | } 203 | } 204 | 205 | deinit { 206 | print("Client DEINIT !") 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Debot/DebotTypes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftExtensionsPack 3 | 4 | 5 | public typealias TSDKDebotHandle = UInt32 6 | 7 | public enum TSDKDebotErrorCode: Int, Codable { 8 | case DebotStartFailed = 801 9 | case DebotFetchFailed = 802 10 | case DebotExecutionFailed = 803 11 | case DebotInvalidHandle = 804 12 | case DebotInvalidJsonParams = 805 13 | case DebotInvalidFunctionId = 806 14 | case DebotInvalidAbi = 807 15 | case DebotGetMethodFailed = 808 16 | case DebotInvalidMsg = 809 17 | case DebotExternalCallFailed = 810 18 | case DebotBrowserCallbackFailed = 811 19 | case DebotOperationRejected = 812 20 | case DebotNoCode = 813 21 | } 22 | 23 | public enum TSDKDebotActivityEnumTypes: String, Codable { 24 | case Transaction = "Transaction" 25 | } 26 | 27 | public enum TSDKParamsOfAppDebotBrowserEnumTypes: String, Codable { 28 | case Log = "Log" 29 | case Switch = "Switch" 30 | case SwitchCompleted = "SwitchCompleted" 31 | case ShowAction = "ShowAction" 32 | case Input = "Input" 33 | case GetSigningBox = "GetSigningBox" 34 | case InvokeDebot = "InvokeDebot" 35 | case Send = "Send" 36 | case Approve = "Approve" 37 | } 38 | 39 | public enum TSDKResultOfAppDebotBrowserEnumTypes: String, Codable { 40 | case Input = "Input" 41 | case GetSigningBox = "GetSigningBox" 42 | case InvokeDebot = "InvokeDebot" 43 | case Approve = "Approve" 44 | } 45 | 46 | public struct TSDKDebotAction: Codable, @unchecked Sendable { 47 | /// A short action description. 48 | /// Should be used by Debot Browser as name of menu item. 49 | public var description: String 50 | /// Depends on action type. 51 | /// Can be a debot function name or a print string (for Print Action). 52 | public var name: String 53 | /// Action type. 54 | public var action_type: UInt8 55 | /// ID of debot context to switch after action execution. 56 | public var to: UInt8 57 | /// Action attributes. 58 | /// In the form of "param=value,flag". attribute example: instant, args, fargs, sign. 59 | public var attributes: String 60 | /// Some internal action data. 61 | /// Used by debot only. 62 | public var misc: String 63 | 64 | public init(description: String, name: String, action_type: UInt8, to: UInt8, attributes: String, misc: String) { 65 | self.description = description 66 | self.name = name 67 | self.action_type = action_type 68 | self.to = to 69 | self.attributes = attributes 70 | self.misc = misc 71 | } 72 | } 73 | 74 | public struct TSDKDebotInfo: Codable, @unchecked Sendable { 75 | /// DeBot short name. 76 | public var name: String? 77 | /// DeBot semantic version. 78 | public var version: String? 79 | /// The name of DeBot deployer. 80 | public var publisher: String? 81 | /// Short info about DeBot. 82 | public var caption: String? 83 | /// The name of DeBot developer. 84 | public var author: String? 85 | /// TON address of author for questions and donations. 86 | public var support: String? 87 | /// String with the first messsage from DeBot. 88 | public var hello: String? 89 | /// String with DeBot interface language (ISO-639). 90 | public var language: String? 91 | /// String with DeBot ABI. 92 | public var dabi: String? 93 | /// DeBot icon. 94 | public var icon: String? 95 | /// Vector with IDs of DInterfaces used by DeBot. 96 | public var interfaces: [String] 97 | /// ABI version ("x.y") supported by DeBot 98 | public var dabiVersion: String 99 | 100 | public init(name: String? = nil, version: String? = nil, publisher: String? = nil, caption: String? = nil, author: String? = nil, support: String? = nil, hello: String? = nil, language: String? = nil, dabi: String? = nil, icon: String? = nil, interfaces: [String], dabiVersion: String) { 101 | self.name = name 102 | self.version = version 103 | self.publisher = publisher 104 | self.caption = caption 105 | self.author = author 106 | self.support = support 107 | self.hello = hello 108 | self.language = language 109 | self.dabi = dabi 110 | self.icon = icon 111 | self.interfaces = interfaces 112 | self.dabiVersion = dabiVersion 113 | } 114 | } 115 | 116 | public struct TSDKDebotActivity: Codable, @unchecked Sendable { 117 | public var type: TSDKDebotActivityEnumTypes 118 | /// External inbound message BOC. 119 | public var msg: String? 120 | /// Target smart contract address. 121 | public var dst: String? 122 | /// List of spendings as a result of transaction. 123 | public var out: [TSDKSpending]? 124 | /// Transaction total fee. 125 | public var fee: Int? 126 | /// Indicates if target smart contract updates its code. 127 | public var setcode: Bool? 128 | /// Public key from keypair that was used to sign external message. 129 | public var signkey: String? 130 | /// Signing box handle used to sign external message. 131 | public var signing_box_handle: UInt32? 132 | 133 | public init(type: TSDKDebotActivityEnumTypes, msg: String? = nil, dst: String? = nil, out: [TSDKSpending]? = nil, fee: Int? = nil, setcode: Bool? = nil, signkey: String? = nil, signing_box_handle: UInt32? = nil) { 134 | self.type = type 135 | self.msg = msg 136 | self.dst = dst 137 | self.out = out 138 | self.fee = fee 139 | self.setcode = setcode 140 | self.signkey = signkey 141 | self.signing_box_handle = signing_box_handle 142 | } 143 | } 144 | 145 | /// [UNSTABLE](UNSTABLE.md) [DEPRECATED](DEPRECATED.md) Describes the operation that the DeBot wants to perform. 146 | public struct TSDKSpending: Codable, @unchecked Sendable { 147 | /// Amount of nanotokens that will be sent to `dst` address. 148 | public var amount: Int 149 | /// Destination address of recipient of funds. 150 | public var dst: String 151 | 152 | public init(amount: Int, dst: String) { 153 | self.amount = amount 154 | self.dst = dst 155 | } 156 | } 157 | 158 | public struct TSDKParamsOfInit: Codable, @unchecked Sendable { 159 | /// Debot smart contract address 160 | public var address: String 161 | 162 | public init(address: String) { 163 | self.address = address 164 | } 165 | } 166 | 167 | public struct TSDKRegisteredDebot: Codable, @unchecked Sendable { 168 | /// Debot handle which references an instance of debot engine. 169 | public var debot_handle: TSDKDebotHandle 170 | /// Debot abi as json string. 171 | public var debot_abi: String 172 | /// Debot metadata. 173 | public var info: TSDKDebotInfo 174 | 175 | public init(debot_handle: TSDKDebotHandle, debot_abi: String, info: TSDKDebotInfo) { 176 | self.debot_handle = debot_handle 177 | self.debot_abi = debot_abi 178 | self.info = info 179 | } 180 | } 181 | 182 | public struct TSDKParamsOfAppDebotBrowser: Codable, @unchecked Sendable { 183 | public var type: TSDKParamsOfAppDebotBrowserEnumTypes 184 | /// A string that must be printed to user. 185 | public var msg: String? 186 | /// Debot context ID to which debot is switched. 187 | public var context_id: UInt8? 188 | /// Debot action that must be shown to user as menu item. At least `description` property must be shown from [DebotAction] structure. 189 | public var action: TSDKDebotAction? 190 | /// A prompt string that must be printed to user before input request. 191 | public var prompt: String? 192 | /// Address of debot in blockchain. 193 | public var debot_addr: String? 194 | /// Internal message to DInterface address. 195 | /// Message body contains interface function and parameters. 196 | public var message: String? 197 | /// DeBot activity details. 198 | public var activity: TSDKDebotActivity? 199 | 200 | public init(type: TSDKParamsOfAppDebotBrowserEnumTypes, msg: String? = nil, context_id: UInt8? = nil, action: TSDKDebotAction? = nil, prompt: String? = nil, debot_addr: String? = nil, message: String? = nil, activity: TSDKDebotActivity? = nil) { 201 | self.type = type 202 | self.msg = msg 203 | self.context_id = context_id 204 | self.action = action 205 | self.prompt = prompt 206 | self.debot_addr = debot_addr 207 | self.message = message 208 | self.activity = activity 209 | } 210 | } 211 | 212 | /// [UNSTABLE](UNSTABLE.md) [DEPRECATED](DEPRECATED.md) Debot Browser callbacks 213 | /// Called by debot engine to communicate with debot browser. 214 | public struct TSDKResultOfAppDebotBrowser: Codable, @unchecked Sendable { 215 | public var type: TSDKResultOfAppDebotBrowserEnumTypes 216 | /// String entered by user. 217 | public var value: String? 218 | /// Signing box for signing data requested by debot engine. 219 | /// Signing box is owned and disposed by debot engine 220 | public var signing_box: TSDKSigningBoxHandle? 221 | /// Indicates whether the DeBot is allowed to perform the specified operation. 222 | public var approved: Bool? 223 | 224 | public init(type: TSDKResultOfAppDebotBrowserEnumTypes, value: String? = nil, signing_box: TSDKSigningBoxHandle? = nil, approved: Bool? = nil) { 225 | self.type = type 226 | self.value = value 227 | self.signing_box = signing_box 228 | self.approved = approved 229 | } 230 | } 231 | 232 | /// [UNSTABLE](UNSTABLE.md) [DEPRECATED](DEPRECATED.md) Returning values from Debot Browser callbacks. 233 | public struct TSDKParamsOfStart: Codable, @unchecked Sendable { 234 | /// Debot handle which references an instance of debot engine. 235 | public var debot_handle: TSDKDebotHandle 236 | 237 | public init(debot_handle: TSDKDebotHandle) { 238 | self.debot_handle = debot_handle 239 | } 240 | } 241 | 242 | public struct TSDKParamsOfFetch: Codable, @unchecked Sendable { 243 | /// Debot smart contract address. 244 | public var address: String 245 | 246 | public init(address: String) { 247 | self.address = address 248 | } 249 | } 250 | 251 | public struct TSDKResultOfFetch: Codable, @unchecked Sendable { 252 | /// Debot metadata. 253 | public var info: TSDKDebotInfo 254 | 255 | public init(info: TSDKDebotInfo) { 256 | self.info = info 257 | } 258 | } 259 | 260 | public struct TSDKParamsOfExecute: Codable, @unchecked Sendable { 261 | /// Debot handle which references an instance of debot engine. 262 | public var debot_handle: TSDKDebotHandle 263 | /// Debot Action that must be executed. 264 | public var action: TSDKDebotAction 265 | 266 | public init(debot_handle: TSDKDebotHandle, action: TSDKDebotAction) { 267 | self.debot_handle = debot_handle 268 | self.action = action 269 | } 270 | } 271 | 272 | public struct TSDKParamsOfSend: Codable, @unchecked Sendable { 273 | /// Debot handle which references an instance of debot engine. 274 | public var debot_handle: TSDKDebotHandle 275 | /// BOC of internal message to debot encoded in base64 format. 276 | public var message: String 277 | 278 | public init(debot_handle: TSDKDebotHandle, message: String) { 279 | self.debot_handle = debot_handle 280 | self.message = message 281 | } 282 | } 283 | 284 | public struct TSDKParamsOfRemove: Codable, @unchecked Sendable { 285 | /// Debot handle which references an instance of debot engine. 286 | public var debot_handle: TSDKDebotHandle 287 | 288 | public init(debot_handle: TSDKDebotHandle) { 289 | self.debot_handle = debot_handle 290 | } 291 | } 292 | 293 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Extensions/FileReader.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 22.10.2020. 6 | // 7 | 8 | import Foundation 9 | 10 | public final class DOFileReader { 11 | 12 | public let fileURL: URL 13 | private var file: UnsafeMutablePointer? = nil 14 | 15 | public init(fileURL: URL) { 16 | self.fileURL = fileURL 17 | } 18 | 19 | deinit { 20 | if self.file != nil { fatalError("Please, close file descriptor.") } 21 | } 22 | 23 | public func open(options: String = "r") throws { 24 | guard let descriptor = fopen(fileURL.path, options) else { 25 | throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil) 26 | } 27 | self.file = descriptor 28 | } 29 | 30 | public func close() { 31 | if let descriptor = self.file { 32 | self.file = nil 33 | let success: Bool = fclose(descriptor) == 0 34 | assert(success) 35 | } 36 | } 37 | 38 | public func readLine(maxLength: Int = 4096) throws -> String? { 39 | guard let descriptor = self.file else { 40 | throw NSError(domain: NSPOSIXErrorDomain, code: Int(EBADF), userInfo: nil) 41 | } 42 | var buffer = [CChar](repeating: 0, count: maxLength) 43 | guard fgets(&buffer, Int32(maxLength), descriptor) != nil else { 44 | if feof(descriptor) != 0 { 45 | return nil 46 | } else { 47 | throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: nil) 48 | } 49 | } 50 | 51 | return String(cString: buffer) 52 | } 53 | 54 | public static func readFile(_ fileURL: URL, _ options: String = "r", _ handler: (_ line: String) -> Void) { 55 | let file: DOFileReader = .init(fileURL: fileURL) 56 | do { 57 | try file.open(options: options) 58 | defer { file.close() } 59 | while let line: String = try file.readLine() { 60 | handler(line) 61 | } 62 | } catch let error { 63 | let message: String = "Please, check working directory in schema for this project. Current workingDirectory is \(ProcessInfo.processInfo.environment["PWD"])" 64 | fatalError("\(String(describing: error)) \(message) ErrorFilePath: \(fileURL.path)") 65 | } 66 | } 67 | 68 | public static func readFile(_ filePath: String, _ options: String = "r", _ handler: (_ line: String) -> Void) { 69 | guard let fileURL: URL = URL(string: filePath) else { fatalError("Can not convert \(filePath) to URL") } 70 | readFile(fileURL, options, handler) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Extensions/Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleh Hudeichuk on 18.10.2020. 3 | // 4 | 5 | import Foundation 6 | 7 | func methodName(_ module: String, _ method: String) -> String { 8 | "\(module).\(method)" 9 | } 10 | 11 | class Log { 12 | 13 | class func log(_ str: Any...) { 14 | print("❇️ logi:", str) 15 | } 16 | 17 | class func warn(_ str: Any...) { 18 | print("⚠️ logi:", str) 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Extensions/SimpleEnv.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleh Hudeichuk on 17.11.2020. 3 | // 4 | 5 | import Foundation 6 | import SwiftRegularExpression 7 | 8 | 9 | public final class SimpleEnv { 10 | 11 | nonisolated(unsafe) private static var env: [String: String] = .init() 12 | private static let debugEnvName: String = "debug" 13 | private static let adhocEnvName: String = "production" 14 | private static let productionEnvName: String = "production" 15 | 16 | nonisolated(unsafe) public static var path: String = "./" 17 | 18 | public class subscript(_ key: String) -> String? { 19 | if env.count == 0 { 20 | parseEnv() 21 | } 22 | return env[key] 23 | } 24 | 25 | private class func parseEnv() { 26 | #if DEBUG 27 | let environment: String = debugEnvName 28 | #elseif ADHOC 29 | let environment: String = adhocEnvName 30 | #else 31 | let environment: String = productionEnvName 32 | #endif 33 | 34 | let envFileName: String = ".env.\(environment)" 35 | let envFilePath: String = "\(path)/\(envFileName)" 36 | if !FileManager.default.fileExists(atPath: envFilePath) { return } 37 | 38 | DOFileReader.readFile("\(path)/\(envFileName)") { (line) in 39 | let line = line.trimmingCharacters(in: .whitespacesAndNewlines) 40 | let matchesWithQuotes: [Int: String] = line.regexp(#"\"([\s\S]+)\"\s*=\s*\"([\s\S]+)\""#) 41 | if line[#"^\/\/"#] { return } 42 | if let key: String = matchesWithQuotes[1], let value: String = matchesWithQuotes[2] { 43 | env[key] = value 44 | return 45 | } 46 | let matchesWithOutQuotes: [Int: String] = line.regexp(#"([\s\S]+)\s*=\s*([\s\S]+)"#) 47 | if let key: String = matchesWithOutQuotes[1], let value: String = matchesWithOutQuotes[2] { 48 | env[key] = value 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Proofs/ProofsTypes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftExtensionsPack 3 | 4 | 5 | public enum TSDKProofsErrorCode: Int, Codable { 6 | case InvalidData = 901 7 | case ProofCheckFailed = 902 8 | case InternalError = 903 9 | case DataDiffersFromProven = 904 10 | } 11 | 12 | public struct TSDKParamsOfProofBlockData: Codable, @unchecked Sendable { 13 | /// Single block's data, retrieved from TONOS API, that needs proof. Required fields are `id` and/or top-level `boc` (for block identification), others are optional. 14 | public var block: AnyValue 15 | 16 | public init(block: AnyValue) { 17 | self.block = block 18 | } 19 | } 20 | 21 | public struct TSDKParamsOfProofTransactionData: Codable, @unchecked Sendable { 22 | /// Single transaction's data as queried from DApp server, without modifications. The required fields are `id` and/or top-level `boc`, others are optional. In order to reduce network requests count, it is recommended to provide `block_id` and `boc` of transaction. 23 | public var transaction: AnyValue 24 | 25 | public init(transaction: AnyValue) { 26 | self.transaction = transaction 27 | } 28 | } 29 | 30 | public struct TSDKParamsOfProofMessageData: Codable, @unchecked Sendable { 31 | /// Single message's data as queried from DApp server, without modifications. The required fields are `id` and/or top-level `boc`, others are optional. In order to reduce network requests count, it is recommended to provide at least `boc` of message and non-null `src_transaction.id` or `dst_transaction.id`. 32 | public var message: AnyValue 33 | 34 | public init(message: AnyValue) { 35 | self.message = message 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Tvm/Tvm.swift: -------------------------------------------------------------------------------- 1 | public final class TSDKTvmModule { 2 | 3 | private var binding: TSDKBindingModule 4 | public let module: String = "tvm" 5 | 6 | public init(binding: TSDKBindingModule) { 7 | self.binding = binding 8 | } 9 | 10 | /// Emulates all the phases of contract execution locally 11 | /// Performs all the phases of contract execution on Transaction Executor -the same component that is used on Validator Nodes. 12 | /// Can be used for contract debugging, to find out the reason why a message was not delivered successfully. 13 | /// Validators throw away the failed external inbound messages (if they failed before `ACCEPT`) in the real network. 14 | /// This is why these messages are impossible to debug in the real network. 15 | /// With the help of run_executor you can do that. In fact, `process_message` functionperforms local check with `run_executor` if there was no transaction as a result of processingand returns the error, if there is one. 16 | /// Another use case to use `run_executor` is to estimate fees for message execution. 17 | /// Set `AccountForExecutor::Account.unlimited_balance`to `true` so that emulation will not depend on the actual balance. 18 | /// This may be needed to calculate deploy fees for an account that does not exist yet. 19 | /// JSON with fees is in `fees` field of the result. 20 | /// One more use case - you can produce the sequence of operations,thus emulating the sequential contract calls locally. 21 | /// And so on. 22 | /// Transaction executor requires account BOC (bag of cells) as a parameter. 23 | /// To get the account BOC - use `net.query` method to download it from GraphQL API(field `boc` of `account`) or generate it with `abi.encode_account` method. 24 | /// Also it requires message BOC. To get the message BOC - use `abi.encode_message` or `abi.encode_internal_message`. 25 | /// If you need this emulation to be as precise as possible (for instance - emulate transactionwith particular lt in particular block or use particular blockchain config,downloaded from a particular key block - then specify `execution_options` parameter. 26 | /// If you need to see the aborted transaction as a result, not as an error, set `skip_transaction_check` to `true`. 27 | public func run_executor(_ payload: TSDKParamsOfRunExecutor, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 28 | ) throws { 29 | let method: String = "run_executor" 30 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 31 | var response: TSDKBindingResponse = .init() 32 | response.update(requestId, params, responseType, finished) 33 | try handler(response) 34 | } 35 | } 36 | 37 | /// Emulates all the phases of contract execution locally 38 | /// Performs all the phases of contract execution on Transaction Executor -the same component that is used on Validator Nodes. 39 | /// Can be used for contract debugging, to find out the reason why a message was not delivered successfully. 40 | /// Validators throw away the failed external inbound messages (if they failed before `ACCEPT`) in the real network. 41 | /// This is why these messages are impossible to debug in the real network. 42 | /// With the help of run_executor you can do that. In fact, `process_message` functionperforms local check with `run_executor` if there was no transaction as a result of processingand returns the error, if there is one. 43 | /// Another use case to use `run_executor` is to estimate fees for message execution. 44 | /// Set `AccountForExecutor::Account.unlimited_balance`to `true` so that emulation will not depend on the actual balance. 45 | /// This may be needed to calculate deploy fees for an account that does not exist yet. 46 | /// JSON with fees is in `fees` field of the result. 47 | /// One more use case - you can produce the sequence of operations,thus emulating the sequential contract calls locally. 48 | /// And so on. 49 | /// Transaction executor requires account BOC (bag of cells) as a parameter. 50 | /// To get the account BOC - use `net.query` method to download it from GraphQL API(field `boc` of `account`) or generate it with `abi.encode_account` method. 51 | /// Also it requires message BOC. To get the message BOC - use `abi.encode_message` or `abi.encode_internal_message`. 52 | /// If you need this emulation to be as precise as possible (for instance - emulate transactionwith particular lt in particular block or use particular blockchain config,downloaded from a particular key block - then specify `execution_options` parameter. 53 | /// If you need to see the aborted transaction as a result, not as an error, set `skip_transaction_check` to `true`. 54 | @available(iOS 13, *) 55 | @available(macOS 12, *) 56 | public func run_executor(_ payload: TSDKParamsOfRunExecutor) async throws -> TSDKResultOfRunExecutor { 57 | try await withCheckedThrowingContinuation { continuation in 58 | do { 59 | let method: String = "run_executor" 60 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 61 | var response: TSDKBindingResponse = .init() 62 | response.update(requestId, params, responseType, finished) 63 | if let error = response.error { 64 | continuation.resume(throwing: error) 65 | } else if let result = response.result { 66 | continuation.resume(returning: result) 67 | } else { 68 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 69 | } 70 | } 71 | } catch { 72 | continuation.resume(throwing: error) 73 | } 74 | } 75 | } 76 | 77 | /// Executes get-methods of ABI-compatible contracts 78 | /// Performs only a part of compute phase of transaction executionthat is used to run get-methods of ABI-compatible contracts. 79 | /// If you try to run get-methods with `run_executor` you will get an error, because it checks ACCEPT and exitsif there is none, which is actually true for get-methods. 80 | /// To get the account BOC (bag of cells) - use `net.query` method to download it from GraphQL API(field `boc` of `account`) or generate it with `abi.encode_account method`. 81 | /// To get the message BOC - use `abi.encode_message` or prepare it any other way, for instance, with FIFT script. 82 | /// Attention! Updated account state is produces as well, but only`account_state.storage.state.data` part of the BOC is updated. 83 | public func run_tvm(_ payload: TSDKParamsOfRunTvm, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 84 | ) throws { 85 | let method: String = "run_tvm" 86 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 87 | var response: TSDKBindingResponse = .init() 88 | response.update(requestId, params, responseType, finished) 89 | try handler(response) 90 | } 91 | } 92 | 93 | /// Executes get-methods of ABI-compatible contracts 94 | /// Performs only a part of compute phase of transaction executionthat is used to run get-methods of ABI-compatible contracts. 95 | /// If you try to run get-methods with `run_executor` you will get an error, because it checks ACCEPT and exitsif there is none, which is actually true for get-methods. 96 | /// To get the account BOC (bag of cells) - use `net.query` method to download it from GraphQL API(field `boc` of `account`) or generate it with `abi.encode_account method`. 97 | /// To get the message BOC - use `abi.encode_message` or prepare it any other way, for instance, with FIFT script. 98 | /// Attention! Updated account state is produces as well, but only`account_state.storage.state.data` part of the BOC is updated. 99 | @available(iOS 13, *) 100 | @available(macOS 12, *) 101 | public func run_tvm(_ payload: TSDKParamsOfRunTvm) async throws -> TSDKResultOfRunTvm { 102 | try await withCheckedThrowingContinuation { continuation in 103 | do { 104 | let method: String = "run_tvm" 105 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 106 | var response: TSDKBindingResponse = .init() 107 | response.update(requestId, params, responseType, finished) 108 | if let error = response.error { 109 | continuation.resume(throwing: error) 110 | } else if let result = response.result { 111 | continuation.resume(returning: result) 112 | } else { 113 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 114 | } 115 | } 116 | } catch { 117 | continuation.resume(throwing: error) 118 | } 119 | } 120 | } 121 | 122 | /// Executes a get-method of FIFT contract 123 | /// Executes a get-method of FIFT contract that fulfills the smc-guidelines https://test.ton.org/smc-guidelines.txtand returns the result data from TVM's stack 124 | public func run_get(_ payload: TSDKParamsOfRunGet, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 125 | ) throws { 126 | let method: String = "run_get" 127 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 128 | var response: TSDKBindingResponse = .init() 129 | response.update(requestId, params, responseType, finished) 130 | try handler(response) 131 | } 132 | } 133 | 134 | /// Executes a get-method of FIFT contract 135 | /// Executes a get-method of FIFT contract that fulfills the smc-guidelines https://test.ton.org/smc-guidelines.txtand returns the result data from TVM's stack 136 | @available(iOS 13, *) 137 | @available(macOS 12, *) 138 | public func run_get(_ payload: TSDKParamsOfRunGet) async throws -> TSDKResultOfRunGet { 139 | try await withCheckedThrowingContinuation { continuation in 140 | do { 141 | let method: String = "run_get" 142 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 143 | var response: TSDKBindingResponse = .init() 144 | response.update(requestId, params, responseType, finished) 145 | if let error = response.error { 146 | continuation.resume(throwing: error) 147 | } else if let result = response.result { 148 | continuation.resume(returning: result) 149 | } else { 150 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 151 | } 152 | } 153 | } catch { 154 | continuation.resume(throwing: error) 155 | } 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Tvm/TvmTypes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftExtensionsPack 3 | 4 | 5 | public enum TSDKTvmErrorCode: Int, Codable { 6 | case CanNotReadTransaction = 401 7 | case CanNotReadBlockchainConfig = 402 8 | case TransactionAborted = 403 9 | case InternalError = 404 10 | case ActionPhaseFailed = 405 11 | case AccountCodeMissing = 406 12 | case LowBalance = 407 13 | case AccountFrozenOrDeleted = 408 14 | case AccountMissing = 409 15 | case UnknownExecutionError = 410 16 | case InvalidInputStack = 411 17 | case InvalidAccountBoc = 412 18 | case InvalidMessageType = 413 19 | case ContractExecutionError = 414 20 | case AccountIsSuspended = 415 21 | } 22 | 23 | public enum TSDKAccountForExecutorEnumTypes: String, Codable { 24 | case None = "None" 25 | case Uninit = "Uninit" 26 | case Account = "Account" 27 | } 28 | 29 | public struct TSDKExecutionOptions: Codable, @unchecked Sendable { 30 | /// boc with config 31 | public var blockchain_config: String? 32 | /// time that is used as transaction time 33 | public var block_time: UInt32? 34 | /// block logical time 35 | public var block_lt: Int? 36 | /// transaction logical time 37 | public var transaction_lt: Int? 38 | /// Overrides standard TVM behaviour. If set to `true` then CHKSIG always will return `true`. 39 | public var chksig_always_succeed: Bool? 40 | /// Signature ID to be used in signature verifying instructions when CapSignatureWithId capability is enabled 41 | public var signature_id: Int32? 42 | 43 | public init(blockchain_config: String? = nil, block_time: UInt32? = nil, block_lt: Int? = nil, transaction_lt: Int? = nil, chksig_always_succeed: Bool? = nil, signature_id: Int32? = nil) { 44 | self.blockchain_config = blockchain_config 45 | self.block_time = block_time 46 | self.block_lt = block_lt 47 | self.transaction_lt = transaction_lt 48 | self.chksig_always_succeed = chksig_always_succeed 49 | self.signature_id = signature_id 50 | } 51 | } 52 | 53 | public struct TSDKAccountForExecutor: Codable, @unchecked Sendable { 54 | public var type: TSDKAccountForExecutorEnumTypes 55 | /// Account BOC. 56 | /// Encoded as base64. 57 | public var boc: String? 58 | /// Flag for running account with the unlimited balance. 59 | /// Can be used to calculate transaction fees without balance check 60 | public var unlimited_balance: Bool? 61 | 62 | public init(type: TSDKAccountForExecutorEnumTypes, boc: String? = nil, unlimited_balance: Bool? = nil) { 63 | self.type = type 64 | self.boc = boc 65 | self.unlimited_balance = unlimited_balance 66 | } 67 | } 68 | 69 | public struct TSDKTransactionFees: Codable, @unchecked Sendable { 70 | /// Deprecated. 71 | /// Contains the same data as ext_in_msg_fee field 72 | public var in_msg_fwd_fee: Int 73 | /// Fee for account storage 74 | public var storage_fee: Int 75 | /// Fee for processing 76 | public var gas_fee: Int 77 | /// Deprecated. 78 | /// Contains the same data as total_fwd_fees field. Deprecated because of its confusing name, that is not the same with GraphQL API Transaction type's field. 79 | public var out_msgs_fwd_fee: Int 80 | /// Deprecated. 81 | /// Contains the same data as account_fees field 82 | public var total_account_fees: Int 83 | /// Deprecated because it means total value sent in the transaction, which does not relate to any fees. 84 | public var total_output: Int 85 | /// Fee for inbound external message import. 86 | public var ext_in_msg_fee: Int 87 | /// Total fees the account pays for message forwarding 88 | public var total_fwd_fees: Int 89 | /// Total account fees for the transaction execution. Compounds of storage_fee + gas_fee + ext_in_msg_fee + total_fwd_fees 90 | public var account_fees: Int 91 | 92 | public init(in_msg_fwd_fee: Int, storage_fee: Int, gas_fee: Int, out_msgs_fwd_fee: Int, total_account_fees: Int, total_output: Int, ext_in_msg_fee: Int, total_fwd_fees: Int, account_fees: Int) { 93 | self.in_msg_fwd_fee = in_msg_fwd_fee 94 | self.storage_fee = storage_fee 95 | self.gas_fee = gas_fee 96 | self.out_msgs_fwd_fee = out_msgs_fwd_fee 97 | self.total_account_fees = total_account_fees 98 | self.total_output = total_output 99 | self.ext_in_msg_fee = ext_in_msg_fee 100 | self.total_fwd_fees = total_fwd_fees 101 | self.account_fees = account_fees 102 | } 103 | } 104 | 105 | public struct TSDKParamsOfRunExecutor: Codable, @unchecked Sendable { 106 | /// Input message BOC. 107 | /// Must be encoded as base64. 108 | public var message: String 109 | /// Account to run on executor 110 | public var account: TSDKAccountForExecutor 111 | /// Execution options. 112 | public var execution_options: TSDKExecutionOptions? 113 | /// Contract ABI for decoding output messages 114 | public var abi: TSDKAbi? 115 | /// Skip transaction check flag 116 | public var skip_transaction_check: Bool? 117 | /// Cache type to put the result. 118 | /// The BOC itself returned if no cache type provided 119 | public var boc_cache: TSDKBocCacheType? 120 | /// Return updated account flag. 121 | /// Empty string is returned if the flag is `false` 122 | public var return_updated_account: Bool? 123 | 124 | public init(message: String, account: TSDKAccountForExecutor, execution_options: TSDKExecutionOptions? = nil, abi: TSDKAbi? = nil, skip_transaction_check: Bool? = nil, boc_cache: TSDKBocCacheType? = nil, return_updated_account: Bool? = nil) { 125 | self.message = message 126 | self.account = account 127 | self.execution_options = execution_options 128 | self.abi = abi 129 | self.skip_transaction_check = skip_transaction_check 130 | self.boc_cache = boc_cache 131 | self.return_updated_account = return_updated_account 132 | } 133 | } 134 | 135 | public struct TSDKResultOfRunExecutor: Codable, @unchecked Sendable { 136 | /// Parsed transaction. 137 | /// In addition to the regular transaction fields there is a`boc` field encoded with `base64` which contains sourcetransaction BOC. 138 | public var transaction: AnyValue 139 | /// List of output messages' BOCs. 140 | /// Encoded as `base64` 141 | public var out_messages: [String] 142 | /// Optional decoded message bodies according to the optional `abi` parameter. 143 | public var decoded: TSDKDecodedOutput? 144 | /// Updated account state BOC. 145 | /// Encoded as `base64` 146 | public var account: String 147 | /// Transaction fees 148 | public var fees: TSDKTransactionFees 149 | 150 | public init(transaction: AnyValue, out_messages: [String], decoded: TSDKDecodedOutput? = nil, account: String, fees: TSDKTransactionFees) { 151 | self.transaction = transaction 152 | self.out_messages = out_messages 153 | self.decoded = decoded 154 | self.account = account 155 | self.fees = fees 156 | } 157 | } 158 | 159 | public struct TSDKParamsOfRunTvm: Codable, @unchecked Sendable { 160 | /// Input message BOC. 161 | /// Must be encoded as base64. 162 | public var message: String 163 | /// Account BOC. 164 | /// Must be encoded as base64. 165 | public var account: String 166 | /// Execution options. 167 | public var execution_options: TSDKExecutionOptions? 168 | /// Contract ABI for decoding output messages 169 | public var abi: TSDKAbi? 170 | /// Cache type to put the result. 171 | /// The BOC itself returned if no cache type provided 172 | public var boc_cache: TSDKBocCacheType? 173 | /// Return updated account flag. 174 | /// Empty string is returned if the flag is `false` 175 | public var return_updated_account: Bool? 176 | 177 | public init(message: String, account: String, execution_options: TSDKExecutionOptions? = nil, abi: TSDKAbi? = nil, boc_cache: TSDKBocCacheType? = nil, return_updated_account: Bool? = nil) { 178 | self.message = message 179 | self.account = account 180 | self.execution_options = execution_options 181 | self.abi = abi 182 | self.boc_cache = boc_cache 183 | self.return_updated_account = return_updated_account 184 | } 185 | } 186 | 187 | public struct TSDKResultOfRunTvm: Codable, @unchecked Sendable { 188 | /// List of output messages' BOCs. 189 | /// Encoded as `base64` 190 | public var out_messages: [String] 191 | /// Optional decoded message bodies according to the optional `abi` parameter. 192 | public var decoded: TSDKDecodedOutput? 193 | /// Updated account state BOC. 194 | /// Encoded as `base64`. Attention! Only `account_state.storage.state.data` part of the BOC is updated. 195 | public var account: String 196 | 197 | public init(out_messages: [String], decoded: TSDKDecodedOutput? = nil, account: String) { 198 | self.out_messages = out_messages 199 | self.decoded = decoded 200 | self.account = account 201 | } 202 | } 203 | 204 | public struct TSDKParamsOfRunGet: Codable, @unchecked Sendable { 205 | /// Account BOC in `base64` 206 | public var account: String 207 | /// Function name 208 | public var function_name: String 209 | /// Input parameters 210 | public var input: AnyValue? 211 | /// Execution options 212 | public var execution_options: TSDKExecutionOptions? 213 | /// Convert lists based on nested tuples in the **result** into plain arrays. 214 | /// Default is `false`. Input parameters may use any of lists representationsIf you receive this error on Web: "Runtime error. Unreachable code should not be executed...",set this flag to true. 215 | /// This may happen, for example, when elector contract contains too many participants 216 | public var tuple_list_as_array: Bool? 217 | 218 | public init(account: String, function_name: String, input: AnyValue? = nil, execution_options: TSDKExecutionOptions? = nil, tuple_list_as_array: Bool? = nil) { 219 | self.account = account 220 | self.function_name = function_name 221 | self.input = input 222 | self.execution_options = execution_options 223 | self.tuple_list_as_array = tuple_list_as_array 224 | } 225 | } 226 | 227 | public struct TSDKResultOfRunGet: Codable, @unchecked Sendable { 228 | /// Values returned by get-method on stack 229 | public var output: AnyValue 230 | 231 | public init(output: AnyValue) { 232 | self.output = output 233 | } 234 | } 235 | 236 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Utils/Utils.swift: -------------------------------------------------------------------------------- 1 | public final class TSDKUtilsModule { 2 | 3 | private var binding: TSDKBindingModule 4 | public let module: String = "utils" 5 | 6 | public init(binding: TSDKBindingModule) { 7 | self.binding = binding 8 | } 9 | 10 | /// Converts address from any TON format to any TON format 11 | public func convert_address(_ payload: TSDKParamsOfConvertAddress, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 12 | ) throws { 13 | let method: String = "convert_address" 14 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 15 | var response: TSDKBindingResponse = .init() 16 | response.update(requestId, params, responseType, finished) 17 | try handler(response) 18 | } 19 | } 20 | 21 | /// Converts address from any TON format to any TON format 22 | @available(iOS 13, *) 23 | @available(macOS 12, *) 24 | public func convert_address(_ payload: TSDKParamsOfConvertAddress) async throws -> TSDKResultOfConvertAddress { 25 | try await withCheckedThrowingContinuation { continuation in 26 | do { 27 | let method: String = "convert_address" 28 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 29 | var response: TSDKBindingResponse = .init() 30 | response.update(requestId, params, responseType, finished) 31 | if let error = response.error { 32 | continuation.resume(throwing: error) 33 | } else if let result = response.result { 34 | continuation.resume(returning: result) 35 | } else { 36 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 37 | } 38 | } 39 | } catch { 40 | continuation.resume(throwing: error) 41 | } 42 | } 43 | } 44 | 45 | /// Validates and returns the type of any TON address. 46 | /// Address types are the following`0:919db8e740d50bf349df2eea03fa30c385d846b991ff5542e67098ee833fc7f7` - standard TON address mostcommonly used in all cases. Also called as hex address`919db8e740d50bf349df2eea03fa30c385d846b991ff5542e67098ee833fc7f7` - account ID. A part of fulladdress. Identifies account inside particular workchain`EQCRnbjnQNUL80nfLuoD+jDDhdhGuZH/VULmcJjugz/H9wam` - base64 address. Also called "user-friendly". 47 | /// Was used at the beginning of TON. Now it is supported for compatibility 48 | public func get_address_type(_ payload: TSDKParamsOfGetAddressType, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 49 | ) throws { 50 | let method: String = "get_address_type" 51 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 52 | var response: TSDKBindingResponse = .init() 53 | response.update(requestId, params, responseType, finished) 54 | try handler(response) 55 | } 56 | } 57 | 58 | /// Validates and returns the type of any TON address. 59 | /// Address types are the following`0:919db8e740d50bf349df2eea03fa30c385d846b991ff5542e67098ee833fc7f7` - standard TON address mostcommonly used in all cases. Also called as hex address`919db8e740d50bf349df2eea03fa30c385d846b991ff5542e67098ee833fc7f7` - account ID. A part of fulladdress. Identifies account inside particular workchain`EQCRnbjnQNUL80nfLuoD+jDDhdhGuZH/VULmcJjugz/H9wam` - base64 address. Also called "user-friendly". 60 | /// Was used at the beginning of TON. Now it is supported for compatibility 61 | @available(iOS 13, *) 62 | @available(macOS 12, *) 63 | public func get_address_type(_ payload: TSDKParamsOfGetAddressType) async throws -> TSDKResultOfGetAddressType { 64 | try await withCheckedThrowingContinuation { continuation in 65 | do { 66 | let method: String = "get_address_type" 67 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 68 | var response: TSDKBindingResponse = .init() 69 | response.update(requestId, params, responseType, finished) 70 | if let error = response.error { 71 | continuation.resume(throwing: error) 72 | } else if let result = response.result { 73 | continuation.resume(returning: result) 74 | } else { 75 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 76 | } 77 | } 78 | } catch { 79 | continuation.resume(throwing: error) 80 | } 81 | } 82 | } 83 | 84 | /// Calculates storage fee for an account over a specified time period 85 | public func calc_storage_fee(_ payload: TSDKParamsOfCalcStorageFee, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 86 | ) throws { 87 | let method: String = "calc_storage_fee" 88 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 89 | var response: TSDKBindingResponse = .init() 90 | response.update(requestId, params, responseType, finished) 91 | try handler(response) 92 | } 93 | } 94 | 95 | /// Calculates storage fee for an account over a specified time period 96 | @available(iOS 13, *) 97 | @available(macOS 12, *) 98 | public func calc_storage_fee(_ payload: TSDKParamsOfCalcStorageFee) async throws -> TSDKResultOfCalcStorageFee { 99 | try await withCheckedThrowingContinuation { continuation in 100 | do { 101 | let method: String = "calc_storage_fee" 102 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 103 | var response: TSDKBindingResponse = .init() 104 | response.update(requestId, params, responseType, finished) 105 | if let error = response.error { 106 | continuation.resume(throwing: error) 107 | } else if let result = response.result { 108 | continuation.resume(returning: result) 109 | } else { 110 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 111 | } 112 | } 113 | } catch { 114 | continuation.resume(throwing: error) 115 | } 116 | } 117 | } 118 | 119 | /// Compresses data using Zstandard algorithm 120 | public func compress_zstd(_ payload: TSDKParamsOfCompressZstd, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 121 | ) throws { 122 | let method: String = "compress_zstd" 123 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 124 | var response: TSDKBindingResponse = .init() 125 | response.update(requestId, params, responseType, finished) 126 | try handler(response) 127 | } 128 | } 129 | 130 | /// Compresses data using Zstandard algorithm 131 | @available(iOS 13, *) 132 | @available(macOS 12, *) 133 | public func compress_zstd(_ payload: TSDKParamsOfCompressZstd) async throws -> TSDKResultOfCompressZstd { 134 | try await withCheckedThrowingContinuation { continuation in 135 | do { 136 | let method: String = "compress_zstd" 137 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 138 | var response: TSDKBindingResponse = .init() 139 | response.update(requestId, params, responseType, finished) 140 | if let error = response.error { 141 | continuation.resume(throwing: error) 142 | } else if let result = response.result { 143 | continuation.resume(returning: result) 144 | } else { 145 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 146 | } 147 | } 148 | } catch { 149 | continuation.resume(throwing: error) 150 | } 151 | } 152 | } 153 | 154 | /// Decompresses data using Zstandard algorithm 155 | public func decompress_zstd(_ payload: TSDKParamsOfDecompressZstd, _ handler: @escaping @Sendable (TSDKBindingResponse) throws -> Void 156 | ) throws { 157 | let method: String = "decompress_zstd" 158 | try binding.requestLibraryAsync(methodName(module, method), payload) { (requestId, params, responseType, finished) in 159 | var response: TSDKBindingResponse = .init() 160 | response.update(requestId, params, responseType, finished) 161 | try handler(response) 162 | } 163 | } 164 | 165 | /// Decompresses data using Zstandard algorithm 166 | @available(iOS 13, *) 167 | @available(macOS 12, *) 168 | public func decompress_zstd(_ payload: TSDKParamsOfDecompressZstd) async throws -> TSDKResultOfDecompressZstd { 169 | try await withCheckedThrowingContinuation { continuation in 170 | do { 171 | let method: String = "decompress_zstd" 172 | try binding.requestLibraryAsyncAwait(methodName(module, method), payload) { (requestId, params, responseType, finished) in 173 | var response: TSDKBindingResponse = .init() 174 | response.update(requestId, params, responseType, finished) 175 | if let error = response.error { 176 | continuation.resume(throwing: error) 177 | } else if let result = response.result { 178 | continuation.resume(returning: result) 179 | } else { 180 | continuation.resume(throwing: TSDKClientError("Nothing for return")) 181 | } 182 | } 183 | } catch { 184 | continuation.resume(throwing: error) 185 | } 186 | } 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /Sources/EverscaleClientSwift/Utils/UtilsTypes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftExtensionsPack 3 | 4 | 5 | public enum TSDKAddressStringFormatEnumTypes: String, Codable { 6 | case AccountId = "AccountId" 7 | case Hex = "Hex" 8 | case Base64 = "Base64" 9 | } 10 | 11 | public enum TSDKAccountAddressType: String, Codable { 12 | case AccountId = "AccountId" 13 | case Hex = "Hex" 14 | case Base64 = "Base64" 15 | } 16 | 17 | public struct TSDKAddressStringFormat: Codable, @unchecked Sendable { 18 | public var type: TSDKAddressStringFormatEnumTypes 19 | public var url: Bool? 20 | public var test: Bool? 21 | public var bounce: Bool? 22 | 23 | public init(type: TSDKAddressStringFormatEnumTypes, url: Bool? = nil, test: Bool? = nil, bounce: Bool? = nil) { 24 | self.type = type 25 | self.url = url 26 | self.test = test 27 | self.bounce = bounce 28 | } 29 | } 30 | 31 | public struct TSDKParamsOfConvertAddress: Codable, @unchecked Sendable { 32 | /// Account address in any TON format. 33 | public var address: String 34 | /// Specify the format to convert to. 35 | public var output_format: TSDKAddressStringFormat 36 | 37 | public init(address: String, output_format: TSDKAddressStringFormat) { 38 | self.address = address 39 | self.output_format = output_format 40 | } 41 | } 42 | 43 | public struct TSDKResultOfConvertAddress: Codable, @unchecked Sendable { 44 | /// Address in the specified format 45 | public var address: String 46 | 47 | public init(address: String) { 48 | self.address = address 49 | } 50 | } 51 | 52 | public struct TSDKParamsOfGetAddressType: Codable, @unchecked Sendable { 53 | /// Account address in any TON format. 54 | public var address: String 55 | 56 | public init(address: String) { 57 | self.address = address 58 | } 59 | } 60 | 61 | public struct TSDKResultOfGetAddressType: Codable, @unchecked Sendable { 62 | /// Account address type. 63 | public var address_type: TSDKAccountAddressType 64 | 65 | public init(address_type: TSDKAccountAddressType) { 66 | self.address_type = address_type 67 | } 68 | } 69 | 70 | public struct TSDKParamsOfCalcStorageFee: Codable, @unchecked Sendable { 71 | public var account: String 72 | public var period: UInt32 73 | 74 | public init(account: String, period: UInt32) { 75 | self.account = account 76 | self.period = period 77 | } 78 | } 79 | 80 | public struct TSDKResultOfCalcStorageFee: Codable, @unchecked Sendable { 81 | public var fee: String 82 | 83 | public init(fee: String) { 84 | self.fee = fee 85 | } 86 | } 87 | 88 | public struct TSDKParamsOfCompressZstd: Codable, @unchecked Sendable { 89 | /// Uncompressed data. 90 | /// Must be encoded as base64. 91 | public var uncompressed: String 92 | /// Compression level, from 1 to 21. Where: 1 - lowest compression level (fastest compression); 21 - highest compression level (slowest compression). If level is omitted, the default compression level is used (currently `3`). 93 | public var level: Int32? 94 | 95 | public init(uncompressed: String, level: Int32? = nil) { 96 | self.uncompressed = uncompressed 97 | self.level = level 98 | } 99 | } 100 | 101 | public struct TSDKResultOfCompressZstd: Codable, @unchecked Sendable { 102 | /// Compressed data. 103 | /// Must be encoded as base64. 104 | public var compressed: String 105 | 106 | public init(compressed: String) { 107 | self.compressed = compressed 108 | } 109 | } 110 | 111 | public struct TSDKParamsOfDecompressZstd: Codable, @unchecked Sendable { 112 | /// Compressed data. 113 | /// Must be encoded as base64. 114 | public var compressed: String 115 | 116 | public init(compressed: String) { 117 | self.compressed = compressed 118 | } 119 | } 120 | 121 | public struct TSDKResultOfDecompressZstd: Codable, @unchecked Sendable { 122 | /// Decompressed data. 123 | /// Must be encoded as base64. 124 | public var decompressed: String 125 | 126 | public init(decompressed: String) { 127 | self.decompressed = decompressed 128 | } 129 | } 130 | 131 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/BindingTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleh Hudeichuk on 18.10.2020. 3 | // 4 | 5 | import XCTest 6 | import class Foundation.Bundle 7 | @testable import EverscaleClientSwift 8 | @testable import CTonSDK 9 | @testable import SwiftExtensionsPack 10 | 11 | final class BindingTests: XCTestCase { 12 | 13 | func testConvertToTSDKString() throws { 14 | var string: tc_string_data_t! 15 | try TSDKBindingModule.convertToTSDKString("Hello😀") { tsdkString in 16 | string = tsdkString 17 | } 18 | XCTAssertEqual(string.len, 9) 19 | } 20 | 21 | func testConvertFromTSDKString() throws { 22 | var swiftString: String = .init() 23 | try TSDKBindingModule.convertToTSDKString("Hello😀") { tsdkString in 24 | swiftString = try TSDKBindingModule.convertFromTSDKString(tsdkString) 25 | } 26 | XCTAssertEqual(swiftString, "Hello😀") 27 | } 28 | 29 | struct Test: Codable { 30 | var version: String 31 | } 32 | 33 | struct TestError: Codable { 34 | var code: UInt32 35 | var message: String 36 | var data: AnyValue 37 | } 38 | 39 | func testRequestLibraryAsync() throws { 40 | let binding: TSDKBindingModule = try .init() 41 | for _ in 1...500 { 42 | try binding.requestLibraryAsync("client.version", "{}") { (requestId, params, responseType, finished) in 43 | var response: TSDKBindingResponse = .init() 44 | response.update(requestId, params, responseType, finished) 45 | XCTAssertTrue(response.result?.version != nil) 46 | XCTAssertEqual(response.error?.message, nil) 47 | } 48 | } 49 | usleep(500000) 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/ClientTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 19.11.2020. 6 | // 7 | 8 | import XCTest 9 | import class Foundation.Bundle 10 | @testable import EverscaleClientSwift 11 | @testable import CTonSDK 12 | 13 | final class ClientTests: XCTestCase { 14 | 15 | func testGet_api_reference() throws { 16 | try testAsyncMethods { (client, group) in 17 | group.enter() 18 | try client.get_api_reference { (response) in 19 | XCTAssertTrue(response.result?.api != nil) 20 | group.leave() 21 | } 22 | group.wait() 23 | } 24 | } 25 | 26 | func testVersion() throws { 27 | try testAsyncMethods { (client, group) in 28 | group.enter() 29 | try client.version { (response) in 30 | XCTAssertTrue(response.result?.version != nil) 31 | if response.finished { 32 | group.leave() 33 | } 34 | } 35 | group.wait() 36 | } 37 | } 38 | 39 | func testBuild_info() throws { 40 | try testAsyncMethods { (client, group) in 41 | group.enter() 42 | try client.build_info { (response) in 43 | XCTAssertTrue(response.result?.build_number != nil) 44 | if response.finished { 45 | group.leave() 46 | } 47 | } 48 | group.wait() 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/ErrorsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorsTests.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 17.09.2022. 6 | // 7 | 8 | import XCTest 9 | import class Foundation.Bundle 10 | @testable import EverscaleClientSwift 11 | @testable import CTonSDK 12 | 13 | final class ErrorsTests: XCTestCase { 14 | 15 | func testClientError() throws { 16 | try testAsyncMethods { (client, group) in 17 | let paramsOfQueryCollection: TSDKParamsOfQueryCollection = .init(collection: "accounts", 18 | filter: [ 19 | "id": [ 20 | "eq": "0:b5e9240fc2d2f1ff8cbb1d1dee7fb7cae155e5f6320e585fcc685698994a19a5" 21 | ] 22 | ].toAnyValue(), 23 | result: "boc") 24 | group.enter() 25 | do { 26 | try client.net.query_collection(paramsOfQueryCollection) { [group] response in 27 | if response.error != nil { 28 | group.leave() 29 | } else { 30 | throw TSDKClientError("FATAL ERROR") 31 | } 32 | } 33 | } catch { 34 | group.leave() 35 | } 36 | group.wait() 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Events.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "emitValue", 7 | "inputs": [ 8 | {"name":"id","type":"uint256"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "returnValue", 15 | "inputs": [ 16 | {"name":"id","type":"uint256"} 17 | ], 18 | "outputs": [ 19 | {"name":"value0","type":"uint256"} 20 | ] 21 | }, 22 | { 23 | "name": "sendAllMoney", 24 | "inputs": [ 25 | {"name":"dest_addr","type":"address"} 26 | ], 27 | "outputs": [ 28 | ] 29 | }, 30 | { 31 | "name": "constructor", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | } 37 | ], 38 | "data": [ 39 | ], 40 | "events": [ 41 | { 42 | "name": "EventThrown", 43 | "inputs": [ 44 | {"name":"id","type":"uint256"} 45 | ], 46 | "outputs": [ 47 | ] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Events.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/Events.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Giver.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time"], 4 | "functions": [ 5 | { 6 | "name": "grant", 7 | "inputs": [ 8 | {"name":"addr","type":"address"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "constructor", 15 | "inputs": [ 16 | ], 17 | "outputs": [ 18 | ] 19 | } 20 | ], 21 | "data": [ 22 | ], 23 | "events": [ 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverNodeSE.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 1, 3 | "functions": [ 4 | { 5 | "name": "constructor", 6 | "inputs": [], 7 | "outputs": [] 8 | }, 9 | { 10 | "name": "sendGrams", 11 | "inputs": [ 12 | {"name": "dest", "type": "address"}, 13 | {"name": "amount", "type": "uint64"} 14 | ], 15 | "outputs": [] 16 | } 17 | ], 18 | "events": [], 19 | "data": [] 20 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverNodeSE_v2.abi.json: -------------------------------------------------------------------------------- 1 | {"ABI version": 2, 2 | "header": ["time", "expire"], 3 | "functions": [ 4 | { 5 | "name": "upgrade", 6 | "inputs": [ 7 | {"name":"newcode","type":"cell"} 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "sendTransaction", 14 | "inputs": [ 15 | {"name":"dest","type":"address"}, 16 | {"name":"value","type":"uint128"}, 17 | {"name":"bounce","type":"bool"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "getMessages", 24 | "inputs": [ 25 | ], 26 | "outputs": [ 27 | {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint64"}],"name":"messages","type":"tuple[]"} 28 | ] 29 | }, 30 | { 31 | "name": "constructor", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | } 37 | ], 38 | "events": [ 39 | ] 40 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverNodeSE_v2.keys.json: -------------------------------------------------------------------------------- 1 | { 2 | "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", 3 | "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3" 4 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverV2.abi.json: -------------------------------------------------------------------------------- 1 | {"ABI version": 2, 2 | "header": ["time", "expire"], 3 | "functions": [ 4 | { 5 | "name": "upgrade", 6 | "inputs": [ 7 | {"name":"newcode","type":"cell"} 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "sendTransaction", 14 | "inputs": [ 15 | {"name":"dest","type":"address"}, 16 | {"name":"value","type":"uint128"}, 17 | {"name":"bounce","type":"bool"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "getMessages", 24 | "inputs": [ 25 | ], 26 | "outputs": [ 27 | {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint64"}],"name":"messages","type":"tuple[]"} 28 | ] 29 | }, 30 | { 31 | "name": "constructor", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | } 37 | ], 38 | "events": [ 39 | ] 40 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverV2.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverV2.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/GiverWallet.abi.json: -------------------------------------------------------------------------------- 1 | {"ABI version": 2, 2 | "header": ["time", "expire"], 3 | "functions": [ 4 | { 5 | "name": "upgrade", 6 | "inputs": [ 7 | {"name":"newcode","type":"cell"} 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "sendTransaction", 14 | "inputs": [ 15 | {"name":"dest","type":"address"}, 16 | {"name":"value","type":"uint128"}, 17 | {"name":"bounce","type":"bool"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "getMessages", 24 | "inputs": [ 25 | ], 26 | "outputs": [ 27 | {"components":[{"name":"hash","type":"uint256"},{"name":"expireAt","type":"uint64"}],"name":"messages","type":"tuple[]"} 28 | ] 29 | }, 30 | { 31 | "name": "constructor", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | } 37 | ], 38 | "events": [ 39 | ] 40 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Hello.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "touch", 14 | "inputs": [ 15 | ], 16 | "outputs": [ 17 | ] 18 | }, 19 | { 20 | "name": "sayHello", 21 | "inputs": [ 22 | ], 23 | "outputs": [ 24 | {"name":"value0","type":"uint32"} 25 | ] 26 | }, 27 | { 28 | "name": "sendAllMoney", 29 | "inputs": [ 30 | {"name":"dest_addr","type":"address"} 31 | ], 32 | "outputs": [ 33 | ] 34 | } 35 | ], 36 | "events": [ 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Hello.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/Hello.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/LimitWallet.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "sendTransaction", 7 | "inputs": [ 8 | {"name":"dest","type":"address"}, 9 | {"name":"value","type":"uint128"}, 10 | {"name":"bounce","type":"bool"} 11 | ], 12 | "outputs": [ 13 | ] 14 | }, 15 | { 16 | "name": "fallback", 17 | "inputs": [ 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "setSubscriptionAccount", 24 | "inputs": [ 25 | {"name":"addr","type":"address"} 26 | ], 27 | "outputs": [ 28 | ] 29 | }, 30 | { 31 | "name": "getSubscriptionAccount", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | {"name":"value0","type":"address"} 36 | ] 37 | }, 38 | { 39 | "name": "createOperationLimit", 40 | "inputs": [ 41 | {"name":"value","type":"uint256"} 42 | ], 43 | "outputs": [ 44 | {"name":"value0","type":"uint256"} 45 | ] 46 | }, 47 | { 48 | "name": "createArbitraryLimit", 49 | "inputs": [ 50 | {"name":"value","type":"uint256"}, 51 | {"name":"period","type":"uint32"} 52 | ], 53 | "outputs": [ 54 | {"name":"value0","type":"uint64"} 55 | ] 56 | }, 57 | { 58 | "name": "changeLimit", 59 | "inputs": [ 60 | {"name":"limitId","type":"uint64"}, 61 | {"name":"value","type":"uint256"}, 62 | {"name":"period","type":"uint32"} 63 | ], 64 | "outputs": [ 65 | ] 66 | }, 67 | { 68 | "name": "deleteLimit", 69 | "inputs": [ 70 | {"name":"limitId","type":"uint64"} 71 | ], 72 | "outputs": [ 73 | ] 74 | }, 75 | { 76 | "name": "getLimit", 77 | "inputs": [ 78 | {"name":"limitId","type":"uint64"} 79 | ], 80 | "outputs": [ 81 | {"components":[{"name":"value","type":"uint256"},{"name":"period","type":"uint32"},{"name":"ltype","type":"uint8"},{"name":"spent","type":"uint256"},{"name":"start","type":"uint32"}],"name":"value0","type":"tuple"} 82 | ] 83 | }, 84 | { 85 | "name": "getLimitCount", 86 | "inputs": [ 87 | ], 88 | "outputs": [ 89 | {"name":"value0","type":"uint64"} 90 | ] 91 | }, 92 | { 93 | "name": "getLimits", 94 | "inputs": [ 95 | ], 96 | "outputs": [ 97 | {"components":[{"name":"value","type":"uint256"},{"name":"period","type":"uint32"},{"name":"ltype","type":"uint8"},{"name":"spent","type":"uint256"},{"name":"start","type":"uint32"}],"name":"limits","type":"tuple[]"} 98 | ] 99 | }, 100 | { 101 | "name": "constructor", 102 | "inputs": [ 103 | ], 104 | "outputs": [ 105 | ] 106 | } 107 | ], 108 | "events": [ 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/LimitWallet.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/LimitWallet.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Piggy.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"amount","type":"uint64"}, 9 | {"name":"goal","type":"bytes"} 10 | ], 11 | "outputs": [ 12 | ] 13 | }, 14 | { 15 | "name": "transfer", 16 | "inputs": [ 17 | {"name":"to","type":"address"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "getGoal", 24 | "inputs": [ 25 | ], 26 | "outputs": [ 27 | {"name":"value0","type":"bytes"} 28 | ] 29 | }, 30 | { 31 | "name": "getTargetAmount", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | {"name":"value0","type":"uint64"} 36 | ] 37 | }, 38 | { 39 | "name": "fallback", 40 | "inputs": [ 41 | ], 42 | "outputs": [ 43 | ] 44 | } 45 | ], 46 | "events": [ 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Piggy.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/Piggy.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/SetcodeMultisigWallet2.abi.json: -------------------------------------------------------------------------------- 1 | { "ABI version": 2, "header": ["pubkey", "time", "expire"], "functions": [ { "name": "constructor", "inputs": [ {"name":"owners","type":"uint256[]"}, {"name":"reqConfirms","type":"uint8"} ], "outputs": [ ] }, { "name": "acceptTransfer", "inputs": [ {"name":"payload","type":"bytes"} ], "outputs": [ ] }, { "name": "sendTransaction", "inputs": [ {"name":"dest","type":"address"}, {"name":"value","type":"uint128"}, {"name":"bounce","type":"bool"}, {"name":"flags","type":"uint8"}, {"name":"payload","type":"cell"} ], "outputs": [ ] }, { "name": "submitTransaction", "inputs": [ {"name":"dest","type":"address"}, {"name":"value","type":"uint128"}, {"name":"bounce","type":"bool"}, {"name":"allBalance","type":"bool"}, {"name":"payload","type":"cell"} ], "outputs": [ {"name":"transId","type":"uint64"} ] }, { "name": "confirmTransaction", "inputs": [ {"name":"transactionId","type":"uint64"} ], "outputs": [ ] }, { "name": "isConfirmed", "inputs": [ {"name":"mask","type":"uint32"}, {"name":"index","type":"uint8"} ], "outputs": [ {"name":"confirmed","type":"bool"} ] }, { "name": "getParameters", "inputs": [ ], "outputs": [ {"name":"maxQueuedTransactions","type":"uint8"}, {"name":"maxCustodianCount","type":"uint8"}, {"name":"expirationTime","type":"uint64"}, {"name":"minValue","type":"uint128"}, {"name":"requiredTxnConfirms","type":"uint8"}, {"name":"requiredUpdConfirms","type":"uint8"} ] }, { "name": "getTransaction", "inputs": [ {"name":"transactionId","type":"uint64"} ], "outputs": [ {"components":[{"name":"id","type":"uint64"},{"name":"confirmationsMask","type":"uint32"},{"name":"signsRequired","type":"uint8"},{"name":"signsReceived","type":"uint8"},{"name":"creator","type":"uint256"},{"name":"index","type":"uint8"},{"name":"dest","type":"address"},{"name":"value","type":"uint128"},{"name":"sendFlags","type":"uint16"},{"name":"payload","type":"cell"},{"name":"bounce","type":"bool"}],"name":"trans","type":"tuple"} ] }, { "name": "getTransactions", "inputs": [ ], "outputs": [ {"components":[{"name":"id","type":"uint64"},{"name":"confirmationsMask","type":"uint32"},{"name":"signsRequired","type":"uint8"},{"name":"signsReceived","type":"uint8"},{"name":"creator","type":"uint256"},{"name":"index","type":"uint8"},{"name":"dest","type":"address"},{"name":"value","type":"uint128"},{"name":"sendFlags","type":"uint16"},{"name":"payload","type":"cell"},{"name":"bounce","type":"bool"}],"name":"transactions","type":"tuple[]"} ] }, { "name": "getTransactionIds", "inputs": [ ], "outputs": [ {"name":"ids","type":"uint64[]"} ] }, { "name": "getCustodians", "inputs": [ ], "outputs": [ {"components":[{"name":"index","type":"uint8"},{"name":"pubkey","type":"uint256"}],"name":"custodians","type":"tuple[]"} ] }, { "name": "submitUpdate", "inputs": [ {"name":"codeHash","type":"uint256"}, {"name":"owners","type":"uint256[]"}, {"name":"reqConfirms","type":"uint8"} ], "outputs": [ {"name":"updateId","type":"uint64"} ] }, { "name": "confirmUpdate", "inputs": [ {"name":"updateId","type":"uint64"} ], "outputs": [ ] }, { "name": "executeUpdate", "inputs": [ {"name":"updateId","type":"uint64"}, {"name":"code","type":"cell"} ], "outputs": [ ] }, { "name": "getUpdateRequests", "inputs": [ ], "outputs": [ {"components":[{"name":"id","type":"uint64"},{"name":"index","type":"uint8"},{"name":"signs","type":"uint8"},{"name":"confirmationsMask","type":"uint32"},{"name":"creator","type":"uint256"},{"name":"codeHash","type":"uint256"},{"name":"custodians","type":"uint256[]"},{"name":"reqConfirms","type":"uint8"}],"name":"updates","type":"tuple[]"} ] } ], "data": [ ], "events": [ { "name": "TransferAccepted", "inputs": [ {"name":"payload","type":"bytes"} ], "outputs": [ ] } ] } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/SetcodeMultisigWallet2.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/SetcodeMultisigWallet2.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Subscription.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"wallet","type":"address"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "getWallet", 15 | "inputs": [ 16 | ], 17 | "outputs": [ 18 | {"name":"value0","type":"address"} 19 | ] 20 | }, 21 | { 22 | "name": "getSubscription", 23 | "inputs": [ 24 | {"name":"subscriptionId","type":"uint256"} 25 | ], 26 | "outputs": [ 27 | {"components":[{"name":"pubkey","type":"uint256"},{"name":"to","type":"address"},{"name":"value","type":"uint64"},{"name":"period","type":"uint32"},{"name":"start","type":"uint32"},{"name":"status","type":"uint8"}],"name":"value0","type":"tuple"} 28 | ] 29 | }, 30 | { 31 | "name": "subscribe", 32 | "inputs": [ 33 | {"name":"subscriptionId","type":"uint256"}, 34 | {"name":"pubkey","type":"uint256"}, 35 | {"name":"to","type":"address"}, 36 | {"name":"value","type":"uint64"}, 37 | {"name":"period","type":"uint32"} 38 | ], 39 | "outputs": [ 40 | ] 41 | }, 42 | { 43 | "name": "cancel", 44 | "inputs": [ 45 | {"name":"subscriptionId","type":"uint256"} 46 | ], 47 | "outputs": [ 48 | ] 49 | }, 50 | { 51 | "name": "executeSubscription", 52 | "inputs": [ 53 | {"name":"subscriptionId","type":"uint256"} 54 | ], 55 | "outputs": [ 56 | ] 57 | }, 58 | { 59 | "name": "sendAllMoney", 60 | "inputs": [ 61 | {"name":"dest_addr","type":"address"} 62 | ], 63 | "outputs": [ 64 | ] 65 | } 66 | ], 67 | "events": [ 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Subscription.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/Subscription.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Wallet.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "sendTransaction", 14 | "inputs": [ 15 | {"name":"dest","type":"address"}, 16 | {"name":"value","type":"uint128"}, 17 | {"name":"bounce","type":"bool"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "sendAllMoney", 24 | "inputs": [ 25 | {"name":"dest_addr","type":"address"} 26 | ], 27 | "outputs": [ 28 | ] 29 | } 30 | ], 31 | "events": [ 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/Wallet.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/Wallet.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "setIcon", 7 | "inputs": [ 8 | {"name":"icon","type":"bytes"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "start", 15 | "inputs": [ 16 | ], 17 | "outputs": [ 18 | ] 19 | }, 20 | { 21 | "name": "getDebotInfo", 22 | "id": "0xDEB", 23 | "inputs": [ 24 | ], 25 | "outputs": [ 26 | {"name":"name","type":"bytes"}, 27 | {"name":"version","type":"bytes"}, 28 | {"name":"publisher","type":"bytes"}, 29 | {"name":"caption","type":"bytes"}, 30 | {"name":"author","type":"bytes"}, 31 | {"name":"support","type":"address"}, 32 | {"name":"hello","type":"bytes"}, 33 | {"name":"language","type":"bytes"}, 34 | {"name":"dabi","type":"bytes"}, 35 | {"name":"icon","type":"bytes"} 36 | ] 37 | }, 38 | { 39 | "name": "getRequiredInterfaces", 40 | "inputs": [ 41 | ], 42 | "outputs": [ 43 | {"name":"interfaces","type":"uint256[]"} 44 | ] 45 | }, 46 | { 47 | "name": "setUserInput", 48 | "inputs": [ 49 | {"name":"value","type":"bytes"} 50 | ], 51 | "outputs": [ 52 | ] 53 | }, 54 | { 55 | "name": "getDebotOptions", 56 | "inputs": [ 57 | ], 58 | "outputs": [ 59 | {"name":"options","type":"uint8"}, 60 | {"name":"debotAbi","type":"bytes"}, 61 | {"name":"targetAbi","type":"bytes"}, 62 | {"name":"targetAddr","type":"address"} 63 | ] 64 | }, 65 | { 66 | "name": "setABI", 67 | "inputs": [ 68 | {"name":"dabi","type":"bytes"} 69 | ], 70 | "outputs": [ 71 | ] 72 | }, 73 | { 74 | "name": "constructor", 75 | "inputs": [ 76 | ], 77 | "outputs": [ 78 | ] 79 | } 80 | ], 81 | "data": [ 82 | ], 83 | "events": [ 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.png -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.sol: -------------------------------------------------------------------------------- 1 | pragma ton-solidity >=0.35.0; 2 | pragma AbiHeader expire; 3 | pragma AbiHeader time; 4 | pragma AbiHeader pubkey; 5 | // import required DeBot interfaces and basic DeBot contract. 6 | import "../Debot.sol"; 7 | import "../Terminal.sol"; 8 | 9 | contract HelloDebot is Debot { 10 | bytes m_icon; 11 | 12 | function setIcon(bytes icon) public { 13 | require(msg.pubkey() == tvm.pubkey(), 100); 14 | tvm.accept(); 15 | m_icon = icon; 16 | } 17 | 18 | /// @notice Entry point function for DeBot. 19 | function start() public override { 20 | // print string to user. 21 | Terminal.print(0, "Hello, World!"); 22 | // input string from user and define callback that receives entered string. 23 | Terminal.input(tvm.functionId(setUserInput), "How is it going?", false); 24 | } 25 | 26 | /// @notice Returns Metadata about DeBot. 27 | function getDebotInfo() public functionID(0xDEB) override view returns( 28 | string name, string version, string publisher, string caption, string author, 29 | address support, string hello, string language, string dabi, bytes icon 30 | ) { 31 | name = "HelloWorld"; 32 | version = "0.2.0"; 33 | publisher = "TON Labs"; 34 | caption = "Start develop DeBot from here"; 35 | author = "TON Labs"; 36 | support = address.makeAddrStd(0, 0x841288ed3b55d9cdafa806807f02a0ae0c169aa5edfe88a789a6482429756a94); 37 | hello = "Hello, i am a HelloWorld DeBot."; 38 | language = "en"; 39 | dabi = m_debotAbi.get(); 40 | icon = m_icon; 41 | } 42 | 43 | function getRequiredInterfaces() public view override returns (uint256[] interfaces) { 44 | return [ Terminal.ID ]; 45 | } 46 | 47 | function setUserInput(string value) public { 48 | // TODO: continue DeBot logic here... 49 | Terminal.print(0, format("You have entered \"{}\"", value)); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/helloDebot.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/tda.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"targetAddr","type":"address"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "setAbi", 15 | "inputs": [ 16 | {"name":"debotAbi","type":"bytes"} 17 | ], 18 | "outputs": [ 19 | ] 20 | }, 21 | { 22 | "name": "start", 23 | "inputs": [ 24 | ], 25 | "outputs": [ 26 | ] 27 | }, 28 | { 29 | "name": "getVersion", 30 | "inputs": [ 31 | ], 32 | "outputs": [ 33 | {"name":"name","type":"bytes"}, 34 | {"name":"semver","type":"uint24"} 35 | ] 36 | }, 37 | { 38 | "name": "onResponse", 39 | "inputs": [ 40 | {"name":"value","type":"bytes"} 41 | ], 42 | "outputs": [ 43 | ] 44 | }, 45 | { 46 | "name": "fetch", 47 | "inputs": [ 48 | ], 49 | "outputs": [ 50 | {"components":[{"name":"id","type":"uint8"},{"name":"desc","type":"bytes"},{"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"}],"name":"contexts","type":"tuple[]"} 51 | ] 52 | }, 53 | { 54 | "name": "getDebotOptions", 55 | "inputs": [ 56 | ], 57 | "outputs": [ 58 | {"name":"options","type":"uint8"}, 59 | {"name":"debotAbi","type":"bytes"}, 60 | {"name":"targetAbi","type":"bytes"}, 61 | {"name":"targetAddr","type":"address"} 62 | ] 63 | } 64 | ], 65 | "data": [ 66 | ], 67 | "events": [ 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/tda.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/tda.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/tdb.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "setAbi", 14 | "inputs": [ 15 | {"name":"debotAbi","type":"bytes"} 16 | ], 17 | "outputs": [ 18 | ] 19 | }, 20 | { 21 | "name": "start", 22 | "inputs": [ 23 | ], 24 | "outputs": [ 25 | ] 26 | }, 27 | { 28 | "name": "getVersion", 29 | "inputs": [ 30 | ], 31 | "outputs": [ 32 | {"name":"name","type":"bytes"}, 33 | {"name":"semver","type":"uint24"} 34 | ] 35 | }, 36 | { 37 | "name": "onRequest", 38 | "inputs": [ 39 | {"name":"request","type":"bytes"} 40 | ], 41 | "outputs": [ 42 | ] 43 | }, 44 | { 45 | "name": "fetch", 46 | "inputs": [ 47 | ], 48 | "outputs": [ 49 | {"components":[{"name":"id","type":"uint8"},{"name":"desc","type":"bytes"},{"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"}],"name":"contexts","type":"tuple[]"} 50 | ] 51 | }, 52 | { 53 | "name": "getDebotOptions", 54 | "inputs": [ 55 | ], 56 | "outputs": [ 57 | {"name":"options","type":"uint8"}, 58 | {"name":"debotAbi","type":"bytes"}, 59 | {"name":"targetAbi","type":"bytes"}, 60 | {"name":"targetAddr","type":"address"} 61 | ] 62 | } 63 | ], 64 | "data": [ 65 | ], 66 | "events": [ 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/tdb.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/tdb.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"targetAbi","type":"bytes"}, 9 | {"name":"targetAddr","type":"address"} 10 | ], 11 | "outputs": [ 12 | ] 13 | }, 14 | { 15 | "name": "setAbi", 16 | "inputs": [ 17 | {"name":"debotAbi","type":"bytes"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "fetch", 24 | "inputs": [ 25 | ], 26 | "outputs": [ 27 | {"components":[{"name":"id","type":"uint8"},{"name":"desc","type":"bytes"},{"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"}],"name":"contexts","type":"tuple[]"} 28 | ] 29 | }, 30 | { 31 | "name": "start", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | }, 37 | { 38 | "name": "quit", 39 | "inputs": [ 40 | ], 41 | "outputs": [ 42 | ] 43 | }, 44 | { 45 | "name": "getVersion", 46 | "inputs": [ 47 | ], 48 | "outputs": [ 49 | {"name":"name","type":"bytes"}, 50 | {"name":"semver","type":"uint24"} 51 | ] 52 | }, 53 | { 54 | "name": "getErrorDescription", 55 | "inputs": [ 56 | {"name":"error","type":"uint32"} 57 | ], 58 | "outputs": [ 59 | {"name":"desc","type":"bytes"} 60 | ] 61 | }, 62 | { 63 | "name": "testThrowException", 64 | "inputs": [ 65 | ], 66 | "outputs": [ 67 | ] 68 | }, 69 | { 70 | "name": "testThrowUnknownException", 71 | "inputs": [ 72 | ], 73 | "outputs": [ 74 | ] 75 | }, 76 | { 77 | "name": "testThrowTvmException", 78 | "inputs": [ 79 | ], 80 | "outputs": [ 81 | ] 82 | }, 83 | { 84 | "name": "setInteger", 85 | "inputs": [ 86 | ], 87 | "outputs": [ 88 | ] 89 | }, 90 | { 91 | "name": "enterAddress", 92 | "inputs": [ 93 | {"name":"addr","type":"address"} 94 | ], 95 | "outputs": [ 96 | ] 97 | }, 98 | { 99 | "name": "enterDebotAddress", 100 | "inputs": [ 101 | {"name":"debot","type":"address"} 102 | ], 103 | "outputs": [ 104 | ] 105 | }, 106 | { 107 | "name": "enterString", 108 | "inputs": [ 109 | {"name":"str","type":"bytes"} 110 | ], 111 | "outputs": [ 112 | ] 113 | }, 114 | { 115 | "name": "getPrintArgs", 116 | "inputs": [ 117 | ], 118 | "outputs": [ 119 | {"name":"number0","type":"int256"}, 120 | {"name":"param1","type":"address"}, 121 | {"name":"str2","type":"bytes"} 122 | ] 123 | }, 124 | { 125 | "name": "getDataArgs", 126 | "inputs": [ 127 | ], 128 | "outputs": [ 129 | {"name":"number0","type":"uint256"} 130 | ] 131 | }, 132 | { 133 | "name": "setData", 134 | "inputs": [ 135 | {"name":"num","type":"uint256"} 136 | ], 137 | "outputs": [ 138 | ] 139 | }, 140 | { 141 | "name": "setData2", 142 | "inputs": [ 143 | {"name":"num","type":"uint256"} 144 | ], 145 | "outputs": [ 146 | ] 147 | }, 148 | { 149 | "name": "getKey", 150 | "inputs": [ 151 | ], 152 | "outputs": [ 153 | {"name":"key","type":"uint32"} 154 | ] 155 | }, 156 | { 157 | "name": "invokeDebot", 158 | "inputs": [ 159 | ], 160 | "outputs": [ 161 | {"name":"debot","type":"address"}, 162 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"action","type":"tuple"} 163 | ] 164 | }, 165 | { 166 | "name": "sendSetDataMsg", 167 | "inputs": [ 168 | ], 169 | "outputs": [ 170 | {"name":"dest","type":"address"}, 171 | {"name":"body","type":"cell"} 172 | ] 173 | }, 174 | { 175 | "name": "sendTestMsg", 176 | "inputs": [ 177 | ], 178 | "outputs": [ 179 | {"name":"dest","type":"address"}, 180 | {"name":"body","type":"cell"} 181 | ] 182 | }, 183 | { 184 | "name": "setTargetAddr", 185 | "inputs": [ 186 | ], 187 | "outputs": [ 188 | ] 189 | }, 190 | { 191 | "name": "testgenKeypairFromSecret", 192 | "inputs": [ 193 | ], 194 | "outputs": [ 195 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"} 196 | ] 197 | }, 198 | { 199 | "name": "testgenRandom", 200 | "inputs": [ 201 | ], 202 | "outputs": [ 203 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"} 204 | ] 205 | }, 206 | { 207 | "name": "testencryptAuth", 208 | "inputs": [ 209 | ], 210 | "outputs": [ 211 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"} 212 | ] 213 | }, 214 | { 215 | "name": "testgetAccountState", 216 | "inputs": [ 217 | ], 218 | "outputs": [ 219 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"} 220 | ] 221 | }, 222 | { 223 | "name": "setKeypair", 224 | "inputs": [ 225 | {"name":"publicKey","type":"uint256"}, 226 | {"name":"secretKey","type":"uint256"} 227 | ], 228 | "outputs": [ 229 | ] 230 | }, 231 | { 232 | "name": "setEncrypted", 233 | "inputs": [ 234 | {"name":"encrypted","type":"bytes"} 235 | ], 236 | "outputs": [ 237 | ] 238 | }, 239 | { 240 | "name": "getSecret", 241 | "inputs": [ 242 | ], 243 | "outputs": [ 244 | {"name":"secret","type":"uint256"} 245 | ] 246 | }, 247 | { 248 | "name": "getLength", 249 | "inputs": [ 250 | ], 251 | "outputs": [ 252 | {"name":"length","type":"uint32"} 253 | ] 254 | }, 255 | { 256 | "name": "setRandom", 257 | "inputs": [ 258 | {"name":"buffer","type":"bytes"} 259 | ], 260 | "outputs": [ 261 | ] 262 | }, 263 | { 264 | "name": "getEncryptParams", 265 | "inputs": [ 266 | ], 267 | "outputs": [ 268 | {"name":"decrypted","type":"bytes"}, 269 | {"name":"nonce","type":"bytes"}, 270 | {"name":"publicKey","type":"uint256"}, 271 | {"name":"secretKey","type":"uint256"} 272 | ] 273 | }, 274 | { 275 | "name": "setState", 276 | "inputs": [ 277 | {"name":"balance","type":"uint256"}, 278 | {"name":"acc_type","type":"int8"}, 279 | {"name":"last_trans_lt","type":"uint64"}, 280 | {"name":"code","type":"cell"}, 281 | {"name":"data","type":"cell"}, 282 | {"name":"lib","type":"cell"} 283 | ], 284 | "outputs": [ 285 | ] 286 | }, 287 | { 288 | "name": "testgetBalance", 289 | "inputs": [ 290 | ], 291 | "outputs": [ 292 | {"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"} 293 | ] 294 | }, 295 | { 296 | "name": "getAddr", 297 | "inputs": [ 298 | ], 299 | "outputs": [ 300 | {"name":"addr","type":"address"} 301 | ] 302 | }, 303 | { 304 | "name": "setBalance", 305 | "inputs": [ 306 | {"name":"arg1","type":"uint128"} 307 | ], 308 | "outputs": [ 309 | ] 310 | }, 311 | { 312 | "name": "callInterface", 313 | "inputs": [ 314 | ], 315 | "outputs": [ 316 | ] 317 | }, 318 | { 319 | "name": "echo", 320 | "inputs": [ 321 | {"name":"response","type":"bytes"} 322 | ], 323 | "outputs": [ 324 | ] 325 | }, 326 | { 327 | "name": "getDebotOptions", 328 | "inputs": [ 329 | ], 330 | "outputs": [ 331 | {"name":"options","type":"uint8"}, 332 | {"name":"debotAbi","type":"bytes"}, 333 | {"name":"targetAbi","type":"bytes"}, 334 | {"name":"targetAddr","type":"address"} 335 | ] 336 | } 337 | ], 338 | "data": [ 339 | ], 340 | "events": [ 341 | ] 342 | } 343 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot2.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"pub","type":"uint256"}, 9 | {"name":"sec","type":"uint256"} 10 | ], 11 | "outputs": [ 12 | ] 13 | }, 14 | { 15 | "name": "setAbi", 16 | "inputs": [ 17 | {"name":"debotAbi","type":"bytes"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "increment", 24 | "inputs": [ 25 | {"name":"value","type":"uint32"} 26 | ], 27 | "outputs": [ 28 | ] 29 | }, 30 | { 31 | "name": "start", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | ] 36 | }, 37 | { 38 | "name": "getVersion", 39 | "inputs": [ 40 | ], 41 | "outputs": [ 42 | {"name":"name","type":"bytes"}, 43 | {"name":"semver","type":"uint24"} 44 | ] 45 | }, 46 | { 47 | "name": "callIncrement", 48 | "inputs": [ 49 | ], 50 | "outputs": [ 51 | ] 52 | }, 53 | { 54 | "name": "onSuccess", 55 | "inputs": [ 56 | ], 57 | "outputs": [ 58 | ] 59 | }, 60 | { 61 | "name": "onError", 62 | "inputs": [ 63 | {"name":"sdkError","type":"uint32"}, 64 | {"name":"exitCode","type":"uint32"} 65 | ], 66 | "outputs": [ 67 | ] 68 | }, 69 | { 70 | "name": "getCounter", 71 | "inputs": [ 72 | ], 73 | "outputs": [ 74 | ] 75 | }, 76 | { 77 | "name": "setCounter", 78 | "inputs": [ 79 | {"name":"counter","type":"uint32"} 80 | ], 81 | "outputs": [ 82 | ] 83 | }, 84 | { 85 | "name": "fetch", 86 | "inputs": [ 87 | ], 88 | "outputs": [ 89 | {"components":[{"name":"id","type":"uint8"},{"name":"desc","type":"bytes"},{"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"}],"name":"contexts","type":"tuple[]"} 90 | ] 91 | }, 92 | { 93 | "name": "getDebotOptions", 94 | "inputs": [ 95 | ], 96 | "outputs": [ 97 | {"name":"options","type":"uint8"}, 98 | {"name":"debotAbi","type":"bytes"}, 99 | {"name":"targetAbi","type":"bytes"}, 100 | {"name":"targetAddr","type":"address"} 101 | ] 102 | }, 103 | { 104 | "name": "counter", 105 | "inputs": [ 106 | ], 107 | "outputs": [ 108 | {"name":"counter","type":"uint32"} 109 | ] 110 | } 111 | ], 112 | "data": [ 113 | ], 114 | "events": [ 115 | ] 116 | } 117 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot2.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot2.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot3.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "start", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "getDebotInfo", 14 | "id": "0xDEB", 15 | "inputs": [ 16 | ], 17 | "outputs": [ 18 | {"name":"name","type":"bytes"}, 19 | {"name":"version","type":"bytes"}, 20 | {"name":"publisher","type":"bytes"}, 21 | {"name":"caption","type":"bytes"}, 22 | {"name":"author","type":"bytes"}, 23 | {"name":"support","type":"address"}, 24 | {"name":"hello","type":"bytes"}, 25 | {"name":"language","type":"bytes"}, 26 | {"name":"dabi","type":"bytes"}, 27 | {"name":"icon","type":"bytes"} 28 | ] 29 | }, 30 | { 31 | "name": "getRequiredInterfaces", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | {"name":"interfaces","type":"uint256[]"} 36 | ] 37 | }, 38 | { 39 | "name": "runAll", 40 | "inputs": [ 41 | ], 42 | "outputs": [ 43 | ] 44 | }, 45 | { 46 | "name": "testhdkeyXprv", 47 | "inputs": [ 48 | {"name":"index","type":"uint32"} 49 | ], 50 | "outputs": [ 51 | ] 52 | }, 53 | { 54 | "name": "hdkeyXprvFromMnemonicRes", 55 | "inputs": [ 56 | {"name":"xprv","type":"bytes"} 57 | ], 58 | "outputs": [ 59 | ] 60 | }, 61 | { 62 | "name": "hdkeyDeriveFromXprvRes", 63 | "inputs": [ 64 | {"name":"xprv","type":"bytes"} 65 | ], 66 | "outputs": [ 67 | ] 68 | }, 69 | { 70 | "name": "hdkeyDeriveFromXprvPathRes", 71 | "inputs": [ 72 | {"name":"xprv","type":"bytes"} 73 | ], 74 | "outputs": [ 75 | ] 76 | }, 77 | { 78 | "name": "hdkeySecretFromXprvRes", 79 | "inputs": [ 80 | {"name":"sec","type":"uint256"} 81 | ], 82 | "outputs": [ 83 | ] 84 | }, 85 | { 86 | "name": "naclSignKeypairFromSecretKeyRes", 87 | "inputs": [ 88 | {"name":"sec","type":"uint256"}, 89 | {"name":"pub","type":"uint256"} 90 | ], 91 | "outputs": [ 92 | ] 93 | }, 94 | { 95 | "name": "testMnemonicDeriveSignKeys", 96 | "inputs": [ 97 | {"name":"index","type":"uint32"} 98 | ], 99 | "outputs": [ 100 | ] 101 | }, 102 | { 103 | "name": "checkMnemonicDeriveSignKeys", 104 | "inputs": [ 105 | {"name":"pub","type":"uint256"}, 106 | {"name":"sec","type":"uint256"} 107 | ], 108 | "outputs": [ 109 | ] 110 | }, 111 | { 112 | "name": "testMnemonic", 113 | "inputs": [ 114 | {"name":"index","type":"uint32"} 115 | ], 116 | "outputs": [ 117 | ] 118 | }, 119 | { 120 | "name": "genMnemonic", 121 | "inputs": [ 122 | {"name":"phrase","type":"bytes"} 123 | ], 124 | "outputs": [ 125 | ] 126 | }, 127 | { 128 | "name": "verifyPhrase", 129 | "inputs": [ 130 | {"name":"valid","type":"bool"} 131 | ], 132 | "outputs": [ 133 | ] 134 | }, 135 | { 136 | "name": "testString", 137 | "inputs": [ 138 | {"name":"index","type":"uint32"} 139 | ], 140 | "outputs": [ 141 | ] 142 | }, 143 | { 144 | "name": "testCut1", 145 | "inputs": [ 146 | {"name":"substr","type":"bytes"} 147 | ], 148 | "outputs": [ 149 | ] 150 | }, 151 | { 152 | "name": "testCut2", 153 | "inputs": [ 154 | {"name":"substr","type":"bytes"} 155 | ], 156 | "outputs": [ 157 | ] 158 | }, 159 | { 160 | "name": "testAccount", 161 | "inputs": [ 162 | ], 163 | "outputs": [ 164 | ] 165 | }, 166 | { 167 | "name": "setBalance", 168 | "inputs": [ 169 | {"name":"nanotokens","type":"uint128"} 170 | ], 171 | "outputs": [ 172 | ] 173 | }, 174 | { 175 | "name": "setBalance2", 176 | "inputs": [ 177 | {"name":"nanotokens","type":"uint128"} 178 | ], 179 | "outputs": [ 180 | ] 181 | }, 182 | { 183 | "name": "setAccountType", 184 | "inputs": [ 185 | {"name":"acc_type","type":"int8"} 186 | ], 187 | "outputs": [ 188 | ] 189 | }, 190 | { 191 | "name": "setAccountType2", 192 | "inputs": [ 193 | {"name":"acc_type","type":"int8"} 194 | ], 195 | "outputs": [ 196 | ] 197 | }, 198 | { 199 | "name": "setCodeHash", 200 | "inputs": [ 201 | {"name":"code_hash","type":"uint256"} 202 | ], 203 | "outputs": [ 204 | ] 205 | }, 206 | { 207 | "name": "setCodeHash2", 208 | "inputs": [ 209 | {"name":"code_hash","type":"uint256"} 210 | ], 211 | "outputs": [ 212 | ] 213 | }, 214 | { 215 | "name": "testRandom", 216 | "inputs": [ 217 | ], 218 | "outputs": [ 219 | ] 220 | }, 221 | { 222 | "name": "setRandom1", 223 | "inputs": [ 224 | {"name":"buffer","type":"bytes"} 225 | ], 226 | "outputs": [ 227 | ] 228 | }, 229 | { 230 | "name": "setRandom2", 231 | "inputs": [ 232 | {"name":"buffer","type":"bytes"} 233 | ], 234 | "outputs": [ 235 | ] 236 | }, 237 | { 238 | "name": "testNaclbox", 239 | "inputs": [ 240 | ], 241 | "outputs": [ 242 | ] 243 | }, 244 | { 245 | "name": "getEnc", 246 | "inputs": [ 247 | {"name":"encrypted","type":"bytes"} 248 | ], 249 | "outputs": [ 250 | ] 251 | }, 252 | { 253 | "name": "getDec", 254 | "inputs": [ 255 | {"name":"decrypted","type":"bytes"} 256 | ], 257 | "outputs": [ 258 | ] 259 | }, 260 | { 261 | "name": "testKeysFromSecret", 262 | "inputs": [ 263 | ], 264 | "outputs": [ 265 | ] 266 | }, 267 | { 268 | "name": "getPair", 269 | "inputs": [ 270 | {"name":"publicKey","type":"uint256"}, 271 | {"name":"secretKey","type":"uint256"} 272 | ], 273 | "outputs": [ 274 | ] 275 | }, 276 | { 277 | "name": "testHexEncode", 278 | "inputs": [ 279 | ], 280 | "outputs": [ 281 | ] 282 | }, 283 | { 284 | "name": "hexEnc", 285 | "inputs": [ 286 | {"name":"hexstr","type":"bytes"} 287 | ], 288 | "outputs": [ 289 | ] 290 | }, 291 | { 292 | "name": "testHexDecode", 293 | "inputs": [ 294 | ], 295 | "outputs": [ 296 | ] 297 | }, 298 | { 299 | "name": "hexDec", 300 | "inputs": [ 301 | {"name":"data","type":"bytes"} 302 | ], 303 | "outputs": [ 304 | ] 305 | }, 306 | { 307 | "name": "testBase64Encode", 308 | "inputs": [ 309 | ], 310 | "outputs": [ 311 | ] 312 | }, 313 | { 314 | "name": "base64Enc", 315 | "inputs": [ 316 | {"name":"base64","type":"bytes"} 317 | ], 318 | "outputs": [ 319 | ] 320 | }, 321 | { 322 | "name": "testBase64Decode", 323 | "inputs": [ 324 | ], 325 | "outputs": [ 326 | ] 327 | }, 328 | { 329 | "name": "base64Dec", 330 | "inputs": [ 331 | {"name":"data","type":"bytes"} 332 | ], 333 | "outputs": [ 334 | ] 335 | }, 336 | { 337 | "name": "testSign", 338 | "inputs": [ 339 | ], 340 | "outputs": [ 341 | ] 342 | }, 343 | { 344 | "name": "setSigningBox", 345 | "inputs": [ 346 | {"name":"handle","type":"uint32"} 347 | ], 348 | "outputs": [ 349 | ] 350 | }, 351 | { 352 | "name": "setSignature", 353 | "inputs": [ 354 | {"name":"signature","type":"bytes"} 355 | ], 356 | "outputs": [ 357 | ] 358 | }, 359 | { 360 | "name": "getDebotOptions", 361 | "inputs": [ 362 | ], 363 | "outputs": [ 364 | {"name":"options","type":"uint8"}, 365 | {"name":"debotAbi","type":"bytes"}, 366 | {"name":"targetAbi","type":"bytes"}, 367 | {"name":"targetAddr","type":"address"} 368 | ] 369 | }, 370 | { 371 | "name": "setABI", 372 | "inputs": [ 373 | {"name":"dabi","type":"bytes"} 374 | ], 375 | "outputs": [ 376 | ] 377 | }, 378 | { 379 | "name": "constructor", 380 | "inputs": [ 381 | ], 382 | "outputs": [ 383 | ] 384 | } 385 | ], 386 | "data": [ 387 | ], 388 | "events": [ 389 | ] 390 | } 391 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot3.sol: -------------------------------------------------------------------------------- 1 | pragma ton-solidity >=0.40.0; 2 | pragma AbiHeader expire; 3 | pragma AbiHeader time; 4 | pragma AbiHeader pubkey; 5 | import "../Debot.sol"; 6 | import "../Sdk.sol"; 7 | import "../Base64.sol"; 8 | import "../Hex.sol"; 9 | import "../Terminal.sol"; 10 | import "../SigningBoxInput.sol"; 11 | 12 | contract testDebot3 is Debot { 13 | 14 | /* 15 | Storage 16 | */ 17 | 18 | uint32 m_rnd1; 19 | uint32 m_rnd2; 20 | 21 | /* 22 | * Overrided Debot functions 23 | */ 24 | 25 | // Entry point for new debots 26 | function start() override public { 27 | runAll(); 28 | } 29 | 30 | /// @notice Returns Metadata about DeBot. 31 | function getDebotInfo() public functionID(0xDEB) override view returns( 32 | string name, string version, string publisher, string caption, string author, 33 | address support, string hello, string language, string dabi, bytes icon 34 | ) { 35 | name = "TestSdk"; 36 | version = "0.4.0"; 37 | publisher = "TON Labs"; 38 | caption = "Test for SDK interface"; 39 | author = "TON Labs"; 40 | support = address(0); 41 | hello = "Hello, I'm a test."; 42 | language = "en"; 43 | dabi = m_debotAbi.get(); 44 | icon = ""; 45 | } 46 | 47 | function getRequiredInterfaces() public view override returns (uint256[] interfaces) { 48 | return [ Terminal.ID ]; 49 | } 50 | 51 | function runAll() public { 52 | testMnemonic(0); 53 | testString(0); 54 | testMnemonicDeriveSignKeys(0); 55 | testhdkeyXprv(0); 56 | testAccount(); 57 | testRandom(); 58 | testNaclbox(); 59 | testKeysFromSecret(); 60 | testHexEncode(); 61 | testBase64Encode(); 62 | testSign(); 63 | } 64 | 65 | function testhdkeyXprv(uint32 index) public { 66 | index = index; 67 | string ph = "blood genius security pen scissors tissue coil wish devote silk minimum remind"; 68 | Sdk.hdkeyXprvFromMnemonic(tvm.functionId(hdkeyXprvFromMnemonicRes),ph); 69 | } 70 | 71 | function hdkeyXprvFromMnemonicRes(string xprv) public{ 72 | require(xprv=="xprv9s21ZrQH143K4bDg2b9x7Y81Qw5LcfJ6D6YStM2rZVZP1DcYvmadfUXmV8wFb77Jp6s88VykAvdFAey3b5B1ykToXVJo5nnG26VVupdDxS3",130); 73 | Sdk.hdkeyDeriveFromXprv(tvm.functionId(hdkeyDeriveFromXprvRes),xprv,1,true); 74 | } 75 | 76 | function hdkeyDeriveFromXprvRes(string xprv) public{ 77 | require(xprv=="xprv9vDCWeesvU6UAq8cHqF3Pxyrju8oWRw9czjRrGbHpRWhUrp36MxX2WbGKuQdtKB24Z7bsThjfexsnWFwpjU81WKhGE9KuT7RJmJ2yDb6TeJ",131); 78 | string path = "m/44'/396'/0'/0/1"; 79 | Sdk.hdkeyDeriveFromXprvPath(tvm.functionId(hdkeyDeriveFromXprvPathRes),xprv,path); 80 | } 81 | 82 | function hdkeyDeriveFromXprvPathRes(string xprv) public{ 83 | require(xprv=="xprvA5Hr4SR7z6JmHGYJmDJefc8PETc7JSEV7iQGmr1AxycsddzVvHeZPpomy4ygLDiUbUu7322yTba9JxomxPM3TNH4TVHx6ZDysE6WX3X5Ym9",132); 84 | Sdk.hdkeySecretFromXprv(tvm.functionId(hdkeySecretFromXprvRes),xprv); 85 | } 86 | 87 | function hdkeySecretFromXprvRes(uint256 sec) public{ 88 | require(sec==0xa2087ef167360868a5153cd84182221388a79a26fe5a8557da0430b354dcc096,133); 89 | Sdk.naclSignKeypairFromSecretKey(tvm.functionId(naclSignKeypairFromSecretKeyRes),sec); 90 | 91 | } 92 | function naclSignKeypairFromSecretKeyRes(uint256 sec, uint256 pub) public{ 93 | require(pub==0x33d6e80fb461e6b1f7592970112a13f398428dcecc18431fead5ade906bce304,134); 94 | require(sec==0xa2087ef167360868a5153cd84182221388a79a26fe5a8557da0430b354dcc096,135); 95 | Terminal.print(0, "test hdkeyXprv passed"); 96 | } 97 | 98 | function testMnemonicDeriveSignKeys(uint32 index) public { 99 | index = index; 100 | string ph = "blood genius security pen scissors tissue coil wish devote silk minimum remind"; 101 | string path = "m/44'/396'/0'/0/1"; 102 | Sdk.mnemonicDeriveSignKeys(tvm.functionId(checkMnemonicDeriveSignKeys),ph,path); 103 | } 104 | 105 | function checkMnemonicDeriveSignKeys(uint256 pub, uint256 sec) public { 106 | require(pub == 0x07c31538a8371ced8ec6bd37c1b6dde86cf7246495e5ce538d58256c4f73dc5f,128); 107 | require(sec == 0xbc6464a6003bcb94659a03a1e705dd3d857bd270fb35acfd9bd460136e33ae39,129); 108 | Terminal.print(0, "test mnemonicDeriveSignKeys passed"); 109 | } 110 | 111 | 112 | function testMnemonic(uint32 index) public { 113 | index = index; 114 | Sdk.mnemonicFromRandom(tvm.functionId(genMnemonic),1,12); 115 | } 116 | 117 | function genMnemonic(string phrase) public { 118 | Sdk.mnemonicVerify(tvm.functionId(verifyPhrase),phrase); 119 | } 120 | 121 | function verifyPhrase(bool valid) public { 122 | require(valid, 125); 123 | Terminal.print(0, "test mnemonic passed"); 124 | } 125 | 126 | function testString(uint32 index) public { 127 | index = index; 128 | Sdk.substring(tvm.functionId(testCut1),"one two three",0,3); 129 | Sdk.substring(tvm.functionId(testCut2),"one two three",4,3); 130 | } 131 | 132 | function testCut1(string substr) public { 133 | require(substr=="one", 126); 134 | Terminal.print(0, "test substring1 passed"); 135 | } 136 | 137 | function testCut2(string substr) public { 138 | require(substr=="two", 127); 139 | Terminal.print(0, "test substring2 passed"); 140 | } 141 | 142 | function testAccount() public { 143 | Sdk.getBalance(tvm.functionId(setBalance), address(this)); 144 | Sdk.getBalance(tvm.functionId(setBalance2), address.makeAddrStd(0, 1)); 145 | } 146 | 147 | function setBalance(uint128 nanotokens) public { 148 | require(nanotokens > 0, 130); 149 | Sdk.getAccountType(tvm.functionId(setAccountType), address(this)); 150 | Sdk.getAccountType(tvm.functionId(setAccountType2), address.makeAddrStd(0, 1)); 151 | } 152 | 153 | function setBalance2(uint128 nanotokens) public pure { 154 | require(nanotokens == 0, 131); 155 | } 156 | 157 | function setAccountType(int8 acc_type) public { 158 | require(acc_type == 1, 132); 159 | Sdk.getAccountCodeHash(tvm.functionId(setCodeHash), address(this)); 160 | Sdk.getAccountCodeHash(tvm.functionId(setCodeHash2), address.makeAddrStd(0, 1)); 161 | } 162 | 163 | function setAccountType2(int8 acc_type) public pure { 164 | require(acc_type == -1, 133); 165 | } 166 | 167 | function setCodeHash(uint256 code_hash) public { 168 | require(code_hash != 0, 134); 169 | Terminal.print(0, "test account passed"); 170 | } 171 | 172 | function setCodeHash2(uint256 code_hash) public pure { 173 | require(code_hash == 0, 135); 174 | } 175 | 176 | function testRandom() public { 177 | Sdk.genRandom(tvm.functionId(setRandom1), 32); 178 | Sdk.genRandom(tvm.functionId(setRandom2), 32); 179 | } 180 | 181 | function setRandom1(bytes buffer) public { 182 | m_rnd1 = buffer.toSlice().decode(uint32); 183 | } 184 | 185 | function setRandom2(bytes buffer) public { 186 | m_rnd2 = buffer.toSlice().decode(uint32); 187 | require(m_rnd1 != m_rnd2, 140); 188 | Terminal.print(0, "test genRandom passed"); 189 | } 190 | 191 | function testNaclbox() public { 192 | /* 193 | const pub1 = "47F7C36DC0896FD2C020BB21F1605A3C161BF4EC5C5A23E5B5A111288CE59F19"; 194 | const sec1 = "4DD67EBD0431CEC53C60499775423695C4407A2CFABB6E7569046C1E7445A89C"; 195 | 196 | const pub2 = "552bc62d6e65294c0dea6c9143163dfcca6e1da4ea8411241e949925d07a0204"; 197 | const sec2 = "6817601a9b60fc4c449d3dc72e30600bddc74eeb4ad00e8d4d223f4b6dd94f3c"; 198 | */ 199 | string dec = "hello"; 200 | bytes nonce = bytes("000000000000000000000001"); 201 | uint256 tp = 0x552bc62d6e65294c0dea6c9143163dfcca6e1da4ea8411241e949925d07a0204; 202 | uint256 s = 0x4DD67EBD0431CEC53C60499775423695C4407A2CFABB6E7569046C1E7445A89C; 203 | Sdk.naclBox(tvm.functionId(getEnc),dec,nonce,tp,s); 204 | } 205 | 206 | function getEnc(bytes encrypted)public { 207 | require(encrypted.length==21,151); 208 | Terminal.print(0,"test naclbox passed"); 209 | bytes nonce = bytes("000000000000000000000001"); 210 | uint256 tp = 0x47F7C36DC0896FD2C020BB21F1605A3C161BF4EC5C5A23E5B5A111288CE59F19; 211 | uint256 s = 0x6817601a9b60fc4c449d3dc72e30600bddc74eeb4ad00e8d4d223f4b6dd94f3c; 212 | Sdk.naclBoxOpen(tvm.functionId(getDec),encrypted,nonce,tp,s); 213 | } 214 | 215 | function getDec(bytes decrypted)public { 216 | require(string(decrypted)=="hello",152); 217 | Terminal.print(0,"test naclboxopen passed"); 218 | } 219 | 220 | function testKeysFromSecret() public { 221 | uint256 sec = 0x4dd67ebd0431cec53c60499775423695c4407a2cfabb6e7569046c1e7445a89c; 222 | Sdk.naclKeypairFromSecret(tvm.functionId(getPair),sec); 223 | } 224 | 225 | function getPair(uint256 publicKey, uint256 secretKey)public { 226 | require(publicKey==0x47f7c36dc0896fd2c020bb21f1605a3c161bf4ec5c5a23e5b5a111288ce59f19,153); 227 | require(secretKey==0x4dd67ebd0431cec53c60499775423695c4407a2cfabb6e7569046c1e7445a89c,154); 228 | Terminal.print(0,"test naclKeypairFromSecret passed"); 229 | } 230 | 231 | function testHexEncode() public { 232 | bytes data = bytes("hello"); 233 | Hex.encode(tvm.functionId(hexEnc),data); 234 | } 235 | function hexEnc(string hexstr) public { 236 | require(hexstr=="68656c6c6f",130); 237 | Terminal.print(tvm.functionId(testHexDecode),"test hex encode passed"); 238 | } 239 | function testHexDecode() public { 240 | string hexstr = "68656c6c6f"; 241 | Hex.decode(tvm.functionId(hexDec),hexstr); 242 | } 243 | function hexDec(bytes data) public { 244 | require(string(data)=="hello",131); 245 | Terminal.print(0,"test hex decode passed"); 246 | } 247 | 248 | function testBase64Encode() public { 249 | bytes data = bytes("hello"); 250 | Base64.encode(tvm.functionId(base64Enc),data); 251 | } 252 | function base64Enc(string base64) public { 253 | require(base64=="aGVsbG8=",132); 254 | Terminal.print(tvm.functionId(testBase64Decode),"test base64 encode passed"); 255 | } 256 | function testBase64Decode() public { 257 | string base64 = "aGVsbG8="; 258 | Base64.decode(tvm.functionId(base64Dec),base64); 259 | } 260 | function base64Dec(bytes data) public { 261 | require(string(data)=="hello",133); 262 | Terminal.print(0,"test base64 decode passed"); 263 | } 264 | 265 | // 266 | // Sign functions 267 | // 268 | 269 | function testSign() public { 270 | uint256[] possibleKeys; 271 | SigningBoxInput.get(tvm.functionId(setSigningBox), "Enter key:", possibleKeys); 272 | } 273 | 274 | function setSigningBox(uint32 handle) public { 275 | uint256 hash = sha256("test sign string"); 276 | Sdk.signHash(tvm.functionId(setSignature), handle, hash); 277 | } 278 | 279 | function setSignature(bytes signature) public { 280 | require(signature.length == 64, 200); 281 | Terminal.print(0,"test sign hash passed"); 282 | uint256 hash = sha256("test sign string"); 283 | require(tvm.checkSign(hash, signature.toSlice(), tvm.pubkey()), 201); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot3.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot3.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot4.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"targetAbi","type":"bytes"}, 9 | {"name":"targetAddr","type":"address"} 10 | ], 11 | "outputs": [ 12 | ] 13 | }, 14 | { 15 | "name": "setAbi", 16 | "inputs": [ 17 | {"name":"debotAbi","type":"bytes"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "setImage", 24 | "inputs": [ 25 | {"name":"image","type":"cell"}, 26 | {"name":"pubkey","type":"uint256"} 27 | ], 28 | "outputs": [ 29 | ] 30 | }, 31 | { 32 | "name": "start", 33 | "inputs": [ 34 | ], 35 | "outputs": [ 36 | ] 37 | }, 38 | { 39 | "name": "getVersion", 40 | "inputs": [ 41 | ], 42 | "outputs": [ 43 | {"name":"name","type":"bytes"}, 44 | {"name":"semver","type":"uint24"} 45 | ] 46 | }, 47 | { 48 | "name": "onSuccess", 49 | "inputs": [ 50 | ], 51 | "outputs": [ 52 | ] 53 | }, 54 | { 55 | "name": "queryData", 56 | "inputs": [ 57 | {"name":"value","type":"int256"} 58 | ], 59 | "outputs": [ 60 | ] 61 | }, 62 | { 63 | "name": "onDeployFailed", 64 | "inputs": [ 65 | {"name":"sdkError","type":"uint32"}, 66 | {"name":"exitCode","type":"uint32"} 67 | ], 68 | "outputs": [ 69 | ] 70 | }, 71 | { 72 | "name": "sendMsg", 73 | "inputs": [ 74 | ], 75 | "outputs": [ 76 | ] 77 | }, 78 | { 79 | "name": "setData", 80 | "inputs": [ 81 | {"name":"num","type":"uint256"} 82 | ], 83 | "outputs": [ 84 | ] 85 | }, 86 | { 87 | "name": "onError", 88 | "inputs": [ 89 | {"name":"sdkError","type":"uint32"}, 90 | {"name":"exitCode","type":"uint32"} 91 | ], 92 | "outputs": [ 93 | ] 94 | }, 95 | { 96 | "name": "setResult", 97 | "inputs": [ 98 | ], 99 | "outputs": [ 100 | ] 101 | }, 102 | { 103 | "name": "setData2", 104 | "inputs": [ 105 | {"name":"num","type":"uint256"} 106 | ], 107 | "outputs": [ 108 | ] 109 | }, 110 | { 111 | "name": "fetch", 112 | "inputs": [ 113 | ], 114 | "outputs": [ 115 | {"components":[{"name":"id","type":"uint8"},{"name":"desc","type":"bytes"},{"components":[{"name":"desc","type":"bytes"},{"name":"name","type":"bytes"},{"name":"actionType","type":"uint8"},{"name":"attrs","type":"bytes"},{"name":"to","type":"uint8"},{"name":"misc","type":"cell"}],"name":"actions","type":"tuple[]"}],"name":"contexts","type":"tuple[]"} 116 | ] 117 | }, 118 | { 119 | "name": "getDebotOptions", 120 | "inputs": [ 121 | ], 122 | "outputs": [ 123 | {"name":"options","type":"uint8"}, 124 | {"name":"debotAbi","type":"bytes"}, 125 | {"name":"targetAbi","type":"bytes"}, 126 | {"name":"targetAddr","type":"address"} 127 | ] 128 | } 129 | ], 130 | "data": [ 131 | ], 132 | "events": [ 133 | ] 134 | } 135 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot4.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot4.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot5.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | {"name":"codeHash","type":"uint256"} 9 | ], 10 | "outputs": [ 11 | ] 12 | }, 13 | { 14 | "name": "start", 15 | "inputs": [ 16 | ], 17 | "outputs": [ 18 | ] 19 | }, 20 | { 21 | "name": "setHash", 22 | "inputs": [ 23 | {"name":"value","type":"bytes"} 24 | ], 25 | "outputs": [ 26 | ] 27 | }, 28 | { 29 | "name": "getAccountsDataByHash", 30 | "inputs": [ 31 | {"name":"value","type":"bool"} 32 | ], 33 | "outputs": [ 34 | ] 35 | }, 36 | { 37 | "name": "onDataResult", 38 | "inputs": [ 39 | {"components":[{"name":"id","type":"address"},{"name":"data","type":"cell"}],"name":"accounts","type":"tuple[]"} 40 | ], 41 | "outputs": [ 42 | ] 43 | }, 44 | { 45 | "name": "getVersion", 46 | "inputs": [ 47 | ], 48 | "outputs": [ 49 | {"name":"name","type":"bytes"}, 50 | {"name":"semver","type":"uint24"} 51 | ] 52 | }, 53 | { 54 | "name": "getDebotOptions", 55 | "inputs": [ 56 | ], 57 | "outputs": [ 58 | {"name":"options","type":"uint8"}, 59 | {"name":"debotAbi","type":"bytes"}, 60 | {"name":"targetAbi","type":"bytes"}, 61 | {"name":"targetAddr","type":"address"} 62 | ] 63 | }, 64 | { 65 | "name": "setABI", 66 | "inputs": [ 67 | {"name":"dabi","type":"bytes"} 68 | ], 69 | "outputs": [ 70 | ] 71 | } 72 | ], 73 | "data": [ 74 | ], 75 | "events": [ 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot5.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot5.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot6.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "start", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "onSuccess1", 14 | "inputs": [ 15 | ], 16 | "outputs": [ 17 | ] 18 | }, 19 | { 20 | "name": "onSuccess2", 21 | "inputs": [ 22 | ], 23 | "outputs": [ 24 | ] 25 | }, 26 | { 27 | "name": "onSuccess3", 28 | "inputs": [ 29 | ], 30 | "outputs": [ 31 | ] 32 | }, 33 | { 34 | "name": "onError1", 35 | "inputs": [ 36 | {"name":"sdkError","type":"uint32"}, 37 | {"name":"exitCode","type":"uint32"} 38 | ], 39 | "outputs": [ 40 | ] 41 | }, 42 | { 43 | "name": "onError2", 44 | "inputs": [ 45 | {"name":"sdkError","type":"uint32"}, 46 | {"name":"exitCode","type":"uint32"} 47 | ], 48 | "outputs": [ 49 | ] 50 | }, 51 | { 52 | "name": "onError3", 53 | "inputs": [ 54 | {"name":"sdkError","type":"uint32"}, 55 | {"name":"exitCode","type":"uint32"} 56 | ], 57 | "outputs": [ 58 | ] 59 | }, 60 | { 61 | "name": "send3", 62 | "inputs": [ 63 | ], 64 | "outputs": [ 65 | ] 66 | }, 67 | { 68 | "name": "send2", 69 | "inputs": [ 70 | ], 71 | "outputs": [ 72 | ] 73 | }, 74 | { 75 | "name": "send1", 76 | "inputs": [ 77 | {"name":"value1","type":"uint64"}, 78 | {"name":"value2","type":"uint64"} 79 | ], 80 | "outputs": [ 81 | ] 82 | }, 83 | { 84 | "name": "getVersion", 85 | "inputs": [ 86 | ], 87 | "outputs": [ 88 | {"name":"name","type":"bytes"}, 89 | {"name":"semver","type":"uint24"} 90 | ] 91 | }, 92 | { 93 | "name": "getDebotOptions", 94 | "inputs": [ 95 | ], 96 | "outputs": [ 97 | {"name":"options","type":"uint8"}, 98 | {"name":"debotAbi","type":"bytes"}, 99 | {"name":"targetAbi","type":"bytes"}, 100 | {"name":"targetAddr","type":"address"} 101 | ] 102 | }, 103 | { 104 | "name": "setABI", 105 | "inputs": [ 106 | {"name":"dabi","type":"bytes"} 107 | ], 108 | "outputs": [ 109 | ] 110 | }, 111 | { 112 | "name": "constructor", 113 | "inputs": [ 114 | ], 115 | "outputs": [ 116 | ] 117 | } 118 | ], 119 | "data": [ 120 | ], 121 | "events": [ 122 | ] 123 | } 124 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot6.sol: -------------------------------------------------------------------------------- 1 | pragma ton-solidity >=0.35.0; 2 | pragma AbiHeader expire; 3 | pragma AbiHeader time; 4 | pragma AbiHeader pubkey; 5 | // import required DeBot interfaces and basic DeBot contract. 6 | import "../Debot.sol"; 7 | import "../Terminal.sol"; 8 | 9 | contract testDebot is Debot { 10 | 11 | /// @notice Entry point function for DeBot. 12 | function start() public override { 13 | optional(uint256) pubkey = tvm.pubkey(); 14 | this.send1{ 15 | abiVer: 2, 16 | extMsg: true, 17 | sign: true, 18 | time: 0, 19 | expire: 0, 20 | pubkey: pubkey, 21 | callbackId: tvm.functionId(onSuccess1), 22 | onErrorId: tvm.functionId(onError1) 23 | }(2.2 ton, 3.5 ton); 24 | 25 | this.send2{ 26 | abiVer: 2, 27 | extMsg: true, 28 | sign: true, 29 | time: 0, 30 | expire: 0, 31 | pubkey: pubkey, 32 | callbackId: tvm.functionId(onSuccess2), 33 | onErrorId: tvm.functionId(onError2) 34 | }(); 35 | 36 | this.send3{ 37 | abiVer: 2, 38 | extMsg: true, 39 | sign: true, 40 | time: 0, 41 | expire: 0, 42 | pubkey: pubkey, 43 | callbackId: tvm.functionId(onSuccess3), 44 | onErrorId: tvm.functionId(onError3) 45 | }(); 46 | } 47 | 48 | function onSuccess1() public { 49 | Terminal.print(0, "Send1 succeeded"); 50 | } 51 | 52 | function onSuccess2() public pure { 53 | require(false, 201); 54 | } 55 | 56 | function onSuccess3() public pure { 57 | require(false, 304); 58 | } 59 | 60 | function onError1(uint32 sdkError, uint32 exitCode) public pure { 61 | sdkError = sdkError; 62 | exitCode = exitCode; 63 | require(false, 200); 64 | } 65 | 66 | function onError2(uint32 sdkError, uint32 exitCode) public { 67 | require(sdkError == 812, 300); 68 | require(exitCode == 0, 301); 69 | Terminal.print(0, "Send2 rejected"); 70 | } 71 | 72 | function onError3(uint32 sdkError, uint32 exitCode) public pure { 73 | require(sdkError == 414, 102); 74 | require(exitCode == 303, 103); 75 | } 76 | 77 | function send3() public view { 78 | require(false, 303); 79 | } 80 | 81 | function send2() public view { 82 | require(msg.pubkey() == tvm.pubkey(), 101); 83 | tvm.accept(); 84 | address(this).transfer(10 ton, true, 1); 85 | } 86 | 87 | function send1(uint64 value1, uint64 value2) public view { 88 | require(msg.pubkey() == tvm.pubkey(), 101); 89 | tvm.accept(); 90 | address(this).transfer(value1, true, 1); 91 | address addr = address.makeAddrStd(0, 0); 92 | addr.transfer(value2, false, 1); 93 | } 94 | 95 | // @notice Define DeBot version and title here. 96 | function getVersion() public override returns (string name, uint24 semver) { 97 | (name, semver) = ("Test DeBot 6 for testing approve callback", _version(0,1,0)); 98 | } 99 | 100 | function _version(uint24 major, uint24 minor, uint24 fix) private pure inline returns (uint24) { 101 | return (major << 16) | (minor << 8) | (fix); 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot6.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot6.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot7.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "start", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "setResult", 14 | "inputs": [ 15 | {"name":"result","type":"bool"}, 16 | {"components":[{"name":"name","type":"bytes"},{"name":"tags","type":"bytes[]"},{"name":"age","type":"uint8"},{"name":"numbers","type":"uint8[]"},{"name":"addrs","type":"map(address,bytes)"}],"name":"obj","type":"tuple"} 17 | ], 18 | "outputs": [ 19 | ] 20 | }, 21 | { 22 | "name": "getRequiredInterfaces", 23 | "inputs": [ 24 | ], 25 | "outputs": [ 26 | {"name":"interfaces","type":"uint256[]"} 27 | ] 28 | }, 29 | { 30 | "name": "getDebotInfo", 31 | "id": "0xDEB", 32 | "inputs": [ 33 | ], 34 | "outputs": [ 35 | {"name":"name","type":"bytes"}, 36 | {"name":"version","type":"bytes"}, 37 | {"name":"publisher","type":"bytes"}, 38 | {"name":"key","type":"bytes"}, 39 | {"name":"author","type":"bytes"}, 40 | {"name":"support","type":"address"}, 41 | {"name":"hello","type":"bytes"}, 42 | {"name":"language","type":"bytes"}, 43 | {"name":"dabi","type":"bytes"}, 44 | {"name":"icon","type":"bytes"} 45 | ] 46 | }, 47 | { 48 | "name": "getVersion", 49 | "inputs": [ 50 | ], 51 | "outputs": [ 52 | {"name":"name","type":"bytes"}, 53 | {"name":"semver","type":"uint24"} 54 | ] 55 | }, 56 | { 57 | "name": "getDebotOptions", 58 | "inputs": [ 59 | ], 60 | "outputs": [ 61 | {"name":"options","type":"uint8"}, 62 | {"name":"debotAbi","type":"bytes"}, 63 | {"name":"targetAbi","type":"bytes"}, 64 | {"name":"targetAddr","type":"address"} 65 | ] 66 | }, 67 | { 68 | "name": "setABI", 69 | "inputs": [ 70 | {"name":"dabi","type":"bytes"} 71 | ], 72 | "outputs": [ 73 | ] 74 | }, 75 | { 76 | "name": "constructor", 77 | "inputs": [ 78 | ], 79 | "outputs": [ 80 | ] 81 | } 82 | ], 83 | "data": [ 84 | ], 85 | "events": [ 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot7.sol: -------------------------------------------------------------------------------- 1 | pragma ton-solidity >=0.40.0; 2 | pragma AbiHeader expire; 3 | pragma AbiHeader time; 4 | pragma AbiHeader pubkey; 5 | import "../Debot.sol"; 6 | import "../Terminal.sol"; 7 | import "../Json.sol"; 8 | 9 | contract TestDebot7 is Debot { 10 | struct Info{ 11 | string name; 12 | string[] tags; 13 | uint8 age; 14 | uint8[] numbers; 15 | mapping (address => string) addrs; 16 | } 17 | 18 | /// @notice Entry point function for DeBot. 19 | function start() public override { 20 | string json = "{\"name\":\"Joe\",\"tags\":[\"good\",\"bad\",\"ugly\"],\"age\":73,\"numbers\":[1,2,3],\"addrs\":{\"0:1111111111111111111111111111111111111111111111111111111111111111\":\"My main account\"}}"; 21 | Json.deserialize(tvm.functionId(setResult), json); 22 | } 23 | 24 | function setResult(bool result, Info obj) public pure { 25 | uint8[] numbers = [1,2,3]; 26 | string[] tags = ["good", "bad", "ugly"]; 27 | require(result == true, 99); 28 | require(obj.name =="Joe", 100); 29 | for(uint i = 0; i < tags.length; i++) { 30 | require(tvm.hash(bytes(tags[i])) == tvm.hash(bytes(obj.tags[i])), (i << 4) & 1); 31 | } 32 | require(obj.age == 73, 102); 33 | for(uint i = 0; i < numbers.length; i++) { 34 | require(obj.numbers[i]==numbers[i], 103); 35 | } 36 | address testAddr = address.makeAddrStd(0, 0x1111111111111111111111111111111111111111111111111111111111111111); 37 | optional(string) titleOpt = obj.addrs.fetch(testAddr); 38 | require(titleOpt.hasValue(), 104); 39 | string title = titleOpt.get(); 40 | require(tvm.hash(bytes(title)) == tvm.hash(bytes("My main account")), 105); 41 | } 42 | 43 | function getRequiredInterfaces() public view override returns (uint256[] interfaces) { 44 | return [ Terminal.ID, Json.ID ]; 45 | } 46 | 47 | function getDebotInfo() public functionID(0xDEB) view override returns( 48 | string name, string version, string publisher, string key, string author, 49 | address support, string hello, string language, string dabi, bytes icon) { 50 | name = "Test DeBot 7"; 51 | version = "0.1.0"; 52 | publisher = "TON Labs"; 53 | key = "Test for Json interface"; 54 | author = "TON Labs"; 55 | support = address(0); 56 | hello = "Test DeBot 7"; 57 | language = "en"; 58 | dabi = m_debotAbi.get(); 59 | icon = ""; 60 | } 61 | 62 | function getVersion() public override returns (string name, uint24 semver) { 63 | name = "Test DeBot 7"; 64 | semver = 1 << 8; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot7.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot7.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot8.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["pubkey", "time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "start", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "setResponse", 14 | "inputs": [ 15 | {"name":"statusCode","type":"int32"}, 16 | {"name":"retHeaders","type":"bytes[]"}, 17 | {"name":"content","type":"bytes"} 18 | ], 19 | "outputs": [ 20 | ] 21 | }, 22 | { 23 | "name": "setGetResponse", 24 | "inputs": [ 25 | {"name":"statusCode","type":"int32"}, 26 | {"name":"retHeaders","type":"bytes[]"}, 27 | {"name":"content","type":"bytes"} 28 | ], 29 | "outputs": [ 30 | ] 31 | }, 32 | { 33 | "name": "setResult", 34 | "inputs": [ 35 | {"name":"result","type":"bool"}, 36 | {"components":[{"components":[{"name":"ProviderCode","type":"uint32"},{"name":"CountryIso","type":"bytes"},{"name":"Name","type":"bytes"},{"name":"LogoUrl","type":"bytes"}],"name":"Result","type":"tuple[]"},{"name":"Status","type":"bytes"}],"name":"obj","type":"tuple"} 37 | ], 38 | "outputs": [ 39 | ] 40 | }, 41 | { 42 | "name": "setResult2", 43 | "inputs": [ 44 | {"name":"result","type":"bool"}, 45 | {"components":[{"components":[{"name":"name1","type":"bytes"}],"name":"args","type":"tuple"},{"components":[{"name":"Accept","type":"bytes"},{"name":"Host","type":"bytes"},{"name":"X_Amzn_Trace_Id","type":"bytes"}],"name":"headers","type":"tuple"},{"name":"origin","type":"bytes"},{"name":"url","type":"bytes"}],"name":"obj","type":"tuple"} 46 | ], 47 | "outputs": [ 48 | ] 49 | }, 50 | { 51 | "name": "getRequiredInterfaces", 52 | "inputs": [ 53 | ], 54 | "outputs": [ 55 | {"name":"interfaces","type":"uint256[]"} 56 | ] 57 | }, 58 | { 59 | "name": "getDebotInfo", 60 | "id": "0xDEB", 61 | "inputs": [ 62 | ], 63 | "outputs": [ 64 | {"name":"name","type":"bytes"}, 65 | {"name":"version","type":"bytes"}, 66 | {"name":"publisher","type":"bytes"}, 67 | {"name":"key","type":"bytes"}, 68 | {"name":"author","type":"bytes"}, 69 | {"name":"support","type":"address"}, 70 | {"name":"hello","type":"bytes"}, 71 | {"name":"language","type":"bytes"}, 72 | {"name":"dabi","type":"bytes"}, 73 | {"name":"icon","type":"bytes"} 74 | ] 75 | }, 76 | { 77 | "name": "getDebotOptions", 78 | "inputs": [ 79 | ], 80 | "outputs": [ 81 | {"name":"options","type":"uint8"}, 82 | {"name":"debotAbi","type":"bytes"}, 83 | {"name":"targetAbi","type":"bytes"}, 84 | {"name":"targetAddr","type":"address"} 85 | ] 86 | }, 87 | { 88 | "name": "setABI", 89 | "inputs": [ 90 | {"name":"dabi","type":"bytes"} 91 | ], 92 | "outputs": [ 93 | ] 94 | }, 95 | { 96 | "name": "constructor", 97 | "inputs": [ 98 | ], 99 | "outputs": [ 100 | ] 101 | } 102 | ], 103 | "data": [ 104 | ], 105 | "events": [ 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot8.sol: -------------------------------------------------------------------------------- 1 | pragma ton-solidity >=0.40.0; 2 | pragma AbiHeader expire; 3 | pragma AbiHeader time; 4 | pragma AbiHeader pubkey; 5 | import "../Debot.sol"; 6 | import "../Terminal.sol"; 7 | import "../Network.sol"; 8 | import "../Json.sol"; 9 | 10 | contract TestDebot8 is Debot { 11 | 12 | struct Response { 13 | Provider[] Result; 14 | string Status; 15 | } 16 | 17 | struct Provider { 18 | uint32 ProviderCode; 19 | string CountryIso; 20 | string Name; 21 | string LogoUrl; 22 | } 23 | 24 | struct Args { 25 | string name1; 26 | } 27 | struct Headers { 28 | string Accept; 29 | string Host; 30 | string X_Amzn_Trace_Id; 31 | } 32 | struct GetResponse { 33 | Args args; 34 | Headers headers; 35 | string origin; 36 | string url; 37 | } 38 | 39 | function start() public override { 40 | string[] headers; 41 | string url = "http://ptsv2.com/t/qajss-1618330246/post"; 42 | headers.push("Content-Type: application/x-www-form-urlencoded"); 43 | string body = "key1=value1"; 44 | Network.post(tvm.functionId(setResponse), url, headers, body); 45 | url = "https://httpbin.org/get?name1=value1"; 46 | string[] headers2; 47 | Network.get(tvm.functionId(setGetResponse), url, headers2); 48 | } 49 | 50 | function setResponse(int32 statusCode, string[] retHeaders, string content) public { 51 | retHeaders = retHeaders; 52 | require(statusCode == 200, 199); 53 | Json.deserialize(tvm.functionId(setResult), content); 54 | } 55 | 56 | function setGetResponse(int32 statusCode, string[] retHeaders, string content) public { 57 | retHeaders = retHeaders; 58 | require(statusCode == 200, 199); 59 | Json.deserialize(tvm.functionId(setResult2), content); 60 | } 61 | 62 | function setResult(bool result, Response obj) public pure { 63 | require(result == true, 200); 64 | require(tvm.hash(bytes(obj.Status)) == tvm.hash(bytes("success")), 201); 65 | require(obj.Result[0].ProviderCode == 678, 202); 66 | require(tvm.hash(bytes(obj.Result[0].Name)) == tvm.hash(bytes("Wonderland")), 203); 67 | require(tvm.hash(bytes(obj.Result[0].CountryIso)) == tvm.hash(bytes("WDL")), 204); 68 | require(tvm.hash(bytes(obj.Result[0].LogoUrl)) == tvm.hash(bytes("http://path.to.logo/url")), 205); 69 | } 70 | 71 | function setResult2(bool result, GetResponse obj) public pure { 72 | require(result == true, 300); 73 | require(tvm.hash(bytes(obj.args.name1)) == tvm.hash(bytes("value1")), 301); 74 | } 75 | 76 | function getRequiredInterfaces() public view override returns (uint256[] interfaces) { 77 | return [ Terminal.ID, Network.ID, Json.ID ]; 78 | } 79 | 80 | function getDebotInfo() public functionID(0xDEB) view override returns( 81 | string name, string version, string publisher, string key, string author, 82 | address support, string hello, string language, string dabi, bytes icon) { 83 | name = "Test DeBot 8"; 84 | version = "0.1.0"; 85 | publisher = "TON Labs"; 86 | string iface = "Network"; 87 | key = format("Test for {} interface", iface); 88 | author = "TON Labs"; 89 | support = address(0); 90 | hello = "Test DeBot 8"; 91 | language = "en"; 92 | dabi = m_debotAbi.get(); 93 | icon = ""; 94 | } 95 | } -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot8.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebot8.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebotTarget.abi.json: -------------------------------------------------------------------------------- 1 | { 2 | "ABI version": 2, 3 | "header": ["time", "expire"], 4 | "functions": [ 5 | { 6 | "name": "constructor", 7 | "inputs": [ 8 | ], 9 | "outputs": [ 10 | ] 11 | }, 12 | { 13 | "name": "getData", 14 | "inputs": [ 15 | {"name":"key","type":"uint32"} 16 | ], 17 | "outputs": [ 18 | {"name":"num","type":"uint256"} 19 | ] 20 | }, 21 | { 22 | "name": "setData", 23 | "inputs": [ 24 | {"name":"key","type":"uint32"}, 25 | {"name":"val","type":"uint256"} 26 | ], 27 | "outputs": [ 28 | ] 29 | } 30 | ], 31 | "data": [ 32 | ], 33 | "events": [ 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebotTarget.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-swift/295076ad5e3acadb8de8b5b61819522df6912e33/Tests/EverscaleClientSwiftTests/Fixtures/abi/testDebotTarget.tvc -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/NetTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 21.10.2020. 6 | // 7 | 8 | import XCTest 9 | import class Foundation.Bundle 10 | @testable import EverscaleClientSwift 11 | @testable import CTonSDK 12 | @testable import SwiftExtensionsPack 13 | 14 | final class NetTests: XCTestCase { 15 | 16 | func testQuery_collection() throws { 17 | try testAsyncMethods { (client, group) in 18 | group.enter() 19 | let any = AnyValue.object( 20 | [ 21 | "created_at" : AnyValue.object( 22 | [ 23 | "gt" : AnyValue.int(1562342740) 24 | ]) 25 | ]) 26 | let payload: TSDKParamsOfQueryCollection = .init(collection: "messages", 27 | filter: any, 28 | result: "body created_at", 29 | order: nil, 30 | limit: nil) 31 | try client.net.query_collection(payload) { [group] (response) in 32 | if let first = response.result?.result.first?.toAny() as? [String: Any] { 33 | let created_at: Int? = first["created_at"] as? Int 34 | XCTAssertTrue(created_at ?? 0 > 1562342740) 35 | } else { 36 | XCTAssertTrue(false, "No Data") 37 | } 38 | group.leave() 39 | } 40 | group.wait() 41 | } 42 | } 43 | 44 | func testWait_for_collection() throws { 45 | try testAsyncMethods { (client, group) in 46 | let now: Int = Int(Date().timeIntervalSince1970) 47 | let any = AnyValue.object( 48 | [ 49 | "now" : AnyValue.object( 50 | [ 51 | "gt" : AnyValue.int(now) 52 | ]) 53 | ]) 54 | let payload: TSDKParamsOfWaitForCollection = .init(collection: "transactions", 55 | filter: any, 56 | result: "id now", 57 | timeout: nil) 58 | group.enter() 59 | try client.net.wait_for_collection(payload) { [group] (response) in 60 | if let json = response.result?.result.toAny() as? [String: Any], 61 | let thisNow = json["now"] as? Int 62 | { 63 | XCTAssertTrue(thisNow > now) 64 | } else { 65 | XCTAssertTrue(false, "No Data") 66 | } 67 | group.leave() 68 | } 69 | Thread { 70 | // Just generate transactions 71 | usleep(1_000_000) 72 | for _ in 1...2 { 73 | _ = try? self.getGramsFromGiverSync(client) 74 | } 75 | }.start() 76 | group.wait() 77 | } 78 | } 79 | 80 | func testSubscribe_collection() throws { 81 | try testAsyncMethods { (client, group) in 82 | group.enter() 83 | let payload: TSDKParamsOfSubscribeCollection = .init(collection: "transactions", 84 | filter: nil, 85 | result: "id account_addr") 86 | try client.net.subscribe_collection(payload) { [group] (response) in 87 | if response.result?.handle != nil { 88 | BindingStore.deleteResponseHandler(response.requestId) 89 | group.leave() 90 | return 91 | } else if let result = response.rawResponse.toModel(TSDKDefault.self)?.result?.toAny() as? [String: Any], 92 | let account_addr = result["account_addr"] 93 | { 94 | XCTAssertTrue((account_addr as? String) != nil) 95 | } 96 | if response.finished { 97 | BindingStore.deleteResponseHandler(response.requestId) 98 | group.leave() 99 | } 100 | } 101 | group.wait() 102 | } 103 | } 104 | 105 | 106 | func testUnsubscribe() throws { 107 | try testAsyncMethods { (client, group) in 108 | /// groupCounter - for safe exit from response if execute "UNSUBSCRIBE THREAD" 109 | var groupCounter: Int = .init() 110 | let groupCounterLock: NSLock = .init() 111 | 112 | group.enter() 113 | groupCounter += 1 114 | let payload: TSDKParamsOfSubscribeCollection = .init(collection: "transactions", 115 | filter: nil, 116 | result: "id account_addr") 117 | var handle: UInt32 = .init() 118 | var requestId: UInt32 = .init() 119 | let handleGroup: DispatchGroup = .init() 120 | handleGroup.enter() 121 | try client.net.subscribe_collection(payload) { [group, handleGroup, groupCounterLock] (response) in 122 | groupCounterLock.lock() 123 | if response.result != nil { 124 | XCTAssertTrue(response.result?.handle != nil) 125 | handle = response.result?.handle ?? 0 126 | requestId = response.requestId 127 | handleGroup.leave() 128 | } 129 | if response.finished { 130 | BindingStore.deleteResponseHandler(response.requestId) 131 | if groupCounter > 0 { 132 | groupCounter -= 1 133 | group.leave() 134 | } 135 | } 136 | groupCounterLock.unlock() 137 | } 138 | 139 | groupCounterLock.lock() 140 | let copyRequestId: UInt32 = requestId 141 | groupCounterLock.unlock() 142 | Thread { [group, copyRequestId, groupCounterLock] in 143 | sleep(5) 144 | groupCounterLock.lock() 145 | if groupCounter > 0 { 146 | groupCounter -= 1 147 | BindingStore.deleteResponseHandler(copyRequestId) 148 | XCTAssertTrue(false, "NOT UNSUBSCRIBED") 149 | group.leave() 150 | } 151 | groupCounterLock.unlock() 152 | }.start() 153 | handleGroup.wait() 154 | 155 | group.enter() 156 | groupCounter += 1 157 | let payloadUnsubscribe: TSDKResultOfSubscribeCollection = .init(handle: handle) 158 | try client.net.unsubscribe(payloadUnsubscribe) { [group, groupCounterLock] (response) in 159 | groupCounterLock.lock() 160 | if groupCounter > 0 { 161 | groupCounter -= 1 162 | group.leave() 163 | } 164 | groupCounterLock.unlock() 165 | } 166 | group.wait() 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/ProcessingTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 27.10.2020. 6 | // 7 | 8 | import XCTest 9 | import class Foundation.Bundle 10 | @testable import EverscaleClientSwift 11 | @testable import CTonSDK 12 | @testable import SwiftExtensionsPack 13 | 14 | final class ProcessingTests: XCTestCase { 15 | 16 | func testWait_for_transaction() throws { 17 | try testAsyncMethods { (client, group) in 18 | let tvcData: Data = self.readTvc("Events") 19 | let abiJSONValue: AnyValue = self.readAbi("Events") 20 | let abi: TSDKAbi = .init(type: .Serialized, value: abiJSONValue) 21 | let keys: TSDKKeyPair = try self.generateKeys() 22 | let signer: TSDKSigner = .init(type: .Keys, 23 | public_key: nil, 24 | keys: keys, 25 | handle: nil) 26 | let callSet: TSDKCallSet = .init(function_name: "constructor", 27 | header: TSDKFunctionHeader(expire: nil, 28 | time: nil, 29 | pubkey: keys.public), 30 | input: nil) 31 | let deploySet: TSDKDeploySet = .init(tvc: tvcData.base64EncodedString(), workchain_id: nil, initial_data: nil) 32 | let payloadEncodeMessage: TSDKParamsOfEncodeMessage = .init(abi: abi, 33 | address: nil, 34 | deploy_set: deploySet, 35 | call_set: callSet, 36 | signer: signer, 37 | processing_try_index: nil) 38 | var encodedMessage: TSDKResultOfEncodeMessage! 39 | group.enter() 40 | try client.abi.encode_message(payloadEncodeMessage) { [group] (response) in 41 | guard let responseResult = response.result else { 42 | XCTAssertTrue(response.result?.address != nil, "Must be not nil") 43 | return 44 | } 45 | encodedMessage = responseResult 46 | group.leave() 47 | } 48 | group.wait() 49 | Log.warn("address - ", encodedMessage.address) 50 | 51 | try self.getGramsFromGiverSync(client, encodedMessage.address) 52 | 53 | let paramsOfSendMessage: TSDKParamsOfSendMessage = .init(message: encodedMessage.message, abi: abi, send_events: true) 54 | var maybeResultOfSendMessage: TSDKResultOfSendMessage? 55 | group.enter() 56 | try client.processing.send_message(paramsOfSendMessage) { (response) in 57 | if response.result != nil { 58 | maybeResultOfSendMessage = response.result 59 | } 60 | if response.finished { 61 | group.leave() 62 | } 63 | } 64 | group.wait() 65 | guard let resultOfSendMessage = maybeResultOfSendMessage else { 66 | XCTAssertTrue(false, "resultOfSendMessage is nil") 67 | return 68 | } 69 | 70 | let paramsOfWaitForTransaction: TSDKParamsOfWaitForTransaction = .init(abi: abi, 71 | message: encodedMessage.message, 72 | shard_block_id: resultOfSendMessage.shard_block_id, 73 | send_events: true) 74 | var resultOfProcessMessage: TSDKResultOfProcessMessage? 75 | group.enter() 76 | try client.processing.wait_for_transaction(paramsOfWaitForTransaction) { (response) in 77 | if response.result != nil { 78 | resultOfProcessMessage = response.result 79 | } 80 | if response.finished { 81 | group.leave() 82 | } 83 | } 84 | group.wait() 85 | XCTAssertEqual(resultOfProcessMessage?.out_messages.count, 0) 86 | XCTAssertEqual(resultOfProcessMessage?.decoded?.out_messages.count, 0) 87 | XCTAssertNil(resultOfProcessMessage?.decoded?.output) 88 | } 89 | } 90 | 91 | func testProcess_mesage() throws { 92 | try testAsyncMethods { (client, group) in 93 | let tvcData: Data = self.generateAbiAndTvc("Events").tvc 94 | let abiJSONValue: AnyValue = self.generateAbiAndTvc("Events").abiJSON 95 | let abi: TSDKAbi = .init(type: .Serialized, value: abiJSONValue) 96 | let keys: TSDKKeyPair = try self.generateKeys() 97 | let signer: TSDKSigner = .init(type: .Keys, 98 | public_key: nil, 99 | keys: keys, 100 | handle: nil) 101 | let callSet: TSDKCallSet = .init(function_name: "constructor", 102 | header: TSDKFunctionHeader(expire: nil, 103 | time: nil, 104 | pubkey: keys.public), 105 | input: nil) 106 | let deploySet: TSDKDeploySet = .init(tvc: tvcData.base64EncodedString(), workchain_id: nil, initial_data: nil) 107 | let payloadEncodeMessage: TSDKParamsOfEncodeMessage = .init(abi: abi, 108 | address: nil, 109 | deploy_set: deploySet, 110 | call_set: callSet, 111 | signer: signer, 112 | processing_try_index: nil) 113 | var result: TSDKResultOfEncodeMessage! 114 | group.enter() 115 | try client.abi.encode_message(payloadEncodeMessage) { [group] (response) in 116 | guard let responseResult = response.result else { 117 | XCTAssertTrue(response.result?.address != nil, "Must be not nil") 118 | return 119 | } 120 | result = responseResult 121 | group.leave() 122 | } 123 | group.wait() 124 | Log.warn("address - ", result.address) 125 | try self.getGramsFromGiverSync(client, result.address) 126 | 127 | let payloadProcessMessage: TSDKParamsOfProcessMessage = .init(message_encode_params: payloadEncodeMessage, send_events: true) 128 | var resultOfProcessMessage: TSDKResultOfProcessMessage? 129 | group.enter() 130 | try client.processing.process_message(payloadProcessMessage) { [group] (response) in 131 | if let result = response.result { 132 | resultOfProcessMessage = result 133 | } 134 | if response.finished { 135 | group.leave() 136 | } 137 | } 138 | group.wait() 139 | 140 | if let resultOfProcessMessage = resultOfProcessMessage { 141 | XCTAssertTrue(resultOfProcessMessage.fees.total_account_fees > 0) 142 | XCTAssertEqual(resultOfProcessMessage.out_messages.count, 0) 143 | XCTAssertEqual(resultOfProcessMessage.decoded?.out_messages.count, 0) 144 | XCTAssertNil(resultOfProcessMessage.decoded?.output) 145 | } else { 146 | XCTAssertTrue(false, "resultOfProcessMessage is nil") 147 | } 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Tests/EverscaleClientSwiftTests/UtilsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // 4 | // 5 | // Created by Oleh Hudeichuk on 18.11.2020. 6 | // 7 | 8 | import XCTest 9 | import class Foundation.Bundle 10 | @testable import EverscaleClientSwift 11 | 12 | final class UtilsTests: XCTestCase { 13 | 14 | func testAccountIdToHex() throws { 15 | try testAsyncMethods { [self] (client, group) in 16 | group.enter() 17 | let format: TSDKAddressStringFormat = .init(type: .Hex, url: nil, test: nil, bounce: nil) 18 | let payload: TSDKParamsOfConvertAddress = .init(address: self.accountId, output_format: format) 19 | var maybeResultOfConvertAddress: TSDKResultOfConvertAddress? 20 | try client.utils.convert_address(payload) { (response) in 21 | if let result = response.result { 22 | maybeResultOfConvertAddress = result 23 | } 24 | if response.finished { 25 | group.leave() 26 | } 27 | } 28 | group.wait() 29 | guard let resultOfConvertAddress = maybeResultOfConvertAddress else { 30 | XCTAssertTrue(false, "resultOfConvertAddress must not be nil") 31 | return 32 | } 33 | XCTAssertEqual(resultOfConvertAddress.address, self.hexWorkchain0) 34 | } 35 | } 36 | 37 | func testAccountIdToAccountId() throws { 38 | try testAsyncMethods { [self] (client, group) in 39 | group.enter() 40 | let format: TSDKAddressStringFormat = .init(type: .AccountId, url: nil, test: nil, bounce: nil) 41 | let payload: TSDKParamsOfConvertAddress = .init(address: self.accountId, output_format: format) 42 | var maybeResultOfConvertAddress: TSDKResultOfConvertAddress? 43 | try client.utils.convert_address(payload) { (response) in 44 | if let result = response.result { 45 | maybeResultOfConvertAddress = result 46 | } 47 | if response.finished { 48 | group.leave() 49 | } 50 | } 51 | group.wait() 52 | guard let resultOfConvertAddress = maybeResultOfConvertAddress else { 53 | XCTAssertTrue(false, "resultOfConvertAddress must not be nil") 54 | return 55 | } 56 | XCTAssertEqual(resultOfConvertAddress.address, self.accountId) 57 | } 58 | } 59 | 60 | func testHexToBase64() throws { 61 | try testAsyncMethods { [self] (client, group) in 62 | group.enter() 63 | let format: TSDKAddressStringFormat = .init(type: .Base64, url: false, test: false, bounce: false) 64 | let payload: TSDKParamsOfConvertAddress = .init(address: self.hex, output_format: format) 65 | var maybeResultOfConvertAddress: TSDKResultOfConvertAddress? 66 | try client.utils.convert_address(payload) { (response) in 67 | if let result = response.result { 68 | maybeResultOfConvertAddress = result 69 | } 70 | if response.finished { 71 | group.leave() 72 | } 73 | } 74 | group.wait() 75 | guard let resultOfConvertAddress = maybeResultOfConvertAddress else { 76 | XCTAssertTrue(false, "resultOfConvertAddress must not be nil") 77 | return 78 | } 79 | XCTAssertEqual(resultOfConvertAddress.address, self.base64) 80 | } 81 | } 82 | 83 | func testBase64ToBase64URL() throws { 84 | try testAsyncMethods { [self] (client, group) in 85 | group.enter() 86 | let format: TSDKAddressStringFormat = .init(type: .Base64, url: true, test: true, bounce: true) 87 | let payload: TSDKParamsOfConvertAddress = .init(address: self.base64, output_format: format) 88 | var maybeResultOfConvertAddress: TSDKResultOfConvertAddress? 89 | try client.utils.convert_address(payload) { (response) in 90 | if let result = response.result { 91 | maybeResultOfConvertAddress = result 92 | } 93 | if response.finished { 94 | group.leave() 95 | } 96 | } 97 | group.wait() 98 | guard let resultOfConvertAddress = maybeResultOfConvertAddress else { 99 | XCTAssertTrue(false, "resultOfConvertAddress must not be nil") 100 | return 101 | } 102 | XCTAssertEqual(resultOfConvertAddress.address, self.base64url) 103 | } 104 | } 105 | 106 | func testBase64URLToHex() throws { 107 | try testAsyncMethods { [self] (client, group) in 108 | group.enter() 109 | let format: TSDKAddressStringFormat = .init(type: .Hex, url: nil, test: nil, bounce: nil) 110 | let payload: TSDKParamsOfConvertAddress = .init(address: self.base64url, output_format: format) 111 | var maybeResultOfConvertAddress: TSDKResultOfConvertAddress? 112 | try client.utils.convert_address(payload) { (response) in 113 | if let result = response.result { 114 | maybeResultOfConvertAddress = result 115 | } 116 | if response.finished { 117 | group.leave() 118 | } 119 | } 120 | group.wait() 121 | guard let resultOfConvertAddress = maybeResultOfConvertAddress else { 122 | XCTAssertTrue(false, "resultOfConvertAddress must not be nil") 123 | return 124 | } 125 | XCTAssertEqual(resultOfConvertAddress.address, self.hex) 126 | } 127 | } 128 | 129 | 130 | let accountId: String = "fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 131 | let hex: String = "-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 132 | let hexWorkchain0: String = "0:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 133 | let base64: String = "Uf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15+KsQHFLbKSMiYG+9" 134 | let base64url: String = "kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny" 135 | } 136 | 137 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import EverscaleClientSwiftTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /api_generate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | git pull --ff-only 4 | cd ApiParser 5 | swift build -c release 6 | curl https://raw.githubusercontent.com/everx-labs/ever-sdk/refs/heads/master/tools/api.json > api.json 7 | if [ `uname -m` = arm64 ]; then 8 | ./.build/arm64-apple-macosx/release/ApiParser ./api.json 9 | else 10 | ./.build/x86_64-apple-macosx/release/ApiParser ./api.json 11 | fi 12 | -------------------------------------------------------------------------------- /scripts/install_rust.sh: -------------------------------------------------------------------------------- 1 | commandExist() { 2 | which $1 > /dev/null && echo '1' && return; 3 | echo '0'; 4 | } 5 | 6 | if [ $(commandExist 'cargo') == "1" ]; then 7 | echo "RUST ALREADY INSTALLED TO YOUR OS"; 8 | else 9 | echo "CARGO NOT FOUND"; 10 | echo "INSTALL RUST TO YOUR OS ?"; 11 | echo "y / n ?"; 12 | read answer 13 | if [ $answer == "y" ]; then 14 | if [ $(commandExist 'curl') != "1" ]; then 15 | echo "Please install curl"; 16 | exit 0; 17 | fi 18 | echo "INSTALL RUST..."; 19 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 20 | source ~/.profile 21 | else 22 | echo "RUST NOT INSTALLED. EXIT."; 23 | exit 0; 24 | fi 25 | fi; 26 | 27 | if [ `uname -s` = Darwin ]; then 28 | source ~/.profile 29 | echo "Install cargo-lipo" 30 | USER=$(whoami) 31 | sudo -H -u $USER bash -lc 'cargo install cargo-lipo' 32 | sudo -H -u $USER bash -lc 'rustup target add aarch64-apple-ios x86_64-apple-ios' 33 | fi 34 | 35 | echo $'\nINSTALLATION RUST COMPLETE' 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /scripts/install_tonsdk.sh: -------------------------------------------------------------------------------- 1 | commandExist() { 2 | which $1 > /dev/null && echo '1' && return; 3 | echo '0'; 4 | } 5 | 6 | if [ `uname -s` = Linux ]; then 7 | sudo echo $(whoami) 8 | fi 9 | 10 | 11 | # INSTALL RUST 12 | SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 13 | bash "$SCRIPTPATH/install_rust.sh" 14 | source ~/.profile 15 | 16 | # INSTALL SDK 17 | if [ -d "./SDK" ]; then 18 | echo "SDK FOLDER ALREADY EXISTS" 19 | else 20 | git clone https://github.com/tonlabs/ever-sdk.git ./SDK 21 | fi 22 | cd ./SDK && git reset --hard HEAD && git pull --ff-only 23 | cargo update 24 | 25 | # if [ `uname -s` = Darwin ]; then 26 | # if [ `uname -m` = arm64 ]; then 27 | # rustup target add x86_64-apple-darwin 28 | # cargo build --release --target x86_64-apple-darwin 29 | # else 30 | # cargo build --release 31 | # fi 32 | # else 33 | # cargo build --release 34 | # fi 35 | cargo build --release 36 | 37 | if [ `uname -s` = Darwin ]; then 38 | if [ $(commandExist 'port') == "1" ]; then 39 | MACOS_LIB_INCLUDE_DIR="/opt/local" 40 | echo "CHOOSE MACOS MACPORT INCLUDE DIR"; 41 | fi 42 | if [ $(commandExist 'brew') == "1" ]; then 43 | if [ -d "/opt/homebrew" ]; then 44 | MACOS_LIB_INCLUDE_DIR="/opt/homebrew" 45 | echo "CHOOSE MACOS HOMEBREW /opt/homebrew"; 46 | else 47 | MACOS_LIB_INCLUDE_DIR="/usr/local" 48 | echo "CHOOSE MACOS HOMEBREW /usr/local"; 49 | fi 50 | fi 51 | if [ $(commandExist 'port') == "1" ]; then 52 | echo "..."; 53 | elif [ $(commandExist 'brew') == "1" ]; then 54 | echo "..."; 55 | else 56 | echo 'ERROR: homebrew or macport is not installed' 57 | fi 58 | fi 59 | 60 | LINUX_LIB_INCLUDE_DIR="/usr" 61 | 62 | 63 | LINUX_PKG_CONFIG=$'prefix='"$LINUX_LIB_INCLUDE_DIR"' 64 | exec_prefix=${prefix} 65 | includedir=${prefix}/include 66 | libdir=${exec_prefix}/lib 67 | 68 | Name: ton_client 69 | Description: ton_client 70 | Version: 1.0.0 71 | Cflags: -I${includedir} 72 | Libs: -L${libdir} -lton_client' 73 | 74 | MACOS_PKG_CONFIG=$'prefix='"$MACOS_LIB_INCLUDE_DIR"' 75 | exec_prefix=${prefix} 76 | includedir=${prefix}/include 77 | libdir=${exec_prefix}/lib 78 | 79 | Name: ton_client 80 | Description: ton_client 81 | Version: 1.0.0 82 | Cflags: -I${includedir} 83 | Libs: -L${libdir} -lton_client' 84 | 85 | HEADER="$(pwd)/ton_client/tonclient.h" 86 | 87 | echo "" 88 | if [[ -f "$HEADER" ]]; then 89 | echo "CHECK: $HEADER - EXIST" 90 | else 91 | echo "" 92 | echo "ERROR: $HEADER - FILE NOT FOUND" 93 | exit 1; 94 | fi 95 | 96 | if [[ -f "./libton_client.pc" ]]; then 97 | rm ./libton_client.pc 98 | else 99 | echo "OK: libton_client.pc already deleted" 100 | fi 101 | 102 | if [ `uname -s` = Linux ]; then 103 | echo "" 104 | echo "Create symbolic link tonclient.h" 105 | if [[ -h "${LINUX_LIB_INCLUDE_DIR}/include/tonclient.h" ]]; then 106 | sudo rm ${LINUX_LIB_INCLUDE_DIR}/include/tonclient.h 107 | echo "OK: ${LINUX_LIB_INCLUDE_DIR}/include/tonclient.h old symlink already deleted and will create new" 108 | fi 109 | sudo ln -s $HEADER ${LINUX_LIB_INCLUDE_DIR}/include/tonclient.h || echo "ERROR: symbolic link tonclient.h already exist" 110 | 111 | DYLIB="$(pwd)/target/release/libton_client.so" 112 | echo "" 113 | echo "Create symbolic link libton_client.so" 114 | if [ -h "${LINUX_LIB_INCLUDE_DIR}/lib/libton_client.so" ]; then 115 | sudo rm ${LINUX_LIB_INCLUDE_DIR}/lib/libton_client.so 116 | echo "OK: ${LINUX_LIB_INCLUDE_DIR}/lib/libton_client.so old symlink already deleted and will create new" 117 | fi 118 | sudo ln -s $DYLIB ${LINUX_LIB_INCLUDE_DIR}/lib/libton_client.so || echo "ERROR: symbolic link libton_client.so already exist" 119 | 120 | 121 | echo "$LINUX_PKG_CONFIG" >> libton_client.pc 122 | sudo mv libton_client.pc ${LINUX_LIB_INCLUDE_DIR}/lib/pkgconfig/libton_client.pc 123 | 124 | 125 | 126 | elif [ `uname -s` = Darwin ]; then 127 | echo "" 128 | echo "Create symbolic link tonclient.h" 129 | if [[ -h "${MACOS_LIB_INCLUDE_DIR}/include/tonclient.h" ]]; then 130 | sudo rm ${MACOS_LIB_INCLUDE_DIR}/include/tonclient.h 131 | echo "OK: ${MACOS_LIB_INCLUDE_DIR}/include/tonclient.h old symlink deleted and will create new" 132 | fi 133 | echo "$HEADER ${MACOS_LIB_INCLUDE_DIR}/include/tonclient.h" 134 | sudo ln -s $HEADER ${MACOS_LIB_INCLUDE_DIR}/include/tonclient.h || echo "ERROR: symbolic link tonclient.h already exist" 135 | 136 | # if [ `uname -m` = arm64 ]; then 137 | # DYLIB="$(pwd)/target/x86_64-apple-darwin/release/libton_client.dylib" 138 | # else 139 | # DYLIB="$(pwd)/target/release/libton_client.dylib" 140 | # fi 141 | DYLIB="$(pwd)/target/release/libton_client.dylib" 142 | echo "" 143 | echo "Create symbolic link libton_client.dylib" 144 | if [[ -h "${MACOS_LIB_INCLUDE_DIR}/lib/libton_client.dylib" ]]; then 145 | sudo rm ${MACOS_LIB_INCLUDE_DIR}/lib/libton_client.dylib 146 | echo "OK: ${MACOS_LIB_INCLUDE_DIR}/lib/libton_client.dylib old symlink deleted and will create new" 147 | fi 148 | sudo ln -s $DYLIB ${MACOS_LIB_INCLUDE_DIR}/lib/libton_client.dylib || echo "ERROR: symbolic link libton_client.dylib already exist" 149 | echo "${DYLIB} to ${MACOS_LIB_INCLUDE_DIR}/lib/libton_client.dylib" 150 | 151 | echo "" 152 | echo "Copy pc file" 153 | echo "$MACOS_PKG_CONFIG" >> libton_client.pc 154 | sudo mv libton_client.pc ${MACOS_LIB_INCLUDE_DIR}/lib/pkgconfig/libton_client.pc 155 | echo "libton_client.pc to ${MACOS_LIB_INCLUDE_DIR}/lib/pkgconfig/libton_client.pc" 156 | else 157 | echo "I CAN INSTALL ONLY LINUX(DEBIAN / UBUNTU / ...) OR MACOS" 158 | fi 159 | 160 | echo $'\nINSTALLATION SDK COMPLETE' 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | --------------------------------------------------------------------------------