near_api 0.1.0 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d9a8146bb7d005f8f833531892e9ba17f44545dd30da6b15d86f2343cc1f9d5
4
- data.tar.gz: d7e51a87f8f3a9c36fa45c85327985c0fd56cc6c1df32dab18cac84dad3f9ded
3
+ metadata.gz: 1c8844d644d14d1d32fa4d27ef9247f0e5de59019dd195272a457b531935a416
4
+ data.tar.gz: 3196cdfe44e96d18f997a67d8d55ec159c24158f3afdac7c3b30656a946bab34
5
5
  SHA512:
6
- metadata.gz: 7f6030857da43b0b2b039d6f2f82155a57d5743e0287e376ce7d30181812f885b925282429c2afe3595dca6505e89f97128790dc4a974263a2b65c1f14f2b297
7
- data.tar.gz: f0b7b6d68bd0038ccc90635f935d804fcb19de534a00dc9275e9aa920c2e7516a7f89d02af2f6b15f75454b83b3c8cfaeade9edb0dc500f5e61f77dda2f9e10b
6
+ metadata.gz: 6d6d9e682ce1392ed9314d62340ea56e68fe81a48ed00bb8e981b950380613ea5f79b9df6c4ab3da7dd5a3e1cf5fe0c847ae6c6dcf7fd485b3a3e508a114ad76
7
+ data.tar.gz: f89dfa4956871b176517e52cc868a26a9115aa6ae0beb1efbe634807f0e2d538e13d9cfbc56c81958bf948c1ce19b9ed3593da22439507950a1870004f4a7d26
data/Gemfile CHANGED
@@ -6,5 +6,3 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "rake", "~> 13.0"
9
-
10
- gem "rspec", "~> 3.0"
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Action::FunctionCall
4
+ include Borsh
5
+
6
+ borsh action_code: :u8,
7
+ method_name: :string,
8
+ args: :string,
9
+ gas: :u64,
10
+ amount: :u128
11
+
12
+ def initialize(method_name, args, gas: 100000000000000, amount: 0)
13
+ @method_name = method_name
14
+ @args = args
15
+ @gas = gas
16
+ @amount = amount
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :method_name, :args, :gas, :amount
22
+
23
+ def action_code
24
+ 2
25
+ end
26
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Action
4
+ include Borsh
5
+
6
+ borsh signer_id: :string,
7
+ key: { key_type: :u8, public_key: 32 },
8
+ nonce: :u64,
9
+ receiver_id: :string,
10
+ block_hash: 32,
11
+ actions: [:borsh]
12
+
13
+ def self.call(*args)
14
+ new(*args).call
15
+ end
16
+
17
+ def self.async(*args)
18
+ new(*args).async
19
+ end
20
+
21
+ def initialize(receiver_id, actions, config: NearApi.config, key: NearApi.key)
22
+ @key = key
23
+ @receiver_id = receiver_id
24
+ @actions = Array(actions)
25
+ @config = config
26
+ @api = NearApi::Api.new(config)
27
+ end
28
+
29
+ def call
30
+ signature = key.sign(message.digest)
31
+ call_api('broadcast_tx_commit', message.message, signature)
32
+ end
33
+
34
+ def async
35
+ signature = key.sign(message.digest)
36
+ call_api('broadcast_tx_async', message.message, signature)
37
+ end
38
+
39
+ def message
40
+ @message ||= begin
41
+ message = to_borsh
42
+ Struct.new(:message, :digest).new(message, Digest::SHA256.digest(message))
43
+ end
44
+ end
45
+
46
+ def call_api(method, message, signature)
47
+ signed_transaction = message + Borsh::Integer.new(key.key_type, :u8).to_borsh + signature
48
+ api.json_rpc(method, [Base64.strict_encode64(signed_transaction)])
49
+ end
50
+
51
+ private
52
+
53
+ def signer_id
54
+ key.signer_id
55
+ end
56
+
57
+ def nonce
58
+ api.nonce(key) + 1
59
+ end
60
+
61
+ def block_hash
62
+ api.block_hash
63
+ end
64
+
65
+ attr_reader :receiver_id, :actions, :key, :config, :api
66
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Api
4
+ def initialize(config = NearApi.config)
5
+ @config = config
6
+ end
7
+
8
+ def call(method, payload)
9
+ json_rpc(method, payload)
10
+ end
11
+
12
+ def status
13
+ uri = URI("#{config.node_url}/status")
14
+ JSON.parse(Net::HTTP.get(uri))
15
+ end
16
+
17
+ def view_access_key(key)
18
+ call(
19
+ 'query',
20
+ {
21
+ "request_type": "view_access_key",
22
+ "account_id": key.signer_id,
23
+ "public_key": NearApi::Base58.encode(key.public_key),
24
+ "finality": 'optimistic'
25
+ }
26
+ )
27
+ end
28
+
29
+ def nonce(key)
30
+ view_access_key(key)['result']['nonce']
31
+ end
32
+
33
+ def block_hash
34
+ NearApi::Base58.decode(status['sync_info']['latest_block_hash'])
35
+ end
36
+
37
+ def json_rpc(method, payload)
38
+ json_rpc_payload = {
39
+ id: 'dontcare',
40
+ jsonrpc: "2.0",
41
+ method: method,
42
+ params: payload
43
+ }
44
+
45
+ uri = URI.parse(config.node_url)
46
+ req = Net::HTTP::Post.new(uri.to_s)
47
+ req.body = json_rpc_payload.to_json
48
+ req['Content-Type'] = 'application/json'
49
+ response = Net::HTTP.new(uri.host, uri.port).tap { |http| http.use_ssl = true }.request(req)
50
+
51
+ JSON.parse(response.body)
52
+ end
53
+
54
+ private
55
+
56
+ attr_reader :config
57
+ end
58
+
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Base58
4
+ BASE = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
5
+
6
+ def self.encode(bytestring)
7
+ number = bytestring.unpack("C*").reverse.each_with_index.inject(0) do |sum, (byte, index)|
8
+ sum + byte * (256 ** index)
9
+ end
10
+ tos number
11
+ end
12
+
13
+ def self.decode(encoded_string)
14
+ integer = toi encoded_string
15
+ to_bytestring(integer)
16
+ end
17
+
18
+ def self.toi(string=to_s, base=58, digits=BASE)
19
+ return nil if string.empty?
20
+
21
+ integer = 0
22
+ string.each_char do |c|
23
+ index = digits.index(c)
24
+ integer = integer * base + index
25
+ end
26
+ integer
27
+ end
28
+
29
+ def self.tos(integer=to_i, base=58, digits=BASE)
30
+ return '' if integer.nil?
31
+ return digits[0] if integer == 0
32
+ string = ''
33
+ while integer > 0
34
+ integer, index = integer.divmod(base)
35
+ string = digits[index] + string
36
+ end
37
+ string
38
+ end
39
+
40
+ def self.to_bytestring(number)
41
+ integer = number
42
+ result = ''
43
+ while integer > 0
44
+ integer, remain = integer.divmod(256)
45
+ result = remain.chr + result
46
+ end
47
+ result
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Config
4
+ def initialize(node_url: ENV.fetch('NEAR_NODE_URL'))
5
+ @node_url = node_url
6
+ end
7
+
8
+ attr_reader :node_url
9
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ require 'ed25519'
3
+
4
+ class NearApi::Key
5
+ attr_reader :signer_id, :public_key
6
+
7
+ def initialize(signer_id = ENV.fetch('NEAR_SIGNER_ID'),
8
+ key_pair: ENV.fetch('NEAR_KEYPAIR', nil),
9
+ public_key: ENV.fetch('NEAR_PUBLIC_KEY', nil))
10
+ @signer_id = signer_id
11
+ if (!key_pair.nil? && !public_key.nil?) || (key_pair.nil? && public_key.nil?)
12
+ raise ArgumentError, "please specify one of: key_pair or public_key"
13
+ end
14
+
15
+ unless key_pair.nil?
16
+ key_value = if key_pair.include?(':')
17
+ key_pair.split(':').last
18
+ else
19
+ key_pair
20
+ end
21
+ bytestring = NearApi::Base58.decode(key_value)
22
+ @key_pair = Ed25519::SigningKey.from_keypair(bytestring)
23
+ @public_key = @key_pair.verify_key.to_bytes
24
+ end
25
+
26
+ unless public_key.nil?
27
+ key_value = if public_key.include?(':')
28
+ public_key.split(':').last
29
+ else
30
+ public_key
31
+ end
32
+ bytestring = NearApi::Base58.decode(key_value)
33
+ @public_key = Ed25519::VerifyKey.new(bytestring).to_bytes
34
+ end
35
+ end
36
+
37
+ def key_type
38
+ 0
39
+ end
40
+
41
+ def sign(msg)
42
+ key_pair.sign(msg)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :key_pair
48
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NearApi::Query
4
+ def initialize(config = NearApi.config)
5
+ @api = NearApi::Api.new(config)
6
+ end
7
+
8
+ def function(account_id, method_name, args, finality: 'final')
9
+ params = {
10
+ request_type: 'call_function',
11
+ finality: finality,
12
+ account_id: account_id,
13
+ method_name: method_name,
14
+ args_base64: Base64.strict_encode64(args.to_json)
15
+ }
16
+ call_api(params)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :api
22
+
23
+ def call_api(params)
24
+ api.json_rpc('query', params)
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NearApi
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.4"
5
5
  end
data/lib/near_api.rb CHANGED
@@ -1,8 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'uri'
4
+ require 'net/https'
5
+ require 'json'
6
+ require "base64"
7
+ require 'borsh'
3
8
  require_relative "near_api/version"
9
+ require_relative "near_api/key"
10
+ require_relative "near_api/action"
11
+ require_relative 'near_api/query'
12
+ require_relative "near_api/action/function_call"
13
+ require_relative "near_api/config"
14
+ require_relative 'near_api/api'
15
+ require_relative "near_api/base58"
4
16
 
5
17
  module NearApi
6
18
  class Error < StandardError; end
7
- # Your code goes here...
19
+
20
+ def self.config
21
+ @config ||= Config.new
22
+ end
23
+
24
+ def config=(config)
25
+ @config = config
26
+ end
27
+
28
+ def self.key
29
+ @key ||= Key.new
30
+ end
31
+
32
+ def key=(key)
33
+ @key = key
34
+ end
8
35
  end
data/near_api.gemspec CHANGED
@@ -26,6 +26,12 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ["lib"]
28
28
 
29
+ spec.add_dependency "borsh-rb"
30
+ spec.add_dependency "ed25519"
31
+
32
+ spec.add_development_dependency "rspec", "~> 3.10"
33
+ spec.add_development_dependency "pry"
34
+
29
35
  # Uncomment to register a new dependency of your gem
30
36
  # spec.add_dependency "example-gem", "~> 1.0"
31
37
 
metadata CHANGED
@@ -1,15 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: near_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serg Tyatin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-13 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: borsh-rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ed25519
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  description:
14
70
  email:
15
71
  - 700@2rba.com
@@ -26,6 +82,13 @@ files:
26
82
  - bin/console
27
83
  - bin/setup
28
84
  - lib/near_api.rb
85
+ - lib/near_api/action.rb
86
+ - lib/near_api/action/function_call.rb
87
+ - lib/near_api/api.rb
88
+ - lib/near_api/base58.rb
89
+ - lib/near_api/config.rb
90
+ - lib/near_api/key.rb
91
+ - lib/near_api/query.rb
29
92
  - lib/near_api/version.rb
30
93
  - near_api.gemspec
31
94
  homepage: https://github.com/2rba/near_api