使用 Ruby 与 Flow 进行交互,Daniel Podaru 著。在本文中,我们将探讨如何使用 Ruby 编程语言与 Flow 进行交互。这篇文章也可以作为一个很好的例子,说明你如何利用任何还没有 Flow SDK 支持的编程语言与 Flow 进行交互,极大地扩大了你的选择范围。
本文的代码可以在 Github 上找到,在这里 [1]
终端 / 命令提示符
使用 MacOS 上的 Terminal 或 Windows 上的 Command Prompt 来运行命令。
Ruby
在开始之前,检查你是否安装了 Ruby。在终端中,运行以下命令。
ruby -vruby
2.7.1p83
如果你没有安装 Ruby,你可以从 https://www.ruby-lang.org[2]。
项目文件夹
为你的项目新建一个文件夹。
cd ~
mkdir flow-ruby
gRPC 和 Protocol Buffers
我们将使用 gRPC[3] 和 Protocol Buffers[4] 与 Flow 节点进行交互。
Protocol Buffers,是 Google 公司开发的一种数据描述语言,类似于 XML 或 JSON 能够将结构化数据序列化,但更小、更快、更简单 , 可用于数据存储、通信协议等方面。gRPC 是一个基于 Protocol Buffers 和 HTTP2 的 RPC[5] 框架。
安装 grpc
、grpc-tools
和 json gem
。
gem install grpc grpc-tools json
Flow Protocol Buffer definitions
从 GitHub 克隆 Flow 仓库。
在您的终端中,运行以下命令。
cd ~
git clone https://github.com/onflow/flow
从 Flow .proto
文件中生成 Ruby 代码。
在终端中,运行以下命令。
cd flow/protobuf
grpc_tools_ruby_protoc --proto_path=. --ruby_out=ruby/ --grpc_out=ruby/ flow/**/*.proto
将新生成的 flow 文件夹从 protobuf/ruby/
复制到 flow-ruby
在终端,运行以下命令。
cp -r ~/flow/protobuf/ruby/ ~/flow-ruby/
列出 flow-ruby
文件夹的内容,以确保 flow
文件夹被复制 . 在终端中,运行以下命令。
cd ~/flow-ruby
ls flow
Ruby 代码
启动你最喜欢的 IDE 并创建一个名为 flow.rb
的新文件。
在 flow.rb
文件中添加以下代码。
require 'flow/access/access_services_pb'
require 'flow/execution/execution_services_pb'
require 'json'
class Flow
# 1
def initialize(node_address)
@stub = Access::AccessAPI::Stub.new(node_address, :this_channel_is_insecure)
end
# 2
def ping
req = Access::PingRequest.new
@stub.ping(req)
end
# 3
def get_account(address)
req = Access::GetAccountAtLatestBlockRequest.new(address: to_bytes(address))
res = @stub.get_account_at_latest_block(req)
res.account
end
# 4
def execute_script(script, args = [])
req = Access::ExecuteScriptAtLatestBlockRequest.new(
script: script,
arguments: args
)
res = @stub.execute_script_at_latest_block(req)
parse_json(res.value)
end
private
# 5
def parse_json(event_payload)
JSON.parse(event_payload, object_class: OpenStruct)
end
# 6
def to_bytes(string)
[string].pack('H*')
end
# 7
def to_string(bytes)
bytes.unpack('H*').first
end
end
Flow 类是由协议定义生成的代码的封装器。
•initialize 将在我们实例化 Flow 类时被调用。Access::AccessAPI::Stub 是我们从协议定义中自动生成的类的名称。我们创建一个新的实例,传递一个 Flow Access Node 的地址。该对象提供了允许调用 Access 节点上的方法的方法。•.ping 方法允许对 Flow Access 节点进行 ping,看看它是否还活着。我们创建一个新的 ping 请求。Access::PingRequest, 并在 ping 方法调用中传递它 : @stub.ping(req).•get_account(address) 方法允许获取 Flow 网络上的地址信息。我们使用 Access::GetAccountAtLatestBlockRequest.new 创建一个获取地址信息的请求,并在最新的块上使用 @stub.execute_script_at_latest_block(req) 执行该请求。•.execute_script 方法允许执行一个 Cadence 脚本。同样,我们创建一个请求对象并执行该请求。•parse_json 是一个实用方法,用于将脚本的响应解析为一个结构。•to_bytes 是一个实用方法,它将 Flow 地址从字符串转换为字节。•to_string 是一个实用方法。我们还没有在其他方法中使用它,但如果你想从 Flow 账户中读取代码字段,它是有用的。
Flow Emulator
Flow Emulator[6] 是一个轻量级的工具,它可以模拟真实 Flow 网络的行为。
我们将使用仿真器来测试 Ruby 客户端。按照以下步骤 [7] 安装模拟器。
启动 Flow 模拟器,在一个单独的终端窗口中,运行以下命令。
flow emulator start
与 Flow 的互动
启动 Ruby REPL 并调用 flow.rb
文件。
irb -I . -r flow.rb
在终端中,运行以下命令。在启动 REPL 的终端窗口中,运行以下命令。
f = Flow.new("127.0.0.1:3569")
f.ping
< Access::PingResponse: >
我们 ping 通了 Flow 模拟器,它响应成功。
获取现有账户的信息
要使用现有的 Flow 地址进行测试,请在启动 Flow 模拟器的终端窗口中查找,并使用服务账户的地址。
运行以下命令。
a = f.get_account('0xf8d6e0586b0a20c7')
< Entities::Account: address: "\xF8\xD6\xE0Xk
\xC7", balance: 0, code: "", keys: []>
响应会显示地址为 Flow 账户的信息。0xf8d6e0586b0a20c7。
数据显示为字节,我们可以使用 unpack('H*').first
将其解码为十六进制字符串。
a.address
"\xF8\xD6\xE0Xk
\xC7"
a.address.unpack('H*').first
"f8d6e0586b0a20c7"
a.balance
0
a.keys.first.public_key.unpack('H*').first
"61762b3fd6d94e456701938c43432a899431673aa75905a90b50fcf0af4eddae455d13f93941af12302979adca61c08edf5d6859dc1582a296444bcb46c2fb42"
我们可以看到,该账户的余额为 0,目前有一个公钥被授权访问。
执行 Cadence 脚本
脚本是一个只读的 Cadence 片段,用于查询区块链的计算状态。
运行以下命令。
script = 'pub fun main(): Int { return 1 }'
result = f.execute_script(script)
result.type
"Int"
result.value
"1"
脚本是一个简单的 Cadence 脚本,返回 1。
脚本由 execute_script
函数执行,结果在 result
变量中可用。
访问和执行 API
流程访问节点和流程执行节点提供的方法比较多。
探索 flow/access
、flow/execution
和 flow/entities
文件夹中的方法定义。
交易
一个交易是一个 Cadence 片段,它的执行是为了更新区块链的计算状态。一个事务可以更新一个或多个签名账户的存储。
执行事务的代码已经在 flow/execution
文件夹中生成,但是对事务的有效载荷进行加密签名所需的代码不能从 .proto
定义中生成,必须要实现。在安全的环境中,签名将由硬件安全模块(HSM)处理,它能够安全地存储私钥。如果你对从 Ruby 中签署交易感兴趣,你将需要自己编写这部分。
首先,你需要安装 rlp
和 openssl gem
。接下来,你需要看看 Go SDK[8] 中的签名实现,了解签名的工作原理,然后再将代码移植到 Ruby 中。
结束语
如果您正在开发的编程语言尚未提供 Flow SDK,您仍然可以使用该语言与 Flow 交互。Protocol Buffers 是语言中立和平台中立的,所以你可以从任何编程语言的协议定义中生成代码。
我们在本文中写的 Ruby 代码可以作为 Ruby 的 Flow SDK 的开始。我们鼓励你加入 Discord 上的 Flow 社区,在那里你可以和其他开发者一起用你最喜欢的编程语言构建 Flow SDK。
References
[1]
在这里 : https://github.com/cybercent/flow-ruby[2]
https://www.ruby-lang.org: https://www.ruby-lang.org/zh_cn/[3]
gRPC: https://grpc.io/[4]
Protocol Buffers: https://developers.google.com/protocol-buffers[5]
RPC: https://en.wikipedia.org/wiki/Remote_procedure_call[6]
Flow Emulator: https://github.com/onflow/flow-emulator[7]
以下步骤 : https://github.com/onflow/flow/blob/master/docs/cli.md[8]
Go SDK: https://github.com/onflow/flow-go-sdk/tree/master/crypto