Module: Solace::Utils::Codecs
- Extended by:
- Codecs
- Included in:
- Codecs
- Defined in:
- lib/solace/squads_smart_accounts/codecs_extensions.rb
Overview
Extensions to Solace::Utils::Codecs for Anchor programs and Borsh types not covered by the base gem. Candidates for upstreaming to solace when the need is confirmed across other extension gems.
Instance Method Summary collapse
-
#decode_le_i64(stream) ⇒ Integer
Decodes an i64 from 8 little-endian bytes (two’s complement).
-
#decode_le_u128(stream) ⇒ Integer
Decodes a u128 from 16 little-endian bytes (two u64 words, low word first).
-
#decode_le_u16(stream) ⇒ Integer
Decodes a u16 from 2 little-endian bytes.
-
#decode_le_u32(stream) ⇒ Integer
Decodes a u32 from 4 little-endian bytes.
-
#decode_option_pubkey(stream) ⇒ String?
Decodes an Option<publicKey> in Borsh format.
-
#decode_pubkey(stream) ⇒ String
Decodes a public key from 32 bytes.
-
#decode_smart_account_signers(stream) ⇒ Array<SquadsSmartAccounts::SmartAccountSigner>
Decodes a Vec<SmartAccountSigner> in Borsh format.
-
#decode_u8(stream) ⇒ Integer
Decodes a u8 from 1 byte.
-
#decode_vec_pubkeys(stream) ⇒ Array<String>
Decodes a Vec<publicKey> in Borsh format.
-
#encode_bool(bool) ⇒ Array<Integer>
Encodes a Borsh bool as a single byte: false → 0, true → 1.
-
#encode_bytes(bytes) ⇒ Array<Integer>
Encodes a Borsh bytes field: u32 LE length prefix + raw bytes.
-
#encode_compiled_instructions(instructions) ⇒ Array<Integer>
Encodes a SmallVec<u8, CompiledInstruction> — the wire format the Squads program expects for synchronously executed inner instructions.
-
#encode_le_i64(i64) ⇒ String
Encodes an i64 as 8 little-endian bytes (two’s complement).
-
#encode_le_u128(u128) ⇒ String
Encodes a u128 as 16 little-endian bytes (two u64 words, low word first).
-
#encode_le_u16(u16) ⇒ String
Encodes a u16 as 2 little-endian bytes.
-
#encode_le_u32(u32) ⇒ String
Encodes a u32 as 4 little-endian bytes.
-
#encode_option_pubkey(pubkey) ⇒ Array<Integer>
Encodes an Option<publicKey> in Borsh format.
-
#encode_option_string(str) ⇒ Array<Integer>
Encodes an Option<String> in Borsh format.
-
#encode_pubkey(pubkey) ⇒ Array<Integer>
Encodes a public key as 32 bytes.
-
#encode_settings_actions(actions) ⇒ Array<Integer>
Encodes a Vec<SettingsAction> in Borsh format.
-
#encode_smallvec_u16_bytes(bytes) ⇒ Array<Integer>
Encodes a SmallVec<u16, u8>: u16 LE length prefix + raw bytes.
-
#encode_smallvec_u8_bytes(bytes) ⇒ Array<Integer>
Encodes a SmallVec<u8, u8>: u8 length prefix + raw bytes.
-
#encode_smallvec_u8_pubkeys(pubkeys) ⇒ Array<Integer>
Encodes a SmallVec<u8, Pubkey>: u8 count prefix followed by each 32-byte pubkey.
-
#encode_smart_account_signers(signers) ⇒ Array<Integer>
Encodes a Vec<SmartAccountSigner> in Borsh format.
-
#encode_vec_pubkeys(pubkeys) ⇒ Array<Integer>
Encodes a Vec<publicKey> in Borsh format.
Instance Method Details
#decode_le_i64(stream) ⇒ Integer
Decodes an i64 from 8 little-endian bytes (two’s complement).
180 181 182 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 180 def decode_le_i64(stream) stream.read(8).unpack1('q<') end |
#decode_le_u128(stream) ⇒ Integer
Decodes a u128 from 16 little-endian bytes (two u64 words, low word first).
220 221 222 223 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 220 def decode_le_u128(stream) lo, hi = stream.read(16).unpack('Q<Q<') lo + (hi << 64) end |
#decode_le_u16(stream) ⇒ Integer
Decodes a u16 from 2 little-endian bytes.
204 205 206 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 204 def decode_le_u16(stream) stream.read(2).unpack1('S<') end |
#decode_le_u32(stream) ⇒ Integer
Decodes a u32 from 4 little-endian bytes.
212 213 214 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 212 def decode_le_u32(stream) stream.read(4).unpack1('L<') end |
#decode_option_pubkey(stream) ⇒ String?
Decodes an Option<publicKey> in Borsh format. None → nil, Some(key) → base58 pubkey.
238 239 240 241 242 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 238 def decode_option_pubkey(stream) return nil if decode_u8(stream).zero? decode_pubkey(stream) end |
#decode_pubkey(stream) ⇒ String
Decodes a public key from 32 bytes.
229 230 231 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 229 def decode_pubkey(stream) Solace::Utils::Codecs.bytes_to_base58(stream.read(32).bytes) end |
#decode_smart_account_signers(stream) ⇒ Array<SquadsSmartAccounts::SmartAccountSigner>
Decodes a Vec<SmartAccountSigner> in Borsh format. u32 length prefix followed by each signer’s 32-byte pubkey + 1-byte permission mask.
249 250 251 252 253 254 255 256 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 249 def decode_smart_account_signers(stream) Array.new(decode_le_u32(stream)) do SquadsSmartAccounts::SmartAccountSigner.new( pubkey: decode_pubkey(stream), permission: decode_u8(stream) ) end end |
#decode_u8(stream) ⇒ Integer
Decodes a u8 from 1 byte.
196 197 198 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 196 def decode_u8(stream) stream.read(1).unpack1('C') end |
#decode_vec_pubkeys(stream) ⇒ Array<String>
Decodes a Vec<publicKey> in Borsh format.
188 189 190 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 188 def decode_vec_pubkeys(stream) Array.new(decode_le_u32(stream)) { decode_pubkey(stream) } end |
#encode_bool(bool) ⇒ Array<Integer>
Encodes a Borsh bool as a single byte: false → 0, true → 1.
55 56 57 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 55 def encode_bool(bool) [bool ? 1 : 0] end |
#encode_bytes(bytes) ⇒ Array<Integer>
Encodes a Borsh bytes field: u32 LE length prefix + raw bytes.
71 72 73 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 71 def encode_bytes(bytes) encode_le_u32(bytes.length).bytes + bytes end |
#encode_compiled_instructions(instructions) ⇒ Array<Integer>
Encodes a SmallVec<u8, CompiledInstruction> — the wire format the Squads program expects for synchronously executed inner instructions.
NOTE: this intentionally does NOT reuse Solace’s InstructionSerializer. That serializer produces the Solana transaction wire format, which uses compact-u16 (varint) length prefixes for the vec count, account indexes, and data. The Squads SmallVec format uses fixed-width prefixes instead: u8 for the vec count, u8 for the account indexes length, and u16 LE for the data length. The two encodings coincide for lengths < 128 (compact-u16 encodes those as a single byte) but diverge beyond that, so reusing the Solana format would corrupt larger instructions silently.
Each instruction is a Instruction whose program_index and accounts are indexes into the full remaining-accounts list (signers included). Layout per instruction: u8 program_id_index + SmallVec<u8,u8> account indexes + SmallVec<u16,u8> data.
167 168 169 170 171 172 173 174 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 167 def encode_compiled_instructions(instructions) [instructions.length] + instructions.flat_map do |ix| [ix.program_index] + encode_smallvec_u8_bytes(ix.accounts) + encode_smallvec_u16_bytes(ix.data) end end |
#encode_le_i64(i64) ⇒ String
Encodes an i64 as 8 little-endian bytes (two’s complement).
47 48 49 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 47 def encode_le_i64(i64) [i64].pack('q<') end |
#encode_le_u128(u128) ⇒ String
Encodes a u128 as 16 little-endian bytes (two u64 words, low word first).
63 64 65 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 63 def encode_le_u128(u128) [u128 & 0xFFFFFFFFFFFFFFFF, u128 >> 64].pack('Q<Q<') end |
#encode_le_u16(u16) ⇒ String
Encodes a u16 as 2 little-endian bytes.
23 24 25 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 23 def encode_le_u16(u16) [u16].pack('S<') end |
#encode_le_u32(u32) ⇒ String
Encodes a u32 as 4 little-endian bytes.
39 40 41 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 39 def encode_le_u32(u32) [u32].pack('L<') end |
#encode_option_pubkey(pubkey) ⇒ Array<Integer>
Encodes an Option<publicKey> in Borsh format. None → [0], Some(key) → [1] + 32 bytes.
101 102 103 104 105 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 101 def encode_option_pubkey(pubkey) return [0] if pubkey.nil? [1] + encode_pubkey(pubkey) end |
#encode_option_string(str) ⇒ Array<Integer>
Encodes an Option<String> in Borsh format. None → [0], Some(str) → [1] + u32 length + UTF-8 bytes.
80 81 82 83 84 85 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 80 def encode_option_string(str) return [0] if str.nil? bytes = str.encode('UTF-8').bytes [1] + encode_le_u32(bytes.length).bytes + bytes end |
#encode_pubkey(pubkey) ⇒ Array<Integer>
Encodes a public key as 32 bytes. Accepts any representation that resolves to a base58 string via #to_s (String, Keypair, PublicKey).
92 93 94 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 92 def encode_pubkey(pubkey) Solace::Utils::Codecs.base58_to_bytes(pubkey.to_s) end |
#encode_settings_actions(actions) ⇒ Array<Integer>
Encodes a Vec<SettingsAction> in Borsh format. u32 LE count prefix followed by each action’s variant index + field bytes.
144 145 146 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 144 def encode_settings_actions(actions) encode_le_u32(actions.length).bytes + actions.flat_map(&:serialize) end |
#encode_smallvec_u16_bytes(bytes) ⇒ Array<Integer>
Encodes a SmallVec<u16, u8>: u16 LE length prefix + raw bytes.
31 32 33 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 31 def encode_smallvec_u16_bytes(bytes) encode_le_u16(bytes.length).bytes + bytes end |
#encode_smallvec_u8_bytes(bytes) ⇒ Array<Integer>
Encodes a SmallVec<u8, u8>: u8 length prefix + raw bytes.
15 16 17 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 15 def encode_smallvec_u8_bytes(bytes) [bytes.length] + bytes end |
#encode_smallvec_u8_pubkeys(pubkeys) ⇒ Array<Integer>
Encodes a SmallVec<u8, Pubkey>: u8 count prefix followed by each 32-byte pubkey. Used by the transaction message header’s account_keys (distinct from encode_vec_pubkeys, which uses a u32 count).
123 124 125 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 123 def encode_smallvec_u8_pubkeys(pubkeys) [pubkeys.length] + pubkeys.flat_map { |pubkey| encode_pubkey(pubkey) } end |
#encode_smart_account_signers(signers) ⇒ Array<Integer>
Encodes a Vec<SmartAccountSigner> in Borsh format. u32 length prefix followed by each signer’s 32-byte pubkey + 1-byte permission mask.
132 133 134 135 136 137 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 132 def encode_smart_account_signers(signers) encode_le_u32(signers.length).bytes + signers.flat_map do |signer| encode_pubkey(signer.pubkey) + [signer.] end end |
#encode_vec_pubkeys(pubkeys) ⇒ Array<Integer>
Encodes a Vec<publicKey> in Borsh format. u32 LE count prefix followed by each 32-byte pubkey.
112 113 114 115 |
# File 'lib/solace/squads_smart_accounts/codecs_extensions.rb', line 112 def encode_vec_pubkeys(pubkeys) encode_le_u32(pubkeys.length).bytes + pubkeys.flat_map { |pubkey| encode_pubkey(pubkey) } end |