Module: BSV::WireFormat

Defined in:
lib/bsv/wire_format.rb

Overview

Provides deep camelCase <-> snake_case key conversion for JSON wire boundaries.

Used wherever the SDK serialises or deserialises JSON payloads that follow the BRC-100/BRC-103 naming conventions (camelCase on the wire, snake_case in Ruby).

Examples:

Convert a hash to wire format

BSV::WireFormat.to_wire({ identity_key: '02abc', protocol_id: [2, 'test'] })
# => { 'identityKey' => '02abc', 'protocolID' => [2, 'test'] }

Convert a wire format hash to Ruby

BSV::WireFormat.from_wire({ 'identityKey' => '02abc' })
# => { identity_key: '02abc' }

Deep conversion with nested hashes and arrays

BSV::WireFormat.to_wire({ outputs: [{ locking_script: 'abc' }] })
# => { 'outputs' => [{ 'lockingScript' => 'abc' }] }

Constant Summary collapse

SNAKE_TO_CAMEL =

Well-known snake_case -> camelCase pairs for BRC-100/BRC-103 protocol keys.

Acronyms like protocolID, keyID are canonical per the TS SDK (Wallet.interfaces.ts). Generic regex fallback handles all other keys.

{
  # BRC-103 / Auth handshake keys
  'message_type' => 'messageType',
  'identity_key' => 'identityKey',
  'initial_nonce' => 'initialNonce',
  'your_nonce' => 'yourNonce',
  'requested_certificates' => 'requestedCertificates',
  'serial_number' => 'serialNumber',
  'revocation_outpoint' => 'revocationOutpoint',

  # BRC-100 parameter names (acronym forms from TS SDK Wallet.interfaces.ts)
  'protocol_id' => 'protocolID',
  'key_id' => 'keyID',
  'input_beef' => 'inputBEEF',
  'locking_script' => 'lockingScript',
  'unlocking_script' => 'unlockingScript',
  'label_query_mode' => 'labelQueryMode',
  'tag_query_mode' => 'tagQueryMode',
  'include_labels' => 'includeLabels',
  'include_inputs' => 'includeInputs',
  'include_outputs' => 'includeOutputs',
  'include_custom_instructions' => 'includeCustomInstructions',
  'include_tags' => 'includeTags',
  'counterparty_can_see_reveal' => 'counterpartyCanSeeReveal',
  'is_authenticated' => 'isAuthenticated',
  'wait_for_authentication' => 'waitForAuthentication',
  'get_public_key' => 'getPublicKey',
  'create_action' => 'createAction',
  'sign_action' => 'signAction',
  'abort_action' => 'abortAction',
  'list_actions' => 'listActions',
  'internalize_action' => 'internalizeAction',
  'list_outputs' => 'listOutputs',
  'relinquish_output' => 'relinquishOutput',
  'reveal_counterparty_key_linkage' => 'revealCounterpartyKeyLinkage',
  'reveal_specific_key_linkage' => 'revealSpecificKeyLinkage',
  'create_hmac' => 'createHMAC',
  'verify_hmac' => 'verifyHMAC',
  'create_signature' => 'createSignature',
  'verify_signature' => 'verifySignature',
  'acquire_certificate' => 'acquireCertificate',
  'list_certificates' => 'listCertificates',
  'prove_certificate' => 'proveCertificate',
  'relinquish_certificate' => 'relinquishCertificate',
  'discover_by_identity_key' => 'discoverByIdentityKey',
  'discover_by_attributes' => 'discoverByAttributes',
  'get_height' => 'getHeight',
  'get_header_for_height' => 'getHeaderForHeight',
  'get_network' => 'getNetwork',
  'get_version' => 'getVersion'
}.freeze
CAMEL_TO_SNAKE =

Inverse lookup table: camelCase -> snake_case.

SNAKE_TO_CAMEL.invert.freeze

Class Method Summary collapse

Class Method Details

.camel_to_snake(str) ⇒ String

Converts a single camelCase string to snake_case.

Uses the lookup table for known protocol keys. Falls back to generic regex substitution for unknown keys.

Parameters:

  • str (String)

    a camelCase string

Returns:

  • (String)

    the snake_case equivalent



166
167
168
# File 'lib/bsv/wire_format.rb', line 166

def camel_to_snake(str)
  CAMEL_TO_SNAKE.fetch(str) { generic_camel_to_snake(str) }
end

.from_wire(hash) ⇒ Hash

Deeply converts all Hash keys from camelCase strings to snake_case symbols.

Recurses into nested Hash values and Array elements. Non-Hash, non-Array values are passed through unchanged (only keys are converted, not values).

Parameters:

  • hash (Hash)

    the hash to convert

Returns:

  • (Hash)

    a new hash with snake_case symbol keys

Raises:

  • (ArgumentError)

    if the argument is nil



107
108
109
110
111
112
113
114
# File 'lib/bsv/wire_format.rb', line 107

def from_wire(hash)
  raise ArgumentError, 'argument must not be nil' if hash.nil?

  hash.each_with_object({}) do |(k, v), out|
    snake_key = camel_to_snake(k.to_s).to_sym
    out[snake_key] = deep_convert_value_from_wire(v)
  end
end

.shallow_from_wire(hash) ⇒ Hash

Converts top-level Hash keys only from camelCase to snake_case symbols.

Unlike from_wire, this does NOT recurse into nested hashes. Use this for auth handshake messages where nested values may contain user-data keys (e.g. base64 certificate type identifiers) that must not be mangled.

Parameters:

  • hash (Hash)

    the hash to convert

Returns:

  • (Hash)

    a new hash with snake_case symbol keys (values unchanged)

Raises:

  • (ArgumentError)


140
141
142
143
144
145
146
# File 'lib/bsv/wire_format.rb', line 140

def shallow_from_wire(hash)
  raise ArgumentError, 'argument must not be nil' if hash.nil?

  hash.each_with_object({}) do |(k, v), out|
    out[camel_to_snake(k.to_s).to_sym] = v
  end
end

.shallow_to_wire(hash) ⇒ Hash

Converts top-level Hash keys only from snake_case to camelCase strings.

Unlike to_wire, this does NOT recurse into nested hashes. Use this for auth handshake messages where nested values may contain user-data keys (e.g. base64 certificate type identifiers) that must not be mangled.

Parameters:

  • hash (Hash)

    the hash to convert

Returns:

  • (Hash)

    a new hash with camelCase string keys (values unchanged)

Raises:

  • (ArgumentError)


124
125
126
127
128
129
130
# File 'lib/bsv/wire_format.rb', line 124

def shallow_to_wire(hash)
  raise ArgumentError, 'argument must not be nil' if hash.nil?

  hash.each_with_object({}) do |(k, v), out|
    out[snake_to_camel(k.to_s)] = v
  end
end

.snake_to_camel(str) ⇒ String

Converts a single snake_case string to camelCase.

Uses the lookup table for known protocol keys (preserving acronyms like protocolID). Falls back to generic capitalisation for unknown keys.

Parameters:

  • str (String)

    a snake_case string

Returns:

  • (String)

    the camelCase equivalent



155
156
157
# File 'lib/bsv/wire_format.rb', line 155

def snake_to_camel(str)
  SNAKE_TO_CAMEL.fetch(str) { generic_snake_to_camel(str) }
end

.to_wire(hash) ⇒ Hash

Deeply converts all Hash keys from snake_case symbols/strings to camelCase strings.

Recurses into nested Hash values and Array elements. Non-Hash, non-Array values are passed through unchanged (only keys are converted, not values).

Parameters:

  • hash (Hash)

    the hash to convert

Returns:

  • (Hash)

    a new hash with camelCase string keys

Raises:

  • (ArgumentError)

    if the argument is nil



90
91
92
93
94
95
96
97
# File 'lib/bsv/wire_format.rb', line 90

def to_wire(hash)
  raise ArgumentError, 'argument must not be nil' if hash.nil?

  hash.each_with_object({}) do |(k, v), out|
    camel_key = snake_to_camel(k.to_s)
    out[camel_key] = deep_convert_value_to_wire(v)
  end
end