solace 0.0.10 → 0.1.0

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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +104 -23
  3. data/README.md +10 -8
  4. data/lib/solace/composers/base.rb +35 -0
  5. data/lib/solace/composers/spl_token_program_initialize_mint_composer.rb +95 -0
  6. data/lib/solace/composers/spl_token_program_mint_to_composer.rb +86 -0
  7. data/lib/solace/composers/spl_token_program_transfer_composer.rb +90 -0
  8. data/lib/solace/composers/system_program_create_account_composer.rb +98 -0
  9. data/lib/solace/connection.rb +88 -13
  10. data/lib/solace/errors/confirmation_timeout.rb +18 -4
  11. data/lib/solace/errors/http_error.rb +16 -1
  12. data/lib/solace/errors/parse_error.rb +15 -1
  13. data/lib/solace/errors/rpc_error.rb +17 -1
  14. data/lib/solace/errors.rb +8 -3
  15. data/lib/solace/instructions/associated_token_account/create_associated_token_account_instruction.rb +9 -2
  16. data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +0 -1
  17. data/lib/solace/instructions/spl_token/transfer_instruction.rb +21 -0
  18. data/lib/solace/instructions/system_program/create_account_instruction.rb +30 -0
  19. data/lib/solace/instructions/system_program/transfer_instruction.rb +11 -0
  20. data/lib/solace/programs/associated_token_account.rb +57 -30
  21. data/lib/solace/programs/base.rb +23 -0
  22. data/lib/solace/programs/spl_token.rb +197 -125
  23. data/lib/solace/serializers/base_serializer.rb +29 -1
  24. data/lib/solace/tokens/token.rb +53 -0
  25. data/lib/solace/tokens.rb +86 -0
  26. data/lib/solace/transaction.rb +24 -21
  27. data/lib/solace/transaction_composer.rb +77 -3
  28. data/lib/solace/utils/account_context.rb +1 -1
  29. data/lib/solace/utils/codecs.rb +17 -0
  30. data/lib/solace/utils/pda.rb +13 -5
  31. data/lib/solace/version.rb +3 -2
  32. data/lib/solace.rb +38 -11
  33. metadata +21 -1
@@ -2,7 +2,16 @@
2
2
 
3
3
  # lib/solace/transaction_composer.rb
4
4
  module Solace
5
- # Composes multi-instruction transactions with automatic account management
5
+ # Composes transactions with automatic account management and instruction building.
6
+ #
7
+ # This class allows you to add multiple instruction composers, manage account contexts,
8
+ # and build a complete transaction in a flexible way. It is a high-level abstraction over
9
+ # the process of creating Solana transactions, making it easier to work with complex
10
+ # transaction scenarios.
11
+ #
12
+ # For most use cases, you will create an instance of this class, add instruction composers,
13
+ # and then call the `compose_transaction` method to build the final transaction. That said,
14
+ # all of the individual pieces are also accessible for more advanced use cases.
6
15
  #
7
16
  # @example
8
17
  # # Initialize a transaction composer
@@ -38,6 +47,18 @@ module Solace
38
47
  # # Sign the transaction with all required signers
39
48
  # tx.sign(*required_signers)
40
49
  #
50
+ # @example
51
+ # # Chaining methods will return the composer itself for further modifications. The add, prepend,
52
+ # # and insert methods allow for dynamic insertion of instruction composers at required positions.
53
+ # transaction_composer = Solace::TransactionComposer
54
+ # .new(connection: connection)
55
+ # .add_instruction(instruction_composer_1)
56
+ # .prepend_instruction(instruction_composer_2)
57
+ # .insert_instruction(1, instruction_composer_3)
58
+ # .set_fee_payer(fee_payer_pubkey)
59
+ # .compose_transaction
60
+ #
61
+ # @see Solace::Composers::Base
41
62
  # @since 0.0.6
42
63
  class TransactionComposer
43
64
  # @!attribute connection
@@ -71,9 +92,62 @@ module Solace
71
92
  self
72
93
  end
73
94
 
95
+ # Prepend an instruction composer to the transaction
96
+ #
97
+ # @param composer [Composers::Base] The instruction composer
98
+ # @return [TransactionComposer] Self for chaining
99
+ #
100
+ # @since 0.1.0
101
+ def prepend_instruction(composer)
102
+ merge_accounts(composer.account_context)
103
+ instruction_composers.unshift(composer)
104
+ self
105
+ end
106
+
107
+ # Insert an instruction composer at a specific index
108
+ #
109
+ # @param index [Integer] The index to insert at
110
+ # @param composer [Composers::Base] The instruction composer
111
+ # @return [TransactionComposer] Self for chaining
112
+ #
113
+ # @since 0.1.0
114
+ def insert_instruction(index, composer)
115
+ merge_accounts(composer.account_context)
116
+ instruction_composers.insert(index, composer)
117
+ self
118
+ end
119
+
120
+ # Merge another TransactionComposer into this one
121
+ #
122
+ # @param other [TransactionComposer] The other composer to merge
123
+ # @param placement [Symbol] :add to append, :prepend to prepend
124
+ # @param index [Integer, nil] The index to insert at if placement is :insert
125
+ # @return [TransactionComposer] Self for chaining
126
+ #
127
+ # @since 0.1.0
128
+ def merge(other, placement: :add, index: nil)
129
+ merge_accounts(other.context)
130
+
131
+ case placement
132
+ when :add
133
+ # Appends the other's instruction composers to this one's list
134
+ instruction_composers.concat(other.instruction_composers)
135
+ when :insert
136
+ # Inserts the other's instruction composers at the specified index
137
+ instruction_composers.insert(index, *other.instruction_composers)
138
+ when :prepend
139
+ # Prepends the other's instruction composers to this one's list
140
+ instruction_composers.unshift(*other.instruction_composers)
141
+ else
142
+ raise ArgumentError, "Invalid placement option: #{placement}"
143
+ end
144
+
145
+ self
146
+ end
147
+
74
148
  # Set the fee payer for the transaction
75
149
  #
76
- # @param pubkey [String, Solace::PublicKey, Solace::Keypair] The fee payer pubkey
150
+ # @param pubkey [#to_s, PublicKey] The fee payer pubkey
77
151
  # @return [TransactionComposer] Self for chaining
78
152
  def set_fee_payer(pubkey)
79
153
  context.set_fee_payer(pubkey.to_s)
@@ -82,7 +156,7 @@ module Solace
82
156
 
83
157
  # Compose the final transaction
84
158
  #
85
- # @return [Solace::Transaction] The composed transaction (unsigned)
159
+ # @return [Transaction] The composed transaction (unsigned)
86
160
  def compose_transaction
87
161
  context.compile
88
162
 
@@ -199,7 +199,7 @@ module Solace
199
199
 
200
200
  # Add or merge an account into the context
201
201
  #
202
- # @param pubkey [String, Solace::PublicKey, Solace::Keypair] The public key of the account
202
+ # @param pubkey [#to_s, PublicKey] The public key of the account
203
203
  # @param signer [Boolean] Whether the account is a signer
204
204
  # @param writable [Boolean] Whether the account is writable
205
205
  # @param [Boolean] fee_payer
@@ -6,6 +6,23 @@ require 'base58'
6
6
  require 'stringio'
7
7
 
8
8
  module Solace
9
+ # The Utils module contains utility classes and helper methods used throughout
10
+ # the Solace gem.
11
+ #
12
+ # This module provides foundational utilities that support the core functionality
13
+ # of the gem, including:
14
+ # - {Solace::Utils::AccountContext} - Account management for transactions
15
+ # - {Solace::Utils::Codecs} - Encoding and decoding utilities
16
+ # - {Solace::Utils::Curve25519Dalek} - Cryptographic operations via FFI
17
+ # - {Solace::Utils::PDA} - Program Derived Address generation
18
+ # - {Solace::Utils::RPCClient} - Low-level RPC communication
19
+ #
20
+ # These utilities are primarily used internally by other parts of the gem, but
21
+ # can also be used directly for advanced use cases.
22
+ #
23
+ # @see Solace::Connection
24
+ # @see Solace::Keypair
25
+ # @since 0.0.1
9
26
  module Utils
10
27
  # Module for encoding and decoding data
11
28
  #
@@ -5,13 +5,21 @@ require 'digest'
5
5
 
6
6
  module Solace
7
7
  module Utils
8
- # Module for generating program addresses
8
+ # Raised when Program Derived Address (PDA) generation fails.
9
9
  #
10
- # This module provides methods for generating program addresses from seeds and program IDs. It interfaces
11
- # with the Curve25519 Dalek library to check if a point is on the curve. It also provides a method for
12
- # converting seeds to bytes and a method for checking if a string looks like a base58 address.
10
+ # This error is raised when attempting to derive a PDA that is invalid, typically
11
+ # because the seeds and program ID combination results in a point that lies on
12
+ # the Ed25519 curve (PDAs must be off-curve). This is a rare occurrence but can
13
+ # happen with certain seed combinations.
13
14
  #
14
- # @see Solace::Utils::Curve25519Dalek
15
+ # @example Handling invalid PDA
16
+ # begin
17
+ # pda = Solace::Utils::PDA.find_program_address(seeds, program_id)
18
+ # rescue Solace::Utils::PDA::InvalidPDAError => e
19
+ # puts "Failed to derive PDA: #{e.message}"
20
+ # end
21
+ #
22
+ # @see Solace::Utils::PDA
15
23
  # @since 0.0.1
16
24
  module PDA
17
25
  # InvalidPDAError is an error raised when an invalid PDA is generated
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Solace::VERSION is the version of the Solace gem
4
3
  module Solace
5
- VERSION = '0.0.10'
4
+ # Latest version of the Solace gem.
5
+ # @since 0.1.0
6
+ VERSION = '0.1.0'
6
7
  end
data/lib/solace.rb CHANGED
@@ -1,9 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # 🏷️ Version
3
+ # Solace is a Ruby gem for interacting with the Solana blockchain.
4
+ #
5
+ # This gem provides a comprehensive toolkit for building, signing, and sending
6
+ # transactions to Solana RPC nodes. It includes utilities for managing keypairs,
7
+ # composing complex instructions, serializing data, and interacting with
8
+ # on-chain programs like the System Program, SPL Token Program, and Associated
9
+ # Token Account Program.
10
+ #
11
+ # The gem is designed to be modular and extensible, with clear separation between
12
+ # low-level primitives (instructions, serializers) and high-level abstractions
13
+ # (composers, programs).
14
+ #
15
+ # @example Basic usage
16
+ # # Connect to a Solana RPC node
17
+ # connection = Solace::Connection.new('https://api.mainnet-beta.solana.com')
18
+ #
19
+ # # Generate a keypair
20
+ # keypair = Solace::Keypair.generate
21
+ #
22
+ # # Check balance
23
+ # balance = connection.get_balance(keypair.public_key)
24
+ #
25
+ # @see https://docs.solana.com/
26
+ # @see https://github.com/zarpay/solace
27
+ # @author Sebastian Scholl
28
+ # @since 0.0.1
29
+ module Solace; end
30
+
31
+ # Version
4
32
  require_relative 'solace/version'
5
33
 
6
- # 🛠️ Helpers
34
+ # Helpers
7
35
  require_relative 'solace/errors'
8
36
  require_relative 'solace/constants'
9
37
  require_relative 'solace/connection'
@@ -13,11 +41,14 @@ require_relative 'solace/utils/account_context'
13
41
  require_relative 'solace/utils/curve25519_dalek'
14
42
  require_relative 'solace/concerns/binary_serializable'
15
43
 
16
- # ✨ Serializers
44
+ # Tokens
45
+ require_relative 'solace/tokens'
46
+
47
+ # Serializers
17
48
  require_relative 'solace/serializers/base_serializer'
18
49
  require_relative 'solace/serializers/base_deserializer'
19
50
 
20
- # 🧬 Primitives
51
+ # Primitives
21
52
  require_relative 'solace/keypair'
22
53
  require_relative 'solace/public_key'
23
54
  require_relative 'solace/transaction'
@@ -30,16 +61,12 @@ require_relative 'solace/transaction_composer'
30
61
  require_relative 'solace/programs/base'
31
62
  require_relative 'solace/composers/base'
32
63
 
33
- # 📦 Composers
34
- #
35
- # Glob require all composers
64
+ # Composers
36
65
  Dir[File.join(__dir__, 'solace/composers', '**', '*.rb')].each { |file| require file }
37
66
 
38
- # 📦 Instructions (Builders)
39
- #
40
- # Glob require all instructions
67
+ # Instructions (Builders)
41
68
  Dir[File.join(__dir__, 'solace/instructions', '**', '*.rb')].each { |file| require file }
42
69
 
43
- # 📦 Programs
70
+ # Programs
44
71
  require_relative 'solace/programs/spl_token'
45
72
  require_relative 'solace/programs/associated_token_account'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Scholl
@@ -79,6 +79,20 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '13.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: tty-spinner
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
82
96
  description: A Ruby library for working with Solana blockchain. Provides both low-level
83
97
  instruction builders and high-level program clients for interacting with Solana
84
98
  programs.
@@ -95,7 +109,11 @@ files:
95
109
  - lib/solace/address_lookup_table.rb
96
110
  - lib/solace/composers/associated_token_account_program_create_account_composer.rb
97
111
  - lib/solace/composers/base.rb
112
+ - lib/solace/composers/spl_token_program_initialize_mint_composer.rb
113
+ - lib/solace/composers/spl_token_program_mint_to_composer.rb
98
114
  - lib/solace/composers/spl_token_program_transfer_checked_composer.rb
115
+ - lib/solace/composers/spl_token_program_transfer_composer.rb
116
+ - lib/solace/composers/system_program_create_account_composer.rb
99
117
  - lib/solace/composers/system_program_transfer_composer.rb
100
118
  - lib/solace/concerns/binary_serializable.rb
101
119
  - lib/solace/connection.rb
@@ -130,6 +148,8 @@ files:
130
148
  - lib/solace/serializers/message_serializer.rb
131
149
  - lib/solace/serializers/transaction_deserializer.rb
132
150
  - lib/solace/serializers/transaction_serializer.rb
151
+ - lib/solace/tokens.rb
152
+ - lib/solace/tokens/token.rb
133
153
  - lib/solace/transaction.rb
134
154
  - lib/solace/transaction_composer.rb
135
155
  - lib/solace/utils/account_context.rb