├── .gitignore ├── .rspec ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin └── everscale-client-ruby ├── everscale-client-ruby.gemspec ├── lib ├── code_generator │ ├── api_converter.rb │ ├── code_generator.rb │ ├── helpers.rb │ └── release.rb ├── everscale-client-ruby.rb └── everscale-client-ruby │ ├── Binding │ ├── binding.rb │ └── struct.rb │ ├── Client │ ├── Abi.rb │ ├── Boc.rb │ ├── Client.rb │ ├── Crypto.rb │ ├── Debot.rb │ ├── Net.rb │ ├── Processing.rb │ ├── Proofs.rb │ ├── Tvm.rb │ └── Utils.rb │ ├── Helpers │ └── CommonHelpers.rb │ └── version.rb ├── release.rb └── spec ├── Fixtures └── abi │ ├── Events.abi.json │ ├── Events.tvc │ ├── Giver.abi.json │ ├── GiverNodeSE.abi.json │ ├── GiverNodeSE_v2.abi.json │ ├── GiverNodeSE_v2.keys.json │ ├── GiverWallet.abi.json │ ├── Hello.abi.json │ ├── Hello.tvc │ ├── LimitWallet.abi.json │ ├── LimitWallet.tvc │ ├── Piggy.abi.json │ ├── Piggy.tvc │ ├── Subscription.abi.json │ ├── Subscription.tvc │ ├── Wallet.abi.json │ └── Wallet.tvc ├── abi.rb ├── all.rb ├── binding.rb ├── boc.rb ├── client.rb ├── context.rb ├── crypto.rb ├── net.rb ├── processing.rb ├── processing_sync.rb ├── spec_helper.rb ├── sync_spec_helper.rb ├── tests.rb ├── tvm.rb ├── tvm_sync.rb └── utils.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | 11 | # rspec failure tracking 12 | .rspec_status 13 | 14 | /.idea 15 | /.byebug_history 16 | *.DS_Store 17 | /gems 18 | /.env* 19 | /TON-SDK 20 | api.json 21 | test.rb -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | git_source(:github) { |repo_name| "https://github.com/nerzh/everscale-client-ruby" } 4 | 5 | gemspec 6 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | task :default => :spec 3 | -------------------------------------------------------------------------------- /bin/everscale-client-ruby: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require File.dirname(__FILE__) + '/../lib/code_generator/api_converter.rb' 4 | require File.dirname(__FILE__) + '/../lib/code_generator/code_generator.rb' 5 | GEM_DIR = File.dirname(__FILE__) + '/..' 6 | 7 | if ARGV[0] == 'update' && ARGV[1] == nil 8 | script_file_path = File.expand_path(File.dirname(__FILE__)) 9 | `cd #{script_file_path}/.. && curl https://raw.githubusercontent.com/tonlabs/TON-SDK/master/tools/api.json > api.json` 10 | api_json_path = "#{script_file_path}/../api.json" 11 | json = '' 12 | if File.exist?(api_json_path) 13 | json = File.read(api_json_path) 14 | else 15 | p "File #{api_json_path} is not exist" 16 | exit 0 17 | end 18 | converter = ApiConverter.new(json) 19 | types = converter.convert 20 | generator = CodeGenerator.new(types, GEM_DIR) 21 | generator.generate_self_code 22 | system(%{bash -lc 'ruby #{script_file_path}/../lib/code_generator/release.rb'}) 23 | elsif ARGV[0] == 'update' 24 | api_json_path = ARGV[1] 25 | json = '' 26 | if File.exist?(api_json_path) 27 | json = File.read(api_json_path) 28 | else 29 | p "Current directory: #{Dir.pwd}. File #{api_json_path} is not exist" 30 | exit 0 31 | end 32 | converter = ApiConverter.new(json) 33 | types = converter.convert 34 | generator = CodeGenerator.new(types, GEM_DIR) 35 | generator.generate_self_code 36 | system(%{bash -lc 'ruby #{script_file_path}/../lib/code_generator/release.rb'}) 37 | 38 | elsif ARGV[0] == 'setup' 39 | raise "\nPLEASE INSTALL RUST TO YOUR SYSTEM. \nTry this command: \ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh" if `which rustc`.strip.empty? 40 | unless Dir.exist?("#{GEM_DIR}/TON-SDK") 41 | system("cd #{GEM_DIR} && git clone https://github.com/tonlabs/TON-SDK ./TON-SDK") 42 | end 43 | system("cd #{GEM_DIR}/TON-SDK && git reset --hard HEAD") 44 | system("cd #{GEM_DIR}/TON-SDK && git pull --ff-only") 45 | system("cd #{GEM_DIR}/TON-SDK && cargo update") 46 | system("cd #{GEM_DIR}/TON-SDK && cargo build --release") 47 | puts '' 48 | puts "PATH TO YOR DYNAMIC LIBRARY FOR MACOS IS: #{GEM_DIR}/TON-SDK/target/release/libton_client.dylib" 49 | puts "PATH TO YOR DYNAMIC LIBRARY FOR LINUX IS: #{GEM_DIR}/TON-SDK/target/release/libton_client.so" 50 | puts '' 51 | end -------------------------------------------------------------------------------- /everscale-client-ruby.gemspec: -------------------------------------------------------------------------------- 1 | 2 | lib = File.expand_path("../lib", __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require "everscale-client-ruby/version" 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "everscale-client-ruby" 8 | spec.version = TonClient::VERSION 9 | spec.authors = ["nerzh"] 10 | spec.email = ["emptystamp@gmail.com"] 11 | 12 | spec.summary = 'This is gem everscale-client-ruby' 13 | spec.description = 'Gem Ton Client Ruby for all ruby projects' 14 | spec.homepage = 'https://github.com/nerzh/everscale-client-ruby' 15 | spec.license = 'MIT' 16 | 17 | spec.files = Dir['lib/**/*'] 18 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 19 | spec.require_paths = ["lib"] 20 | spec.bindir = "bin" 21 | spec.executables = ["everscale-client-ruby"] 22 | 23 | spec.add_dependency 'ffi', '1.15.5' 24 | spec.add_dependency 'dotenv', '~> 2.7.6' 25 | 26 | spec.add_development_dependency "bundler", "~> 2.0" 27 | spec.add_development_dependency "byebug" 28 | spec.add_development_dependency "rspec" 29 | spec.add_development_dependency "rake" 30 | end 31 | -------------------------------------------------------------------------------- /lib/code_generator/api_converter.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'set' 3 | require File.dirname(__FILE__) + '/helpers.rb' 4 | 5 | 6 | 7 | class ApiConverter 8 | include InstanceHelpers 9 | 10 | attr_reader :api_hash 11 | 12 | def initialize(api_json) 13 | @api_hash = JSON.parse(api_json) 14 | end 15 | 16 | def convert 17 | ruby_types = ApiRubyTypes.new(version: api_hash['version'], modules: []) 18 | 19 | (api_hash['modules'] || []).each do |mod| 20 | new_mod = convert_module(mod) 21 | ruby_types.modules << new_mod 22 | ruby_types.all_types.merge!(new_mod.types_hash) 23 | end 24 | 25 | ruby_types 26 | end 27 | 28 | private 29 | 30 | def convert_module(mod) 31 | new_module = Module.new(name: mod['name'], alias: [], functions: [], enums: [], types: [], summary: mod['summary'], description: mod['description']) 32 | (mod['types'] || []).each do |type| 33 | if type['type'] == 'EnumOfTypes' 34 | new_enum, new_struct = convert_fucking_enum_of_types(type) 35 | new_module.enums << new_enum 36 | new_module.types << new_struct 37 | new_module.types_hash[new_enum.name] = new_enum 38 | new_module.types_hash[new_struct.name] = new_struct 39 | elsif type['type'] == 'EnumOfConsts' 40 | new_type = convertEnumOfConsts(type) 41 | new_module.enums << new_type 42 | new_module.types_hash[new_type.name] = new_type 43 | elsif type['type'] == 'Struct' 44 | new_type = convertStruct(type) 45 | new_module.types << new_type 46 | new_module.types_hash[new_type.name] = new_type 47 | elsif type['type'] == 'Number' 48 | new_type = convertTypeAlias(type) 49 | new_module.alias << new_type 50 | new_module.types_hash[new_type.name] = new_type 51 | else 52 | raise "Unkown NEW TYPE for module #{type['name']} \"types\": #{type['types']}" 53 | end 54 | end 55 | 56 | # /// FUNCTIONS 57 | (mod['functions'] || []).each do |function| 58 | result = "" 59 | if function['result']['type'] == "Generic" 60 | ref_type = function['result']['generic_args'].first&.send(:[], 'type') || "" 61 | if ref_type == "Ref" 62 | ref_name = function['result']['generic_args'].first&.send(:[], 'ref_name') || "" 63 | if ref_name[/^(.+)\.(.+)$/] 64 | mod = $1 65 | type = $2 66 | result = "#{lib_prefix}#{type}" 67 | else 68 | raise "Bad function result ref_name: #{ref_name}, function name: #{function['name']}, result: #{function['result']}" 69 | end 70 | elsif ref_type == "None" 71 | result = "Void" 72 | end 73 | else 74 | raise "New function result type !" 75 | end 76 | 77 | # /// function 78 | newFunction = StructFunction.new(name: checkFunctionName(function['name']), arguments: [], result: result, summary: function['summary'], description: function['description']) 79 | # /// FUNCTION PARAMETERS 80 | paramsCount = 0 81 | (function['params'] || []).each do |parameter| 82 | if parameter['name'] == "params" 83 | paramsCount += 1 84 | if parameter['type'] == "Ref" 85 | ref_name = parameter['ref_name'] || "" 86 | if ref_name[/^(.+)\.(.+)$/] 87 | mod = $1 88 | type = $2 89 | newFunction.arguments << FunctionArgument.new(name: "payload", type: "#{lib_prefix}#{type}") 90 | else 91 | raise "Bad function params ref_name: #{ref_name}, function name: #{function['name']}, result: #{function['result']}" 92 | end 93 | else 94 | raise "NEW CASE! New parameter type: #{parameter['type']}" 95 | end 96 | end 97 | raise "NEW CASE ! More then one parameter for functions !" if paramsCount > 1 98 | end 99 | 100 | new_module.functions << newFunction 101 | end 102 | 103 | new_module 104 | end 105 | 106 | def convertTypeAlias(from) 107 | TypeAlias.new(name: "#{lib_prefix}#{from['name']}", type: generateType(from)) 108 | end 109 | 110 | def convertStruct(from) 111 | result = TypeStruct.new(name: "#{lib_prefix}#{from['name']}", parents: [], fields: [], functions: []) 112 | (from['struct_fields'] || []).each do |field| 113 | if isValidPropertyName(field['name']) 114 | type = generateType(field) 115 | if ( (from['name'] || "")[/Params/] || (field['name'] || "")[/input/]) && type[/Value/] 116 | type = "Value" 117 | elsif (field['name'] || "")[/^dictionary$/] 118 | type = "#{lib_prefix}MnemonicDictionary" 119 | elsif type[/Abi/] 120 | type = "Value" 121 | elsif type[/Abi/] 122 | type = "Value" 123 | end 124 | property = StructField.new(name: checkPropertyName(field['name']), type: type, summary: field['summary'], description: field['description']) 125 | result.fields << property 126 | end 127 | end 128 | 129 | result 130 | end 131 | 132 | private def checkPropertyName(name) 133 | result = "" 134 | raise "Property Name is nil" unless name 135 | 136 | case name 137 | when "public" 138 | result = "public" 139 | else 140 | result = name 141 | end 142 | 143 | return result 144 | end 145 | 146 | private def checkFunctionName(name) 147 | result = "" 148 | raise "Property Name is nil" unless name 149 | case name 150 | when "init" 151 | result = "init" 152 | else 153 | result = name 154 | end 155 | 156 | return result 157 | end 158 | 159 | private def isValidPropertyName(name) 160 | !(name || " ")[/\s/] 161 | end 162 | 163 | def convertEnumOfConsts(from) 164 | result = TypeEnum.new(name: "#{lib_prefix}#{from['name']}", parents: [], cases: [], summary: from['summary'], description: from['description']) 165 | (from['enum_consts'] || []).each do |enumConst| 166 | caseName = enumConst['name'] 167 | caseValue = enumConst['value'] 168 | result.cases << EnumCase.new(name: caseName, value: caseValue, summary: enumConst['summary'], description: enumConst['description']) 169 | end 170 | 171 | return result 172 | end 173 | 174 | def convert_fucking_enum_of_types(enum) 175 | result = [ 176 | TypeEnum.new(name: generate_enum_name(enum['name']), parents: [], cases: []), 177 | TypeStruct.new(name: generate_struct_name(enum['name']), parents: [], fields: [], functions: [], summary: enum['summary'], description: enum['description']) 178 | ] 179 | properties_name_set = Set.new 180 | properties = [] 181 | (enum['enum_types'] || []).each do |enum_type| 182 | result[0].cases << EnumCase.new(name: enum_type['name'], value: enum_type['name']) 183 | (enum_type['struct_fields'] || []).each do |field| 184 | if !properties_name_set.include?(field['name']) 185 | properties << field 186 | end 187 | properties_name_set << field['name'] 188 | end 189 | end 190 | 191 | result[1].fields << StructField.new(name: "type", type: generate_enum_name(enum['name'])) 192 | properties.each do |property| 193 | type = generateType(property) 194 | if property['name'][/^dictionary$/] 195 | type = "#{lib_prefix}MnemonicDictionary" 196 | end 197 | result[1].fields << StructField.new(name: property['name'], type: type, summary: property['summary'], description: property['description']) 198 | end 199 | result 200 | end 201 | 202 | private def generateSimpleType(type) 203 | tempType = "" 204 | 205 | if type['type'] == "Ref" 206 | if type['ref_name'] == "Value" || type['ref_name'] == "API" 207 | tempType = "Value" 208 | else 209 | return type['optional'] ? "#{generateRefType(type['ref_name'] || "nil")}" : generateRefType(type['ref_name'] || "nil") 210 | end 211 | else 212 | tempType = type['type'] 213 | end 214 | tempType = "#{tempType}" if type['optional'] 215 | 216 | tempType 217 | end 218 | 219 | private def generateRefType(type) 220 | result = "" 221 | 222 | if type[/(.+)\.(.+)/] 223 | mod = $1 224 | typeName = $2 225 | result = "#{lib_prefix}#{typeName}" 226 | else 227 | result = "#{lib_prefix}#{type}" 228 | end 229 | 230 | result 231 | end 232 | 233 | private def generateType(type) 234 | if type['type'] == "Optional" && type['optional_inner'] 235 | type['optional'] = true 236 | type['optional_inner']['optional'] = true 237 | if type['optional_inner']['type'] == "Optional" 238 | return generateType(type['optional_inner']) 239 | else 240 | return generateSimpleType(type['optional_inner']) 241 | end 242 | else 243 | return generateSimpleType(type) 244 | end 245 | end 246 | 247 | private def generate_enum_name(name) 248 | "#{lib_prefix}#{name}#{lib_enum_postfix}" 249 | end 250 | 251 | private def generate_struct_name(name) 252 | "#{lib_prefix}#{name}" 253 | end 254 | end 255 | 256 | 257 | class ApiRubyTypes 258 | attr_accessor :version 259 | attr_accessor :modules 260 | attr_accessor :all_types 261 | 262 | def initialize(params) 263 | @all_types = {} 264 | params.each do |k, v| 265 | if self.respond_to?(k.to_sym) 266 | instance_variable_set("@#{k}".to_sym, v) 267 | end 268 | end 269 | end 270 | end 271 | 272 | class Module 273 | attr_accessor :name 274 | attr_accessor :summary 275 | attr_accessor :description 276 | attr_accessor :alias 277 | attr_accessor :enums 278 | attr_accessor :types 279 | attr_accessor :types_hash 280 | attr_accessor :functions 281 | attr_accessor :summary 282 | attr_accessor :description 283 | 284 | def initialize(params) 285 | @types_hash = {} 286 | params.each do |k, v| 287 | if self.respond_to?(k.to_sym) 288 | instance_variable_set("@#{k}".to_sym, v) 289 | end 290 | end 291 | end 292 | end 293 | 294 | class TypeAlias 295 | attr_accessor :name 296 | attr_accessor :type 297 | attr_accessor :summary 298 | attr_accessor :description 299 | 300 | def initialize(params) 301 | params.each do |k, v| 302 | if self.respond_to?(k.to_sym) 303 | instance_variable_set("@#{k}".to_sym, v) 304 | end 305 | end 306 | end 307 | end 308 | 309 | class TypeEnum 310 | attr_accessor :name 311 | attr_accessor :parents 312 | attr_accessor :cases 313 | attr_accessor :summary 314 | attr_accessor :description 315 | 316 | def initialize(params) 317 | params.each do |k, v| 318 | if self.respond_to?(k.to_sym) 319 | instance_variable_set("@#{k}".to_sym, v) 320 | end 321 | end 322 | end 323 | end 324 | 325 | class EnumCase 326 | attr_accessor :name 327 | attr_accessor :value 328 | attr_accessor :summary 329 | attr_accessor :description 330 | 331 | def initialize(params) 332 | params.each do |k, v| 333 | if self.respond_to?(k) 334 | instance_variable_set("@#{k}".to_sym, v) 335 | end 336 | end 337 | end 338 | end 339 | 340 | class TypeStruct 341 | attr_accessor :name 342 | attr_accessor :parents 343 | attr_accessor :fields 344 | attr_accessor :functions 345 | attr_accessor :summary 346 | attr_accessor :description 347 | 348 | def initialize(params) 349 | params.each do |k, v| 350 | if self.respond_to?(k.to_sym) 351 | instance_variable_set("@#{k}".to_sym, v) 352 | end 353 | end 354 | end 355 | end 356 | 357 | class StructField 358 | attr_accessor :name 359 | attr_accessor :type 360 | attr_accessor :summary 361 | attr_accessor :description 362 | 363 | def initialize(params) 364 | params.each do |k, v| 365 | if self.respond_to?(k.to_sym) 366 | instance_variable_set("@#{k}".to_sym, v) 367 | end 368 | end 369 | end 370 | end 371 | 372 | class StructFunction 373 | attr_accessor :name 374 | attr_accessor :arguments 375 | attr_accessor :result 376 | attr_accessor :summary 377 | attr_accessor :description 378 | 379 | def initialize(params) 380 | params.each do |k, v| 381 | if self.respond_to?(k.to_sym) 382 | instance_variable_set("@#{k}".to_sym, v) 383 | end 384 | end 385 | end 386 | end 387 | 388 | class FunctionArgument 389 | attr_accessor :name 390 | attr_accessor :type 391 | 392 | def initialize(params) 393 | params.each do |k, v| 394 | if self.respond_to?(k.to_sym) 395 | instance_variable_set("@#{k}".to_sym, v) 396 | end 397 | end 398 | end 399 | end 400 | -------------------------------------------------------------------------------- /lib/code_generator/code_generator.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require File.dirname(__FILE__) + '/helpers.rb' 3 | 4 | class CodeGenerator 5 | include InstanceHelpers 6 | 7 | attr_accessor :types 8 | attr_accessor :root_dir 9 | 10 | TAB = " " 11 | 12 | def initialize(types, root_dir) 13 | @types = types 14 | @root_dir = root_dir 15 | end 16 | 17 | def generate_self_code 18 | generateModules(types) 19 | generateReadme(types) 20 | end 21 | 22 | private 23 | 24 | def generateModules(types) 25 | types.modules.each do |mod| 26 | modulesFolder = root_dir + "/lib/everscale-client-ruby/Client" 27 | moduleFilePath = "#{modulesFolder}/#{mod.name.capitalize}.rb" 28 | newModuleContent = "" 29 | if mod.name == "client" 30 | newModuleContent = generateClientModule(mod, types.modules) 31 | else 32 | newModuleContent = generateModule(mod) 33 | end 34 | if File.exist?(moduleFilePath) 35 | File.delete(moduleFilePath) 36 | end 37 | File.open(moduleFilePath, 'w+') { |f| f.write(newModuleContent) } 38 | end 39 | 40 | p 'generate_self_code ok' 41 | end 42 | 43 | def generateReadme(types) 44 | readmePath = root_dir + "/README.md" 45 | content = %{ 46 | # Ruby Client for TVM SDK Toncoin, Everscale, Venom, Gosh 47 | 48 |

49 | 50 | Logo 51 | 52 |

53 | 54 | [![GEM](https://img.shields.io/badge/ruby-gem-orange)](https://rubygems.org/gems/everscale-client-ruby) 55 | [![SPM](https://img.shields.io/badge/SDK%20VERSION-#{types.version}-green)](https://github.com/tonlabs/TON-SDK) 56 | 57 | ## Get api keys and TVM endpoints: 58 | 59 | You need to get an API-KEY here [https://dashboard.evercloud.dev](https://dashboard.evercloud.dev) 60 | 61 | 62 | ## Install 63 | 64 | Install gem 65 | ```bash 66 | gem install everscale-client-ruby 67 | ``` 68 | 69 | Install TON-SDK 70 | 71 | ##### result - path to dylib file for everscale-client-ruby configuration 72 | ```bash 73 | everscale-client-ruby setup 74 | ``` 75 | 76 | ### Manual build TVM SDK 77 | 0. Install Rust to your OS 78 | 1. git clone https://github.com/tonlabs/ever-sdk 79 | 2. cd ./ever-sdk 80 | 3. cargo update 81 | 4. cargo build --release 82 | 83 | ## Usage 84 | 85 | ```ruby 86 | # For MAcOS 87 | TonClient.configure { |config| config.ffi_lib(./ever-sdk/target/release/libton_client.dylib) } 88 | # For Linux 89 | # TonClient.configure { |config| config.ffi_lib(./ever-sdk/target/release/libton_client.so) } 90 | 91 | client = TonClient.create(config: {network: {endpoints: ["https://eri01.net.everos.dev/YOUR-X-API-KEY", "https://rbx01.net.everos.dev/YOUR-X-API-KEY"]}}) 92 | 93 | # All methods are asynchronous 94 | 95 | ## example 1: call method for Crypto module 96 | payload = {composite: '17ED48941A08F981'} 97 | 98 | # Sync 99 | response = client.crypto.factorize_sync(payload) 100 | p response['result']['factors'] 101 | 102 | # Async 103 | client.crypto.factorize(payload) do |response| 104 | p response.result['factors'] 105 | end 106 | 107 | 108 | ## example 2: parse message from boc base64 encoded 109 | payload = {boc: "te6ccgEBAQEAWAAAq2n+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzSsG8DgAAAAAjuOu9NAL7BxYpA"} 110 | 111 | # Sync 112 | response = client.boc.parse_message_sync(payload) 113 | p response['result']['parsed']['id'] 114 | p response['result']['parsed']['src'] 115 | p response['result']['parsed']['dst'] 116 | 117 | # Async 118 | client.boc.parse_message(payload) do |response| 119 | p response.result['parsed']['id'] 120 | p response.result['parsed']['src'] 121 | p response.result['parsed']['dst'] 122 | end 123 | 124 | # e.g. ... 125 | ```\n\n 126 | } 127 | content << "## All Modules, methods and types\n\n" 128 | 129 | # types 130 | content << "
\n#{TAB}Types\n\n" 131 | 132 | content << "#{customTypes()}\n" 133 | 134 | types.modules.each do |mod| 135 | (mod.enums || []).each do |type| 136 | content << checkComment(type.summary, 0) if type.summary 137 | content << checkComment(type.description, 0) if type.description 138 | content << "\n- #### #{type.name}\n" 139 | (type.cases || []).each do |enum_case| 140 | content << "#{checkComment(enum_case.summary, 1).gsub(/#/, '')}" if enum_case.summary 141 | content << "#{checkComment(enum_case.description, 1).gsub(/#/, '')}" if enum_case.description 142 | content << "#{TAB}- case #{enum_case.name} = #{enum_case.value}\n\n" 143 | end 144 | end 145 | 146 | (mod.types || []).each do |type| 147 | content << checkComment(type.summary, 0) if type.summary 148 | content << checkComment(type.description, 0) if type.description 149 | content << "\n- #### #{type.name}\n" 150 | (type.fields || []).each do |field| 151 | content << "#{checkComment(field.summary, 1).gsub(/#/, '')}\n" if field.summary 152 | content << "#{checkComment(field.description, 1).gsub(/#/, '')}\n" if field.description 153 | content << "#{TAB}- #{field.name}: #{field.type}\n\n" 154 | end 155 | end 156 | end 157 | content << "
\n\n" 158 | 159 | # methods 160 | types.modules.each do |mod| 161 | content << "
\n#{TAB}#{mod.name&.upcase}\n\n" 162 | (mod.functions || []).each do |function| 163 | content << "```ruby\n" 164 | content << checkComment(function.summary, 2) if function.summary 165 | content << checkComment(function.description, 2) if function.description 166 | content << "\n#{TAB}#{TAB}def #{function.name}" 167 | if function.arguments.empty? 168 | content << "(&block)\n" 169 | else 170 | content << "(payload, &block)\n" 171 | end 172 | content << getFunctionComment(function, types) 173 | content << "```\n" 174 | end 175 | content << "
\n\n" 176 | end 177 | 178 | content << %{ 179 | \n## Tests 180 | 181 | 1. create __.env.test__ file inside root directory of this library with variables 182 | 183 | example for NodeSE 184 | ``` 185 | spec_ffi=./ever-sdk/target/release/libton_client.dylib 186 | server_address=http://localhost:80 187 | giver_abi_name=GiverNodeSE 188 | giver_amount=10000000000 189 | ``` 190 | 2. Run tests: inside folder of this library execute this commands 191 | **rspec spec/binding.rb** 192 | **rspec spec/client.rb** 193 | **rspec spec/context.rb** 194 | **rspec spec/abi.rb** 195 | **rspec spec/boc.rb** 196 | **rspec spec/crypto.rb** 197 | **rspec spec/net.rb** 198 | **rspec spec/processing.rb** 199 | **rspec spec/tvm.rb** 200 | **rspec spec/utils.rb** 201 | 202 | \n## Update\n\n 203 | ```\n 204 | everscale-client-ruby update\n 205 | ```\n\n 206 | or\n\n 207 | ```\n 208 | curl https://raw.githubusercontent.com/tonlabs/ever-sdk/master/tools/api.json > api.json\n\n 209 | ```\n\n 210 | ```\n 211 | everscale-client-ruby update ./api.json\n 212 | ```\n 213 | or\n\n 214 | ```\n 215 | cd everscale-client-ruby\n 216 | ```\n\n 217 | ```\n 218 | ./bin/everscale-client-ruby update\n 219 | ```\n 220 | } 221 | content = checkContent(content) 222 | if File.exist?(readmePath) 223 | File.delete(readmePath) 224 | end 225 | File.open(readmePath, 'w+') { |f| f.write(content) } 226 | end 227 | 228 | private def checkContent(content) 229 | content.gsub!(/^([\s]+)# RESPONSE/, "\n\\1# RESPONSE") 230 | content.gsub(//i, '<Optional>') 231 | content.gsub(/(```ruby[\s\S]+?)<Optional>([\s\S]+?)```/, '\1\2```') 232 | content.gsub!(/ +# +# +/, " ") 233 | # content.gsub!(/ +# +/, '. ') 234 | end 235 | 236 | def customTypes 237 | content = %{ 238 | - #### #{lib_prefix}MnemonicDictionary 239 | #{TAB}- case TON = 0 240 | #{TAB}- case ENGLISH = 1 241 | #{TAB}- case CHINESE_SIMPLIFIED = 2 242 | #{TAB}- case CHINESE_TRADITIONAL = 3 243 | #{TAB}- case FRENCH = 4 244 | #{TAB}- case ITALIAN = 5 245 | #{TAB}- case JAPANESE = 6 246 | #{TAB}- case KOREAN = 7 247 | #{TAB}- case SPANISH = 8 248 | } 249 | content 250 | end 251 | 252 | private def checkComment(string, tabs = 1) 253 | replacedString = "\n" 254 | tab = "" 255 | tabs.times do |i| 256 | tab << TAB 257 | end 258 | comment = "#" 259 | replacedString << "#{tab}#{comment} " 260 | symbolsWithSpace = "\\.|\\:|\\!|\\?|\\;" 261 | regxp = /([^#{symbolsWithSpace}])\n/ 262 | result = string 263 | result.gsub!(/\n+/, "\n") 264 | result.gsub!(/ \n/, "\n#{comment} ") 265 | result.gsub!(/(#{symbolsWithSpace})\s*\n/, "\\1#{replacedString}") 266 | result.gsub!(regxp, "\\1") 267 | "#{tab}# #{result}" 268 | end 269 | 270 | private def generateClientModule(mod, modules) 271 | content = "module TonClient\n\n#{TAB}class #{mod.name.capitalize}\n#{TAB}#{TAB}include CommonInstanceHelpers\n\n" 272 | content << "#{TAB}#{TAB}attr_reader :context, :context_config, :request_id, :requests, :monitor\n" 273 | content << "#{TAB}#{TAB}private_accessor " 274 | modules.each_with_index do |m, i| 275 | next if m.name.downcase == 'client' 276 | content << ((modules.size - 1) == i ? ":_#{m.name}\n" : ":_#{m.name}, ") 277 | end 278 | content << "#{TAB}#{TAB}MODULE = self.to_s.downcase.gsub(/^(.+::|)(\\w+)$/, '\\2').freeze\n\n" 279 | content << "#{TAB}#{TAB}def initialize(context_config: {})\n" 280 | content << "#{TAB}#{TAB}#{TAB}@context_config = context_config\n" 281 | content << "#{TAB}#{TAB}#{TAB}@request_id = RequestId.new\n" 282 | content << "#{TAB}#{TAB}#{TAB}@requests = Requests.new\n" 283 | content << "#{TAB}#{TAB}#{TAB}@monitor = Monitor.new\n" 284 | content << "#{TAB}#{TAB}#{TAB}config = TonBinding.make_string(context_config.to_json)\n" 285 | content << "#{TAB}#{TAB}#{TAB}context_ptr = TonBinding.tc_create_context(config)\n" 286 | content << "#{TAB}#{TAB}#{TAB}context_response = TonBinding.read_string_data_ref(context_ptr)\n" 287 | content << "#{TAB}#{TAB}#{TAB}@context = TonBinding.read_string_to_hash(context_response)['result']\n" 288 | content << "#{TAB}#{TAB}#{TAB}ObjectSpace.define_finalizer(self, self.class.finalize(@context))\n" 289 | content << "#{TAB}#{TAB}end\n\n" 290 | content << "#{TAB}#{TAB}def self.finalize(ctx)\n" 291 | content << "#{TAB}#{TAB}#{TAB}Proc.new do\n" 292 | content << "#{TAB}#{TAB}#{TAB}#{TAB}if (ctx != nil) && (ctx > 0)\n" 293 | content << "#{TAB}#{TAB}#{TAB}#{TAB}#{TAB}TonBinding.tc_destroy_context(ctx)\n" 294 | content << "#{TAB}#{TAB}#{TAB}#{TAB}end\n" 295 | content << "#{TAB}#{TAB}#{TAB}end\n" 296 | content << "#{TAB}#{TAB}end\n\n" 297 | modules.each_with_index do |m, i| 298 | next if m.name.downcase == 'client' 299 | content << "#{TAB}#{TAB}def #{m.name}\n" 300 | content << "#{TAB}#{TAB}#{TAB}_#{m.name} ||= #{m.name.capitalize}.new(context: context, request_id: request_id, requests: requests, monitor: monitor)\n" 301 | content << "#{TAB}#{TAB}end\n\n" 302 | end 303 | 304 | mod.functions.each do |func| 305 | content << gen_function(func, types) 306 | end 307 | 308 | content << "#{TAB}end\n" 309 | content << "end\n\n" 310 | 311 | content 312 | end 313 | 314 | private def generateModule(mod) 315 | content = "module TonClient\n\n#{TAB}class #{mod.name.capitalize}\n#{TAB}#{TAB}include CommonInstanceHelpers\n\n" 316 | content << "#{TAB}#{TAB}attr_reader :context, :request_id, :requests, :monitor\n" 317 | content << "#{TAB}#{TAB}MODULE = self.to_s.downcase.gsub(/^(.+::|)(\\w+)$/, '\\2').freeze\n\n" 318 | content << "#{TAB}#{TAB}def initialize(context: nil, request_id: nil, requests: nil, monitor: nil)\n" 319 | content << "#{TAB}#{TAB}#{TAB}@context = context\n" 320 | content << "#{TAB}#{TAB}#{TAB}@request_id = request_id\n" 321 | content << "#{TAB}#{TAB}#{TAB}@requests = requests\n" 322 | content << "#{TAB}#{TAB}#{TAB}@monitor = monitor\n" 323 | content << "#{TAB}#{TAB}end\n\n" 324 | 325 | mod.functions.each do |func| 326 | content << gen_function(func, types) 327 | end 328 | 329 | content << "#{TAB}end\n" 330 | content << "end\n\n" 331 | 332 | content 333 | end 334 | 335 | private def gen_function(function, types) 336 | content = getFunctionComment(function, types) 337 | content << "#{TAB}#{TAB}# Async\n" 338 | content << "#{TAB}#{TAB}def #{function.name}" 339 | if function.arguments.empty? 340 | content << "(&block)\n" 341 | payload = "{}" 342 | else 343 | content << "(payload, &block)\n" 344 | payload = "payload" 345 | end 346 | content << "#{TAB}#{TAB}#{TAB}TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: #{payload}, &block)\n" 347 | content << "#{TAB}#{TAB}end\n\n" 348 | 349 | content << "#{TAB}#{TAB}# Sync\n" 350 | content << "#{TAB}#{TAB}def #{function.name}_sync" 351 | if function.arguments.empty? 352 | content << "()\n" 353 | payload = "{}" 354 | else 355 | content << "(payload)\n" 356 | payload = "payload" 357 | end 358 | content << "#{TAB}#{TAB}#{TAB}TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: #{payload})\n" 359 | content << "#{TAB}#{TAB}end\n\n" 360 | 361 | content 362 | end 363 | 364 | def getFunctionComment(function, types) 365 | content = '' 366 | if argument = function.arguments.first 367 | content << "#{TAB}#{TAB}# INPUT: #{argument.type}\n" 368 | if types.all_types[argument.type].respond_to?(:fields) 369 | types.all_types[argument.type].fields.each do |arg| 370 | content << "#{TAB}#{TAB}# #{arg.name}: #{arg.type} - " 371 | content << "#{TAB}#{TAB}# #{checkComment(arg.summary, 2)}" if arg.summary 372 | content << "#{TAB}#{TAB}# #{checkComment(arg.description, 2)}" if arg.description 373 | content << "\n" 374 | end 375 | elsif types.all_types[argument.type].respond_to?(:cases) 376 | end 377 | end 378 | 379 | if types.all_types[function.result] 380 | content << "#{TAB}#{TAB}# RESPONSE: #{function.result}\n" 381 | if types.all_types[function.result].respond_to?(:fields) 382 | types.all_types[function.result].fields.each do |arg| 383 | content << "#{TAB}#{TAB}# #{arg.name}: #{arg.type} - " 384 | content << "#{TAB}#{TAB}# #{checkComment(arg.summary, 2)}" if arg.summary 385 | content << "#{TAB}#{TAB}# #{checkComment(arg.description, 2)}" if arg.description 386 | content << "\n" 387 | end 388 | elsif types.all_types[function.result].respond_to?(:cases) 389 | end 390 | end 391 | 392 | content 393 | end 394 | end 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | -------------------------------------------------------------------------------- /lib/code_generator/helpers.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | module InstanceHelpers 4 | 5 | def lib_prefix 6 | '' 7 | end 8 | 9 | def lib_enum_postfix 10 | '' 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/code_generator/release.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | script_file_path = File.expand_path(File.dirname(__FILE__)) 4 | 5 | require "#{script_file_path}/api_converter.rb" 6 | require "#{script_file_path}/code_generator.rb" 7 | GEM_DIR = "#{script_file_path}/../.." 8 | 9 | 10 | `cd #{script_file_path} && curl https://raw.githubusercontent.com/tonlabs/TON-SDK/master/tools/api.json > api.json` 11 | api_json_path = "#{script_file_path}/../../api.json" 12 | json = '' 13 | if File.exist?(api_json_path) 14 | json = File.read(api_json_path) 15 | else 16 | p "File #{api_json_path} is not exist" 17 | exit 0 18 | end 19 | converter = ApiConverter.new(json) 20 | types = converter.convert 21 | generator = CodeGenerator.new(types, GEM_DIR) 22 | generator.generate_self_code 23 | 24 | version_file = "#{script_file_path}/../everscale-client-ruby/version.rb" 25 | file = File.read(version_file) 26 | 27 | p 'check version' 28 | if file[/VERSION = "(\d+)\.(\d+)\.(\d+)"/] 29 | major = $1 30 | minor = $2 31 | current = $3 32 | version = "#{major}.#{minor}.#{current.to_i + 1}" 33 | p version 34 | data = "module TonClient\n VERSION = \"#{version}\"\nend\n\n" 35 | p data 36 | p version_file 37 | File.open(version_file, 'wb') { |f| f.write(data) } 38 | p 'update version' 39 | 40 | puts "make release? Y/N" 41 | option = gets 42 | if option.strip.downcase == 'y' 43 | system(%{cd #{GEM_DIR} && git add .}) 44 | system(%{cd #{GEM_DIR} && git commit -m 'version #{version}'}) 45 | system(%{cd #{GEM_DIR} && bash -lc 'rake release'}) 46 | end 47 | end 48 | 49 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby.rb: -------------------------------------------------------------------------------- 1 | require 'ffi' 2 | require "base64" 3 | require 'json' 4 | require 'dotenv' 5 | require 'fileutils' 6 | require 'monitor' 7 | require_relative './everscale-client-ruby/Helpers/CommonHelpers.rb' 8 | require_relative './everscale-client-ruby/Binding/struct.rb' 9 | require_relative './everscale-client-ruby/Binding/binding.rb' 10 | require_relative './everscale-client-ruby/Client/Client.rb' 11 | require_relative './everscale-client-ruby/Client/Crypto.rb' 12 | require_relative './everscale-client-ruby/Client/Abi.rb' 13 | require_relative './everscale-client-ruby/Client/Boc.rb' 14 | require_relative './everscale-client-ruby/Client/Net.rb' 15 | require_relative './everscale-client-ruby/Client/Processing.rb' 16 | require_relative './everscale-client-ruby/Client/Tvm.rb' 17 | require_relative './everscale-client-ruby/Client/Utils.rb' 18 | require_relative './everscale-client-ruby/Client/Debot.rb' 19 | require_relative './everscale-client-ruby/version' 20 | 21 | module TonClient 22 | 23 | @@configured = false 24 | 25 | def self.check_configuration 26 | raise "Not configured! Please configure TonClient: call ffi_lib(dylib_path)" unless !!@@configured 27 | end 28 | 29 | def self.configure 30 | yield self 31 | end 32 | 33 | def self.ffi_lib(dylib_path = nil) 34 | TonBinding.ffi_lib(dylib_path) 35 | TonBinding.setup_bindings() 36 | @@configured = true 37 | end 38 | 39 | def self.create(config: {}) 40 | check_configuration 41 | Client.new(context_config: config) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Binding/binding.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | module TonBinding 3 | class Response 4 | attr_accessor :result, :error, :custom_response, :finished, :request_id, :response_type 5 | 6 | def initialize(request_id, string_data, response_type, finished) 7 | update(request_id, string_data, response_type, finished) 8 | end 9 | 10 | private 11 | def update(request_id, string_data, response_type, finished) 12 | if response_type == -1 13 | @finished = true 14 | @request_id = request_id 15 | @response_type = response_type 16 | @error = string_data || "Client deallocated" 17 | p "ERROR: #{@error}" 18 | return self 19 | end 20 | 21 | response_hash = TonBinding.read_string_to_hash(TonBinding.read_string_data(string_data)) 22 | @finished = finished 23 | @request_id = request_id 24 | @response_type = response_type 25 | 26 | case response_type 27 | when 0 28 | # result 29 | @result = response_hash 30 | when 1 31 | # error 32 | @error = response_hash 33 | else 34 | # # another 35 | # if response_type >= 100 36 | @custom_response = response_hash 37 | # end 38 | end 39 | 40 | self 41 | end 42 | end 43 | end 44 | end 45 | 46 | 47 | module TonClient 48 | 49 | module TonBinding 50 | extend FFI::Library 51 | ffi_lib FFI::Library::LIBC 52 | ffi_lib 'ruby' 53 | 54 | # memory allocators 55 | attach_function :malloc, [:size_t], :pointer 56 | # attach_function :calloc, [:size_t], :pointer 57 | # attach_function :valloc, [:size_t], :pointer 58 | # attach_function :realloc, [:pointer, :size_t], :pointer 59 | attach_function :free, [:pointer], :void 60 | 61 | # # memory movers 62 | # attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer 63 | # attach_function :bcopy, [:pointer, :pointer, :size_t], :void 64 | 65 | def self.setup_bindings 66 | 67 | # tc_string_handle_t* tc_create_context(tc_string_data_t config); 68 | # attach_function :tc_create_context, [TcStringDataT.by_value], TcStringDataT.by_ref 69 | attach_function :tc_create_context, [TcStringDataT.by_value], :pointer 70 | 71 | # fn tc_destroy_context(context: InteropContext) 72 | attach_function :tc_destroy_context, [:uint32], :void 73 | 74 | # tc_string_handle_t* tc_request_sync( 75 | # uint32_t context, 76 | # tc_string_data_t function_name, 77 | # tc_string_data_t function_params_json); 78 | # attach_function :tc_request_sync, [:uint32, TcStringDataT.by_value, TcStringDataT.by_value], TcStringDataT.by_ref 79 | attach_function :tc_request_sync, [:uint32, TcStringDataT.by_value, TcStringDataT.by_value], :pointer 80 | 81 | # enum tc_response_types_t { 82 | # tc_response_success = 0, 83 | # tc_response_error = 1, 84 | # tc_response_nop = 2, 85 | # tc_response_custom = 100, 86 | # }; 87 | # typedef void (*tc_response_handler_t)( 88 | # uint32_t request_id, 89 | # tc_string_data_t params_json, 90 | # uint32_t response_type, 91 | # bool finished); 92 | callback :tc_response_handler_t, [:uint32, TcStringDataT.by_value, :uint32, :bool], :void 93 | 94 | # void tc_request( 95 | # uint32_t context, 96 | # tc_string_data_t function_name, 97 | # tc_string_data_t function_params_json, 98 | # uint32_t request_id, 99 | # tc_response_handler_t response_handler); 100 | attach_function :tc_request, [:uint32, TcStringDataT.by_value, TcStringDataT.by_value, :uint32, :tc_response_handler_t], :void 101 | 102 | # tc_string_data_t tc_read_string(const tc_string_handle_t* handle); 103 | # attach_function :tc_read_string, [TcStringDataT.by_ref], TcStringDataT.by_value 104 | attach_function :tc_read_string, [:pointer], TcStringDataT.by_value 105 | 106 | # void tc_destroy_string(const tc_string_handle_t* handle) 107 | # attach_function :tc_destroy_string, [TcStringDataT.by_ref], :void 108 | attach_function :tc_destroy_string, [:pointer], :void 109 | end 110 | 111 | def self.make_string(string) 112 | string = string.encode("utf-8").freeze 113 | result = TonBinding::TcStringDataT.new 114 | result[:content] = FFI::MemoryPointer.from_string(string) 115 | result[:len] = string.bytesize 116 | result 117 | end 118 | 119 | def self.read_string_data_ref(tc_string_handle_ref) 120 | string = tc_read_string(tc_string_handle_ref) 121 | 122 | if string[:len] > 0 123 | result = string[:content].read_string(string[:len]).freeze 124 | if tc_string_handle_ref 125 | tc_destroy_string(tc_string_handle_ref) 126 | else 127 | p "NOOOOOOOOOOOO" 128 | end 129 | # free(tc_string_handle_ref) 130 | result 131 | else 132 | nil 133 | end 134 | end 135 | 136 | def self.read_string_data(tc_string_data) 137 | if tc_string_data[:len] > 0 138 | result = tc_string_data[:content].read_string(tc_string_data[:len]).freeze 139 | # free(tc_string_data) 140 | result 141 | else 142 | nil 143 | end 144 | end 145 | 146 | def self.read_string_to_hash(json_string) 147 | JSON.parse(json_string, {max_nesting: false}) if json_string 148 | end 149 | 150 | def self.send_request_sync(context: 1, method_name: '', payload: {}) 151 | raise 'context not found' unless context 152 | raise 'method_name is empty' if method_name.empty? 153 | 154 | method_name_string = make_string(method_name) 155 | payload_string = make_string(payload.to_json) 156 | 157 | sdk_json_response = tc_request_sync(context, method_name_string, payload_string) 158 | response = read_string_to_hash(read_string_data_ref(sdk_json_response)) 159 | 160 | response 161 | end 162 | 163 | # block = { |response| } 164 | def self.requestLibrary(context: nil, 165 | request_id: nil, 166 | requests: nil, 167 | monitor: nil, 168 | method_name: '', 169 | payload: {}, 170 | &block 171 | ) 172 | monitor&.synchronize do 173 | raise 'context not found' unless context 174 | raise 'method_name is empty' if method_name.empty? 175 | # raise "context: #{context}. request_id not is nil. Client dealloc." unless request_id 176 | unless request_id 177 | # p "context: #{context}. request_id is nil. Client deallocated." 178 | block.call(Response.new(request_id, "Client deallocated", -1, true)) if block 179 | return 180 | end 181 | method_name_string = make_string(method_name) 182 | payload_string = make_string(payload.to_json) 183 | 184 | request_id = request_id.increment 185 | requests[request_id] = block 186 | # p "start id #{request_id} - requests #{requests.object_id}" 187 | tc_request(context, method_name_string, payload_string, request_id) do |request_id, string_data, response_type, finished| 188 | # p "rust inside id #{request_id} - #{method_name}" 189 | begin 190 | monitor&.synchronize do 191 | # p "request_id #{request_id}, monitor #{monitor.object_id} - requests #{requests.object_id}" 192 | request = requests[request_id] 193 | if request 194 | request.call(Response.new(request_id, string_data, response_type, finished)) 195 | requests.delete(request_id) if finished 196 | end 197 | end 198 | rescue => ex 199 | block.call(Response.new(request_id, ex.message, -1, true)) if block 200 | end 201 | end 202 | end 203 | rescue => ex 204 | block.call(Response.new(request_id, ex.message, -1, true)) if block 205 | end 206 | 207 | end 208 | end 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Binding/struct.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | module TonBinding 3 | 4 | # typedef struct { 5 | # const char* content; 6 | # uint32_t len; 7 | # } tc_string_data_t; 8 | class TcStringDataT < FFI::Struct 9 | layout :content, :pointer, 10 | :len, :uint32 11 | 12 | # def initialize(*args) 13 | # super 14 | # ObjectSpace.define_finalizer(self, self.class.finalize(@content)) 15 | # end 16 | # 17 | # def self.finalize(ctx) 18 | # Proc.new do 19 | # if ctx != nil 20 | # TonBinding.free(ctx) 21 | # end 22 | # end 23 | # end 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Abi.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Abi 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfEncodeMessageBody 17 | # abi: Value - # # Contract ABI. 18 | # call_set: CallSet - # # Function call parameters. # # Must be specified in non deploy message. 19 | # In case of deploy message contains parameters of constructor. 20 | # is_internal: Boolean - # # True if internal message body must be encoded. 21 | # signer: Signer - # # Signing parameters. 22 | # processing_try_index: Number - # # Processing try index. # # Used in message processing with retries. 23 | # Encoder uses the provided try index to calculate messageexpiration time. 24 | # Expiration timeouts will grow with every retry. 25 | # Default value is 0. 26 | # address: String - # # Destination address of the message # # Since ABI version 2.3 destination address of external inbound message is used in messagebody signature calculation. Should be provided when signed external inbound message body iscreated. Otherwise can be omitted. 27 | # signature_id: Number - # # Signature ID to be used in data to sign preparing when CapSignatureWithId capability is enabled 28 | # RESPONSE: ResultOfEncodeMessageBody 29 | # body: String - # # Message body BOC encoded with `base64`. 30 | # data_to_sign: String - # # Optional data to sign. # # Encoded with `base64`. 31 | # # Presents when `message` is unsigned. Can be used for externalmessage signing. Is this case you need to sing this data andproduce signed message using `abi.attach_signature`. 32 | # Async 33 | def encode_message_body(payload, &block) 34 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 35 | end 36 | 37 | # Sync 38 | def encode_message_body_sync(payload) 39 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 40 | end 41 | 42 | # INPUT: ParamsOfAttachSignatureToMessageBody 43 | # abi: Value - # # Contract ABI 44 | # public_key: String - # # Public key. # # Must be encoded with `hex`. 45 | # message: String - # # Unsigned message body BOC. # # Must be encoded with `base64`. 46 | # signature: String - # # Signature. # # Must be encoded with `hex`. 47 | # RESPONSE: ResultOfAttachSignatureToMessageBody 48 | # body: String - 49 | # Async 50 | def attach_signature_to_message_body(payload, &block) 51 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 52 | end 53 | 54 | # Sync 55 | def attach_signature_to_message_body_sync(payload) 56 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 57 | end 58 | 59 | # INPUT: ParamsOfEncodeMessage 60 | # abi: Value - # # Contract ABI. 61 | # address: String - # # Target address the message will be sent to. # # Must be specified in case of non-deploy message. 62 | # deploy_set: DeploySet - # # Deploy parameters. # # Must be specified in case of deploy message. 63 | # call_set: CallSet - # # Function call parameters. # # Must be specified in case of non-deploy message. 64 | # In case of deploy message it is optional and contains parametersof the functions that will to be called upon deploy transaction. 65 | # signer: Signer - # # Signing parameters. 66 | # processing_try_index: Number - # # Processing try index. # # Used in message processing with retries (if contract's ABI includes "expire" header). 67 | # Encoder uses the provided try index to calculate messageexpiration time. The 1st message expiration time is specified inClient config. 68 | # Expiration timeouts will grow with every retry. 69 | # Retry grow factor is set in Client config: 70 | # <.....add config parameter with default value here>Default value is 0. 71 | # signature_id: Number - # # Signature ID to be used in data to sign preparing when CapSignatureWithId capability is enabled 72 | # RESPONSE: ResultOfEncodeMessage 73 | # message: String - # # Message BOC encoded with `base64`. 74 | # data_to_sign: String - # # Optional data to be signed encoded in `base64`. # # Returned in case of `Signer::External`. Can be used for externalmessage signing. Is this case you need to use this data to create signature andthen produce signed message using `abi.attach_signature`. 75 | # address: String - # # Destination address. 76 | # message_id: String - # # Message id. 77 | # Async 78 | def encode_message(payload, &block) 79 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 80 | end 81 | 82 | # Sync 83 | def encode_message_sync(payload) 84 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 85 | end 86 | 87 | # INPUT: ParamsOfEncodeInternalMessage 88 | # abi: Value - # # Contract ABI. # # Can be None if both deploy_set and call_set are None. 89 | # address: String - # # Target address the message will be sent to. # # Must be specified in case of non-deploy message. 90 | # src_address: String - # # Source address of the message. 91 | # deploy_set: DeploySet - # # Deploy parameters. # # Must be specified in case of deploy message. 92 | # call_set: CallSet - # # Function call parameters. # # Must be specified in case of non-deploy message. 93 | # In case of deploy message it is optional and contains parametersof the functions that will to be called upon deploy transaction. 94 | # value: String - # # Value in nanotokens to be sent with message. 95 | # bounce: Boolean - # # Flag of bounceable message. # # Default is true. 96 | # enable_ihr: Boolean - # # Enable Instant Hypercube Routing for the message. # # Default is false. 97 | # RESPONSE: ResultOfEncodeInternalMessage 98 | # message: String - # # Message BOC encoded with `base64`. 99 | # address: String - # # Destination address. 100 | # message_id: String - # # Message id. 101 | # Async 102 | def encode_internal_message(payload, &block) 103 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 104 | end 105 | 106 | # Sync 107 | def encode_internal_message_sync(payload) 108 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 109 | end 110 | 111 | # INPUT: ParamsOfAttachSignature 112 | # abi: Value - # # Contract ABI 113 | # public_key: String - # # Public key encoded in `hex`. 114 | # message: String - # # Unsigned message BOC encoded in `base64`. 115 | # signature: String - # # Signature encoded in `hex`. 116 | # RESPONSE: ResultOfAttachSignature 117 | # message: String - # # Signed message BOC 118 | # message_id: String - # # Message ID 119 | # Async 120 | def attach_signature(payload, &block) 121 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 122 | end 123 | 124 | # Sync 125 | def attach_signature_sync(payload) 126 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 127 | end 128 | 129 | # INPUT: ParamsOfDecodeMessage 130 | # abi: Value - # # contract ABI 131 | # message: String - # # Message BOC 132 | # allow_partial: Boolean - # # Flag allowing partial BOC decoding when ABI doesn't describe the full body BOC. Controls decoder behaviour when after decoding all described in ABI params there are some data left in BOC: `true` - return decoded values `false` - return error of incomplete BOC deserialization (default) 133 | # function_name: String - # # Function name or function id if is known in advance 134 | # data_layout: DataLayout - 135 | # RESPONSE: DecodedMessageBody 136 | # body_type: MessageBodyType - # # Type of the message body content. 137 | # name: String - # # Function or event name. 138 | # value: Value - # # Parameters or result value. 139 | # header: FunctionHeader - # # Function header. 140 | # Async 141 | def decode_message(payload, &block) 142 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 143 | end 144 | 145 | # Sync 146 | def decode_message_sync(payload) 147 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 148 | end 149 | 150 | # INPUT: ParamsOfDecodeMessageBody 151 | # abi: Value - # # Contract ABI used to decode. 152 | # body: String - # # Message body BOC encoded in `base64`. 153 | # is_internal: Boolean - # # True if the body belongs to the internal message. 154 | # allow_partial: Boolean - # # Flag allowing partial BOC decoding when ABI doesn't describe the full body BOC. Controls decoder behaviour when after decoding all described in ABI params there are some data left in BOC: `true` - return decoded values `false` - return error of incomplete BOC deserialization (default) 155 | # function_name: String - # # Function name or function id if is known in advance 156 | # data_layout: DataLayout - 157 | # RESPONSE: DecodedMessageBody 158 | # body_type: MessageBodyType - # # Type of the message body content. 159 | # name: String - # # Function or event name. 160 | # value: Value - # # Parameters or result value. 161 | # header: FunctionHeader - # # Function header. 162 | # Async 163 | def decode_message_body(payload, &block) 164 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 165 | end 166 | 167 | # Sync 168 | def decode_message_body_sync(payload) 169 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 170 | end 171 | 172 | # INPUT: ParamsOfEncodeAccount 173 | # state_init: StateInitSource - # # Source of the account state init. 174 | # balance: BigInt - # # Initial balance. 175 | # last_trans_lt: BigInt - # # Initial value for the `last_trans_lt`. 176 | # last_paid: Number - # # Initial value for the `last_paid`. 177 | # boc_cache: BocCacheType - # # Cache type to put the result. # # The BOC itself returned if no cache type provided 178 | # RESPONSE: ResultOfEncodeAccount 179 | # account: String - # # Account BOC encoded in `base64`. 180 | # id: String - # # Account ID encoded in `hex`. 181 | # Async 182 | def encode_account(payload, &block) 183 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 184 | end 185 | 186 | # Sync 187 | def encode_account_sync(payload) 188 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 189 | end 190 | 191 | # INPUT: ParamsOfDecodeAccountData 192 | # abi: Value - # # Contract ABI 193 | # data: String - # # Data BOC or BOC handle 194 | # allow_partial: Boolean - # # Flag allowing partial BOC decoding when ABI doesn't describe the full body BOC. Controls decoder behaviour when after decoding all described in ABI params there are some data left in BOC: `true` - return decoded values `false` - return error of incomplete BOC deserialization (default) 195 | # RESPONSE: ResultOfDecodeAccountData 196 | # data: Value - # # Decoded data as a JSON structure. 197 | # Async 198 | def decode_account_data(payload, &block) 199 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 200 | end 201 | 202 | # Sync 203 | def decode_account_data_sync(payload) 204 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 205 | end 206 | 207 | # INPUT: ParamsOfUpdateInitialData 208 | # abi: Value - # # Contract ABI 209 | # data: String - # # Data BOC or BOC handle 210 | # initial_data: Value - # # List of initial values for contract's static variables. # # `abi` parameter should be provided to set initial data 211 | # initial_pubkey: String - # # Initial account owner's public key to set into account data 212 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 213 | # RESPONSE: ResultOfUpdateInitialData 214 | # data: String - # # Updated data BOC or BOC handle 215 | # Async 216 | def update_initial_data(payload, &block) 217 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 218 | end 219 | 220 | # Sync 221 | def update_initial_data_sync(payload) 222 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 223 | end 224 | 225 | # INPUT: ParamsOfEncodeInitialData 226 | # abi: Value - # # Contract ABI 227 | # initial_data: Value - # # List of initial values for contract's static variables. # # `abi` parameter should be provided to set initial data 228 | # initial_pubkey: String - # # Initial account owner's public key to set into account data 229 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 230 | # RESPONSE: ResultOfEncodeInitialData 231 | # data: String - # # Updated data BOC or BOC handle 232 | # Async 233 | def encode_initial_data(payload, &block) 234 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 235 | end 236 | 237 | # Sync 238 | def encode_initial_data_sync(payload) 239 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 240 | end 241 | 242 | # INPUT: ParamsOfDecodeInitialData 243 | # abi: Value - # # Contract ABI. # # Initial data is decoded if this parameter is provided 244 | # data: String - # # Data BOC or BOC handle 245 | # allow_partial: Boolean - # # Flag allowing partial BOC decoding when ABI doesn't describe the full body BOC. Controls decoder behaviour when after decoding all described in ABI params there are some data left in BOC: `true` - return decoded values `false` - return error of incomplete BOC deserialization (default) 246 | # RESPONSE: ResultOfDecodeInitialData 247 | # initial_data: Value - # # List of initial values of contract's public variables. # # Initial data is decoded if `abi` input parameter is provided 248 | # initial_pubkey: String - # # Initial account owner's public key 249 | # Async 250 | def decode_initial_data(payload, &block) 251 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 252 | end 253 | 254 | # Sync 255 | def decode_initial_data_sync(payload) 256 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 257 | end 258 | 259 | # INPUT: ParamsOfDecodeBoc 260 | # params: Array - # # Parameters to decode from BOC 261 | # boc: String - # # Data BOC or BOC handle 262 | # allow_partial: Boolean - 263 | # RESPONSE: ResultOfDecodeBoc 264 | # data: Value - # # Decoded data as a JSON structure. 265 | # Async 266 | def decode_boc(payload, &block) 267 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 268 | end 269 | 270 | # Sync 271 | def decode_boc_sync(payload) 272 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 273 | end 274 | 275 | # INPUT: ParamsOfAbiEncodeBoc 276 | # params: Array - # # Parameters to encode into BOC 277 | # data: Value - # # Parameters and values as a JSON structure 278 | # boc_cache: BocCacheType - # # Cache type to put the result. # # The BOC itself returned if no cache type provided 279 | # RESPONSE: ResultOfAbiEncodeBoc 280 | # boc: String - # # BOC encoded as base64 281 | # Async 282 | def encode_boc(payload, &block) 283 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 284 | end 285 | 286 | # Sync 287 | def encode_boc_sync(payload) 288 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 289 | end 290 | 291 | # INPUT: ParamsOfCalcFunctionId 292 | # abi: Value - # # Contract ABI. 293 | # function_name: String - # # Contract function name 294 | # output: Boolean - # # If set to `true` output function ID will be returned which is used in contract response. Default is `false` 295 | # RESPONSE: ResultOfCalcFunctionId 296 | # function_id: Number - # # Contract function ID 297 | # Async 298 | def calc_function_id(payload, &block) 299 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 300 | end 301 | 302 | # Sync 303 | def calc_function_id_sync(payload) 304 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 305 | end 306 | 307 | # INPUT: ParamsOfGetSignatureData 308 | # abi: Value - # # Contract ABI used to decode. 309 | # message: String - # # Message BOC encoded in `base64`. 310 | # signature_id: Number - # # Signature ID to be used in unsigned data preparing when CapSignatureWithId capability is enabled 311 | # RESPONSE: ResultOfGetSignatureData 312 | # signature: String - # # Signature from the message in `hex`. 313 | # unsigned: String - # # Data to verify the signature in `base64`. 314 | # Async 315 | def get_signature_data(payload, &block) 316 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 317 | end 318 | 319 | # Sync 320 | def get_signature_data_sync(payload) 321 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 322 | end 323 | 324 | end 325 | end 326 | 327 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Boc.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Boc 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfDecodeTvc 17 | # tvc: String - # # Contract TVC BOC encoded as base64 or BOC handle 18 | # RESPONSE: ResultOfDecodeTvc 19 | # tvc: Tvc - # # Decoded TVC 20 | # Async 21 | def decode_tvc(payload, &block) 22 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 23 | end 24 | 25 | # Sync 26 | def decode_tvc_sync(payload) 27 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 28 | end 29 | 30 | # INPUT: ParamsOfParse 31 | # boc: String - # # BOC encoded as base64 32 | # RESPONSE: ResultOfParse 33 | # parsed: Value - # # JSON containing parsed BOC 34 | # Async 35 | def parse_message(payload, &block) 36 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 37 | end 38 | 39 | # Sync 40 | def parse_message_sync(payload) 41 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 42 | end 43 | 44 | # INPUT: ParamsOfParse 45 | # boc: String - # # BOC encoded as base64 46 | # RESPONSE: ResultOfParse 47 | # parsed: Value - # # JSON containing parsed BOC 48 | # Async 49 | def parse_transaction(payload, &block) 50 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 51 | end 52 | 53 | # Sync 54 | def parse_transaction_sync(payload) 55 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 56 | end 57 | 58 | # INPUT: ParamsOfParse 59 | # boc: String - # # BOC encoded as base64 60 | # RESPONSE: ResultOfParse 61 | # parsed: Value - # # JSON containing parsed BOC 62 | # Async 63 | def parse_account(payload, &block) 64 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 65 | end 66 | 67 | # Sync 68 | def parse_account_sync(payload) 69 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 70 | end 71 | 72 | # INPUT: ParamsOfParse 73 | # boc: String - # # BOC encoded as base64 74 | # RESPONSE: ResultOfParse 75 | # parsed: Value - # # JSON containing parsed BOC 76 | # Async 77 | def parse_block(payload, &block) 78 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 79 | end 80 | 81 | # Sync 82 | def parse_block_sync(payload) 83 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 84 | end 85 | 86 | # INPUT: ParamsOfParseShardstate 87 | # boc: String - # # BOC encoded as base64 88 | # id: String - # # Shardstate identifier 89 | # workchain_id: Number - # # Workchain shardstate belongs to 90 | # RESPONSE: ResultOfParse 91 | # parsed: Value - # # JSON containing parsed BOC 92 | # Async 93 | def parse_shardstate(payload, &block) 94 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 95 | end 96 | 97 | # Sync 98 | def parse_shardstate_sync(payload) 99 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 100 | end 101 | 102 | # INPUT: ParamsOfGetBlockchainConfig 103 | # block_boc: String - # # Key block BOC or zerostate BOC encoded as base64 104 | # RESPONSE: ResultOfGetBlockchainConfig 105 | # config_boc: String - # # Blockchain config BOC encoded as base64 106 | # Async 107 | def get_blockchain_config(payload, &block) 108 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 109 | end 110 | 111 | # Sync 112 | def get_blockchain_config_sync(payload) 113 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 114 | end 115 | 116 | # INPUT: ParamsOfGetBocHash 117 | # boc: String - # # BOC encoded as base64 or BOC handle 118 | # RESPONSE: ResultOfGetBocHash 119 | # hash: String - # # BOC root hash encoded with hex 120 | # Async 121 | def get_boc_hash(payload, &block) 122 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 123 | end 124 | 125 | # Sync 126 | def get_boc_hash_sync(payload) 127 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 128 | end 129 | 130 | # INPUT: ParamsOfGetBocDepth 131 | # boc: String - # # BOC encoded as base64 or BOC handle 132 | # RESPONSE: ResultOfGetBocDepth 133 | # depth: Number - # # BOC root cell depth 134 | # Async 135 | def get_boc_depth(payload, &block) 136 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 137 | end 138 | 139 | # Sync 140 | def get_boc_depth_sync(payload) 141 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 142 | end 143 | 144 | # INPUT: ParamsOfGetCodeFromTvc 145 | # tvc: String - # # Contract TVC image or image BOC handle 146 | # RESPONSE: ResultOfGetCodeFromTvc 147 | # code: String - # # Contract code encoded as base64 148 | # Async 149 | def get_code_from_tvc(payload, &block) 150 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 151 | end 152 | 153 | # Sync 154 | def get_code_from_tvc_sync(payload) 155 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 156 | end 157 | 158 | # INPUT: ParamsOfBocCacheGet 159 | # boc_ref: String - # # Reference to the cached BOC 160 | # RESPONSE: ResultOfBocCacheGet 161 | # boc: String - # # BOC encoded as base64. 162 | # Async 163 | def cache_get(payload, &block) 164 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 165 | end 166 | 167 | # Sync 168 | def cache_get_sync(payload) 169 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 170 | end 171 | 172 | # INPUT: ParamsOfBocCacheSet 173 | # boc: String - # # BOC encoded as base64 or BOC reference 174 | # cache_type: BocCacheType - # # Cache type 175 | # RESPONSE: ResultOfBocCacheSet 176 | # boc_ref: String - # # Reference to the cached BOC 177 | # Async 178 | def cache_set(payload, &block) 179 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 180 | end 181 | 182 | # Sync 183 | def cache_set_sync(payload) 184 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 185 | end 186 | 187 | # INPUT: ParamsOfBocCacheUnpin 188 | # pin: String - # # Pinned name 189 | # boc_ref: String - # # Reference to the cached BOC. # # If it is provided then only referenced BOC is unpinned 190 | # Async 191 | def cache_unpin(payload, &block) 192 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 193 | end 194 | 195 | # Sync 196 | def cache_unpin_sync(payload) 197 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 198 | end 199 | 200 | # INPUT: ParamsOfEncodeBoc 201 | # builder: Array - # # Cell builder operations. 202 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 203 | # RESPONSE: ResultOfEncodeBoc 204 | # boc: String - # # Encoded cell BOC or BOC cache key. 205 | # Async 206 | def encode_boc(payload, &block) 207 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 208 | end 209 | 210 | # Sync 211 | def encode_boc_sync(payload) 212 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 213 | end 214 | 215 | # INPUT: ParamsOfGetCodeSalt 216 | # code: String - # # Contract code BOC encoded as base64 or code BOC handle 217 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 218 | # RESPONSE: ResultOfGetCodeSalt 219 | # salt: String - # # Contract code salt if present. # # BOC encoded as base64 or BOC handle 220 | # Async 221 | def get_code_salt(payload, &block) 222 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 223 | end 224 | 225 | # Sync 226 | def get_code_salt_sync(payload) 227 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 228 | end 229 | 230 | # INPUT: ParamsOfSetCodeSalt 231 | # code: String - # # Contract code BOC encoded as base64 or code BOC handle 232 | # salt: String - # # Code salt to set. # # BOC encoded as base64 or BOC handle 233 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 234 | # RESPONSE: ResultOfSetCodeSalt 235 | # code: String - # # Contract code with salt set. # # BOC encoded as base64 or BOC handle 236 | # Async 237 | def set_code_salt(payload, &block) 238 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 239 | end 240 | 241 | # Sync 242 | def set_code_salt_sync(payload) 243 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 244 | end 245 | 246 | # INPUT: ParamsOfDecodeStateInit 247 | # state_init: String - # # Contract StateInit image BOC encoded as base64 or BOC handle 248 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 249 | # RESPONSE: ResultOfDecodeStateInit 250 | # code: String - # # Contract code BOC encoded as base64 or BOC handle 251 | # code_hash: String - # # Contract code hash 252 | # code_depth: Number - # # Contract code depth 253 | # data: String - # # Contract data BOC encoded as base64 or BOC handle 254 | # data_hash: String - # # Contract data hash 255 | # data_depth: Number - # # Contract data depth 256 | # library: String - # # Contract library BOC encoded as base64 or BOC handle 257 | # tick: Boolean - # # `special.tick` field. # # Specifies the contract ability to handle tick transactions 258 | # tock: Boolean - # # `special.tock` field. # # Specifies the contract ability to handle tock transactions 259 | # split_depth: Number - # # Is present and non-zero only in instances of large smart contracts 260 | # compiler_version: String - # # Compiler version, for example 'sol 0.49.0' 261 | # Async 262 | def decode_state_init(payload, &block) 263 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 264 | end 265 | 266 | # Sync 267 | def decode_state_init_sync(payload) 268 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 269 | end 270 | 271 | # INPUT: ParamsOfEncodeStateInit 272 | # code: String - # # Contract code BOC encoded as base64 or BOC handle 273 | # data: String - # # Contract data BOC encoded as base64 or BOC handle 274 | # library: String - # # Contract library BOC encoded as base64 or BOC handle 275 | # tick: Boolean - # # `special.tick` field. # # Specifies the contract ability to handle tick transactions 276 | # tock: Boolean - # # `special.tock` field. # # Specifies the contract ability to handle tock transactions 277 | # split_depth: Number - # # Is present and non-zero only in instances of large smart contracts 278 | # boc_cache: BocCacheType - # # Cache type to put the result. The BOC itself returned if no cache type provided. 279 | # RESPONSE: ResultOfEncodeStateInit 280 | # state_init: String - # # Contract StateInit image BOC encoded as base64 or BOC handle of boc_cache parameter was specified 281 | # Async 282 | def encode_state_init(payload, &block) 283 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 284 | end 285 | 286 | # Sync 287 | def encode_state_init_sync(payload) 288 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 289 | end 290 | 291 | # INPUT: ParamsOfEncodeExternalInMessage 292 | # src: String - # # Source address. 293 | # dst: String - # # Destination address. 294 | # init: String - # # Bag of cells with state init (used in deploy messages). 295 | # body: String - # # Bag of cells with the message body encoded as base64. 296 | # boc_cache: BocCacheType - # # Cache type to put the result. # # The BOC itself returned if no cache type provided 297 | # RESPONSE: ResultOfEncodeExternalInMessage 298 | # message: String - # # Message BOC encoded with `base64`. 299 | # message_id: String - # # Message id. 300 | # Async 301 | def encode_external_in_message(payload, &block) 302 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 303 | end 304 | 305 | # Sync 306 | def encode_external_in_message_sync(payload) 307 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 308 | end 309 | 310 | # INPUT: ParamsOfGetCompilerVersion 311 | # code: String - # # Contract code BOC encoded as base64 or code BOC handle 312 | # RESPONSE: ResultOfGetCompilerVersion 313 | # version: String - # # Compiler version, for example 'sol 0.49.0' 314 | # Async 315 | def get_compiler_version(payload, &block) 316 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 317 | end 318 | 319 | # Sync 320 | def get_compiler_version_sync(payload) 321 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 322 | end 323 | 324 | end 325 | end 326 | 327 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Client.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Client 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :context_config, :request_id, :requests, :monitor 7 | private_accessor :_crypto, :_abi, :_boc, :_processing, :_utils, :_tvm, :_net, :_debot, :_proofs 8 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 9 | 10 | def initialize(context_config: {}) 11 | @context_config = context_config 12 | @request_id = RequestId.new 13 | @requests = Requests.new 14 | @monitor = Monitor.new 15 | config = TonBinding.make_string(context_config.to_json) 16 | context_ptr = TonBinding.tc_create_context(config) 17 | context_response = TonBinding.read_string_data_ref(context_ptr) 18 | @context = TonBinding.read_string_to_hash(context_response)['result'] 19 | ObjectSpace.define_finalizer(self, self.class.finalize(@context)) 20 | end 21 | 22 | def self.finalize(ctx) 23 | Proc.new do 24 | if (ctx != nil) && (ctx > 0) 25 | TonBinding.tc_destroy_context(ctx) 26 | end 27 | end 28 | end 29 | 30 | def crypto 31 | _crypto ||= Crypto.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 32 | end 33 | 34 | def abi 35 | _abi ||= Abi.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 36 | end 37 | 38 | def boc 39 | _boc ||= Boc.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 40 | end 41 | 42 | def processing 43 | _processing ||= Processing.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 44 | end 45 | 46 | def utils 47 | _utils ||= Utils.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 48 | end 49 | 50 | def tvm 51 | _tvm ||= Tvm.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 52 | end 53 | 54 | def net 55 | _net ||= Net.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 56 | end 57 | 58 | def debot 59 | _debot ||= Debot.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 60 | end 61 | 62 | def proofs 63 | _proofs ||= Proofs.new(context: context, request_id: request_id, requests: requests, monitor: monitor) 64 | end 65 | 66 | # RESPONSE: ResultOfGetApiReference 67 | # api: Value - 68 | # Async 69 | def get_api_reference(&block) 70 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 71 | end 72 | 73 | # Sync 74 | def get_api_reference_sync() 75 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 76 | end 77 | 78 | # RESPONSE: ResultOfVersion 79 | # version: String - # # Core Library version 80 | # Async 81 | def version(&block) 82 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 83 | end 84 | 85 | # Sync 86 | def version_sync() 87 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 88 | end 89 | 90 | # RESPONSE: ClientConfig 91 | # binding: BindingConfig - 92 | # network: NetworkConfig - 93 | # crypto: CryptoConfig - 94 | # abi: Value - 95 | # boc: BocConfig - 96 | # proofs: ProofsConfig - 97 | # local_storage_path: String - # # For file based storage is a folder name where SDK will store its data. For browser based is a browser async storage key prefix. Default (recommended) value is "~/.tonclient" for native environments and ".tonclient" for web-browser. 98 | # Async 99 | def config(&block) 100 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 101 | end 102 | 103 | # Sync 104 | def config_sync() 105 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 106 | end 107 | 108 | # RESPONSE: ResultOfBuildInfo 109 | # build_number: Number - # # Build number assigned to this build by the CI. 110 | # dependencies: Array - # # Fingerprint of the most important dependencies. 111 | # Async 112 | def build_info(&block) 113 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 114 | end 115 | 116 | # Sync 117 | def build_info_sync() 118 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 119 | end 120 | 121 | # INPUT: ParamsOfResolveAppRequest 122 | # app_request_id: Number - # # Request ID received from SDK 123 | # result: AppRequestResult - # # Result of request processing 124 | # Async 125 | def resolve_app_request(payload, &block) 126 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 127 | end 128 | 129 | # Sync 130 | def resolve_app_request_sync(payload) 131 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 132 | end 133 | 134 | end 135 | end 136 | 137 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Debot.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Debot 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfInit 17 | # address: String - # # Debot smart contract address 18 | # RESPONSE: RegisteredDebot 19 | # debot_handle: DebotHandle - # # Debot handle which references an instance of debot engine. 20 | # debot_abi: String - # # Debot abi as json string. 21 | # info: DebotInfo - # # Debot metadata. 22 | # Async 23 | def init(payload, &block) 24 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 25 | end 26 | 27 | # Sync 28 | def init_sync(payload) 29 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 30 | end 31 | 32 | # INPUT: ParamsOfStart 33 | # debot_handle: DebotHandle - # # Debot handle which references an instance of debot engine. 34 | # Async 35 | def start(payload, &block) 36 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 37 | end 38 | 39 | # Sync 40 | def start_sync(payload) 41 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 42 | end 43 | 44 | # INPUT: ParamsOfFetch 45 | # address: String - # # Debot smart contract address. 46 | # RESPONSE: ResultOfFetch 47 | # info: DebotInfo - # # Debot metadata. 48 | # Async 49 | def fetch(payload, &block) 50 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 51 | end 52 | 53 | # Sync 54 | def fetch_sync(payload) 55 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 56 | end 57 | 58 | # INPUT: ParamsOfExecute 59 | # debot_handle: DebotHandle - # # Debot handle which references an instance of debot engine. 60 | # action: DebotAction - # # Debot Action that must be executed. 61 | # Async 62 | def execute(payload, &block) 63 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 64 | end 65 | 66 | # Sync 67 | def execute_sync(payload) 68 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 69 | end 70 | 71 | # INPUT: ParamsOfSend 72 | # debot_handle: DebotHandle - # # Debot handle which references an instance of debot engine. 73 | # message: String - # # BOC of internal message to debot encoded in base64 format. 74 | # Async 75 | def send(payload, &block) 76 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 77 | end 78 | 79 | # Sync 80 | def send_sync(payload) 81 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 82 | end 83 | 84 | # INPUT: ParamsOfRemove 85 | # debot_handle: DebotHandle - # # Debot handle which references an instance of debot engine. 86 | # Async 87 | def remove(payload, &block) 88 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 89 | end 90 | 91 | # Sync 92 | def remove_sync(payload) 93 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 94 | end 95 | 96 | end 97 | end 98 | 99 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Net.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Net 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfQuery 17 | # query: String - # # GraphQL query text. 18 | # variables: Value - # # Variables used in query. # # Must be a map with named values that can be used in query. 19 | # RESPONSE: ResultOfQuery 20 | # result: Value - # # Result provided by DAppServer. 21 | # Async 22 | def query(payload, &block) 23 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 24 | end 25 | 26 | # Sync 27 | def query_sync(payload) 28 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 29 | end 30 | 31 | # INPUT: ParamsOfBatchQuery 32 | # operations: Array - # # List of query operations that must be performed per single fetch. 33 | # RESPONSE: ResultOfBatchQuery 34 | # results: Array - # # Result values for batched queries. # # Returns an array of values. Each value corresponds to `queries` item. 35 | # Async 36 | def batch_query(payload, &block) 37 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 38 | end 39 | 40 | # Sync 41 | def batch_query_sync(payload) 42 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 43 | end 44 | 45 | # INPUT: ParamsOfQueryCollection 46 | # collection: String - # # Collection name (accounts, blocks, transactions, messages, block_signatures) 47 | # filter: Value - # # Collection filter 48 | # result: String - # # Projection (result) string 49 | # order: Array - # # Sorting order 50 | # limit: Number - # # Number of documents to return 51 | # RESPONSE: ResultOfQueryCollection 52 | # result: Array - # # Objects that match the provided criteria 53 | # Async 54 | def query_collection(payload, &block) 55 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 56 | end 57 | 58 | # Sync 59 | def query_collection_sync(payload) 60 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 61 | end 62 | 63 | # INPUT: ParamsOfAggregateCollection 64 | # collection: String - # # Collection name (accounts, blocks, transactions, messages, block_signatures) 65 | # filter: Value - # # Collection filter 66 | # fields: Array - # # Projection (result) string 67 | # RESPONSE: ResultOfAggregateCollection 68 | # values: Value - # # Values for requested fields. # # Returns an array of strings. Each string refers to the corresponding `fields` item. 69 | # Numeric value is returned as a decimal string representations. 70 | # Async 71 | def aggregate_collection(payload, &block) 72 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 73 | end 74 | 75 | # Sync 76 | def aggregate_collection_sync(payload) 77 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 78 | end 79 | 80 | # INPUT: ParamsOfWaitForCollection 81 | # collection: String - # # Collection name (accounts, blocks, transactions, messages, block_signatures) 82 | # filter: Value - # # Collection filter 83 | # result: String - # # Projection (result) string 84 | # timeout: Number - # # Query timeout 85 | # RESPONSE: ResultOfWaitForCollection 86 | # result: Value - # # First found object that matches the provided criteria 87 | # Async 88 | def wait_for_collection(payload, &block) 89 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 90 | end 91 | 92 | # Sync 93 | def wait_for_collection_sync(payload) 94 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 95 | end 96 | 97 | # INPUT: ResultOfSubscribeCollection 98 | # handle: Number - # # Subscription handle. # # Must be closed with `unsubscribe` 99 | # Async 100 | def unsubscribe(payload, &block) 101 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 102 | end 103 | 104 | # Sync 105 | def unsubscribe_sync(payload) 106 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 107 | end 108 | 109 | # INPUT: ParamsOfSubscribeCollection 110 | # collection: String - # # Collection name (accounts, blocks, transactions, messages, block_signatures) 111 | # filter: Value - # # Collection filter 112 | # result: String - # # Projection (result) string 113 | # RESPONSE: ResultOfSubscribeCollection 114 | # handle: Number - # # Subscription handle. # # Must be closed with `unsubscribe` 115 | # Async 116 | def subscribe_collection(payload, &block) 117 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 118 | end 119 | 120 | # Sync 121 | def subscribe_collection_sync(payload) 122 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 123 | end 124 | 125 | # INPUT: ParamsOfSubscribe 126 | # subscription: String - # # GraphQL subscription text. 127 | # variables: Value - # # Variables used in subscription. # # Must be a map with named values that can be used in query. 128 | # RESPONSE: ResultOfSubscribeCollection 129 | # handle: Number - # # Subscription handle. # # Must be closed with `unsubscribe` 130 | # Async 131 | def subscribe(payload, &block) 132 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 133 | end 134 | 135 | # Sync 136 | def subscribe_sync(payload) 137 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 138 | end 139 | 140 | # Async 141 | def suspend(&block) 142 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 143 | end 144 | 145 | # Sync 146 | def suspend_sync() 147 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 148 | end 149 | 150 | # Async 151 | def resume(&block) 152 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 153 | end 154 | 155 | # Sync 156 | def resume_sync() 157 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 158 | end 159 | 160 | # INPUT: ParamsOfFindLastShardBlock 161 | # address: String - # # Account address 162 | # RESPONSE: ResultOfFindLastShardBlock 163 | # block_id: String - # # Account shard last block ID 164 | # Async 165 | def find_last_shard_block(payload, &block) 166 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 167 | end 168 | 169 | # Sync 170 | def find_last_shard_block_sync(payload) 171 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 172 | end 173 | 174 | # RESPONSE: EndpointsSet 175 | # endpoints: Array - # # List of endpoints provided by server 176 | # Async 177 | def fetch_endpoints(&block) 178 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 179 | end 180 | 181 | # Sync 182 | def fetch_endpoints_sync() 183 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 184 | end 185 | 186 | # INPUT: EndpointsSet 187 | # endpoints: Array - # # List of endpoints provided by server 188 | # Async 189 | def set_endpoints(payload, &block) 190 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 191 | end 192 | 193 | # Sync 194 | def set_endpoints_sync(payload) 195 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 196 | end 197 | 198 | # RESPONSE: ResultOfGetEndpoints 199 | # query: String - # # Current query endpoint 200 | # endpoints: Array - # # List of all endpoints used by client 201 | # Async 202 | def get_endpoints(&block) 203 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 204 | end 205 | 206 | # Sync 207 | def get_endpoints_sync() 208 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 209 | end 210 | 211 | # INPUT: ParamsOfQueryCounterparties 212 | # account: String - # # Account address 213 | # result: String - # # Projection (result) string 214 | # first: Number - # # Number of counterparties to return 215 | # after: String - # # `cursor` field of the last received result 216 | # RESPONSE: ResultOfQueryCollection 217 | # result: Array - # # Objects that match the provided criteria 218 | # Async 219 | def query_counterparties(payload, &block) 220 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 221 | end 222 | 223 | # Sync 224 | def query_counterparties_sync(payload) 225 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 226 | end 227 | 228 | # INPUT: ParamsOfQueryTransactionTree 229 | # in_msg: String - # # Input message id. 230 | # abi_registry: Array - # # List of contract ABIs that will be used to decode message bodies. Library will try to decode each returned message body using any ABI from the registry. 231 | # timeout: Number - # # Timeout used to limit waiting time for the missing messages and transaction. # # If some of the following messages and transactions are missing yetThe maximum waiting time is regulated by this option. 232 | # Default value is 60000 (1 min). If `timeout` is set to 0 then function will wait infinitelyuntil the whole transaction tree is executed 233 | # transaction_max_count: Number - # # Maximum transaction count to wait. # # If transaction tree contains more transaction then this parameter then only first `transaction_max_count` transaction are awaited and returned. 234 | # Default value is 50. If `transaction_max_count` is set to 0 then no limitation ontransaction count is used and all transaction are returned. 235 | # RESPONSE: ResultOfQueryTransactionTree 236 | # messages: Array - # # Messages. 237 | # transactions: Array - # # Transactions. 238 | # Async 239 | def query_transaction_tree(payload, &block) 240 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 241 | end 242 | 243 | # Sync 244 | def query_transaction_tree_sync(payload) 245 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 246 | end 247 | 248 | # INPUT: ParamsOfCreateBlockIterator 249 | # start_time: Number - # # Starting time to iterate from. # # If the application specifies this parameter then the iterationincludes blocks with `gen_utime` >= `start_time`. 250 | # Otherwise the iteration starts from zero state. 251 | # Must be specified in seconds. 252 | # end_time: Number - # # Optional end time to iterate for. # # If the application specifies this parameter then the iterationincludes blocks with `gen_utime` < `end_time`. 253 | # Otherwise the iteration never stops. 254 | # Must be specified in seconds. 255 | # shard_filter: Array - # # Shard prefix filter. # # If the application specifies this parameter and it is not the empty arraythen the iteration will include items related to accounts that belongs tothe specified shard prefixes. 256 | # Shard prefix must be represented as a string "workchain:prefix". 257 | # Where `workchain` is a signed integer and the `prefix` if a hexadecimalrepresentation if the 64-bit unsigned integer with tagged shard prefix. 258 | # For example: "0:3800000000000000". 259 | # result: String - # # Projection (result) string. # # List of the fields that must be returned for iterated items. 260 | # This field is the same as the `result` parameter ofthe `query_collection` function. 261 | # Note that iterated items can contains additional fields that arenot requested in the `result`. 262 | # RESPONSE: RegisteredIterator 263 | # handle: Number - # # Iterator handle. # # Must be removed using `remove_iterator`when it is no more needed for the application. 264 | # Async 265 | def create_block_iterator(payload, &block) 266 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 267 | end 268 | 269 | # Sync 270 | def create_block_iterator_sync(payload) 271 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 272 | end 273 | 274 | # INPUT: ParamsOfResumeBlockIterator 275 | # resume_state: Value - # # Iterator state from which to resume. # # Same as value returned from `iterator_next`. 276 | # RESPONSE: RegisteredIterator 277 | # handle: Number - # # Iterator handle. # # Must be removed using `remove_iterator`when it is no more needed for the application. 278 | # Async 279 | def resume_block_iterator(payload, &block) 280 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 281 | end 282 | 283 | # Sync 284 | def resume_block_iterator_sync(payload) 285 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 286 | end 287 | 288 | # INPUT: ParamsOfCreateTransactionIterator 289 | # start_time: Number - # # Starting time to iterate from. # # If the application specifies this parameter then the iterationincludes blocks with `gen_utime` >= `start_time`. 290 | # Otherwise the iteration starts from zero state. 291 | # Must be specified in seconds. 292 | # end_time: Number - # # Optional end time to iterate for. # # If the application specifies this parameter then the iterationincludes blocks with `gen_utime` < `end_time`. 293 | # Otherwise the iteration never stops. 294 | # Must be specified in seconds. 295 | # shard_filter: Array - # # Shard prefix filters. # # If the application specifies this parameter and it is not an empty arraythen the iteration will include items related to accounts that belongs tothe specified shard prefixes. 296 | # Shard prefix must be represented as a string "workchain:prefix". 297 | # Where `workchain` is a signed integer and the `prefix` if a hexadecimalrepresentation if the 64-bit unsigned integer with tagged shard prefix. 298 | # For example: "0:3800000000000000". 299 | # Account address conforms to the shard filter ifit belongs to the filter workchain and the first bits of address match tothe shard prefix. Only transactions with suitable account addresses are iterated. 300 | # accounts_filter: Array - # # Account address filter. # # Application can specify the list of accounts for whichit wants to iterate transactions. 301 | # If this parameter is missing or an empty list then the library iteratestransactions for all accounts that pass the shard filter. 302 | # Note that the library doesn't detect conflicts between the account filter and the shard filterif both are specified. 303 | # So it is an application responsibility to specify the correct filter combination. 304 | # result: String - # # Projection (result) string. # # List of the fields that must be returned for iterated items. 305 | # This field is the same as the `result` parameter ofthe `query_collection` function. 306 | # Note that iterated items can contain additional fields that arenot requested in the `result`. 307 | # include_transfers: Boolean - # # Include `transfers` field in iterated transactions. # # If this parameter is `true` then each transaction contains field`transfers` with list of transfer. See more about this structure in function description. 308 | # RESPONSE: RegisteredIterator 309 | # handle: Number - # # Iterator handle. # # Must be removed using `remove_iterator`when it is no more needed for the application. 310 | # Async 311 | def create_transaction_iterator(payload, &block) 312 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 313 | end 314 | 315 | # Sync 316 | def create_transaction_iterator_sync(payload) 317 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 318 | end 319 | 320 | # INPUT: ParamsOfResumeTransactionIterator 321 | # resume_state: Value - # # Iterator state from which to resume. # # Same as value returned from `iterator_next`. 322 | # accounts_filter: Array - # # Account address filter. # # Application can specify the list of accounts for whichit wants to iterate transactions. 323 | # If this parameter is missing or an empty list then the library iteratestransactions for all accounts that passes the shard filter. 324 | # Note that the library doesn't detect conflicts between the account filter and the shard filterif both are specified. 325 | # So it is the application's responsibility to specify the correct filter combination. 326 | # RESPONSE: RegisteredIterator 327 | # handle: Number - # # Iterator handle. # # Must be removed using `remove_iterator`when it is no more needed for the application. 328 | # Async 329 | def resume_transaction_iterator(payload, &block) 330 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 331 | end 332 | 333 | # Sync 334 | def resume_transaction_iterator_sync(payload) 335 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 336 | end 337 | 338 | # INPUT: ParamsOfIteratorNext 339 | # iterator: Number - # # Iterator handle 340 | # limit: Number - # # Maximum count of the returned items. # # If value is missing or is less than 1 the library uses 1. 341 | # return_resume_state: Boolean - # # Indicates that function must return the iterator state that can be used for resuming iteration. 342 | # RESPONSE: ResultOfIteratorNext 343 | # items: Array - # # Next available items. # # Note that `iterator_next` can return an empty items and `has_more` equals to `true`. 344 | # In this case the application have to continue iteration. 345 | # Such situation can take place when there is no data yet butthe requested `end_time` is not reached. 346 | # has_more: Boolean - # # Indicates that there are more available items in iterated range. 347 | # resume_state: Value - # # Optional iterator state that can be used for resuming iteration. # # This field is returned only if the `return_resume_state` parameteris specified. 348 | # Note that `resume_state` corresponds to the iteration positionafter the returned items. 349 | # Async 350 | def iterator_next(payload, &block) 351 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 352 | end 353 | 354 | # Sync 355 | def iterator_next_sync(payload) 356 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 357 | end 358 | 359 | # INPUT: RegisteredIterator 360 | # handle: Number - # # Iterator handle. # # Must be removed using `remove_iterator`when it is no more needed for the application. 361 | # Async 362 | def remove_iterator(payload, &block) 363 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 364 | end 365 | 366 | # Sync 367 | def remove_iterator_sync(payload) 368 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 369 | end 370 | 371 | # RESPONSE: ResultOfGetSignatureId 372 | # signature_id: Number - # # Signature ID for configured network if it should be used in messages signature 373 | # Async 374 | def get_signature_id(&block) 375 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: {}, &block) 376 | end 377 | 378 | # Sync 379 | def get_signature_id_sync() 380 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: {}) 381 | end 382 | 383 | end 384 | end 385 | 386 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Processing.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Processing 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfMonitorMessages 17 | # queue: String - # # Name of the monitoring queue. 18 | # messages: Array - # # Messages to start monitoring for. 19 | # Async 20 | def monitor_messages(payload, &block) 21 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 22 | end 23 | 24 | # Sync 25 | def monitor_messages_sync(payload) 26 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 27 | end 28 | 29 | # INPUT: ParamsOfGetMonitorInfo 30 | # queue: String - # # Name of the monitoring queue. 31 | # RESPONSE: MonitoringQueueInfo 32 | # unresolved: Number - # # Count of the unresolved messages. 33 | # resolved: Number - # # Count of resolved results. 34 | # Async 35 | def get_monitor_info(payload, &block) 36 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 37 | end 38 | 39 | # Sync 40 | def get_monitor_info_sync(payload) 41 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 42 | end 43 | 44 | # INPUT: ParamsOfFetchNextMonitorResults 45 | # queue: String - # # Name of the monitoring queue. 46 | # wait_mode: MonitorFetchWaitMode - # # Wait mode. # # Default is `NO_WAIT`. 47 | # RESPONSE: ResultOfFetchNextMonitorResults 48 | # results: Array - # # List of the resolved results. 49 | # Async 50 | def fetch_next_monitor_results(payload, &block) 51 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 52 | end 53 | 54 | # Sync 55 | def fetch_next_monitor_results_sync(payload) 56 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 57 | end 58 | 59 | # INPUT: ParamsOfCancelMonitor 60 | # queue: String - # # Name of the monitoring queue. 61 | # Async 62 | def cancel_monitor(payload, &block) 63 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 64 | end 65 | 66 | # Sync 67 | def cancel_monitor_sync(payload) 68 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 69 | end 70 | 71 | # INPUT: ParamsOfSendMessages 72 | # messages: Array - # # Messages that must be sent to the blockchain. 73 | # monitor_queue: String - # # Optional message monitor queue that starts monitoring for the processing results for sent messages. 74 | # RESPONSE: ResultOfSendMessages 75 | # messages: Array - # # Messages that was sent to the blockchain for execution. 76 | # Async 77 | def send_messages(payload, &block) 78 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 79 | end 80 | 81 | # Sync 82 | def send_messages_sync(payload) 83 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 84 | end 85 | 86 | # INPUT: ParamsOfSendMessage 87 | # message: String - # # Message BOC. 88 | # abi: Value - # # Optional message ABI. # # If this parameter is specified and the message has the`expire` header then expiration time will be checked againstthe current time to prevent unnecessary sending of already expired message. 89 | # The `message already expired` error will be returned in thiscase. 90 | # Note, that specifying `abi` for ABI compliant contracts isstrongly recommended, so that proper processing strategy can bechosen. 91 | # send_events: Boolean - # # Flag for requesting events sending 92 | # RESPONSE: ResultOfSendMessage 93 | # shard_block_id: String - # # The last generated shard block of the message destination account before the message was sent. # # This block id must be used as a parameter of the`wait_for_transaction`. 94 | # sending_endpoints: Array - # # The list of endpoints to which the message was sent. # # This list id must be used as a parameter of the`wait_for_transaction`. 95 | # Async 96 | def send_message(payload, &block) 97 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 98 | end 99 | 100 | # Sync 101 | def send_message_sync(payload) 102 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 103 | end 104 | 105 | # INPUT: ParamsOfWaitForTransaction 106 | # abi: Value - # # Optional ABI for decoding the transaction result. # # If it is specified, then the output messages' bodies will bedecoded according to this ABI. 107 | # The `abi_decoded` result field will be filled out. 108 | # message: String - # # Message BOC. # # Encoded with `base64`. 109 | # shard_block_id: String - # # The last generated block id of the destination account shard before the message was sent. # # You must provide the same value as the `send_message` has returned. 110 | # send_events: Boolean - # # Flag that enables/disables intermediate events 111 | # sending_endpoints: Array - # # The list of endpoints to which the message was sent. # # Use this field to get more informative errors. 112 | # Provide the same value as the `send_message` has returned. 113 | # If the message was not delivered (expired), SDK will log the endpoint URLs, used for its sending. 114 | # RESPONSE: ResultOfProcessMessage 115 | # transaction: Value - # # Parsed transaction. # # In addition to the regular transaction fields there is a`boc` field encoded with `base64` which contains sourcetransaction BOC. 116 | # out_messages: Array - # # List of output messages' BOCs. # # Encoded as `base64` 117 | # decoded: DecodedOutput - # # Optional decoded message bodies according to the optional `abi` parameter. 118 | # fees: TransactionFees - # # Transaction fees 119 | # Async 120 | def wait_for_transaction(payload, &block) 121 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 122 | end 123 | 124 | # Sync 125 | def wait_for_transaction_sync(payload) 126 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 127 | end 128 | 129 | # INPUT: ParamsOfProcessMessage 130 | # message_encode_params: ParamsOfEncodeMessage - # # Message encode parameters. 131 | # send_events: Boolean - # # Flag for requesting events sending 132 | # RESPONSE: ResultOfProcessMessage 133 | # transaction: Value - # # Parsed transaction. # # In addition to the regular transaction fields there is a`boc` field encoded with `base64` which contains sourcetransaction BOC. 134 | # out_messages: Array - # # List of output messages' BOCs. # # Encoded as `base64` 135 | # decoded: DecodedOutput - # # Optional decoded message bodies according to the optional `abi` parameter. 136 | # fees: TransactionFees - # # Transaction fees 137 | # Async 138 | def process_message(payload, &block) 139 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 140 | end 141 | 142 | # Sync 143 | def process_message_sync(payload) 144 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 145 | end 146 | 147 | end 148 | end 149 | 150 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Proofs.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Proofs 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfProofBlockData 17 | # block: Value - # # 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. 18 | # Async 19 | def proof_block_data(payload, &block) 20 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 21 | end 22 | 23 | # Sync 24 | def proof_block_data_sync(payload) 25 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 26 | end 27 | 28 | # INPUT: ParamsOfProofTransactionData 29 | # transaction: Value - # # 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. 30 | # Async 31 | def proof_transaction_data(payload, &block) 32 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 33 | end 34 | 35 | # Sync 36 | def proof_transaction_data_sync(payload) 37 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 38 | end 39 | 40 | # INPUT: ParamsOfProofMessageData 41 | # message: Value - # # 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`. 42 | # Async 43 | def proof_message_data(payload, &block) 44 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 45 | end 46 | 47 | # Sync 48 | def proof_message_data_sync(payload) 49 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 50 | end 51 | 52 | end 53 | end 54 | 55 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Tvm.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Tvm 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfRunExecutor 17 | # message: String - # # Input message BOC. # # Must be encoded as base64. 18 | # account: AccountForExecutor - # # Account to run on executor 19 | # execution_options: ExecutionOptions - # # Execution options. 20 | # abi: Value - # # Contract ABI for decoding output messages 21 | # skip_transaction_check: Boolean - # # Skip transaction check flag 22 | # boc_cache: BocCacheType - # # Cache type to put the result. # # The BOC itself returned if no cache type provided 23 | # return_updated_account: Boolean - # # Return updated account flag. # # Empty string is returned if the flag is `false` 24 | # RESPONSE: ResultOfRunExecutor 25 | # transaction: Value - # # Parsed transaction. # # In addition to the regular transaction fields there is a`boc` field encoded with `base64` which contains sourcetransaction BOC. 26 | # out_messages: Array - # # List of output messages' BOCs. # # Encoded as `base64` 27 | # decoded: DecodedOutput - # # Optional decoded message bodies according to the optional `abi` parameter. 28 | # account: String - # # Updated account state BOC. # # Encoded as `base64` 29 | # fees: TransactionFees - # # Transaction fees 30 | # Async 31 | def run_executor(payload, &block) 32 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 33 | end 34 | 35 | # Sync 36 | def run_executor_sync(payload) 37 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 38 | end 39 | 40 | # INPUT: ParamsOfRunTvm 41 | # message: String - # # Input message BOC. # # Must be encoded as base64. 42 | # account: String - # # Account BOC. # # Must be encoded as base64. 43 | # execution_options: ExecutionOptions - # # Execution options. 44 | # abi: Value - # # Contract ABI for decoding output messages 45 | # boc_cache: BocCacheType - # # Cache type to put the result. # # The BOC itself returned if no cache type provided 46 | # return_updated_account: Boolean - # # Return updated account flag. # # Empty string is returned if the flag is `false` 47 | # RESPONSE: ResultOfRunTvm 48 | # out_messages: Array - # # List of output messages' BOCs. # # Encoded as `base64` 49 | # decoded: DecodedOutput - # # Optional decoded message bodies according to the optional `abi` parameter. 50 | # account: String - # # Updated account state BOC. # # Encoded as `base64`. Attention! Only `account_state.storage.state.data` part of the BOC is updated. 51 | # Async 52 | def run_tvm(payload, &block) 53 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 54 | end 55 | 56 | # Sync 57 | def run_tvm_sync(payload) 58 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 59 | end 60 | 61 | # INPUT: ParamsOfRunGet 62 | # account: String - # # Account BOC in `base64` 63 | # function_name: String - # # Function name 64 | # input: Value - # # Input parameters 65 | # execution_options: ExecutionOptions - # # Execution options 66 | # tuple_list_as_array: Boolean - # # Convert lists based on nested tuples in the **result** into plain arrays. # # 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. 67 | # This may happen, for example, when elector contract contains too many participants 68 | # RESPONSE: ResultOfRunGet 69 | # output: Value - # # Values returned by get-method on stack 70 | # Async 71 | def run_get(payload, &block) 72 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 73 | end 74 | 75 | # Sync 76 | def run_get_sync(payload) 77 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 78 | end 79 | 80 | end 81 | end 82 | 83 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Client/Utils.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | class Utils 4 | include CommonInstanceHelpers 5 | 6 | attr_reader :context, :request_id, :requests, :monitor 7 | MODULE = self.to_s.downcase.gsub(/^(.+::|)(\w+)$/, '\2').freeze 8 | 9 | def initialize(context: nil, request_id: nil, requests: nil, monitor: nil) 10 | @context = context 11 | @request_id = request_id 12 | @requests = requests 13 | @monitor = monitor 14 | end 15 | 16 | # INPUT: ParamsOfConvertAddress 17 | # address: String - # # Account address in any TON format. 18 | # output_format: AddressStringFormat - # # Specify the format to convert to. 19 | # RESPONSE: ResultOfConvertAddress 20 | # address: String - # # Address in the specified format 21 | # Async 22 | def convert_address(payload, &block) 23 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 24 | end 25 | 26 | # Sync 27 | def convert_address_sync(payload) 28 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 29 | end 30 | 31 | # INPUT: ParamsOfGetAddressType 32 | # address: String - # # Account address in any TON format. 33 | # RESPONSE: ResultOfGetAddressType 34 | # address_type: AccountAddressType - # # Account address type. 35 | # Async 36 | def get_address_type(payload, &block) 37 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 38 | end 39 | 40 | # Sync 41 | def get_address_type_sync(payload) 42 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 43 | end 44 | 45 | # INPUT: ParamsOfCalcStorageFee 46 | # account: String - 47 | # period: Number - 48 | # RESPONSE: ResultOfCalcStorageFee 49 | # fee: String - 50 | # Async 51 | def calc_storage_fee(payload, &block) 52 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 53 | end 54 | 55 | # Sync 56 | def calc_storage_fee_sync(payload) 57 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 58 | end 59 | 60 | # INPUT: ParamsOfCompressZstd 61 | # uncompressed: String - # # Uncompressed data. # # Must be encoded as base64. 62 | # level: Number - # # 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`). 63 | # RESPONSE: ResultOfCompressZstd 64 | # compressed: String - # # Compressed data. # # Must be encoded as base64. 65 | # Async 66 | def compress_zstd(payload, &block) 67 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 68 | end 69 | 70 | # Sync 71 | def compress_zstd_sync(payload) 72 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 73 | end 74 | 75 | # INPUT: ParamsOfDecompressZstd 76 | # compressed: String - # # Compressed data. # # Must be encoded as base64. 77 | # RESPONSE: ResultOfDecompressZstd 78 | # decompressed: String - # # Decompressed data. # # Must be encoded as base64. 79 | # Async 80 | def decompress_zstd(payload, &block) 81 | TonBinding.requestLibrary(context: context, request_id: request_id, requests: requests, monitor: monitor, method_name: full_method_name(MODULE, __method__.to_s), payload: payload, &block) 82 | end 83 | 84 | # Sync 85 | def decompress_zstd_sync(payload) 86 | TonBinding.send_request_sync(context: context, method_name: full_method_name(MODULE, __method__.to_s).sub(/_sync$/, ''), payload: payload) 87 | end 88 | 89 | end 90 | end 91 | 92 | -------------------------------------------------------------------------------- /lib/everscale-client-ruby/Helpers/CommonHelpers.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | 3 | def self.read_abi(path_to_file) 4 | file = File.read(path_to_file) 5 | JSON.parse(file) 6 | end 7 | 8 | def self.read_tvc(path_to_file) 9 | data = File.open(path_to_file).read 10 | # Encode the puppy 11 | encoded = Base64.encode64(data) 12 | # Spit it out into one continous string 13 | encoded.gsub(/\n/, '') 14 | end 15 | 16 | def self.callLibraryMethodSync(method, *args) 17 | responses = [] 18 | mutex = Monitor.new 19 | condition = mutex.new_cond 20 | 21 | method.call(*args) do |response| 22 | mutex.synchronize do 23 | responses << response 24 | if response.finished == true 25 | condition.signal 26 | end 27 | end 28 | end 29 | 30 | mutex.synchronize do 31 | condition.wait 32 | end 33 | 34 | yield(responses.map{ |resp| resp if (resp.result || resp.error) }.compact) if block_given? 35 | end 36 | 37 | class RequestId 38 | include MonitorMixin 39 | 40 | def initialize 41 | super 42 | synchronize { @value = 1 } 43 | end 44 | 45 | def increment 46 | synchronize { @value += 1} 47 | end 48 | 49 | def value 50 | synchronize { @value } 51 | end 52 | end 53 | 54 | class Requests 55 | include MonitorMixin 56 | 57 | def initialize 58 | super 59 | synchronize { @value = {} } 60 | end 61 | 62 | def []=(key, value) 63 | synchronize { @value[key] = value } 64 | end 65 | 66 | def [](key) 67 | synchronize { @value[key] } 68 | end 69 | 70 | def delete(key) 71 | synchronize { @value.delete(key) } 72 | end 73 | end 74 | end 75 | 76 | module CommonClassHelpers 77 | 78 | def class_attr_accessor(*names) 79 | names.each do |name| 80 | class_variable_set("@@#{name.to_s}", nil) 81 | 82 | define_singleton_method("#{name.to_s}=".to_sym) do |attr| 83 | class_variable_set("@@#{name.to_s}", attr) 84 | end 85 | 86 | define_singleton_method(name.to_sym) do 87 | class_variable_get("@@#{name.to_s}") 88 | end 89 | end 90 | end 91 | 92 | end 93 | 94 | 95 | module CommonInstanceHelpers 96 | 97 | def full_method_name(module_name, method_name) 98 | "#{module_name}.#{method_name}" 99 | end 100 | 101 | def base64?(value) 102 | value.is_a?(String) && (Base64.encode64(Base64.decode64(value)).strip == value) 103 | end 104 | 105 | def encode_to_base64(message) 106 | Base64.encode64(message.force_encoding('UTF-8')).strip 107 | end 108 | end 109 | 110 | class << Object 111 | def private_accessor(*names) 112 | names.each do |name| 113 | attr_accessor name 114 | private "#{name}=" 115 | end 116 | end 117 | end -------------------------------------------------------------------------------- /lib/everscale-client-ruby/version.rb: -------------------------------------------------------------------------------- 1 | module TonClient 2 | VERSION = "1.1.78" 3 | end 4 | 5 | -------------------------------------------------------------------------------- /release.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | LIB_NAME = 'everscale-client-ruby' 4 | 5 | script_file_path = File.expand_path(File.dirname(__FILE__)) 6 | GEM_DIR = "#{script_file_path}" 7 | 8 | version_file = "#{GEM_DIR}/lib/#{LIB_NAME}/version.rb" 9 | file = File.read(version_file) 10 | 11 | p 'check version' 12 | if file[/VERSION = "(\d+)\.(\d+)\.(\d+)"/] 13 | major = $1 14 | minor = $2 15 | current = $3 16 | version = "#{major}.#{minor}.#{current.to_i + 1}" 17 | p version 18 | data = file 19 | data.gsub!(/VERSION\s+=[\s\S]+?$/, "VERSION = \"#{version}\"") 20 | p data 21 | p version_file 22 | p 'update version' 23 | 24 | puts "make release? Y/N" 25 | File.open(version_file, 'wb') { |f| f.write(data) } 26 | option = gets 27 | if option.strip.downcase == 'y' 28 | system(%{cd #{GEM_DIR} && git add .}) 29 | system(%{cd #{GEM_DIR} && git commit -m 'version #{version}'}) 30 | system(%{cd #{GEM_DIR} && bash -lc 'rake release'}) 31 | end 32 | end 33 | 34 | 35 | -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/Events.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/Events.tvc -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/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 | } -------------------------------------------------------------------------------- /spec/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 | } -------------------------------------------------------------------------------- /spec/Fixtures/abi/GiverNodeSE_v2.keys.json: -------------------------------------------------------------------------------- 1 | { 2 | "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", 3 | "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3" 4 | } -------------------------------------------------------------------------------- /spec/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 | } -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/Hello.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/Hello.tvc -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/LimitWallet.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/LimitWallet.tvc -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/Piggy.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/Piggy.tvc -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/Subscription.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/Subscription.tvc -------------------------------------------------------------------------------- /spec/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 | -------------------------------------------------------------------------------- /spec/Fixtures/abi/Wallet.tvc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nerzh/everscale-client-ruby/e4b88f79be44de63ae1a8cff205962b7710fdfb6/spec/Fixtures/abi/Wallet.tvc -------------------------------------------------------------------------------- /spec/all.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | require 'client' 4 | # require 'binding' 5 | require 'crypto' 6 | require 'abi' 7 | require 'boc' 8 | require 'utils' 9 | 10 | require 'crypto' 11 | require 'net' 12 | require 'tvm' 13 | require 'processing' -------------------------------------------------------------------------------- /spec/binding.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | 5 | describe TonClient::TonBinding do 6 | before(:all) do 7 | TonClient.configure { |config| config.ffi_lib(env['spec_ffi']) } 8 | config = TonClient::TonBinding.make_string('{}') 9 | @context = TonClient::TonBinding.tc_create_context(config) 10 | @id = TonClient::TonBinding.read_string_to_hash(@context)['result'] 11 | end 12 | 13 | it 'tc_create_context + read_string + read_string_to_hash' do 14 | config = TonClient::TonBinding.make_string('{}') 15 | context = TonClient::TonBinding.tc_create_context(config) 16 | result = TonClient::TonBinding.read_string_to_hash(context) 17 | expect(result['result']).to be_a(Integer) 18 | end 19 | 20 | it 'tc_destroy_context' do 21 | config = TonClient::TonBinding.make_string('{}') 22 | context = TonClient::TonBinding.tc_create_context(config) 23 | result = TonClient::TonBinding.read_string_to_hash(context) 24 | expect(TonClient::TonBinding.tc_destroy_context(result['result'])).to be_a(nil.class) 25 | end 26 | 27 | it 'make_string' do 28 | word = "Hello" 29 | result = TonClient::TonBinding.make_string(word) 30 | expect(result[:len]).to eq(word.bytesize) 31 | expect(result[:content].read_string(word.bytesize)).to eq("Hello") 32 | end 33 | 34 | it 'read_string_to_hash' do 35 | config = TonClient::TonBinding.make_string('{}') 36 | context = TonClient::TonBinding.tc_create_context(config) 37 | result = TonClient::TonBinding.read_string_to_hash(context) 38 | expect(result).to be_a(Hash) 39 | end 40 | 41 | it 'tc_request_sync' do 42 | method_name = TonClient::TonBinding.make_string('client.version') 43 | payload = TonClient::TonBinding.make_string('{}') 44 | result = TonClient::TonBinding.tc_request_sync(@id, method_name, payload) 45 | # expect(result).to be_a(TonClient::TonBinding::TcStringHandleT) 46 | expect(result).to be_a(FFI::Pointer) 47 | end 48 | 49 | it 'async tc_request' do 50 | payload = TonClient::TonBinding.make_string('{}') 51 | method_name = TonClient::TonBinding.make_string('client.version') 52 | queue = Queue.new 53 | TonClient::TonBinding.tc_request(@id, method_name, payload, 999) do |request_id, data, response_type, finished| 54 | queue.push request_id 55 | queue.push data 56 | queue.push response_type 57 | queue.push finished 58 | end 59 | request_id = queue.pop 60 | data = queue.pop 61 | response_type = queue.pop 62 | finished = queue.pop 63 | 64 | expect(request_id).to eq(999) 65 | expect(data).to be_a(TonClient::TonBinding::TcStringDataT) 66 | expect(response_type).to be_a(0.class) 67 | expect(finished == finished).to be_a(true.class) 68 | end 69 | 70 | it 'async requestLibrary' do 71 | request_id = Concurrent::AtomicFixnum.new(1) 72 | requests = Concurrent::Hash.new() 73 | queue = Queue.new 74 | TonClient::TonBinding.requestLibrary(context: @id, request_id: request_id, requests: requests, method_name: 'client.version', payload: {}) do |response| 75 | queue.push response 76 | end 77 | response = queue.pop 78 | 79 | expect(response.result["version"].class).to eq(String) 80 | expect(response.error).to be_a(nil.class) 81 | expect(response.custom_response).to be_a(nil.class) 82 | end 83 | end 84 | 85 | -------------------------------------------------------------------------------- /spec/client.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | 5 | describe TonClient::Client do 6 | before(:all) do 7 | @client = make_client 8 | end 9 | 10 | it 'check version' do 11 | callLibraryMethodSync(@client.method(:version)) do |response| 12 | p response.first.result['version'] 13 | expect(response.first.result['version']).to be_a(String) 14 | end 15 | end 16 | 17 | it 'create client' do 18 | client = TonClient.create(config: {network: {server_address: "net.ton.dev"}}) 19 | expect(client.context).to be_a(0.class) 20 | end 21 | 22 | it 'get_api_reference' do 23 | callLibraryMethodSync(@client.method(:get_api_reference)) do |response| 24 | expect(response.first.result['api']).to be_a(Hash) 25 | end 26 | end 27 | end 28 | 29 | -------------------------------------------------------------------------------- /spec/context.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | 5 | describe TonClient::Context do 6 | before(:all) do 7 | TonClient.configure { |config| config.ffi_lib(env['spec_ffi']) } 8 | end 9 | 10 | it 'create context' do 11 | context = TonClient::Context.new 12 | expect(context.id).to be_a(0.class) 13 | end 14 | 15 | it 'destroy context' do 16 | context = TonClient::Context.new 17 | expect(context.destroy).to be_a(nil.class) 18 | end 19 | end 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /spec/crypto.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | describe TonClient::Crypto do 5 | before(:all) do 6 | @client = make_client 7 | end 8 | 9 | it 'factorize' do 10 | payload = {composite: '17ED48941A08F981'} 11 | callLibraryMethodSync(@client.crypto.method(:factorize), payload) do |response| 12 | expect(response.first.result['factors']).to eq(["494C553B", "53911073"]) 13 | end 14 | end 15 | 16 | it 'modular_power' do 17 | payload = {base: '0123456789ABCDEF', exponent: '0123', modulus: '01234567'} 18 | callLibraryMethodSync(@client.crypto.method(:modular_power), payload) do |response| 19 | expect(response.first.result['modular_power']).to eq('63bfdf') 20 | end 21 | end 22 | 23 | it 'ton_crc16' do 24 | payload = {data: 'MHgzMSAweDMyIDB4MzMgMHgzNCAweDM1IDB4MzYgMHgzNyAweDM4IDB4Mzk='} 25 | callLibraryMethodSync(@client.crypto.method(:ton_crc16), payload) do |response| 26 | expect(response.first.result['crc']).to eq(63574) 27 | end 28 | end 29 | 30 | it 'generate_random_bytes' do 31 | payload = {length: 32} 32 | callLibraryMethodSync(@client.crypto.method(:generate_random_bytes), payload) do |response| 33 | expect(response.first.result['bytes'].size).to eq(44) 34 | end 35 | end 36 | 37 | it 'convert_public_key_to_ton_safe_format' do 38 | payload = {public_key: 'd007e112febb206f0871e6b135fb2047ad58e77329035457c0e8b7dfc110294a'} 39 | callLibraryMethodSync(@client.crypto.method(:convert_public_key_to_ton_safe_format), payload) do |response| 40 | expect(response.first.result['ton_public_key']).to eq('PubQB-ES_rsgbwhx5rE1-yBHrVjncykDVFfA6LffwRApSsiQ') 41 | end 42 | end 43 | 44 | it 'generate_random_sign_keys' do 45 | callLibraryMethodSync(@client.crypto.method(:generate_random_sign_keys)) do |response| 46 | expect(response.first.result['public']).to be_a(String) 47 | expect(response.first.result['secret']).to be_a(String) 48 | expect(response.first.result['public'].size).to eq(64) 49 | expect(response.first.result['secret'].size).to eq(64) 50 | end 51 | end 52 | 53 | it 'sign' do 54 | payload = {unsigned: encode_to_base64("Hello"), keys: {"public"=>"a5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661", "secret"=>"254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bb"}} 55 | callLibraryMethodSync(@client.crypto.method(:sign), payload) do |response| 56 | expect(response.first.result['signed']).to eq('JvgdakMHpOdw7PKJX/IMQDygYJxt/kzEge0ebJHXx7H8eUOYMcL7sN0YBfwP/QZ0Z8XpffpyDJdwLpTErtnCDEhlbGxv') 57 | expect(response.first.result['signature']).to eq('26f81d6a4307a4e770ecf2895ff20c403ca0609c6dfe4cc481ed1e6c91d7c7b1fc79439831c2fbb0dd1805fc0ffd067467c5e97dfa720c97702e94c4aed9c20c') 58 | end 59 | end 60 | 61 | it 'verify_signature' do 62 | payload = {signed: 'JvgdakMHpOdw7PKJX/IMQDygYJxt/kzEge0ebJHXx7H8eUOYMcL7sN0YBfwP/QZ0Z8XpffpyDJdwLpTErtnCDEhlbGxv', public: 'a5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661'} 63 | callLibraryMethodSync(@client.crypto.method(:verify_signature), payload) do |response| 64 | expect(response.first.result['unsigned']).to eq('SGVsbG8=') 65 | end 66 | end 67 | 68 | it 'sha256' do 69 | payload = {data: encode_to_base64('hello')} 70 | callLibraryMethodSync(@client.crypto.method(:sha256), payload) do |response| 71 | expect(response.first.result['hash']).to eq('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824') 72 | end 73 | end 74 | 75 | it 'sha512' do 76 | payload = {data: encode_to_base64('hello')} 77 | callLibraryMethodSync(@client.crypto.method(:sha512), payload) do |response| 78 | expect(response.first.result['hash']).to eq('9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043') 79 | end 80 | end 81 | 82 | it 'scrypt' do 83 | payload = { 84 | password: encode_to_base64('Test Password'), 85 | salt: encode_to_base64('Test Salt'), 86 | log_n: 5, 87 | r: 4, 88 | p: 8, 89 | dk_len: 32 90 | } 91 | callLibraryMethodSync(@client.crypto.method(:scrypt), payload) do |response| 92 | expect(response.first.result['key']).to eq('7cc741fa9cb4eb1edd36629e224e9cc8c316810ac540e4eb9ba578ff1643a3b9') 93 | end 94 | end 95 | 96 | it 'nacl_sign_keypair_from_secret_key' do 97 | payload = {secret: '254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bb'} 98 | callLibraryMethodSync(@client.crypto.method(:nacl_sign_keypair_from_secret_key), payload) do |response| 99 | expect(response.first.result['public']).to eq('a5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661') 100 | expect(response.first.result['secret']).to eq('254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bba5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661') 101 | end 102 | end 103 | 104 | it 'nacl_sign' do 105 | payload = { 106 | unsigned: encode_to_base64('Hello'), 107 | secret: '254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bba5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661' 108 | } 109 | callLibraryMethodSync(@client.crypto.method(:nacl_sign), payload) do |response| 110 | expect(response.first.result['signed']).to eq('JvgdakMHpOdw7PKJX/IMQDygYJxt/kzEge0ebJHXx7H8eUOYMcL7sN0YBfwP/QZ0Z8XpffpyDJdwLpTErtnCDEhlbGxv') 111 | end 112 | end 113 | 114 | it 'nacl_sign_open' do 115 | payload = { 116 | signed: 'JvgdakMHpOdw7PKJX/IMQDygYJxt/kzEge0ebJHXx7H8eUOYMcL7sN0YBfwP/QZ0Z8XpffpyDJdwLpTErtnCDEhlbGxv', 117 | public: 'a5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661' 118 | } 119 | callLibraryMethodSync(@client.crypto.method(:nacl_sign_open), payload) do |response| 120 | expect(response.first.result['unsigned']).to eq('SGVsbG8=') 121 | end 122 | end 123 | 124 | it 'nacl_sign_detached' do 125 | payload = { 126 | unsigned: encode_to_base64('Hello'), 127 | secret: '254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bba5c367411a00ab0b542d118649de388b43ce4b7fa6dae2bb9243c6ad9aca7661' 128 | } 129 | callLibraryMethodSync(@client.crypto.method(:nacl_sign_detached), payload) do |response| 130 | expect(response.first.result['signature']).to eq('26f81d6a4307a4e770ecf2895ff20c403ca0609c6dfe4cc481ed1e6c91d7c7b1fc79439831c2fbb0dd1805fc0ffd067467c5e97dfa720c97702e94c4aed9c20c') 131 | end 132 | end 133 | 134 | it 'nacl_box_keypair' do 135 | callLibraryMethodSync(@client.crypto.method(:nacl_box_keypair)) do |response| 136 | expect(response.first.result['public']).to be_a(String) 137 | expect(response.first.result['secret']).to be_a(String) 138 | expect(response.first.result['public'].size).to eq(64) 139 | expect(response.first.result['secret'].size).to eq(64) 140 | end 141 | end 142 | 143 | it 'nacl_box_keypair_from_secret_key' do 144 | payload = { 145 | secret: '254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bb' 146 | } 147 | callLibraryMethodSync(@client.crypto.method(:nacl_box_keypair_from_secret_key), payload) do |response| 148 | expect(response.first.result['public']).to eq('57172b0bd70f4bc65bb8a82bd0926a1a3f8f471e16fd9d8f329bec976afe3454') 149 | expect(response.first.result['secret']).to eq('254c097277e9dd09d16152ee85abde4be54030db9930e38bf7069e4684ac10bb') 150 | end 151 | end 152 | 153 | it 'nacl_box' do 154 | payload = { 155 | decrypted: encode_to_base64('Test Message'), 156 | nonce: 'cd7f99924bf422544046e83595dd5803f17536f5c9a11746', 157 | their_public: 'c4e2d9fe6a6baf8d1812b799856ef2a306291be7a7024837ad33a8530db79c6b', 158 | secret: 'd9b9dc5033fb416134e5d2107fdbacab5aadb297cb82dbdcd137d663bac59f7f' 159 | } 160 | callLibraryMethodSync(@client.crypto.method(:nacl_box), payload) do |response| 161 | expect(response.first.result['encrypted']).to eq('li4XED4kx/pjQ2qdP0eR2d/K30uN94voNADxwA==') 162 | end 163 | end 164 | 165 | it 'nacl_box_open' do 166 | payload = { 167 | encrypted: 'li4XED4kx/pjQ2qdP0eR2d/K30uN94voNADxwA==', 168 | nonce: 'cd7f99924bf422544046e83595dd5803f17536f5c9a11746', 169 | their_public: 'c4e2d9fe6a6baf8d1812b799856ef2a306291be7a7024837ad33a8530db79c6b', 170 | secret: 'd9b9dc5033fb416134e5d2107fdbacab5aadb297cb82dbdcd137d663bac59f7f' 171 | } 172 | callLibraryMethodSync(@client.crypto.method(:nacl_box_open), payload) do |response| 173 | expect(Base64.decode64(response.first.result['decrypted'])).to eq('Test Message') 174 | end 175 | end 176 | 177 | it 'nacl_secret_box' do 178 | payload = { 179 | decrypted: encode_to_base64('Test Message'), 180 | nonce: '2a33564717595ebe53d91a785b9e068aba625c8453a76e45', 181 | key: '8f68445b4e78c000fe4d6b7fc826879c1e63e3118379219a754ae66327764bd8' 182 | } 183 | callLibraryMethodSync(@client.crypto.method(:nacl_secret_box), payload) do |response| 184 | expect(response.first.result['encrypted']).to eq('JL7ejKWe2KXmrsns41yfXoQF0t/C1Q8RGyzQ2A==') 185 | end 186 | end 187 | 188 | it 'nacl_secret_box_open' do 189 | payload = { 190 | encrypted: 'JL7ejKWe2KXmrsns41yfXoQF0t/C1Q8RGyzQ2A==', 191 | nonce: '2a33564717595ebe53d91a785b9e068aba625c8453a76e45', 192 | key: '8f68445b4e78c000fe4d6b7fc826879c1e63e3118379219a754ae66327764bd8' 193 | } 194 | callLibraryMethodSync(@client.crypto.method(:nacl_secret_box_open), payload) do |response| 195 | expect(Base64.decode64(response.first.result['decrypted'])).to eq('Test Message') 196 | end 197 | end 198 | 199 | it 'mnemonic_words' do 200 | callLibraryMethodSync(@client.crypto.method(:mnemonic_words), {dictionary: 1}) do |response| 201 | expect(response.first.result['words'].split(' ').size).to eq(2048) 202 | end 203 | end 204 | 205 | it 'mnemonic_from_random' do 206 | payload = { 207 | dictionary: 1, # English 208 | word_count: 12 209 | } 210 | callLibraryMethodSync(@client.crypto.method(:mnemonic_from_random), payload) do |response| 211 | expect(response.first.result['phrase'].split(' ').size).to eq(12) 212 | end 213 | end 214 | 215 | it 'mnemonic_from_entropy' do 216 | payload = { 217 | entropy: '00112233445566778899AABBCCDDEEFF', 218 | dictionary: 1, # English 219 | word_count: 12 220 | } 221 | callLibraryMethodSync(@client.crypto.method(:mnemonic_from_entropy), payload) do |response| 222 | expect(response.first.result['phrase'].split(' ').size).to eq(12) 223 | end 224 | end 225 | 226 | it 'mnemonic_verify' do 227 | payload = { 228 | phrase: 'abandon math mimic master filter design carbon crystal rookie group knife young', 229 | dictionary: 1, 230 | word_count: 12 231 | } 232 | callLibraryMethodSync(@client.crypto.method(:mnemonic_verify), payload) do |response| 233 | expect(response.first.result['valid']).to eq(true) 234 | end 235 | end 236 | 237 | it 'mnemonic_derive_sign_keys' do 238 | payload = { 239 | phrase: 'abandon math mimic master filter design carbon crystal rookie group knife young', 240 | dictionary: 1, 241 | word_count: 12 242 | } 243 | callLibraryMethodSync(@client.crypto.method(:mnemonic_derive_sign_keys), payload) do |response| 244 | expect(response.first.result['public']).to eq('61c3c5b97a33c9c0a03af112fbb27e3f44d99e1f804853f9842bb7a6e5de3ff9') 245 | expect(response.first.result['secret']).to eq('832410564fbe7b1301cf48dc83cbb8a3008d3cf29e05b7457086d4de041030ea') 246 | end 247 | end 248 | 249 | it 'hdkey_xprv_from_mnemonic' do 250 | payload = { 251 | phrase: 'abandon math mimic master filter design carbon crystal rookie group knife young' 252 | } 253 | callLibraryMethodSync(@client.crypto.method(:hdkey_xprv_from_mnemonic), payload) do |response| 254 | expect(response.first.result['xprv']).to eq('xprv9s21ZrQH143K3M3Auzg5wmEcKzsVbpE9PdPam5QVjW76rZ59Cw8oTg2kEqFJkNx917D8opVbuuz2jTCUtfrB7oEHU99zmnGDtPggrXNSQHB') 255 | end 256 | end 257 | 258 | it 'hdkey_derive_from_xprv_path' do 259 | payload = { 260 | xprv: 'xprv9s21ZrQH143K3M3Auzg5wmEcKzsVbpE9PdPam5QVjW76rZ59Cw8oTg2kEqFJkNx917D8opVbuuz2jTCUtfrB7oEHU99zmnGDtPggrXNSQHB', 261 | path: "m/44'/396'/0'/0/0" 262 | } 263 | callLibraryMethodSync(@client.crypto.method(:hdkey_derive_from_xprv_path), payload) do |response| 264 | expect(response.first.result['xprv']).to eq('xprvA3SdNsXH8HLYpps7fxXtHBSeNfGUH59ReuhXbtCx9VJUFAWaqjpuwV91xu5LFQoHgAt3KNQ8wotGq6W4P2eXaS2VVaN1xPwWzAxYnRcDBPr') 265 | end 266 | end 267 | 268 | it 'hdkey_secret_from_xprv' do 269 | payload = { 270 | xprv: 'xprv9s21ZrQH143K3M3Auzg5wmEcKzsVbpE9PdPam5QVjW76rZ59Cw8oTg2kEqFJkNx917D8opVbuuz2jTCUtfrB7oEHU99zmnGDtPggrXNSQHB' 271 | } 272 | callLibraryMethodSync(@client.crypto.method(:hdkey_secret_from_xprv), payload) do |response| 273 | expect(response.first.result['secret']).to eq('1d2037d1adbd40ccf99d44e7073a9d8e32e5675ee053a2fd1c078ef9e05a807d') 274 | end 275 | end 276 | 277 | it 'hdkey_public_from_xprv' do 278 | payload = { 279 | xprv: 'xprv9s21ZrQH143K3M3Auzg5wmEcKzsVbpE9PdPam5QVjW76rZ59Cw8oTg2kEqFJkNx917D8opVbuuz2jTCUtfrB7oEHU99zmnGDtPggrXNSQHB' 280 | } 281 | callLibraryMethodSync(@client.crypto.method(:hdkey_public_from_xprv), payload) do |response| 282 | expect(response.first.result['public']).to eq('01709823c5ada7fdede9b6a0f7f388eda0c29a54ead5ae90ede3b5baaeb242e3') 283 | end 284 | end 285 | end 286 | 287 | 288 | -------------------------------------------------------------------------------- /spec/net.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'byebug' 3 | 4 | 5 | describe TonClient::Net do 6 | before(:all) do 7 | @client = make_client 8 | end 9 | 10 | it 'query_collection' do 11 | payload = { 12 | collection: "messages", 13 | filter: { created_at: {gt: 1562342740} }, 14 | result: "body created_at", 15 | order: nil, 16 | limit: nil 17 | } 18 | callLibraryMethodSync(@client.net.method(:query_collection), payload) do |response| 19 | expect(response.first.result['result'].first['created_at']).to be > 1562342740 20 | end 21 | end 22 | 23 | it 'wait_for_collection' do 24 | now = Time.now.to_i 25 | payload = {collection: "transactions", filter: {now: {gt: now}}, result: "id now", timeout: nil} 26 | Thread.new do 27 | sleep 2 28 | (1..5).each { get_grams_from_giver_sync(client: @client) } 29 | end 30 | callLibraryMethodSync(@client.net.method(:wait_for_collection), payload) do |response| 31 | expect(response.first.result['result']['now']).to be > now 32 | end 33 | end 34 | 35 | it 'subscribe_collection' do 36 | queue = Queue.new 37 | payload = {collection: "transactions", filter: nil, result: "id account_addr"} 38 | result = nil 39 | @client.net.subscribe_collection(payload) do |response| 40 | result = response.result 41 | queue.push 1 42 | end 43 | queue.pop 44 | expect(result['handle'].class).to be(Integer) 45 | # unsubscribe 46 | @client.net.unsubscribe({handle: result['handle']}) do |response| 47 | queue.push 1 48 | end 49 | queue.pop 50 | end 51 | end 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /spec/processing.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | describe TonClient::Processing do 5 | before(:all) do 6 | p 'Processing' 7 | @client = make_client 8 | end 9 | 10 | it 'wait_for_transaction' do 11 | abi_name = "Events" 12 | abi = { type: 'Serialized', value: read_abi(abi_name) } 13 | tvc = read_tvc(abi_name) 14 | keys = generate_keys(@client) 15 | encoded_message = abiEncodeMessage( 16 | name_abi: abi_name, 17 | name_tvc: abi_name, 18 | address: nil, 19 | public_key: keys['public'], 20 | secret_key: keys['secret'], 21 | call_set_function_name: "constructor", 22 | call_set_header: {expire: nil, time: nil, pubkey: keys['public']}, 23 | call_set_input: nil 24 | ) 25 | 26 | positive_balance = get_grams_from_giver_sync(client: @client, account_address: encoded_message['address']) 27 | expect(positive_balance).to eq(true) 28 | 29 | params_of_send_message = {message: encoded_message['message'], abi: abi, send_events: true} 30 | result_of_send_message = nil 31 | callLibraryMethodSync(@client.processing.method(:send_message), params_of_send_message) do |response| 32 | result_of_send_message = response.first.result 33 | end 34 | 35 | params_of_wait_for_transaction = {abi: abi, message: encoded_message['message'], shard_block_id: result_of_send_message['shard_block_id'], send_events: true} 36 | callLibraryMethodSync(@client.processing.method(:wait_for_transaction), params_of_wait_for_transaction) do |response| 37 | expect(response.first.result['out_messages'].size).to eq(0) 38 | expect(response.first.result['decoded']).to eq({"out_messages" => [], "output" => nil}) 39 | end 40 | end 41 | 42 | it 'process_mesage' do 43 | abi_name = "Events" 44 | abi = { type: 'Serialized', value: read_abi(abi_name) } 45 | tvc = read_tvc(abi_name) 46 | keys = generate_keys(@client) 47 | result = abiEncodeMessage( 48 | name_abi: abi_name, 49 | name_tvc: abi_name, 50 | address: nil, 51 | public_key: keys['public'], 52 | secret_key: keys['secret'], 53 | call_set_function_name: "constructor", 54 | call_set_header: {expire: nil, time: nil, pubkey: keys['public']}, 55 | call_set_input: nil 56 | ) 57 | 58 | positive_balance = get_grams_from_giver_sync(client: @client, account_address: result['address']) 59 | expect(positive_balance).to eq(true) 60 | 61 | payload_encode_message = { 62 | abi: abi, 63 | address: nil, 64 | deploy_set: {tvc: tvc, workchain_id: nil, initial_data: nil}, 65 | call_set: {function_name: "constructor", header: {expire: nil, time: nil, pubkey: keys['public']}, input: nil}, 66 | signer: {type: 'Keys', public_key: nil, keys: keys, handle: nil}, 67 | processing_try_index: nil 68 | } 69 | payload_process_message = {message_encode_params: payload_encode_message, send_events: true} 70 | result_of_process_message = nil 71 | callLibraryMethodSync(@client.processing.method(:process_message), payload_process_message) do |response| 72 | expect(response.first.result['fees']['total_account_fees'].to_f).to be > 0 73 | expect(response.first.result['out_messages'].size).to eq(0) 74 | expect(response.first.result['decoded']).to eq({"out_messages" => [], "output" => nil}) 75 | end 76 | end 77 | end 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /spec/processing_sync.rb: -------------------------------------------------------------------------------- 1 | require 'sync_spec_helper' 2 | 3 | 4 | describe TonClient::Processing do 5 | before(:all) do 6 | p 'Processing' 7 | @client = make_client 8 | end 9 | 10 | it 'wait_for_transaction_sync' do 11 | abi_name = "Events" 12 | abi = { type: 'Serialized', value: read_abi(abi_name) } 13 | tvc = read_tvc(abi_name) 14 | keys = generate_keys(@client) 15 | encoded_message = abiEncodeMessage( 16 | name_abi: abi_name, 17 | name_tvc: abi_name, 18 | address: nil, 19 | public_key: keys['public'], 20 | secret_key: keys['secret'], 21 | call_set_function_name: "constructor", 22 | call_set_header: {expire: nil, time: nil, pubkey: keys['public']}, 23 | call_set_input: nil 24 | ) 25 | 26 | positive_balance = get_grams_from_giver_sync(client: @client, account_address: encoded_message['address']) 27 | expect(positive_balance).to eq(true) 28 | 29 | params_of_send_message = {message: encoded_message['message'], abi: abi, send_events: true} 30 | result_of_send_message = nil 31 | response = @client.processing.send_message_sync(params_of_send_message) 32 | result_of_send_message = response['result'] 33 | 34 | params_of_wait_for_transaction = {abi: abi, message: encoded_message['message'], shard_block_id: result_of_send_message['shard_block_id'], send_events: true} 35 | response = @client.processing.wait_for_transaction_sync(params_of_wait_for_transaction) 36 | expect(response['result']['out_messages'].size).to eq(0) 37 | expect(response['result']['decoded']).to eq({"out_messages" => [], "output" => nil}) 38 | end 39 | 40 | it 'process_mesage_sync' do 41 | abi_name = "Events" 42 | abi = { type: 'Serialized', value: read_abi(abi_name) } 43 | tvc = read_tvc(abi_name) 44 | keys = generate_keys(@client) 45 | result = abiEncodeMessage( 46 | name_abi: abi_name, 47 | name_tvc: abi_name, 48 | address: nil, 49 | public_key: keys['public'], 50 | secret_key: keys['secret'], 51 | call_set_function_name: "constructor", 52 | call_set_header: {expire: nil, time: nil, pubkey: keys['public']}, 53 | call_set_input: nil 54 | ) 55 | 56 | positive_balance = get_grams_from_giver_sync(client: @client, account_address: result['address']) 57 | expect(positive_balance).to eq(true) 58 | 59 | payload_encode_message = { 60 | abi: abi, 61 | address: nil, 62 | deploy_set: {tvc: tvc, workchain_id: nil, initial_data: nil}, 63 | call_set: {function_name: "constructor", header: {expire: nil, time: nil, pubkey: keys['public']}, input: nil}, 64 | signer: {type: 'Keys', public_key: nil, keys: keys, handle: nil}, 65 | processing_try_index: nil 66 | } 67 | payload_process_message = {message_encode_params: payload_encode_message, send_events: true} 68 | result_of_process_message = nil 69 | response = @client.processing.process_message_sync(payload_process_message) 70 | expect(response['result']['fees']['total_account_fees'].to_f).to be > 0 71 | expect(response['result']['out_messages'].size).to eq(0) 72 | expect(response['result']['decoded']).to eq({"out_messages" => [], "output" => nil}) 73 | end 74 | end 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'everscale-client-ruby' # and any other gems you need 2 | require 'byebug' 3 | require 'fiddle' 4 | require 'fiddle/import' 5 | include CommonInstanceHelpers 6 | 7 | # module A 8 | # extend Fiddle::Importer 9 | # 10 | # S = struct([]) 11 | # end 12 | 13 | RSpec.configure do |config| 14 | config.full_backtrace = true 15 | # some (optional) config here 16 | end 17 | 18 | def project_root 19 | # Fiddle::RUBY_FREE 20 | # a = A::S.malloc() 21 | if defined?(Rails) 22 | return Rails.root.to_s 23 | end 24 | 25 | if defined?(Bundler) 26 | return Bundler.root.to_s 27 | end 28 | 29 | Dir.pwd.to_s 30 | end 31 | 32 | def env 33 | Dotenv.parse('.env.test').merge(ENV) 34 | end 35 | 36 | def make_client 37 | TonClient.configure { |config| config.ffi_lib(env['spec_ffi']) } 38 | TonClient.create(config: {network: {endpoints: [env['server_address'] || "net.ton.dev"]}}) 39 | end 40 | 41 | # QUEUE 42 | # def requestLibrarySync(context: 1, method_name: '', payload: {}) 43 | # responses = [] 44 | # queue = Queue.new 45 | # TonClient::TonBinding.requestLibrary(context: context, method_name: method_name, payload: payload) do |response| 46 | # responses << response 47 | # queue.push 1 if response.finished == true 48 | # end 49 | # queue.pop 50 | # yield(responses) if block_given? 51 | # end 52 | 53 | # class A 54 | # @@a = 0 55 | # def self.a 56 | # @@a 57 | # end 58 | 59 | # def self.a=(val) 60 | # @@a = val 61 | # end 62 | # end 63 | 64 | # MUTEX 65 | def callLibraryMethodSync(method, *args) 66 | # number = A.a += 1 67 | # p "actor init #{number}" 68 | responses = [] 69 | mutex = Monitor.new 70 | condition = mutex.new_cond 71 | 72 | method.call(*args) do |response| 73 | mutex.synchronize do 74 | responses << response 75 | if response.finished == true 76 | condition.signal 77 | # p "actor execute block #{number}" 78 | end 79 | end 80 | end 81 | 82 | mutex.synchronize do 83 | condition.wait 84 | end 85 | # p "actor taked response #{number}" 86 | 87 | yield(responses.map{ |resp| resp if (resp.result || resp.error) }.compact) if block_given? 88 | end 89 | 90 | # RActor 91 | # def callLibraryMethodSync(method_p, *args) 92 | # p "actor init #{A.a + 1}" 93 | # wait_actor = Ractor.new("#{A.a + 1}", name: "#{A.a += 1}") do |name| 94 | # data = {condition: true} 95 | # result = [] 96 | # while data[:condition] 97 | # data = Ractor.receive 98 | # result << data[:result] if data[:result] 99 | # end 100 | # p "actor end yield #{name}" 101 | # Ractor.yield result 102 | # end 103 | 104 | # method_p.call(*args) do |response| 105 | # wait_actor.send({condition: true, result: response}) 106 | # # p response if wait_actor.name == '35' 107 | # if response.finished == true 108 | # p "actor execute block #{wait_actor.name}" 109 | # wait_actor.send({condition: false}, move: true) 110 | # end 111 | # end 112 | 113 | # responses = wait_actor.take 114 | # p "actor taked response #{wait_actor.name}" 115 | 116 | # yield(responses.map{ |resp| resp if resp.result }.compact) if block_given? 117 | # end 118 | 119 | def generate_keys(client) 120 | result = nil 121 | callLibraryMethodSync(client.crypto.method(:generate_random_sign_keys)) do |response| 122 | result = response.first.result 123 | end 124 | result 125 | end 126 | 127 | def read_abi(name) 128 | file = File.read(project_root + "/spec/Fixtures/abi/#{name}.abi.json") 129 | JSON.parse(file) 130 | end 131 | 132 | def read_tvc(name) 133 | data = File.open(project_root + "/spec/Fixtures/abi/#{name}.tvc").read 134 | # Encode the puppy 135 | encoded = Base64.encode64(data) 136 | # Spit it out into one continous string 137 | encoded.gsub(/\n/, '') 138 | end 139 | 140 | def abiEncodeMessage(name_abi: '', name_tvc: nil, address: nil, public_key: nil, secret_key: nil, call_set_function_name: nil, call_set_header: nil, call_set_input: nil) 141 | abi = {type: 'Serialized', value: read_abi(name_abi)} 142 | 143 | deploy_set = nil 144 | if name_tvc 145 | deploy_set = {tvc: read_tvc(name_tvc), workchain_id: nil, initial_data: nil} 146 | end 147 | 148 | keys = nil 149 | if public_key && secret_key 150 | keys = {public: public_key, secret: secret_key} 151 | end 152 | 153 | signer = nil 154 | if keys 155 | signer = {type: 'Keys', public_key: nil, keys: keys, handle: nil} 156 | elsif External 157 | signer = {type: 'External', public_key: public_key, keys: nil, handle: nil} 158 | else 159 | signer = {type: 'None'} 160 | end 161 | 162 | call_set = nil 163 | if call_set_function_name 164 | call_set = {function_name: call_set_function_name, header: call_set_header, input: call_set_input} 165 | end 166 | 167 | payload = {abi: abi, address: address, deploy_set: deploy_set, call_set: call_set, signer: signer, processing_try_index: nil} 168 | result = nil 169 | callLibraryMethodSync(@client.abi.method(:encode_message), payload) do |response| 170 | result = response.first.result 171 | end 172 | result 173 | end 174 | 175 | def get_grams_from_giver_sync(client: nil, account_address: nil, value: 10_000_000_000, &block) 176 | test_address = "0:9cb911799a34982a27cb577ce694843f60b9e09fcba4f7fd7e040730acd59baa" 177 | server_address = client.context_config[:network][:endpoints] 178 | raise 'Please, set client network for Giver work !' unless server_address 179 | if env['use_giver'] || env["giver_abi_name"] 180 | get_grams_from_giver_sync_node_se_v2(client, account_address || test_address, value, &block) 181 | elsif server_address[/net\.ton\.dev/] 182 | get_grams_from_giver_sync_net_dev(client, account_address || test_address, value, &block) 183 | else 184 | p "No Giver for this network: #{server_address}" 185 | block.call(nil) if block 186 | return false 187 | end 188 | 189 | tokens_received = false 190 | fuse_counter = 0 191 | while !tokens_received 192 | params_of_wait_for_collection = {collection: "accounts", filter: {"id": {"eq": account_address} }, result: "id balance(format: DEC)", timeout: nil} 193 | callLibraryMethodSync(client.net.method(:wait_for_collection), params_of_wait_for_collection) do |resp| 194 | if resp.first&.result 195 | balance = resp.first.result['result']['balance'] || 0 196 | if balance.to_i > 0 197 | tokens_received = true 198 | end 199 | end 200 | end 201 | fuse_counter += 1 202 | if fuse_counter > 20 && !tokens_received 203 | tokens_received = true 204 | return false 205 | end 206 | return true if tokens_received 207 | end 208 | end 209 | 210 | def get_grams_from_giver_sync_node_se_v2(client, account_address, value, &block) 211 | p 'Giver SE v2 start' 212 | wallet_address = env["giver_address"] || "0:b5e9240fc2d2f1ff8cbb1d1dee7fb7cae155e5f6320e585fcc685698994a19a5" 213 | abi_name = env["giver_abi_name"] 214 | abi = { type: 'Serialized', value: read_abi(abi_name) } 215 | keys = JSON.parse(File.read(project_root + "/spec/Fixtures/abi/#{abi_name}.keys.json")) 216 | signer = {type: 'Keys', keys: keys} 217 | call_set = {function_name: 'sendTransaction', header: nil, input: {dest: account_address, value: env['giver_amount'].to_i || value, bounce: false}} 218 | params_of_encoded_message = {abi: abi, address: wallet_address, call_set: call_set, deploy_set: nil, signer: signer, processing_try_index: nil} 219 | send_paylod = {message_encode_params: params_of_encoded_message, send_events: false} 220 | response = nil 221 | callLibraryMethodSync(client.processing.method(:process_message), send_paylod) do |resp| 222 | response = resp 223 | end 224 | p 'Giver SE v2 - finished' 225 | block.call(response) if block 226 | end 227 | 228 | def get_grams_from_giver_sync_net_dev(client, account_address, value, &block) 229 | p 'Giver NET - start' 230 | wallet_address = env["giver_address"] 231 | abi_name = env["giver_abi_name"] 232 | abi = { type: 'Serialized', value: read_abi(abi_name) } 233 | signer = {type: 'None'} 234 | call_set = {function_name: 'grant', header: nil, input: {addr: account_address}} 235 | params_of_encoded_message = {abi: abi, address: wallet_address, call_set: call_set, deploy_set: nil, signer: signer, processing_try_index: nil} 236 | send_paylod = {message_encode_params: params_of_encoded_message, send_events: false} 237 | response = nil 238 | callLibraryMethodSync(client.processing.method(:process_message), send_paylod) do |resp| 239 | response = resp 240 | end 241 | p 'Giver NET - finished' 242 | block.call(response) if block 243 | end 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /spec/sync_spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'everscale-client-ruby' # and any other gems you need 2 | include CommonInstanceHelpers 3 | 4 | RSpec.configure do |config| 5 | config.full_backtrace = true 6 | # some (optional) config here 7 | end 8 | 9 | def project_root 10 | if defined?(Rails) 11 | return Rails.root.to_s 12 | end 13 | 14 | if defined?(Bundler) 15 | return Bundler.root.to_s 16 | end 17 | 18 | Dir.pwd.to_s 19 | end 20 | 21 | def env 22 | Dotenv.parse('.env.test').merge(ENV) 23 | end 24 | 25 | def make_client 26 | TonClient.configure { |config| config.ffi_lib(env['spec_ffi']) } 27 | TonClient.create(config: {network: {endpoints: [env['server_address'] || "net.ton.dev"]}}) 28 | end 29 | 30 | def read_abi(name) 31 | file = File.read(project_root + "/spec/Fixtures/abi/#{name}.abi.json") 32 | JSON.parse(file) 33 | end 34 | 35 | def read_tvc(name) 36 | data = File.open(project_root + "/spec/Fixtures/abi/#{name}.tvc").read 37 | # Encode the puppy 38 | encoded = Base64.encode64(data) 39 | # Spit it out into one continous string 40 | encoded.gsub(/\n/, '') 41 | end 42 | 43 | def generate_keys(client) 44 | response = client.crypto.generate_random_sign_keys_sync 45 | response['result'] 46 | end 47 | 48 | def abiEncodeMessage(name_abi: '', name_tvc: nil, address: nil, public_key: nil, secret_key: nil, call_set_function_name: nil, call_set_header: nil, call_set_input: nil) 49 | abi = {type: 'Serialized', value: read_abi(name_abi)} 50 | 51 | deploy_set = nil 52 | if name_tvc 53 | deploy_set = {tvc: read_tvc(name_tvc), workchain_id: nil, initial_data: nil} 54 | end 55 | 56 | keys = nil 57 | if public_key && secret_key 58 | keys = {public: public_key, secret: secret_key} 59 | end 60 | 61 | signer = nil 62 | if keys 63 | signer = {type: 'Keys', public_key: nil, keys: keys, handle: nil} 64 | elsif External 65 | signer = {type: 'External', public_key: public_key, keys: nil, handle: nil} 66 | else 67 | signer = {type: 'None'} 68 | end 69 | 70 | call_set = nil 71 | if call_set_function_name 72 | call_set = {function_name: call_set_function_name, header: call_set_header, input: call_set_input} 73 | end 74 | 75 | payload = {abi: abi, address: address, deploy_set: deploy_set, call_set: call_set, signer: signer, processing_try_index: nil} 76 | result = nil 77 | response = @client.abi.encode_message_sync(payload) 78 | response['result'] 79 | end 80 | 81 | def get_grams_from_giver_sync(client: nil, account_address: nil, value: 10_000_000_000, &block) 82 | test_address = "0:9cb911799a34982a27cb577ce694843f60b9e09fcba4f7fd7e040730acd59baa" 83 | server_address = client.context_config[:network][:endpoints] 84 | raise 'Please, set client network for Giver work !' unless server_address 85 | if env['use_giver'] || env["giver_abi_name"] 86 | get_grams_from_giver_sync_node_se_v2(client, account_address || test_address, value, &block) 87 | elsif server_address[/net\.ton\.dev/] 88 | get_grams_from_giver_sync_net_dev(client, account_address || test_address, value, &block) 89 | else 90 | p "No Giver for this network: #{server_address}" 91 | block.call(nil) if block 92 | return false 93 | end 94 | 95 | tokens_received = false 96 | fuse_counter = 0 97 | while !tokens_received 98 | # p 'CYCLE' 99 | # p account_address 100 | params_of_wait_for_collection = {collection: "accounts", filter: {"id": {"eq": account_address} }, result: "id balance(format: DEC)", timeout: nil} 101 | response = client.net.wait_for_collection_sync(params_of_wait_for_collection) 102 | # p 'CYCLE 2' 103 | result = response['result'] 104 | # p result 105 | if result 106 | balance = result['result']['balance'] || 0 107 | if balance.to_i > 0 108 | tokens_received = true 109 | end 110 | end 111 | fuse_counter += 1 112 | if fuse_counter > 20 && !tokens_received 113 | tokens_received = true 114 | return false 115 | end 116 | return true if tokens_received 117 | end 118 | p 'out' 119 | end 120 | 121 | def get_grams_from_giver_sync_node_se_v2(client, account_address, value, &block) 122 | p 'Giver SE v2 start' 123 | wallet_address = env["giver_address"] || "0:b5e9240fc2d2f1ff8cbb1d1dee7fb7cae155e5f6320e585fcc685698994a19a5" 124 | abi_name = env["giver_abi_name"] 125 | abi = { type: 'Serialized', value: read_abi(abi_name) } 126 | keys = JSON.parse(File.read(project_root + "/spec/Fixtures/abi/#{abi_name}.keys.json")) 127 | signer = {type: 'Keys', keys: keys} 128 | call_set = {function_name: 'sendTransaction', header: nil, input: {dest: account_address, value: env['giver_amount'].to_i || value, bounce: false}} 129 | params_of_encoded_message = {abi: abi, address: wallet_address, call_set: call_set, deploy_set: nil, signer: signer, processing_try_index: nil} 130 | send_paylod = {message_encode_params: params_of_encoded_message, send_events: false} 131 | response = client.processing.process_message_sync(send_paylod) 132 | expect(nil).to eq(response['error']) 133 | p 'Giver SE v2 - finished' 134 | block.call(response) if block 135 | end 136 | 137 | def get_grams_from_giver_sync_net_dev(client, account_address, value, &block) 138 | p 'Giver NET - start' 139 | wallet_address = env["giver_address"] 140 | abi_name = env["giver_abi_name"] 141 | abi = { type: 'Serialized', value: read_abi(abi_name) } 142 | signer = {type: 'None'} 143 | call_set = {function_name: 'grant', header: nil, input: {addr: account_address}} 144 | params_of_encoded_message = {abi: abi, address: wallet_address, call_set: call_set, deploy_set: nil, signer: signer, processing_try_index: nil} 145 | send_paylod = {message_encode_params: params_of_encoded_message, send_events: false} 146 | response = client.processing.process_message_sync(send_paylod) 147 | expect(nil).to eq(response['error']) 148 | p 'Giver NET - finished' 149 | block.call(response) if block 150 | end 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /spec/tests.rb: -------------------------------------------------------------------------------- 1 | path = File.expand_path(File.dirname(__FILE__)) 2 | 20.times do 3 | system("rspec #{path}/all.rb") 4 | end 5 | -------------------------------------------------------------------------------- /spec/utils.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | describe TonClient::Utils do 5 | before(:all) do 6 | @client = make_client 7 | @account_id = "fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 8 | @hex = "-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 9 | @hexWorkchain0 = "0:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260" 10 | @base64 = "Uf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15+KsQHFLbKSMiYG+9" 11 | @base64_url = "kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny" 12 | end 13 | 14 | it 'account_id_to_hex' do 15 | format = {type: 'Hex', url: nil, test: nil, bounce: nil} 16 | payload = {address: @account_id, output_format: format} 17 | callLibraryMethodSync(@client.utils.method(:convert_address), payload) do |response| 18 | expect(response.first.result['address']).to eq(@hexWorkchain0) 19 | end 20 | end 21 | 22 | it 'account_id_to_account_id' do 23 | format = {type: 'AccountId', url: nil, test: nil, bounce: nil} 24 | payload = {address: @account_id, output_format: format} 25 | callLibraryMethodSync(@client.utils.method(:convert_address), payload) do |response| 26 | expect(response.first.result['address']).to eq(@account_id) 27 | end 28 | end 29 | 30 | it 'hex_to_base64' do 31 | format = {type: 'Base64', url: false, test: false, bounce: false} 32 | payload = {address: @hex, output_format: format} 33 | callLibraryMethodSync(@client.utils.method(:convert_address), payload) do |response| 34 | expect(response.first.result['address']).to eq(@base64) 35 | end 36 | end 37 | 38 | it 'base64_to_base64_url' do 39 | format = {type: 'Base64', url: true, test: true, bounce: true} 40 | payload = {address: @base64, output_format: format} 41 | callLibraryMethodSync(@client.utils.method(:convert_address), payload) do |response| 42 | expect(response.first.result['address']).to eq(@base64_url) 43 | end 44 | end 45 | 46 | it 'base64_url_to_hex' do 47 | format = {type: 'Hex', url: nil, test: nil, bounce: nil} 48 | payload = {address: @base64_url, output_format: format} 49 | callLibraryMethodSync(@client.utils.method(:convert_address), payload) do |response| 50 | expect(response.first.result['address']).to eq(@hex) 51 | end 52 | end 53 | 54 | end 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | --------------------------------------------------------------------------------