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.
- checksums.yaml +4 -4
- data/lib/solana-ruby/client.rb +755 -234
- data/lib/solana-ruby/keypair.rb +105 -0
- data/lib/solana-ruby/utils.rb +107 -0
- data/lib/solana-ruby/version.rb +3 -3
- data/lib/solana-ruby.rb +4 -2
- metadata +94 -7
@@ -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
|
data/lib/solana-ruby/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module
|
2
|
-
VERSION = '0.1.
|
3
|
-
end
|
1
|
+
module Solana
|
2
|
+
VERSION = '0.1.2'.freeze
|
3
|
+
end
|
data/lib/solana-ruby.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2024-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: httpx
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
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:
|
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
|
188
|
+
summary: A Ruby SDK for the Solana blockchain API
|
102
189
|
test_files: []
|