Class: BSV::Wallet::Wire::Writer

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/wallet/wire/reader_writer.rb

Overview

Writer accumulates bytes into a binary string buffer.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeWriter

Returns a new instance of Writer.



18
19
20
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 18

def initialize
  @buf = String.new(encoding: 'BINARY')
end

Instance Attribute Details

#bufObject (readonly)

Returns the value of attribute buf.



16
17
18
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 16

def buf
  @buf
end

Instance Method Details

#write_byte(byte) ⇒ Object

Write a raw byte.



23
24
25
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 23

def write_byte(byte)
  @buf << [byte].pack('C')
end

#write_bytes(bytes) ⇒ Object

Write raw bytes (binary string).



28
29
30
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 28

def write_bytes(bytes)
  @buf << bytes.b
end

#write_int_bytes(bytes) ⇒ Object

Write a varint length-prefixed byte array (WriteIntBytes in Go).

Parameters:

  • bytes (String, nil)

    binary string; nil or empty → write varint 0



82
83
84
85
86
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 82

def write_int_bytes(bytes)
  raw = bytes ? bytes.b : ''.b
  write_varint(raw.bytesize)
  write_bytes(raw)
end

#write_int_from_base64(base64_str) ⇒ Object

Write a binary value encoded as a Base64 string on the wire. Decodes the Base64 string and writes the raw bytes prefixed by varint length.

Parameters:

  • base64_str (String)

    standard Base64-encoded string



136
137
138
139
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 136

def write_int_from_base64(base64_str)
  raw = Base64.strict_decode64(base64_str)
  write_int_bytes(raw)
end

#write_negative_oneObject

Write the NegativeOne sentinel (MaxUint64 as a 9-byte varint: 9 × 0xFF). Used as a nil sentinel for optional fields in Go-compatible encoding.



76
77
78
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 76

def write_negative_one
  write_varint(0xFFFF_FFFF_FFFF_FFFF)
end

#write_optional_bool(value) ⇒ Object

Write an optional boolean as a single byte (Go/BRC-103 convention). nil → 0xFF, false → 0x00, true → 0x01



46
47
48
49
50
51
52
53
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 46

def write_optional_bool(value)
  byte = case value
         when nil   then 0xFF
         when false then 0x00
         else            0x01
         end
  write_byte(byte)
end

#write_optional_bytes_with_flag(bytes, fixed_size: nil) ⇒ Object

Write optional bytes with a 1-byte flag prefix (Go BytesOptionWithFlag). nil/empty → 0x00; else → 0x01 + varint_len + bytes (or fixed_size bytes).

Parameters:

  • bytes (String, nil)

    binary data

  • fixed_size (Integer, nil) (defaults to: nil)

    if set, omit the varint length prefix



177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 177

def write_optional_bytes_with_flag(bytes, fixed_size: nil)
  raw = bytes ? bytes.b : ''.b
  if raw.empty?
    write_byte(0)
  else
    write_byte(1)
    if fixed_size
      write_bytes(raw)
    else
      write_int_bytes(raw)
    end
  end
end

#write_optional_string(str) ⇒ Object

Write an optional string: nil or empty → NegativeOne; else varint len + bytes. Matches Go WriteOptionalString.

Parameters:

  • str (String, nil)


101
102
103
104
105
106
107
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 101

def write_optional_string(str)
  if str.nil? || str.empty?
    write_negative_one
  else
    write_str_with_varint_len(str)
  end
end

#write_optional_uint32(n) ⇒ Object

Write an optional uint32: nil → NegativeOne; else varint.

Parameters:

  • n (Integer, nil)


90
91
92
93
94
95
96
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 90

def write_optional_uint32(n)
  if n.nil?
    write_negative_one
  else
    write_varint(n)
  end
end

#write_outpoint(txid_hex, vout) ⇒ Object

Write an outpoint: 32-byte display-order txid followed by varint vout.

Go encodeOutpoint calls WriteBytesReverse(Txid) which writes the wire-order (chainhash) bytes reversed — i.e. display order on the wire. The vout is a varint, not a fixed 4-byte LE integer.

Parameters:

  • txid_hex (String)

    64-char display-order hex txid

  • vout (Integer)

    output index



68
69
70
71
72
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 68

def write_outpoint(txid_hex, vout)
  BSV::Primitives::Hex.validate_dtxid_hex!(txid_hex)
  @buf << [txid_hex].pack('H*')
  write_varint(vout)
end

#write_privileged_params(privileged, reason) ⇒ Object

Write the privileged flag and reason (Go encodePrivilegedParams). privileged: nil → NegativeOneByte (0xFF), false → 0x00, true → 0x01. reason: nil or empty → NegativeOneByte; else varint len + bytes.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 144

def write_privileged_params(privileged, reason)
  # Go OptionalBool: nil=0xFF, false=0x00, true=0x01
  byte = case privileged
         when nil   then 0xFF
         when false then 0x00
         else            0x01
         end
  write_byte(byte)
  if reason.nil? || reason.empty?
    write_byte(0xFF)
  else
    write_str_with_varint_len(reason)
  end
end

#write_satoshis(n) ⇒ Object

Write a satoshi amount as 8-byte little-endian uint64.



56
57
58
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 56

def write_satoshis(n)
  @buf << [n].pack('Q<')
end

#write_str_with_varint_len(str) ⇒ Object

Write a UTF-8 string prefixed by its byte length as a varint.



38
39
40
41
42
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 38

def write_str_with_varint_len(str)
  bytes = str.to_s.b
  write_varint(bytes.bytesize)
  write_bytes(bytes)
end

#write_string(str) ⇒ Object

Write a varint-len string (always present, 0-length for nil/empty). Matches Go WriteString which always writes the length prefix.

Parameters:

  • str (String, nil)


194
195
196
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 194

def write_string(str)
  write_str_with_varint_len(str.to_s)
end

#write_string_map(map) ⇒ Object

Write a string map (Hash<String,String>) sorted by key. Matches Go WriteStringMap.

Parameters:

  • map (Hash, nil)


124
125
126
127
128
129
130
131
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 124

def write_string_map(map)
  m = map || {}
  write_varint(m.length)
  m.keys.sort.each do |k|
    write_str_with_varint_len(k)
    write_str_with_varint_len(m[k])
  end
end

#write_string_slice(arr) ⇒ Object

Write an array of strings: nil → NegativeOne; else varint count + each as optional string. Matches Go WriteStringSlice.

Parameters:

  • arr (Array<String>, nil)


112
113
114
115
116
117
118
119
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 112

def write_string_slice(arr)
  if arr.nil?
    write_negative_one
  else
    write_varint(arr.length)
    arr.each { |s| write_optional_string(s) }
  end
end

#write_txid_slice(txids) ⇒ Object

Write a txid slice (array of 32-byte txids in wire order). nil → NegativeOne; else varint count + 32 raw bytes per txid. Txids are passed as 64-char display-order hex; written as-is (no byte reversal) to match Go WriteTxidSlice which writes txID (wire-order bytes directly).

Parameters:

  • txids (Array<String>, nil)

    64-char display-order hex strings



164
165
166
167
168
169
170
171
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 164

def write_txid_slice(txids)
  if txids.nil?
    write_negative_one
  else
    write_varint(txids.length)
    txids.each { |hex| write_bytes([hex].pack('H*')) }
  end
end

#write_varint(n) ⇒ Object

Write a Bitcoin varint.



33
34
35
# File 'lib/bsv/wallet/wire/reader_writer.rb', line 33

def write_varint(n)
  @buf << BSV::Transaction::VarInt.encode(n)
end