Reach 主题专栏 | API 语法

  • Ivan
  • 更新于 2022-02-07 22:11
  • 阅读 2528

Reach 主题专栏系列文章围绕单主题解说并举例,本篇文章主题为 API。

本文由 Reach Developer Evangelist Hamza 编写,Ivan 翻译 原文链接

API 语法

Reach 后端中的 API 是没有绑定到任何参与者的一组函数。也就是说,不同于参与者交互接口只能和特定参与者交互,API可以被任何人调用。

我们可以如下声明一个 API : API(name, interface) => API_Participant

例如: const Spectator = API('Spectator', { rate: Fun([UInt], Bool) })

API 接口中的每一个函数的定义域由 API 传入,并从合约得到回传值。在上面的例子里,调用Spectator.rate时,API 会向合约发送一个 UInt ,并得到一个 Bool 回传值。

我们有两种方式可以调用 API 函数:

  1. call() 函数
  2. fork 函数中的 .api() 函数

call()

call( apiFn ) 函数可以让 Reach 程序知道我们需要等待一个 API 函数调用。这个函数中包含了一个函数句柄(handle)

例如: const [[inputFromAPI], setReturnValue] = call(Spectator.rate)

一个 call 的回传值是一个元组,其中:

  • 第一个元素是函数的传入值,即调用函数时传入的值
  • 第二个元素是回应 API 的设置函数

在上面的例子里,如果调用Spectator.rate() 时传入的值是 5,最终得到的元组就是 [[5], setterFunction]。 而 setterFunction(true) 会回传 true 给 API。

就步骤而言, call 相当于一个发布(publish),他可以与以下语法一起使用:

  • pay((<domain>) => <payment_amount>) 让 API 支付 <payment_amount>
const [[rating], setResponse] = call(Spectator.rate)
  .pay((rating) => rating)
  • assume((<domain>) => <condition>) 确保诚实的参予者总保证 <condition>true.
const [[rating], setResponse] = call(Spectator.rate)
  .assume((rating) => rating < 10)
  • throwTimeout(<time>, <throw_expression>) 会报错 <throw_expression> 如果函数在 <time> 之内没有被调用。
try {
  const [[rating], setResponse] = call(Spectator.rate)
    .throwTimeout(1024, 0)
}
catch (e) { ... }

下面是一个使用 call 的实例:

// Alice is implemented before
Alice.only(() => { doFlip() });
Alice.publish();
commit();

const [[rating], setResponse] = call(Spectator.rate)
  .assume((rating) => rating < 10);

Alice.interact.seeRating(rating);
setResponse(true);
commit();

.api()

.api() 可以加入任何 fork 或 parallelReduce 语句中,作为一个由 API call 发起的 case。语法如下:

fork() // or parallelReduce(INIT_EXPR)
...
.api(API_EXPR,
  API_ASSUME_EXPR,
  API_PAY_EXPR,
  API_CONSENSUS_EXPR)

其中

  • API_EXPR 是 API 参与者函数,
  • API_ASSUME_EXPR 是一个以API传入值为传入值的函数,并回传一个bool 值,在参与者诚实时回传 true 值。这是一个可选的部份。
  • API_PAY_EXPR是一个以函数传入值为传入值的函数,并回传一个支付数额(pay amount),调用者会支付这个数额。这也是一个可选的部份。
  • API_CONSENSUS_EXPR 是一个以函数传入值和设置函数为传入值的函数,随后发起共识转移。

一个实例如下:

// PRICE_PER_RATING declared somewhere before

const totalScore = parallelReduce( 0 ) 
...
api(
  Spectator.rate,
  ((rating) => { assume(rating < 10) }),
  ((rating) => rating * PRICE_PER_RATING)
  ((rating, setResponse) => {
     setResponse(true);
     return totalScore + rating;
  })
);

前端交互

API 函数储存在 contract.apiscontracts.a 中,其中每个API参与者都被存储为一个字段。

contracts.apis.Spectator 会回传 { rate: <async_function> }

...
const stdlib = loadStdlib(process.env);

const startingBalance = stdlib.parseCurrency(100);
const [deployer] = await stdlib.newTestAccount(startingBalance);

const contract = deployer.contract(backend);

try { 
 const res = await contract.apis.Spectator.rate(5);
} 
catch (e) {
 console.error("Error while calling Spectator.rate");
}
...
点赞 1
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Ivan
Ivan
江湖只有他的大名,没有他的介绍。