solace 0.0.3 → 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 +12 -0
- data/README.md +140 -285
- data/lib/solace/address_lookup_table.rb +34 -18
- data/lib/solace/composers/base.rb +16 -11
- data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +27 -1
- data/lib/solace/composers/system_program_transfer_composer.rb +22 -1
- data/lib/solace/concerns/binary_serializable.rb +39 -0
- data/lib/solace/connection.rb +69 -38
- 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 +17 -1
- 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 +15 -7
- data/lib/solace/keypair.rb +64 -31
- data/lib/solace/message.rb +22 -10
- data/lib/solace/programs/associated_token_account.rb +45 -20
- 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 +47 -13
- data/lib/solace/utils/account_context.rb +64 -65
- 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 +4 -9
- metadata +7 -10
- data/lib/solace/instructions/base.rb +0 -21
- data/lib/solace/serializable_record.rb +0 -26
- data/lib/solace/serializers/base.rb +0 -31
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) }
|
@@ -1,21 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# lib/solace/transaction_composer.rb
|
2
4
|
module Solace
|
3
5
|
# Composes multi-instruction transactions with automatic account management
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# # Initialize a transaction composer
|
9
|
+
# composer = Solace::TransactionComposer.new(connection: connection)
|
10
|
+
#
|
11
|
+
# # Add an instruction composer
|
12
|
+
# composer.add_instruction(
|
13
|
+
# Solace::Composers::SystemProgramTransferComposer.new(
|
14
|
+
# to: 'pubkey1',
|
15
|
+
# from: 'pubkey2',
|
16
|
+
# lamports: 100
|
17
|
+
# )
|
18
|
+
# )
|
19
|
+
#
|
20
|
+
# # Add another instruction composer
|
21
|
+
# composer.add_instruction(
|
22
|
+
# Solace::Composers::SplTokenProgramTransferCheckedComposer.new(
|
23
|
+
# from: 'pubkey4',
|
24
|
+
# to: 'pubkey5',
|
25
|
+
# mint: 'pubkey6',
|
26
|
+
# authority: 'pubkey7',
|
27
|
+
# amount: 1_000_000,
|
28
|
+
# decimals: 6
|
29
|
+
# )
|
30
|
+
# )
|
31
|
+
#
|
32
|
+
# # Set the fee payer
|
33
|
+
# composer.set_fee_payer('pubkey8')
|
34
|
+
#
|
35
|
+
# # Compose the transaction
|
36
|
+
# tx = composer.compose_transaction
|
37
|
+
#
|
38
|
+
# # Sign the transaction with all required signers
|
39
|
+
# tx.sign(*required_signers)
|
40
|
+
#
|
41
|
+
# @since 0.0.1
|
4
42
|
class TransactionComposer
|
5
|
-
|
6
43
|
# @!attribute connection
|
7
|
-
#
|
8
|
-
# @return [Solace::Connection] The connection to the Solana cluster
|
44
|
+
# The connection to the Solana cluster
|
9
45
|
attr_reader :connection
|
10
46
|
|
11
47
|
# @!attribute context
|
12
|
-
#
|
13
|
-
# @return [Utils::AccountContext] The account registry
|
48
|
+
# The account context
|
14
49
|
attr_reader :context
|
15
50
|
|
16
51
|
# @!attribute instruction_composers
|
17
|
-
#
|
18
|
-
# @return [Array<Composers::Base>] The instruction composers
|
52
|
+
# The instruction composers
|
19
53
|
attr_reader :instruction_composers
|
20
54
|
|
21
55
|
# Initialize the composer
|
@@ -26,7 +60,7 @@ module Solace
|
|
26
60
|
@instruction_composers = []
|
27
61
|
@context = Utils::AccountContext.new
|
28
62
|
end
|
29
|
-
|
63
|
+
|
30
64
|
# Add an instruction composer to the transaction
|
31
65
|
#
|
32
66
|
# @param composer [Composers::Base] The instruction composer
|
@@ -36,10 +70,10 @@ module Solace
|
|
36
70
|
instruction_composers << composer
|
37
71
|
self
|
38
72
|
end
|
39
|
-
|
73
|
+
|
40
74
|
# Set the fee payer for the transaction
|
41
75
|
#
|
42
|
-
# @param pubkey [String
|
76
|
+
# @param pubkey [String, Solace::PublicKey, Solace::Keypair] The fee payer pubkey
|
43
77
|
# @return [TransactionComposer] Self for chaining
|
44
78
|
def set_fee_payer(pubkey)
|
45
79
|
context.set_fee_payer(pubkey)
|
@@ -56,11 +90,11 @@ module Solace
|
|
56
90
|
header: context.header,
|
57
91
|
accounts: context.accounts,
|
58
92
|
instructions: build_instructions,
|
59
|
-
recent_blockhash: connection.get_latest_blockhash
|
93
|
+
recent_blockhash: connection.get_latest_blockhash
|
60
94
|
)
|
61
|
-
|
95
|
+
|
62
96
|
Solace::Transaction.new(message: message)
|
63
|
-
end
|
97
|
+
end
|
64
98
|
|
65
99
|
private
|
66
100
|
|