solana-ruby 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,105 @@
1
+ require 'rbnacl'
2
+ require 'json'
3
+ require_relative 'utils'
4
+
5
+ module Solana
6
+ ##
7
+ # The Keypair class represents a keypair for signing transactions on the Solana blockchain.
8
+ #
9
+ class Keypair
10
+ attr_reader :public_key, :secret_key
11
+
12
+ ##
13
+ # Initializes a new Keypair.
14
+ #
15
+ # If a +secret_key+ is provided, it must be 64 bytes long. The first 32 bytes are used as the signing key,
16
+ # and the public key is derived from it. If no +secret_key+ is provided, a new keypair is generated.
17
+ #
18
+ # Raises an error if the +secret_key+ is not 64 bytes long.
19
+ #
20
+ # @param [String, nil] secret_key The secret key to use for the keypair, in binary format (optional).
21
+ def initialize(secret_key = nil)
22
+ if secret_key
23
+ raise 'Bad secret key size' unless secret_key.bytesize == 64
24
+ @signing_key = RbNaCl::Signatures::Ed25519::SigningKey.new(secret_key[0, 32])
25
+ @public_key = @signing_key.verify_key.to_bytes
26
+ else
27
+ @signing_key = RbNaCl::Signatures::Ed25519::SigningKey.generate
28
+ @public_key = @signing_key.verify_key.to_bytes
29
+ end
30
+ @secret_key = @signing_key.to_bytes + @public_key
31
+ end
32
+
33
+ ##
34
+ # Generates a new Keypair.
35
+ #
36
+ # @return [Keypair] A new Keypair instance.
37
+ def self.generate
38
+ new
39
+ end
40
+
41
+ ##
42
+ # Creates a Keypair from a provided secret key.
43
+ #
44
+ # @param [String] secret_key The secret key in binary format.
45
+ # @return [Keypair] A new Keypair instance initialized with the provided secret key.
46
+ def self.from_secret_key(secret_key)
47
+ new(secret_key)
48
+ end
49
+
50
+ ##
51
+ # Saves the keypair to a JSON file.
52
+ #
53
+ # The public and secret keys are encoded in Base58 format before being saved.
54
+ #
55
+ # @param [String] file_path The path to the file where the keypair will be saved.
56
+ def save_to_json(file_path)
57
+ data = {
58
+ public_key: Utils::base58_encode(@public_key),
59
+ secret_key: Utils::base58_encode(@secret_key)
60
+ }
61
+ File.write(file_path, data.to_json)
62
+ end
63
+
64
+ ##
65
+ # Loads a keypair from a JSON file.
66
+ #
67
+ # The file must contain the public and secret keys in Base58 format. The method verifies the size of the secret key and
68
+ # checks that the derived public key matches the saved public key.
69
+ #
70
+ # Raises an error if the +secret_key+ is not 64 bytes long or if the derived public key does not match the saved public key.
71
+ #
72
+ # @param [String] file_path The path to the file from which the keypair will be loaded.
73
+ # @return [Keypair] The loaded keypair.
74
+ def self.load_from_json(file_path)
75
+ data = JSON.parse(File.read(file_path), symbolize_names: true)
76
+ secret_key = Utils::base58_decode(data[:secret_key])
77
+ public_key = Utils::base58_decode(data[:public_key])
78
+
79
+ raise 'Bad secret key size' unless secret_key.bytesize == 64
80
+
81
+ signing_key = RbNaCl::Signatures::Ed25519::SigningKey.new(secret_key[0, 32])
82
+ loaded_public_key = signing_key.verify_key.to_bytes
83
+
84
+ raise 'Provided secretKey is invalid' unless loaded_public_key == public_key
85
+
86
+ new(secret_key)
87
+ end
88
+
89
+ ##
90
+ # Returns the public key for this keypair in Base58 format.
91
+ #
92
+ # @return [String] The public key in Base58 format.
93
+ def public_key_base58
94
+ Utils::base58_encode(@public_key)
95
+ end
96
+
97
+ ##
98
+ # Returns the raw secret key for this keypair in Base58 format.
99
+ #
100
+ # @return [String] The secret key in Base58 format.
101
+ def secret_key_base58
102
+ Utils::base58_encode(@secret_key)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,107 @@
1
+ require 'base58'
2
+ require 'base64'
3
+
4
+ module Solana
5
+ ##
6
+ # The Utils module provides utility methods and constants for interacting with the Solana blockchain.
7
+ #
8
+ module Utils
9
+ ##
10
+ # The system program ID for Solana.
11
+ SYSTEM_PROGRAM_ID = '11111111111111111111111111111111'
12
+
13
+ ##
14
+ # The maximum packet data size for Solana transactions.
15
+ PACKET_DATA_SIZE = 1232
16
+
17
+ ##
18
+ # Endpoints for the mainnet.
19
+ module MAINNET
20
+ ##
21
+ # HTTP endpoint for the mainnet.
22
+ HTTP = 'https://api.mainnet-beta.solana.com'
23
+
24
+ ##
25
+ # WebSocket endpoint for the mainnet.
26
+ WS = 'wss://api.mainnet-beta.solana.com'
27
+ end
28
+
29
+ ##
30
+ # Endpoints for the testnet.
31
+ module TESTNET
32
+ ##
33
+ # HTTP endpoint for the testnet.
34
+ HTTP = 'https://api.testnet.solana.com'
35
+
36
+ ##
37
+ # WebSocket endpoint for the testnet.
38
+ WS = 'wss://api.testnet.solana.com'
39
+ end
40
+
41
+ ##
42
+ # Endpoints for the devnet.
43
+ module DEVNET
44
+ ##
45
+ # HTTP endpoint for the devnet.
46
+ HTTP = 'https://api.devnet.solana.com'
47
+
48
+ ##
49
+ # WebSocket endpoint for the devnet.
50
+ WS = 'wss://api.devnet.solana.com'
51
+ end
52
+
53
+ ##
54
+ # Instruction types for Solana transactions.
55
+ module InstructionType
56
+ CREATE_ACCOUNT = 0
57
+ ASSIGN = 1
58
+ TRANSFER = 2
59
+ CREATE_ACCOUNT_WITH_SEED = 3
60
+ ADVANCE_NONCE_ACCOUNT = 4
61
+ WITHDRAW_NONCE_ACCOUNT = 5
62
+ INITIALIZE_NONCE_ACCOUNT = 6
63
+ AUTHORIZE_NONCE_ACCOUNT = 7
64
+ ALLOCATE = 8
65
+ ALLOCATE_WITH_SEED = 9
66
+ ASSIGN_WITH_SEED = 10
67
+ TRANSFER_WITH_SEED = 11
68
+ end
69
+
70
+ ##
71
+ # Encodes a byte array into a Base58 string.
72
+ #
73
+ # @param [String] bytes The byte array to encode.
74
+ # @return [String] The Base58-encoded string.
75
+ def self.base58_encode(bytes)
76
+ Base58.binary_to_base58(bytes, :bitcoin)
77
+ end
78
+
79
+ ##
80
+ # Decodes a Base58 string into a byte array.
81
+ #
82
+ # @param [String] base58 The Base58 string to decode.
83
+ # @return [String] The decoded byte array.
84
+ def self.base58_decode(base58)
85
+ Base58.base58_to_binary(base58, :bitcoin)
86
+ end
87
+
88
+ ##
89
+ # Encodes a byte array into a Base64 string.
90
+ #
91
+ # @param [String] bytes The byte array to encode.
92
+ # @return [String] The Base64-encoded string.
93
+ def self.base64_encode(bytes)
94
+ Base64.strict_encode64(bytes)
95
+ end
96
+
97
+ ##
98
+ # Decodes a Base64 string into a byte array.
99
+ #
100
+ # @param [String] base64 The Base64 string to decode.
101
+ # @return [String] The decoded byte array.
102
+ def self.base64_decode(base64)
103
+ Base64.strict_decode64(base64)
104
+ end
105
+ end
106
+ Utils.freeze
107
+ end
@@ -1,3 +1,3 @@
1
- module SolanaRB
2
- VERSION = '0.1.0'.freeze
3
- end
1
+ module Solana
2
+ VERSION = '0.1.2'.freeze
3
+ end
data/lib/solana-ruby.rb CHANGED
@@ -1,5 +1,7 @@
1
- require_relative 'solana-ruby/version'
2
1
  require_relative 'solana-ruby/client'
2
+ require_relative 'solana-ruby/keypair'
3
+ require_relative 'solana-ruby/utils'
4
+ require_relative 'solana-ruby/version'
3
5
 
4
- module SolanaRB
6
+ module Solana
5
7
  end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solana-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabrice Renard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-23 00:00:00.000000000 Z
11
+ date: 2024-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: httparty
14
+ name: httpx
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.18.0
19
+ version: '1.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.18.0
26
+ version: '1.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faye-websocket
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.11.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.11.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: csv
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,76 @@ dependencies:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
54
  version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ed25519
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: base58
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.2.3
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: base64
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.2.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rdoc
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 6.7.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 6.7.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rqrcode
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '2.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '2.0'
41
125
  - !ruby/object:Gem::Dependency
42
126
  name: rspec
43
127
  requirement: !ruby/object:Gem::Requirement
@@ -75,11 +159,14 @@ extra_rdoc_files: []
75
159
  files:
76
160
  - lib/solana-ruby.rb
77
161
  - lib/solana-ruby/client.rb
162
+ - lib/solana-ruby/keypair.rb
163
+ - lib/solana-ruby/utils.rb
78
164
  - lib/solana-ruby/version.rb
79
165
  homepage: https://github.com/fabricerenard12/solana-ruby
80
166
  licenses:
81
167
  - MIT
82
- metadata: {}
168
+ metadata:
169
+ homepage_uri: https://github.com/fabricerenard12/solana-ruby
83
170
  post_install_message:
84
171
  rdoc_options: []
85
172
  require_paths:
@@ -98,5 +185,5 @@ requirements: []
98
185
  rubygems_version: 3.5.9
99
186
  signing_key:
100
187
  specification_version: 4
101
- summary: A Ruby wrapper for the Solana blockchain API
188
+ summary: A Ruby SDK for the Solana blockchain API
102
189
  test_files: []