How to implement this method in Ruby? or is there third party lib to do this?

I have this ts function:

import { keccak_256 } from "js-sha3";
import { Buffer } from "buffer/";


export function getNamehash(name: string) {
  let node = "0000000000000000000000000000000000000000000000000000000000000000";

  if (name) {
    let labels = name.split(".");

    for (let i = labels.length - 1; i >= 0; i--) {
      let labelSha = keccak_256(labels[i]);
      node = keccak_256(Buffer.from(node + labelSha, "hex"));
    }   
  }

  return "0x" + node;
}

and when calling this method, it gives results like:

getNamehash("a")
// "0xc3025f6c23b9ab4d91adbcccf350072ec880c65db9a3f42e802fe4ceed56e728"

getNamehash("a.b")
// "0xa57dcb7e802753630ec035bae538ca332465791509b1375525fe8b3b0bada7ef"

getNamehash("abc.def")
// "0xc3025f6c23b9ab4d91adbcccf350072ec880c65db9a3f42e802fe4ceed56e728"

How to implement this method in Ruby?

please don't hurry to vote close for this question, I have spent several hours to do this, and got this:

# gem install keccak256   , website: https://github.com/evtaylor/keccak256
require 'keccak256'

  def _nodejs_buffer_to_hex origin_string
    #origin_string = "ce159cf3"

    i = 0 
    result = []
    temp = ""
    loop do
      break if i == origin_string.length
      temp += origin_string[i]
      if i % 2 == 1
        result << temp
        temp = ""
      end 
      i += 1
    end

    result = result.map do |e| 
      "0x#{e}".hex
    end 
    return result
  end 

  def get_name_hash name
    node = "0" * 64

    if (name)
      labels = name.split(".")
      i = labels.size - 1 
      while i >= 0
        labelSha = Digest::Keccak256.new.hexdigest(labels[i])
        # here will throw the exception: 
        node = Digest::Keccak256.new.hexdigest(_nodejs_buffer_to_hex(node + labelSha))
        i -= 1
      end
    end

    return "0x" + node;
  end

the ruby code above gives me this error:

    TypeError:
       no implicit conversion of Array into String
     # ./sdk.rb:160:in `hexdigest'

since the Digest::Keccak256.new.hexdigest only accept String , not Array.

any ideas?

thanks a lot!


Solution 1:

Here you are returning array instead of string which is then being passed to Digest::Keccak256.new.hexdigest
Change this:

result = result.map do |e| 
  "0x#{e}".hex
end

return result

To this:

return result.join

Same can be achieved with:

result = []
"abcd".split("").each_with_index {|letter, idx|
  if idx % 2 == 1
    result << letter.hex
  end
}