solace 0.0.2 → 0.0.5
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/CHANGELOG +57 -0
- data/LICENSE +21 -0
- data/README.md +142 -287
- data/lib/solace/address_lookup_table.rb +34 -18
- data/lib/solace/composers/base.rb +45 -0
- data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +113 -0
- data/lib/solace/composers/system_program_transfer_composer.rb +80 -0
- data/lib/solace/concerns/binary_serializable.rb +39 -0
- data/lib/solace/connection.rb +101 -44
- data/lib/solace/constants.rb +7 -14
- data/lib/solace/instruction.rb +30 -19
- data/lib/solace/instructions/associated_token_account/create_associated_token_account_instruction.rb +18 -3
- data/lib/solace/instructions/spl_token/initialize_account_instruction.rb +24 -3
- data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +18 -1
- data/lib/solace/instructions/spl_token/mint_to_instruction.rb +16 -3
- data/lib/solace/instructions/spl_token/transfer_checked_instruction.rb +76 -0
- data/lib/solace/instructions/spl_token/transfer_instruction.rb +15 -2
- data/lib/solace/instructions/system_program/create_account_instruction.rb +18 -3
- data/lib/solace/instructions/system_program/transfer_instruction.rb +58 -0
- data/lib/solace/keypair.rb +64 -31
- data/lib/solace/message.rb +22 -10
- data/lib/solace/programs/associated_token_account.rb +58 -11
- data/lib/solace/programs/base.rb +6 -0
- data/lib/solace/programs/spl_token.rb +52 -14
- data/lib/solace/public_key.rb +45 -20
- data/lib/solace/serializers/address_lookup_table_deserializer.rb +3 -5
- data/lib/solace/serializers/address_lookup_table_serializer.rb +7 -7
- data/lib/solace/serializers/base_deserializer.rb +29 -19
- data/lib/solace/serializers/base_serializer.rb +18 -9
- data/lib/solace/serializers/instruction_deserializer.rb +5 -7
- data/lib/solace/serializers/instruction_serializer.rb +4 -6
- data/lib/solace/serializers/message_deserializer.rb +3 -5
- data/lib/solace/serializers/message_serializer.rb +3 -5
- data/lib/solace/serializers/transaction_deserializer.rb +5 -7
- data/lib/solace/serializers/transaction_serializer.rb +5 -7
- data/lib/solace/transaction.rb +38 -23
- data/lib/solace/transaction_composer.rb +115 -0
- data/lib/solace/utils/account_context.rb +252 -0
- data/lib/solace/utils/codecs.rb +56 -128
- data/lib/solace/utils/curve25519_dalek.rb +9 -4
- data/lib/solace/utils/pda.rb +22 -24
- data/lib/solace/version.rb +2 -1
- data/lib/solace.rb +9 -7
- metadata +15 -12
- data/lib/solace/instructions/transfer_checked_instruction.rb +0 -58
- data/lib/solace/instructions/transfer_instruction.rb +0 -48
- data/lib/solace/serializable_record.rb +0 -26
- data/lib/solace/serializers/base.rb +0 -31
@@ -2,7 +2,31 @@
|
|
2
2
|
|
3
3
|
module Solace
|
4
4
|
module Programs
|
5
|
-
#
|
5
|
+
# Client for interacting with the SPL Token Program.
|
6
|
+
#
|
7
|
+
# This client provides methods for interacting with the SPL Token Program. It is a wrapper around
|
8
|
+
# the SPL Token Program and provides a more convenient interface for creating and managing SPL
|
9
|
+
# Token mints and accounts.
|
10
|
+
#
|
11
|
+
# @example Create an SPL Token mint
|
12
|
+
# # Initialize the program with a connection
|
13
|
+
# program = Solace::Programs::SplToken.new(connection: connection)
|
14
|
+
#
|
15
|
+
# # Create an SPL Token mint
|
16
|
+
# result = program.create_mint(
|
17
|
+
# payer: payer,
|
18
|
+
# decimals: 6,
|
19
|
+
# mint_keypair: mint_keypair,
|
20
|
+
# mint_authority: mint_authority,
|
21
|
+
# freeze_authority: freeze_authority
|
22
|
+
# )
|
23
|
+
#
|
24
|
+
# # Wait for the transaction to be finalized
|
25
|
+
# @connection.wait_for_confirmed_signature('finalized') { result['result'] }
|
26
|
+
#
|
27
|
+
# @since 0.0.2
|
28
|
+
#
|
29
|
+
# rubocop:disable Metrics/ClassLength
|
6
30
|
class SplToken < Base
|
7
31
|
# Initializes a new SPL Token client.
|
8
32
|
#
|
@@ -29,6 +53,8 @@ module Solace
|
|
29
53
|
# @param freeze_authority [String] (Optional) The base58 public key for the freeze authority.
|
30
54
|
# @param mint_keypair [Solace::Keypair] (Optional) The keypair for the new mint.
|
31
55
|
# @return [Solace::Transaction] The signed transaction.
|
56
|
+
#
|
57
|
+
# rubocop:disable Metrics/MethodLength
|
32
58
|
def prepare_create_mint(
|
33
59
|
payer:,
|
34
60
|
decimals:,
|
@@ -78,6 +104,7 @@ module Solace
|
|
78
104
|
|
79
105
|
tx
|
80
106
|
end
|
107
|
+
# rubocop:enable Metrics/MethodLength
|
81
108
|
|
82
109
|
# Mint tokens to a token account
|
83
110
|
#
|
@@ -91,10 +118,16 @@ module Solace
|
|
91
118
|
|
92
119
|
# Prepares a mint to instruction and returns the signed transaction.
|
93
120
|
#
|
94
|
-
# @param
|
121
|
+
# @param [Integer] amount The amount of tokens to mint.
|
122
|
+
# @param [PublicKey, Keypair, String] payer The payer of the transaction.
|
123
|
+
# @param [PublicKey, Keypair, String] mint The mint of the token.
|
124
|
+
# @param [PublicKey, Keypair, String] destination The destination of the token.
|
125
|
+
# @param [PublicKey, Keypair, String] mint_authority The mint authority of the token.
|
95
126
|
# @return [Solace::Transaction] The signed transaction.
|
127
|
+
#
|
128
|
+
# rubocop:disable Metrics/MethodLength
|
96
129
|
def prepare_mint_to(
|
97
|
-
payer:,
|
130
|
+
payer:,
|
98
131
|
mint:,
|
99
132
|
destination:,
|
100
133
|
amount:,
|
@@ -105,11 +138,11 @@ module Solace
|
|
105
138
|
mint_authority.address,
|
106
139
|
mint.address,
|
107
140
|
destination,
|
108
|
-
Solace::Constants::TOKEN_PROGRAM_ID
|
141
|
+
Solace::Constants::TOKEN_PROGRAM_ID
|
109
142
|
]
|
110
143
|
|
111
144
|
ix = Solace::Instructions::SplToken::MintToInstruction.build(
|
112
|
-
amount
|
145
|
+
amount: amount,
|
113
146
|
mint_authority_index: 1,
|
114
147
|
mint_index: 2,
|
115
148
|
destination_index: 3,
|
@@ -118,9 +151,9 @@ module Solace
|
|
118
151
|
|
119
152
|
message = Solace::Message.new(
|
120
153
|
header: [2, 0, 1],
|
121
|
-
accounts
|
154
|
+
accounts: accounts,
|
122
155
|
instructions: [ix],
|
123
|
-
recent_blockhash: connection.get_latest_blockhash
|
156
|
+
recent_blockhash: connection.get_latest_blockhash
|
124
157
|
)
|
125
158
|
|
126
159
|
tx = Solace::Transaction.new(message: message)
|
@@ -128,6 +161,7 @@ module Solace
|
|
128
161
|
|
129
162
|
tx
|
130
163
|
end
|
164
|
+
# rubocop:enable Metrics/MethodLength
|
131
165
|
|
132
166
|
# Transfers tokens from one account to another
|
133
167
|
#
|
@@ -147,11 +181,13 @@ module Solace
|
|
147
181
|
# @param amount [Integer] The number of tokens to transfer.
|
148
182
|
# @param owner [Solace::Keypair] The keypair of the owner of the source account.
|
149
183
|
# @return [Solace::Transaction] The signed transaction.
|
184
|
+
#
|
185
|
+
# rubocop:disable Metrics/MethodLength
|
150
186
|
def prepare_transfer(
|
151
|
-
amount:,
|
152
|
-
payer:,
|
153
|
-
source:,
|
154
|
-
destination:,
|
187
|
+
amount:,
|
188
|
+
payer:,
|
189
|
+
source:,
|
190
|
+
destination:,
|
155
191
|
owner:
|
156
192
|
)
|
157
193
|
accounts = [
|
@@ -163,7 +199,7 @@ module Solace
|
|
163
199
|
]
|
164
200
|
|
165
201
|
ix = Solace::Instructions::SplToken::TransferInstruction.build(
|
166
|
-
amount
|
202
|
+
amount: amount,
|
167
203
|
owner_index: 1,
|
168
204
|
source_index: 2,
|
169
205
|
destination_index: 3,
|
@@ -172,16 +208,18 @@ module Solace
|
|
172
208
|
|
173
209
|
message = Solace::Message.new(
|
174
210
|
header: [2, 0, 1],
|
175
|
-
accounts
|
211
|
+
accounts: accounts,
|
176
212
|
instructions: [ix],
|
177
213
|
recent_blockhash: connection.get_latest_blockhash
|
178
214
|
)
|
179
215
|
|
180
|
-
tx = Solace::Transaction.new(message:)
|
216
|
+
tx = Solace::Transaction.new(message: message)
|
181
217
|
tx.sign(payer, owner)
|
182
218
|
|
183
219
|
tx
|
184
220
|
end
|
221
|
+
# rubocop:enable Metrics/MethodLength
|
185
222
|
end
|
223
|
+
# rubocop:enable Metrics/ClassLength
|
186
224
|
end
|
187
225
|
end
|
data/lib/solace/public_key.rb
CHANGED
@@ -1,40 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# PublicKey
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Represents a Solana Ed25519 Public Key
|
8
|
-
# Provides utility methods for encoding, decoding, and validation
|
9
3
|
module Solace
|
4
|
+
# Class representing a Solana Ed25519 Public Key
|
5
|
+
#
|
6
|
+
# This class provides utility methods for encoding, decoding, and validating public keys.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # Initialize a public key from a 32-byte array
|
10
|
+
# pubkey = Solace::PublicKey.new(public_key_bytes)
|
11
|
+
#
|
12
|
+
# # Get the address representation of the public key
|
13
|
+
# pubkey.to_base58
|
14
|
+
# pubkey.address
|
15
|
+
#
|
16
|
+
# @since 0.0.1
|
10
17
|
class PublicKey
|
11
18
|
include Solace::Utils::PDA
|
12
19
|
|
13
|
-
#
|
14
|
-
# The length of a Solana public key in bytes
|
15
|
-
#
|
16
|
-
# @return [Integer] The length of a public key
|
20
|
+
# The length of a Solana public key in bytes
|
17
21
|
LENGTH = 32
|
18
22
|
|
19
|
-
#
|
20
|
-
# The maximum seed value for a Program Derived Address
|
21
|
-
#
|
22
|
-
# @return [Integer] The maximum seed value
|
23
|
+
# The maximum seed value for a Program Derived Address
|
23
24
|
MAX_BUMP_SEED = 255
|
24
25
|
|
25
|
-
#
|
26
|
-
# The marker for a Program Derived Address
|
27
|
-
#
|
28
|
-
# @return [String] The marker for a PDA
|
26
|
+
# The marker for a Program Derived Address
|
29
27
|
PDA_MARKER = 'ProgramDerivedAddress'
|
30
28
|
|
31
|
-
#
|
32
|
-
#
|
29
|
+
# The bytes of the public key
|
30
|
+
#
|
31
|
+
# @return [Array<u8>] The bytes of the public key
|
33
32
|
attr_reader :bytes
|
34
33
|
|
35
34
|
# Initialize with a 32-byte array or string
|
36
35
|
#
|
36
|
+
# @example
|
37
|
+
# pubkey = Solace::PubKey.new(bytes)
|
38
|
+
#
|
37
39
|
# @param bytes [String, Array<Integer>] 32-byte array or string
|
40
|
+
# @raise [ArgumentError] If the public key bytes length isn't 32 long
|
38
41
|
# @return [PublicKey]
|
39
42
|
def initialize(bytes)
|
40
43
|
raise ArgumentError, "Public key must be #{LENGTH} bytes" unless bytes.length == LENGTH
|
@@ -44,6 +47,9 @@ module Solace
|
|
44
47
|
|
45
48
|
# Return the base58 representation of the public key
|
46
49
|
#
|
50
|
+
# @example
|
51
|
+
# pubkey_str = instance.to_base58
|
52
|
+
#
|
47
53
|
# @return [String]
|
48
54
|
def to_base58
|
49
55
|
Solace::Utils::Codecs.bytes_to_base58(@bytes)
|
@@ -51,13 +57,29 @@ module Solace
|
|
51
57
|
|
52
58
|
# String representation (base58)
|
53
59
|
#
|
60
|
+
# @example
|
61
|
+
# pubkey_str = instance.to_s
|
62
|
+
#
|
54
63
|
# @return [String]
|
55
64
|
def to_s
|
56
65
|
to_base58
|
57
66
|
end
|
58
67
|
|
68
|
+
# Return the address of the public key
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# pubkey_str = instance.address
|
72
|
+
#
|
73
|
+
# @return [String]
|
74
|
+
def address
|
75
|
+
to_base58
|
76
|
+
end
|
77
|
+
|
59
78
|
# Compare two public keys for equality
|
60
79
|
#
|
80
|
+
# @example
|
81
|
+
# pubkey1 == pubkey2
|
82
|
+
#
|
61
83
|
# @param other [PublicKey]
|
62
84
|
# @return [Boolean]
|
63
85
|
def ==(other)
|
@@ -66,6 +88,9 @@ module Solace
|
|
66
88
|
|
67
89
|
# Return the public key as a byte array
|
68
90
|
#
|
91
|
+
# @example
|
92
|
+
# pubkey_bytes = instance.to_bytes
|
93
|
+
#
|
69
94
|
# @return [Array<Integer>]
|
70
95
|
def to_bytes
|
71
96
|
@bytes.dup
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Address Lookup Table Deserializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Deserializes a Solana address lookup table from a binary format.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Deserializes a Solana address lookup table from a binary format.
|
6
|
+
#
|
7
|
+
# @since 0.0.2
|
10
8
|
class AddressLookupTableDeserializer < Solace::Serializers::BaseDeserializer
|
11
9
|
# @!attribute record_class
|
12
10
|
# The class of the record being deserialized
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Address Lookup Table Serializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Serializes a Solana address lookup table to a binary format.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Serializes a Solana address lookup table to a binary format.
|
6
|
+
#
|
7
|
+
# @since 0.0.2
|
10
8
|
class AddressLookupTableSerializer < Solace::Serializers::BaseSerializer
|
11
9
|
# @!attribute steps
|
12
10
|
# An ordered list of methods to serialize the address lookup table
|
@@ -36,7 +34,8 @@ module Solace
|
|
36
34
|
#
|
37
35
|
# @return [Array<Integer>] The bytes of the encoded writable indexes
|
38
36
|
def encode_writable_indexes
|
39
|
-
Codecs.encode_compact_u16(record.writable_indexes.size).bytes +
|
37
|
+
Codecs.encode_compact_u16(record.writable_indexes.size).bytes +
|
38
|
+
record.writable_indexes
|
40
39
|
end
|
41
40
|
|
42
41
|
# Encodes the readonly indexes of the address lookup table
|
@@ -47,7 +46,8 @@ module Solace
|
|
47
46
|
#
|
48
47
|
# @return [Array<Integer>] The bytes of the encoded readonly indexes
|
49
48
|
def encode_readonly_indexes
|
50
|
-
Codecs.encode_compact_u16(record.readonly_indexes.size).bytes +
|
49
|
+
Codecs.encode_compact_u16(record.readonly_indexes.size).bytes +
|
50
|
+
record.readonly_indexes
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Solace
|
4
|
+
# Serializers module
|
4
5
|
module Serializers
|
5
6
|
# Autoload deserializers
|
6
7
|
autoload :TransactionDeserializer, 'solace/serializers/transaction_deserializer'
|
@@ -8,38 +9,33 @@ module Solace
|
|
8
9
|
autoload :InstructionDeserializer, 'solace/serializers/instruction_deserializer'
|
9
10
|
autoload :AddressLookupTableDeserializer, 'solace/serializers/address_lookup_table_deserializer'
|
10
11
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# @!attribute RECORD_CLASS
|
21
|
-
# The class of the record being deserialized
|
22
|
-
#
|
23
|
-
# @return [Class] The class of the record
|
24
|
-
attr_accessor :record_class
|
25
|
-
end
|
12
|
+
# The base deserializer class
|
13
|
+
#
|
14
|
+
# This class provides a consistent interface for deserializing records.
|
15
|
+
#
|
16
|
+
# @abstract
|
17
|
+
# @since 0.0.1
|
18
|
+
class BaseDeserializer
|
19
|
+
include Solace::Utils
|
26
20
|
|
27
21
|
# @!attribute io
|
28
22
|
# The input to read bytes from.
|
29
23
|
#
|
30
|
-
# @return [IO
|
31
|
-
|
24
|
+
# @return [IO, StringIO] The input to read bytes from.
|
25
|
+
attr_reader :io
|
26
|
+
|
32
27
|
# @!attribute record
|
33
28
|
# The record instance being deserialized.
|
34
29
|
#
|
35
30
|
# @return [Record] The deserialized record.
|
36
|
-
attr_reader :
|
31
|
+
attr_reader :record
|
37
32
|
|
38
33
|
# Initialize a new deserializer
|
39
34
|
#
|
40
|
-
# @param io [IO
|
35
|
+
# @param io [IO, StringIO] The input to read bytes from.
|
41
36
|
# @return [BaseDeserializer] The new deserializer object
|
42
37
|
def initialize(io)
|
38
|
+
super()
|
43
39
|
@io = io
|
44
40
|
@record = self.class.record_class.new
|
45
41
|
end
|
@@ -51,6 +47,20 @@ module Solace
|
|
51
47
|
self.class.steps.each { send(_1) }
|
52
48
|
record
|
53
49
|
end
|
50
|
+
|
51
|
+
class << self
|
52
|
+
# @!attribute steps
|
53
|
+
# An ordered list of methods to deserialize the record
|
54
|
+
#
|
55
|
+
# @return [Array] The steps to deserialize the record
|
56
|
+
attr_accessor :steps
|
57
|
+
|
58
|
+
# @!attribute record_class
|
59
|
+
# The class of the record being deserialized
|
60
|
+
#
|
61
|
+
# @return [Class] The class of the record
|
62
|
+
attr_accessor :record_class
|
63
|
+
end
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Solace
|
4
|
+
# Serializers module
|
4
5
|
module Serializers
|
5
6
|
# Autoload serializers
|
6
7
|
autoload :TransactionSerializer, 'solace/serializers/transaction_serializer'
|
@@ -8,15 +9,14 @@ module Solace
|
|
8
9
|
autoload :InstructionSerializer, 'solace/serializers/instruction_serializer'
|
9
10
|
autoload :AddressLookupTableSerializer, 'solace/serializers/address_lookup_table_serializer'
|
10
11
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
12
|
+
# The base serializer class
|
13
|
+
#
|
14
|
+
# This class provides a consistent interface for serializing records.
|
15
|
+
#
|
16
|
+
# @abstract
|
17
|
+
# @since 0.0.1
|
18
|
+
class BaseSerializer
|
19
|
+
include Solace::Utils
|
20
20
|
|
21
21
|
# @!attribute record
|
22
22
|
# The record instance being serialized.
|
@@ -29,6 +29,7 @@ module Solace
|
|
29
29
|
# @param record [Record] The record to serialize
|
30
30
|
# @return [BaseSerializer] The new serializer object
|
31
31
|
def initialize(record)
|
32
|
+
super()
|
32
33
|
@record = record
|
33
34
|
end
|
34
35
|
|
@@ -47,6 +48,14 @@ module Solace
|
|
47
48
|
rescue NameError => e
|
48
49
|
raise "STEPS must be defined: #{e.message}"
|
49
50
|
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
# @!attribute steps
|
54
|
+
# An ordered list of methods to serialize the record
|
55
|
+
#
|
56
|
+
# @return [Array] The steps to serialize the record
|
57
|
+
attr_accessor :steps
|
58
|
+
end
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
@@ -1,20 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Instruction Deserializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Deserializes a binary instruction into a Solace::Instruction object.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Deserializes a binary instruction into a Solace::Instruction object.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class InstructionDeserializer < Solace::Serializers::BaseDeserializer
|
11
|
-
# @!attribute
|
9
|
+
# @!attribute record_class
|
12
10
|
# The class of the record being deserialized
|
13
11
|
#
|
14
12
|
# @return [Class] The class of the record
|
15
13
|
self.record_class = Solace::Instruction
|
16
14
|
|
17
|
-
# @!attribute
|
15
|
+
# @!attribute steps
|
18
16
|
# An ordered list of methods to deserialize the instruction
|
19
17
|
#
|
20
18
|
# @return [Array] The steps to deserialize the instruction
|
@@ -1,14 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Instruction Serializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Serializes a Solana instruction to a binary format.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Serializes a Solana instruction to a binary format.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class InstructionSerializer < Solace::Serializers::BaseSerializer
|
11
|
-
# @!attribute
|
9
|
+
# @!attribute steps
|
12
10
|
# An ordered list of methods to serialize the instruction
|
13
11
|
#
|
14
12
|
# @return [Array] The steps to serialize the instruction
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Message Deserializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Deserializes a binary message into a Solace::Message object.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Deserializes a binary message into a Solace::Message object.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class MessageDeserializer < Solace::Serializers::BaseDeserializer
|
11
9
|
# @!attribute record_class
|
12
10
|
# The class of the record being deserialized
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Message Serializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Serializes a Solana message to a binary format.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Serializes a Solana message to a binary format.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class MessageSerializer < Solace::Serializers::BaseSerializer
|
11
9
|
# @!attribute steps
|
12
10
|
# An ordered list of methods to serialize the message
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Transaction Deserializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Deserializes a binary transaction into a Solace::Transaction object.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Deserializes a binary transaction into a Solace::Transaction object.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class TransactionDeserializer < Solace::Serializers::BaseDeserializer
|
11
9
|
# @!attribute record_class
|
12
10
|
# The class of the record being deserialized
|
@@ -14,7 +12,7 @@ module Solace
|
|
14
12
|
# @return [Class] The class of the record
|
15
13
|
self.record_class = Solace::Transaction
|
16
14
|
|
17
|
-
# @!attribute
|
15
|
+
# @!attribute steps
|
18
16
|
# An ordered list of methods to deserialize the transaction
|
19
17
|
#
|
20
18
|
# @return [Array] The steps to deserialize the transaction
|
@@ -42,7 +40,7 @@ module Solace
|
|
42
40
|
#
|
43
41
|
# @return [Solace::Message] The deserialized message instance
|
44
42
|
def next_extract_message
|
45
|
-
record.message = Solace::Serializers::MessageDeserializer.
|
43
|
+
record.message = Solace::Serializers::MessageDeserializer.new(io).call
|
46
44
|
end
|
47
45
|
end
|
48
46
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# =============================
|
4
|
-
# Transaction Serializer
|
5
|
-
# =============================
|
6
|
-
#
|
7
|
-
# Serializes a Solana transaction to a binary format.
|
8
3
|
module Solace
|
9
4
|
module Serializers
|
5
|
+
# Serializes a Solana transaction to a binary format.
|
6
|
+
#
|
7
|
+
# @since 0.0.1
|
10
8
|
class TransactionSerializer < Solace::Serializers::BaseSerializer
|
11
|
-
# @!
|
9
|
+
# @!attribute SIGNATURE_PLACEHOLDER
|
12
10
|
# @return [String] Placeholder for a signature in the transaction
|
13
11
|
SIGNATURE_PLACEHOLDER = ([0] * 64).pack('C*')
|
14
12
|
|
@@ -32,7 +30,7 @@ module Solace
|
|
32
30
|
#
|
33
31
|
# @return [Array<Integer>] The bytes of the encoded signatures
|
34
32
|
def encode_signatures
|
35
|
-
Codecs.encode_compact_u16(record.
|
33
|
+
Codecs.encode_compact_u16(record.message.num_required_signatures).bytes +
|
36
34
|
index_signatures(record.message.num_required_signatures)
|
37
35
|
end
|
38
36
|
|
data/lib/solace/transaction.rb
CHANGED
@@ -1,40 +1,54 @@
|
|
1
1
|
# encoding: ASCII-8BIT
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
# =============================
|
5
|
-
# Transaction
|
6
|
-
# =============================
|
7
|
-
#
|
8
|
-
# Class representing a Solana transaction.
|
9
|
-
#
|
10
|
-
# The BufferLayout is:
|
11
|
-
# - [Signatures (variable length)]
|
12
|
-
# - [Version (1 byte)] (if versioned)
|
13
|
-
# - [Message header (3 bytes)]
|
14
|
-
# - [Account keys (variable length)]
|
15
|
-
# - [Recent blockhash (32 bytes)]
|
16
|
-
# - [Instructions (variable length)]
|
17
|
-
# - [Address lookup table (variable length)] (if versioned)
|
18
|
-
#
|
19
4
|
module Solace
|
20
|
-
|
21
|
-
|
5
|
+
# Class representing a Solana transaction
|
6
|
+
#
|
7
|
+
# Transactions are the basic building blocks of Solana. They contain a message and an array of signatures. The
|
8
|
+
# message contains the instructions to be executed and the accounts that are used by the instructions. The signatures
|
9
|
+
# are the signatures of the accounts that are used by the instructions. This class provides methods for signing,
|
10
|
+
# serializing, and deserializing transactions.
|
11
|
+
#
|
12
|
+
# The BufferLayout is:
|
13
|
+
# - [Signatures (variable length)]
|
14
|
+
# - [Version (1 byte)] (if versioned)
|
15
|
+
# - [Message header (3 bytes)]
|
16
|
+
# - [Account keys (variable length)]
|
17
|
+
# - [Recent blockhash (32 bytes)]
|
18
|
+
# - [Instructions (variable length)]
|
19
|
+
# - [Address lookup table (variable length)] (if versioned)
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# # Create a new transaction
|
23
|
+
# tx = Solace::Transaction.new
|
24
|
+
#
|
25
|
+
# # Add a message to the transaction
|
26
|
+
# tx.message = Solace::Message.new(**message_params)
|
27
|
+
#
|
28
|
+
# # Sign the transaction
|
29
|
+
# tx.sign(payer_keypair)
|
30
|
+
#
|
31
|
+
# @since 0.0.1
|
32
|
+
class Transaction
|
33
|
+
include Solace::Concerns::BinarySerializable
|
34
|
+
|
35
|
+
# @!attribute SERIALIZER
|
22
36
|
# @return [Solace::Serializers::TransactionSerializer] The serializer for the transaction
|
23
37
|
SERIALIZER = Solace::Serializers::TransactionSerializer
|
24
38
|
|
25
|
-
# @!
|
39
|
+
# @!attribute DESERIALIZER
|
26
40
|
# @return [Solace::Serializers::TransactionDeserializer] The deserializer for the transaction
|
27
41
|
DESERIALIZER = Solace::Serializers::TransactionDeserializer
|
28
42
|
|
29
|
-
# @!
|
43
|
+
# @!attribute SIGNATURE_PLACEHOLDER
|
30
44
|
# @return [String] Placeholder for a signature in the transaction
|
31
45
|
SIGNATURE_PLACEHOLDER = Solace::Utils::Codecs.base58_to_binary('1' * 64)
|
32
46
|
|
33
|
-
# @!attribute
|
47
|
+
# @!attribute [rw] signatures
|
34
48
|
# @return [Array<String>] Signatures of the transaction (binary)
|
35
49
|
attr_accessor :signatures
|
36
50
|
|
37
|
-
# @!attribute
|
51
|
+
# @!attribute [rw] message
|
38
52
|
# @return [Solace::Message] Message of the transaction
|
39
53
|
attr_accessor :message
|
40
54
|
|
@@ -44,7 +58,7 @@ module Solace
|
|
44
58
|
# @param base64_tx [String] The base64 encoded transaction
|
45
59
|
# @return [Solace::Transaction] The deserialized transaction
|
46
60
|
def from(base64_tx)
|
47
|
-
DESERIALIZER.
|
61
|
+
DESERIALIZER.new(Solace::Utils::Codecs.base64_to_bytestream(base64_tx)).call
|
48
62
|
end
|
49
63
|
end
|
50
64
|
|
@@ -55,6 +69,7 @@ module Solace
|
|
55
69
|
signatures: [],
|
56
70
|
message: Solace::Message.new
|
57
71
|
)
|
72
|
+
super()
|
58
73
|
@signatures = signatures
|
59
74
|
@message = message
|
60
75
|
end
|
@@ -63,7 +78,7 @@ module Solace
|
|
63
78
|
#
|
64
79
|
# Calls sign_and_update_signatures for each keypair passed in.
|
65
80
|
#
|
66
|
-
# @param keypairs [<Solace::Keypair>] The keypairs to sign the transaction with
|
81
|
+
# @param keypairs [Array<Solace::Keypair>] The keypairs to sign the transaction with
|
67
82
|
# @return [Array<String>] The signatures of the transaction
|
68
83
|
def sign(*keypairs)
|
69
84
|
keypairs.map { |keypair| sign_and_update_signatures(keypair) }
|