solace 0.1.4 → 0.1.6
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/solace/composers/associated_token_account_program_create_account_composer.rb +11 -10
- data/lib/solace/composers/associated_token_account_program_create_idempotent_account_composer.rb +2 -1
- data/lib/solace/composers/base.rb +1 -1
- data/lib/solace/composers/spl_token_program_close_account_composer.rb +3 -3
- data/lib/solace/composers/spl_token_program_initialize_mint_composer.rb +5 -5
- data/lib/solace/composers/spl_token_program_mint_to_composer.rb +4 -4
- data/lib/solace/composers/spl_token_program_transfer_checked_composer.rb +6 -6
- data/lib/solace/composers/spl_token_program_transfer_composer.rb +4 -4
- data/lib/solace/composers/system_program_create_account_composer.rb +5 -5
- data/lib/solace/composers/system_program_transfer_composer.rb +3 -3
- data/lib/solace/composers/token_2022_program_close_account_composer.rb +75 -0
- data/lib/solace/composers/token_2022_program_initialize_mint_composer.rb +93 -0
- data/lib/solace/composers/token_2022_program_mint_to_composer.rb +84 -0
- data/lib/solace/composers/token_2022_program_transfer_checked_composer.rb +109 -0
- data/lib/solace/composers/token_2022_program_transfer_composer.rb +86 -0
- data/lib/solace/connection.rb +29 -9
- data/lib/solace/constants.rb +8 -2
- data/lib/solace/errors/confirmation_timeout.rb +4 -4
- data/lib/solace/errors/rpc_error.rb +4 -4
- data/lib/solace/instructions/associated_token_account/create_account_instruction.rb +2 -1
- data/lib/solace/instructions/spl_token/close_account_instruction.rb +2 -2
- data/lib/solace/instructions/spl_token/initialize_account_instruction.rb +2 -2
- data/lib/solace/instructions/spl_token/initialize_mint_instruction.rb +2 -2
- data/lib/solace/instructions/spl_token/mint_to_instruction.rb +2 -2
- data/lib/solace/instructions/spl_token/transfer_checked_instruction.rb +3 -3
- data/lib/solace/instructions/spl_token/transfer_instruction.rb +2 -2
- data/lib/solace/instructions/system_program/create_account_instruction.rb +2 -2
- data/lib/solace/instructions/system_program/transfer_instruction.rb +2 -2
- data/lib/solace/instructions/token_2022/close_account_instruction.rb +50 -0
- data/lib/solace/instructions/token_2022/initialize_account_instruction.rb +62 -0
- data/lib/solace/instructions/token_2022/initialize_mint_instruction.rb +75 -0
- data/lib/solace/instructions/token_2022/mint_to_instruction.rb +59 -0
- data/lib/solace/instructions/token_2022/transfer_checked_instruction.rb +68 -0
- data/lib/solace/instructions/token_2022/transfer_instruction.rb +71 -0
- data/lib/solace/message.rb +5 -5
- data/lib/solace/programs/associated_token_account.rb +35 -17
- data/lib/solace/programs/spl_token.rb +18 -254
- data/lib/solace/programs/token_2022.rb +70 -0
- data/lib/solace/programs/token_program_interface.rb +312 -0
- data/lib/solace/serializers/address_lookup_table_deserializer.rb +2 -2
- data/lib/solace/serializers/base_deserializer.rb +1 -1
- data/lib/solace/serializers/instruction_deserializer.rb +2 -2
- data/lib/solace/serializers/message_deserializer.rb +3 -3
- data/lib/solace/serializers/transaction_deserializer.rb +1 -1
- data/lib/solace/tokens/token.rb +1 -1
- data/lib/solace/tokens.rb +2 -2
- data/lib/solace/transaction.rb +1 -1
- data/lib/solace/transaction_composer.rb +5 -5
- data/lib/solace/utils/account_context.rb +9 -9
- data/lib/solace/utils/codecs.rb +309 -49
- data/lib/solace/utils/rpc_client.rb +9 -9
- data/lib/solace/version.rb +1 -1
- data/lib/solace.rb +2 -0
- metadata +124 -9
- data/CHANGELOG +0 -226
- data/LICENSE +0 -21
- data/README.md +0 -518
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solace
|
|
4
|
+
module Programs
|
|
5
|
+
# Mixin describing the common surface of a token-program client.
|
|
6
|
+
#
|
|
7
|
+
# The legacy SPL Token program and Token-2022 expose a wire-compatible
|
|
8
|
+
# base instruction set (Transfer, TransferChecked, CloseAccount, MintTo,
|
|
9
|
+
# InitializeMint). This module captures the *shape* of a client that
|
|
10
|
+
# speaks that surface — the public methods +create_mint+, +mint_to+,
|
|
11
|
+
# +transfer+, +transfer_checked+ and their +compose_*+ pairs — without
|
|
12
|
+
# binding to either program.
|
|
13
|
+
#
|
|
14
|
+
# State (connection, program_id) lives on {Programs::Base}; this module
|
|
15
|
+
# is purely behavior. Including classes must implement four private
|
|
16
|
+
# readers that name the composer class for each operation:
|
|
17
|
+
#
|
|
18
|
+
# - {#initialize_mint_composer_class}
|
|
19
|
+
# - {#mint_to_composer_class}
|
|
20
|
+
# - {#transfer_composer_class}
|
|
21
|
+
# - {#transfer_checked_composer_class}
|
|
22
|
+
#
|
|
23
|
+
# Each composer returned by those readers is itself bound to a single
|
|
24
|
+
# on-chain program, which is how this mixin keeps the boundary clean:
|
|
25
|
+
# +SplToken+ and +Token2022+ share *methods* but never share a composer.
|
|
26
|
+
#
|
|
27
|
+
# @see Solace::Programs::SplToken
|
|
28
|
+
# @see Solace::Programs::Token2022
|
|
29
|
+
# @since 0.1.5
|
|
30
|
+
# rubocop:disable Metrics/ModuleLength
|
|
31
|
+
module TokenProgramInterface
|
|
32
|
+
# Creates a new mint, signs it, and (optionally) sends it.
|
|
33
|
+
#
|
|
34
|
+
# @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
|
|
35
|
+
# @param sign [Boolean] Whether to sign the transaction.
|
|
36
|
+
# @param execute [Boolean] Whether to execute the transaction.
|
|
37
|
+
# @param composer_opts [Hash] Options for {#compose_create_mint}.
|
|
38
|
+
# @return [Transaction] The created or sent transaction.
|
|
39
|
+
def create_mint(
|
|
40
|
+
payer:,
|
|
41
|
+
sign: true,
|
|
42
|
+
execute: true,
|
|
43
|
+
**composer_opts
|
|
44
|
+
)
|
|
45
|
+
composer = compose_create_mint(**composer_opts)
|
|
46
|
+
|
|
47
|
+
yield composer if block_given?
|
|
48
|
+
|
|
49
|
+
tx = composer
|
|
50
|
+
.set_fee_payer(payer)
|
|
51
|
+
.compose_transaction
|
|
52
|
+
|
|
53
|
+
if sign
|
|
54
|
+
tx.sign(
|
|
55
|
+
payer,
|
|
56
|
+
composer_opts[:funder],
|
|
57
|
+
composer_opts[:mint_account]
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
connection.send_transaction(tx.serialize) if execute
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
tx
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Prepares a new mint transaction.
|
|
67
|
+
#
|
|
68
|
+
# @param funder [#to_s, PublicKey] The keypair that will pay for rent of the new mint account.
|
|
69
|
+
# @param decimals [Integer] The number of decimal places for the token.
|
|
70
|
+
# @param mint_authority [#to_s, PublicKey] The base58 public key for the mint authority.
|
|
71
|
+
# @param freeze_authority [#to_s, PublicKey] (Optional) The base58 public key for the freeze authority.
|
|
72
|
+
# @param mint_account [#to_s, PublicKey] (Optional) The keypair for the new mint.
|
|
73
|
+
# @return [TransactionComposer] A composer with required instructions.
|
|
74
|
+
# rubocop:disable Metrics/MethodLength
|
|
75
|
+
def compose_create_mint(
|
|
76
|
+
funder:,
|
|
77
|
+
decimals:,
|
|
78
|
+
mint_authority:,
|
|
79
|
+
freeze_authority: nil,
|
|
80
|
+
mint_account: Solace::Keypair.generate
|
|
81
|
+
)
|
|
82
|
+
# Mint accounts need 82 bytes of space, and we need to fund it with enough lamports to be rent-exempt
|
|
83
|
+
rent_lamports = connection.get_minimum_lamports_for_rent_exemption(82)
|
|
84
|
+
|
|
85
|
+
# Build the account for the mint
|
|
86
|
+
create_account_ix = Composers::SystemProgramCreateAccountComposer.new(
|
|
87
|
+
from: funder,
|
|
88
|
+
new_account: mint_account,
|
|
89
|
+
owner: program_id,
|
|
90
|
+
lamports: rent_lamports,
|
|
91
|
+
space: 82
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Build the initialize mint composer (per-program class supplied by includer)
|
|
95
|
+
initialize_mint_ix = initialize_mint_composer_class.new(
|
|
96
|
+
decimals: decimals,
|
|
97
|
+
mint_account: mint_account,
|
|
98
|
+
mint_authority: mint_authority,
|
|
99
|
+
freeze_authority: freeze_authority
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
TransactionComposer
|
|
103
|
+
.new(connection: connection)
|
|
104
|
+
.add_instruction(create_account_ix)
|
|
105
|
+
.add_instruction(initialize_mint_ix)
|
|
106
|
+
end
|
|
107
|
+
# rubocop:enable Metrics/MethodLength
|
|
108
|
+
|
|
109
|
+
# Mints tokens to a token account.
|
|
110
|
+
#
|
|
111
|
+
# @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
|
|
112
|
+
# @param sign [Boolean] Whether to sign the transaction.
|
|
113
|
+
# @param execute [Boolean] Whether to execute the transaction.
|
|
114
|
+
# @param composer_opts [Hash] Options for {#compose_mint_to}.
|
|
115
|
+
# @return [Transaction] The created or sent transaction.
|
|
116
|
+
def mint_to(
|
|
117
|
+
payer:,
|
|
118
|
+
sign: true,
|
|
119
|
+
execute: true,
|
|
120
|
+
**composer_opts
|
|
121
|
+
)
|
|
122
|
+
composer = compose_mint_to(**composer_opts)
|
|
123
|
+
|
|
124
|
+
yield composer if block_given?
|
|
125
|
+
|
|
126
|
+
tx = composer
|
|
127
|
+
.set_fee_payer(payer)
|
|
128
|
+
.compose_transaction
|
|
129
|
+
|
|
130
|
+
if sign
|
|
131
|
+
tx.sign(
|
|
132
|
+
payer,
|
|
133
|
+
composer_opts[:mint_authority]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
connection.send_transaction(tx.serialize) if execute
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
tx
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Prepares a mint_to instruction.
|
|
143
|
+
#
|
|
144
|
+
# @param amount [Integer] The amount of tokens to mint.
|
|
145
|
+
# @param mint [#to_s, PublicKey] The mint of the token.
|
|
146
|
+
# @param destination [#to_s, PublicKey] The destination token account.
|
|
147
|
+
# @param mint_authority [#to_s, PublicKey] The mint authority.
|
|
148
|
+
# @return [TransactionComposer] A composer with the mint_to instruction.
|
|
149
|
+
def compose_mint_to(
|
|
150
|
+
mint:,
|
|
151
|
+
amount:,
|
|
152
|
+
destination:,
|
|
153
|
+
mint_authority:
|
|
154
|
+
)
|
|
155
|
+
ix = mint_to_composer_class.new(
|
|
156
|
+
amount: amount,
|
|
157
|
+
mint: mint,
|
|
158
|
+
destination: destination,
|
|
159
|
+
mint_authority: mint_authority
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
TransactionComposer
|
|
163
|
+
.new(connection: connection)
|
|
164
|
+
.add_instruction(ix)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Transfers tokens from one account to another.
|
|
168
|
+
#
|
|
169
|
+
# @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
|
|
170
|
+
# @param sign [Boolean] Whether to sign the transaction.
|
|
171
|
+
# @param execute [Boolean] Whether to execute the transaction.
|
|
172
|
+
# @param composer_opts [Hash] Options for {#compose_transfer}.
|
|
173
|
+
# @return [Transaction] The created or sent transaction.
|
|
174
|
+
def transfer(
|
|
175
|
+
payer:,
|
|
176
|
+
sign: true,
|
|
177
|
+
execute: true,
|
|
178
|
+
**composer_opts
|
|
179
|
+
)
|
|
180
|
+
composer = compose_transfer(**composer_opts)
|
|
181
|
+
|
|
182
|
+
yield composer if block_given?
|
|
183
|
+
|
|
184
|
+
tx = composer
|
|
185
|
+
.set_fee_payer(payer)
|
|
186
|
+
.compose_transaction
|
|
187
|
+
|
|
188
|
+
if sign
|
|
189
|
+
tx.sign(
|
|
190
|
+
payer,
|
|
191
|
+
composer_opts[:owner]
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
connection.send_transaction(tx.serialize) if execute
|
|
195
|
+
end
|
|
196
|
+
tx
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Prepares a transfer instruction.
|
|
200
|
+
#
|
|
201
|
+
# @param source [#to_s, PublicKey] The source token account address.
|
|
202
|
+
# @param destination [#to_s, PublicKey] The destination token account address.
|
|
203
|
+
# @param amount [Integer] The number of tokens to transfer.
|
|
204
|
+
# @param owner [#to_s, PublicKey] The owner of the source account.
|
|
205
|
+
# @return [TransactionComposer] A composer with the transfer instruction.
|
|
206
|
+
def compose_transfer(
|
|
207
|
+
amount:,
|
|
208
|
+
source:,
|
|
209
|
+
destination:,
|
|
210
|
+
owner:
|
|
211
|
+
)
|
|
212
|
+
ix = transfer_composer_class.new(
|
|
213
|
+
amount: amount,
|
|
214
|
+
owner: owner,
|
|
215
|
+
source: source,
|
|
216
|
+
destination: destination
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
TransactionComposer
|
|
220
|
+
.new(connection: connection)
|
|
221
|
+
.add_instruction(ix)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Transfers tokens with decimal precision and validation checks.
|
|
225
|
+
#
|
|
226
|
+
# @param payer [#to_s, PublicKey] The keypair that will pay for fees and rent.
|
|
227
|
+
# @param sign [Boolean] Whether to sign the transaction.
|
|
228
|
+
# @param execute [Boolean] Whether to execute the transaction.
|
|
229
|
+
# @param composer_opts [Hash] Options for {#compose_transfer_checked}.
|
|
230
|
+
# @return [Transaction] The created or sent transaction.
|
|
231
|
+
def transfer_checked(
|
|
232
|
+
payer:,
|
|
233
|
+
sign: true,
|
|
234
|
+
execute: true,
|
|
235
|
+
**composer_opts
|
|
236
|
+
)
|
|
237
|
+
composer = compose_transfer_checked(**composer_opts)
|
|
238
|
+
|
|
239
|
+
yield composer if block_given?
|
|
240
|
+
|
|
241
|
+
tx = composer
|
|
242
|
+
.set_fee_payer(payer)
|
|
243
|
+
.compose_transaction
|
|
244
|
+
|
|
245
|
+
if sign
|
|
246
|
+
tx.sign(
|
|
247
|
+
payer,
|
|
248
|
+
composer_opts[:authority]
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
connection.send_transaction(tx.serialize) if execute
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
tx
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Prepares a transfer_checked instruction.
|
|
258
|
+
#
|
|
259
|
+
# @param amount [Integer] The number of tokens to transfer.
|
|
260
|
+
# @param decimals [Integer] The number of decimals for the token.
|
|
261
|
+
# @param from [#to_s, PublicKey] The source token account address.
|
|
262
|
+
# @param to [#to_s, PublicKey] The destination token account address.
|
|
263
|
+
# @param mint [#to_s, PublicKey] The mint address.
|
|
264
|
+
# @param authority [#to_s, PublicKey] The owner of the source account.
|
|
265
|
+
# @return [TransactionComposer] A composer with the transfer_checked instruction.
|
|
266
|
+
def compose_transfer_checked(
|
|
267
|
+
to:,
|
|
268
|
+
from:,
|
|
269
|
+
mint:,
|
|
270
|
+
authority:,
|
|
271
|
+
amount:,
|
|
272
|
+
decimals:
|
|
273
|
+
)
|
|
274
|
+
ix = transfer_checked_composer_class.new(
|
|
275
|
+
to: to,
|
|
276
|
+
from: from,
|
|
277
|
+
mint: mint,
|
|
278
|
+
authority: authority,
|
|
279
|
+
amount: amount,
|
|
280
|
+
decimals: decimals
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
TransactionComposer
|
|
284
|
+
.new(connection: connection)
|
|
285
|
+
.add_instruction(ix)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
private
|
|
289
|
+
|
|
290
|
+
# @return [Class] Composer class used by {#compose_create_mint}.
|
|
291
|
+
def initialize_mint_composer_class
|
|
292
|
+
raise NotImplementedError, "#{self.class} must implement #initialize_mint_composer_class"
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# @return [Class] Composer class used by {#compose_mint_to}.
|
|
296
|
+
def mint_to_composer_class
|
|
297
|
+
raise NotImplementedError, "#{self.class} must implement #mint_to_composer_class"
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# @return [Class] Composer class used by {#compose_transfer}.
|
|
301
|
+
def transfer_composer_class
|
|
302
|
+
raise NotImplementedError, "#{self.class} must implement #transfer_composer_class"
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# @return [Class] Composer class used by {#compose_transfer_checked}.
|
|
306
|
+
def transfer_checked_composer_class
|
|
307
|
+
raise NotImplementedError, "#{self.class} must implement #transfer_checked_composer_class"
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
# rubocop:enable Metrics/ModuleLength
|
|
311
|
+
end
|
|
312
|
+
end
|
|
@@ -40,7 +40,7 @@ module Solace
|
|
|
40
40
|
#
|
|
41
41
|
# @return [Array<Integer>] The writable indexes
|
|
42
42
|
def next_extract_writable_indexes
|
|
43
|
-
length,
|
|
43
|
+
length, = Codecs.decode_compact_u16(io)
|
|
44
44
|
record.writable_indexes = io.read(length).unpack('C*')
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ module Solace
|
|
|
52
52
|
#
|
|
53
53
|
# @return [Array<Integer>] The readonly indexes
|
|
54
54
|
def next_extract_readonly_indexes
|
|
55
|
-
length,
|
|
55
|
+
length, = Codecs.decode_compact_u16(io)
|
|
56
56
|
record.readonly_indexes = io.read(length).unpack('C*')
|
|
57
57
|
end
|
|
58
58
|
end
|
|
@@ -40,7 +40,7 @@ module Solace
|
|
|
40
40
|
#
|
|
41
41
|
# @return [Array] The accounts
|
|
42
42
|
def next_extract_accounts
|
|
43
|
-
length,
|
|
43
|
+
length, = Codecs.decode_compact_u16(io)
|
|
44
44
|
record.accounts = io.read(length).unpack('C*')
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -52,7 +52,7 @@ module Solace
|
|
|
52
52
|
#
|
|
53
53
|
# @return [Array] The instruction data
|
|
54
54
|
def next_extract_data
|
|
55
|
-
length,
|
|
55
|
+
length, = Codecs.decode_compact_u16(io)
|
|
56
56
|
record.data = io.read(length).unpack('C*')
|
|
57
57
|
end
|
|
58
58
|
end
|
|
@@ -64,7 +64,7 @@ module Solace
|
|
|
64
64
|
#
|
|
65
65
|
# @return [Array<String>] The account keys of the message
|
|
66
66
|
def next_extract_accounts
|
|
67
|
-
count,
|
|
67
|
+
count, = Codecs.decode_compact_u16(io)
|
|
68
68
|
record.accounts = count.times.map do
|
|
69
69
|
Codecs.bytes_to_base58 io.read(32).bytes
|
|
70
70
|
end
|
|
@@ -88,7 +88,7 @@ module Solace
|
|
|
88
88
|
#
|
|
89
89
|
# @return [Array<Solace::Instruction>] The instructions of the message
|
|
90
90
|
def next_extract_instructions
|
|
91
|
-
count,
|
|
91
|
+
count, = Codecs.decode_compact_u16(io)
|
|
92
92
|
record.instructions = count.times.map do
|
|
93
93
|
Solace::Instruction.deserialize(io)
|
|
94
94
|
end
|
|
@@ -104,7 +104,7 @@ module Solace
|
|
|
104
104
|
def next_extract_address_lookup_table
|
|
105
105
|
return unless record.versioned?
|
|
106
106
|
|
|
107
|
-
count,
|
|
107
|
+
count, = Codecs.decode_compact_u16(io)
|
|
108
108
|
record.address_lookup_tables = count.times.map do
|
|
109
109
|
Solace::AddressLookupTable.deserialize(io)
|
|
110
110
|
end
|
data/lib/solace/tokens/token.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Solace
|
|
|
18
18
|
# @param metadata [Hash] A hash containing the token's metadata attributes
|
|
19
19
|
# @return [self] The initialized Token object
|
|
20
20
|
def initialize(symbol, metadata)
|
|
21
|
-
@symbol
|
|
21
|
+
@symbol = symbol
|
|
22
22
|
@metadata = metadata.transform_keys(&:to_sym)
|
|
23
23
|
end
|
|
24
24
|
|
data/lib/solace/tokens.rb
CHANGED
|
@@ -29,7 +29,7 @@ module Solace
|
|
|
29
29
|
# @param network [String, Symbol] Network name (e.g., 'mainnet', 'testnet')
|
|
30
30
|
# @return [void]
|
|
31
31
|
def self.load(path:, network:)
|
|
32
|
-
data
|
|
32
|
+
data = YAML.load_file(path)
|
|
33
33
|
tokens = data.fetch(network.to_s) do
|
|
34
34
|
raise ArgumentError, "Network '#{network}' not found in config"
|
|
35
35
|
end
|
|
@@ -40,7 +40,7 @@ module Solace
|
|
|
40
40
|
@registry = {}
|
|
41
41
|
|
|
42
42
|
tokens.each do |symbol, attrs|
|
|
43
|
-
token
|
|
43
|
+
token = Solace::Tokens::Token.new(symbol, attrs)
|
|
44
44
|
const_set(symbol, token)
|
|
45
45
|
@registry[symbol.to_s] = token
|
|
46
46
|
end
|
data/lib/solace/transaction.rb
CHANGED
|
@@ -77,9 +77,9 @@ module Solace
|
|
|
77
77
|
#
|
|
78
78
|
# @param connection [Solace::Connection] The connection to the Solana cluster
|
|
79
79
|
def initialize(connection:)
|
|
80
|
-
@connection
|
|
80
|
+
@connection = connection
|
|
81
81
|
@instruction_composers = []
|
|
82
|
-
@context
|
|
82
|
+
@context = Utils::AccountContext.new
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
# Add an instruction composer to the transaction
|
|
@@ -161,9 +161,9 @@ module Solace
|
|
|
161
161
|
context.compile
|
|
162
162
|
|
|
163
163
|
message = Solace::Message.new(
|
|
164
|
-
header:
|
|
165
|
-
accounts:
|
|
166
|
-
instructions:
|
|
164
|
+
header: context.header,
|
|
165
|
+
accounts: context.accounts,
|
|
166
|
+
instructions: build_instructions,
|
|
167
167
|
recent_blockhash: connection.get_latest_blockhash[0]
|
|
168
168
|
)
|
|
169
169
|
|
|
@@ -35,8 +35,8 @@ module Solace
|
|
|
35
35
|
#
|
|
36
36
|
# @return [Hash] The default account data with lowest level of permissions
|
|
37
37
|
DEFAULT_ACCOUNT = {
|
|
38
|
-
signer:
|
|
39
|
-
writable:
|
|
38
|
+
signer: false,
|
|
39
|
+
writable: false,
|
|
40
40
|
fee_payer: false
|
|
41
41
|
}.freeze
|
|
42
42
|
|
|
@@ -60,8 +60,8 @@ module Solace
|
|
|
60
60
|
|
|
61
61
|
# Initialize the account context
|
|
62
62
|
def initialize
|
|
63
|
-
@header
|
|
64
|
-
@accounts
|
|
63
|
+
@header = []
|
|
64
|
+
@accounts = []
|
|
65
65
|
@pubkey_account_map = {}
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -175,7 +175,7 @@ module Solace
|
|
|
175
175
|
#
|
|
176
176
|
# @return [Hash] The compiled accounts and header
|
|
177
177
|
def compile
|
|
178
|
-
self.header
|
|
178
|
+
self.header = calculate_header
|
|
179
179
|
self.accounts = order_accounts
|
|
180
180
|
self
|
|
181
181
|
end
|
|
@@ -206,9 +206,9 @@ module Solace
|
|
|
206
206
|
def merge_account(pubkey, signer:, writable:, fee_payer: false)
|
|
207
207
|
pubkey_str = pubkey.is_a?(String) ? pubkey : pubkey.address
|
|
208
208
|
|
|
209
|
-
@pubkey_account_map[pubkey_str]
|
|
210
|
-
@pubkey_account_map[pubkey_str][:signer]
|
|
211
|
-
@pubkey_account_map[pubkey_str][:writable]
|
|
209
|
+
@pubkey_account_map[pubkey_str] ||= DEFAULT_ACCOUNT.dup
|
|
210
|
+
@pubkey_account_map[pubkey_str][:signer] ||= signer
|
|
211
|
+
@pubkey_account_map[pubkey_str][:writable] ||= writable
|
|
212
212
|
@pubkey_account_map[pubkey_str][:fee_payer] ||= fee_payer
|
|
213
213
|
|
|
214
214
|
self
|
|
@@ -242,7 +242,7 @@ module Solace
|
|
|
242
242
|
@pubkey_account_map.keys.each_with_object([0, 0, 0]) do |pubkey, acc|
|
|
243
243
|
acc[0] += 1 if signer?(pubkey)
|
|
244
244
|
|
|
245
|
-
if readonly_signer?(pubkey) then acc[1]
|
|
245
|
+
if readonly_signer?(pubkey) then acc[1] += 1
|
|
246
246
|
elsif readonly_nonsigner?(pubkey) then acc[2] += 1
|
|
247
247
|
end
|
|
248
248
|
end
|