3

Reach 主题专栏 | API 语法

 2 years ago
source link: https://learnblockchain.cn/article/3522
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Reach 主题专栏 | API 语法

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 是一个以函数传入值为传入值的函数,并回传一个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");
}
...

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK