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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +57 -0
  3. data/LICENSE +21 -0
  4. data/README.md +142 -287
  5. data/lib/solace/address_lookup_table.rb +34 -18
  6. data/lib/solace/composers/base.rb +45 -0
  7. data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +113 -0
  8. data/lib/solace/composers/system_program_transfer_composer.rb +80 -0
  9. data/lib/solace/concerns/binary_serializable.rb +39 -0
  10. data/lib/solace/connection.rb +101 -44
  11. data/lib/solace/constants.rb +7 -14
  12. data/lib/solace/instruction.rb +30 -19
  13. data/lib/solace/instructions/associated_token_account/create_associated_token_account_instruction.rb +18 -3
  14. data/lib/solace/instructions/spl_token/initialize_account_instruction.rb +24 -3
  15. data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +18 -1
  16. data/lib/solace/instructions/spl_token/mint_to_instruction.rb +16 -3
  17. data/lib/solace/instructions/spl_token/transfer_checked_instruction.rb +76 -0
  18. data/lib/solace/instructions/spl_token/transfer_instruction.rb +15 -2
  19. data/lib/solace/instructions/system_program/create_account_instruction.rb +18 -3
  20. data/lib/solace/instructions/system_program/transfer_instruction.rb +58 -0
  21. data/lib/solace/keypair.rb +64 -31
  22. data/lib/solace/message.rb +22 -10
  23. data/lib/solace/programs/associated_token_account.rb +58 -11
  24. data/lib/solace/programs/base.rb +6 -0
  25. data/lib/solace/programs/spl_token.rb +52 -14
  26. data/lib/solace/public_key.rb +45 -20
  27. data/lib/solace/serializers/address_lookup_table_deserializer.rb +3 -5
  28. data/lib/solace/serializers/address_lookup_table_serializer.rb +7 -7
  29. data/lib/solace/serializers/base_deserializer.rb +29 -19
  30. data/lib/solace/serializers/base_serializer.rb +18 -9
  31. data/lib/solace/serializers/instruction_deserializer.rb +5 -7
  32. data/lib/solace/serializers/instruction_serializer.rb +4 -6
  33. data/lib/solace/serializers/message_deserializer.rb +3 -5
  34. data/lib/solace/serializers/message_serializer.rb +3 -5
  35. data/lib/solace/serializers/transaction_deserializer.rb +5 -7
  36. data/lib/solace/serializers/transaction_serializer.rb +5 -7
  37. data/lib/solace/transaction.rb +38 -23
  38. data/lib/solace/transaction_composer.rb +115 -0
  39. data/lib/solace/utils/account_context.rb +252 -0
  40. data/lib/solace/utils/codecs.rb +56 -128
  41. data/lib/solace/utils/curve25519_dalek.rb +9 -4
  42. data/lib/solace/utils/pda.rb +22 -24
  43. data/lib/solace/version.rb +2 -1
  44. data/lib/solace.rb +9 -7
  45. metadata +15 -12
  46. data/lib/solace/instructions/transfer_checked_instruction.rb +0 -58
  47. data/lib/solace/instructions/transfer_instruction.rb +0 -48
  48. data/lib/solace/serializable_record.rb +0 -26
  49. data/lib/solace/serializers/base.rb +0 -31
@@ -2,7 +2,31 @@
2
2
 
3
3
  module Solace
4
4
  module Programs
5
- # A client for interacting with the SPL Token Program.
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 options [Hash] Options for calling the prepare_mint_to method.
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
@@ -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
- # !@const LENGTH
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
- # !@const MAX_BUMP_SEED
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
- # !@const PDA_MARKER
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
- # !@attribute bytes
32
- # @return [Array<Integer>] The bytes of the public key
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 + record.writable_indexes
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 + record.readonly_indexes
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
- # Base deserializer class
12
- class BaseDeserializer < Serializers::Base
13
- class << self
14
- # @!attribute STEPS
15
- # An ordered list of methods to deserialize the record
16
- #
17
- # @return [Array] The steps to deserialize the record
18
- attr_accessor :steps
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 or StringIO] The input to read bytes from.
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 :io, :record
31
+ attr_reader :record
37
32
 
38
33
  # Initialize a new deserializer
39
34
  #
40
- # @param io [IO or StringIO] The input to read bytes from.
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
- # Base serializer class
12
- class BaseSerializer < Serializers::Base
13
- class << self
14
- # @!attribute STEPS
15
- # An ordered list of methods to deserialize the record
16
- #
17
- # @return [Array] The steps to deserialize the record
18
- attr_accessor :steps
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 record_class
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 steps
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 steps
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 steps
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.call(io)
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
- # @!const SIGNATURE_PLACEHOLDER
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.signatures.size).bytes +
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
 
@@ -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
- class Transaction < Solace::SerializableRecord
21
- # @!const SERIALIZER
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
- # @!const DESERIALIZER
39
+ # @!attribute DESERIALIZER
26
40
  # @return [Solace::Serializers::TransactionDeserializer] The deserializer for the transaction
27
41
  DESERIALIZER = Solace::Serializers::TransactionDeserializer
28
42
 
29
- # @!const SIGNATURE_PLACEHOLDER
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 [rw] signatures
47
+ # @!attribute [rw] signatures
34
48
  # @return [Array<String>] Signatures of the transaction (binary)
35
49
  attr_accessor :signatures
36
50
 
37
- # @!attribute [rw] message
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.call Solace::Utils::Codecs.base64_to_bytestream(base64_tx)
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) }