高级
预言机 (Oracle)
连接链上与链下数据的桥梁
1
注册预言机 (Register)
首先创建 Oracle 类实例。预言机地址与账户地址相同,只是前缀不同(ok_ 代替 ak_)。
import { AeSdk, Oracle, AccountMemory, ORACLE_TTL_TYPES } from '@aeternity/aepp-sdk';
const aeSdk = new AeSdk({ ... });
const oracleAccount = new AccountMemory(ORACLE_SECRET_KEY);
// 创建预言机实例
const oracle = new Oracle(oracleAccount, aeSdk.getContext());
// 注册预言机
// 第一个参数是查询格式,第二个是响应格式
await oracle.register(
'{"city": "str"}', // 查询格式
'{"temperature": "int"}', // 响应格式
{
queryFee: 1337, // 查询费用(可选,默认 0)
oracleTtlType: ORACLE_TTL_TYPES.delta, // TTL 类型
oracleTtlValue: 1000 // 存活 1000 个区块
}
);
TTL 说明:
delta: 从当前区块开始的相对区块数block: 指定的绝对区块高度- 默认存活 500 个关键区块
2
查询预言机 (Query)
知道 oracleId 的任何人都可以查询预言机:
import { OracleClient, ORACLE_TTL_TYPES } from '@aeternity/aepp-sdk';
const oracleId = 'ok_...';
// 创建预言机客户端
const oracleClient = new OracleClient(oracleId, aeSdk.getContext());
// 查询并等待响应
const response = await oracleClient.query('{"city": "Berlin"}', {
queryFee: 1337, // 查询费用
queryTtlType: ORACLE_TTL_TYPES.delta, // 查询 TTL 类型
queryTtlValue: 20, // 查询有效期
responseTtlType: ORACLE_TTL_TYPES.delta, // 响应 TTL 类型
responseTtlValue: 50, // 响应有效期
interval: 6000 // 轮询间隔(毫秒)
});
console.log('预言机响应:', response);
分步方式(发送查询 + 轮询响应)
// 只发送查询,不等待响应
const { queryId } = await oracleClient.postQuery('{"city": "Berlin"}');
console.log('查询 ID:', queryId); // oq_...
// 稍后轮询响应
const response = await oracleClient.pollForResponse(queryId);
console.log('响应:', response);
3
响应查询 (Respond)
预言机服务通常轮询自己的查询并尽快响应:
推荐方式:handleQueries
// 自动处理所有查询
const stopHandling = await oracle.handleQueries(
(query) => {
// 根据查询内容返回响应
if (query.decodedQuery === '{"city": "Berlin"}') {
return '{"temperature": 27}';
}
return '{"error": "Unknown city"}';
},
{ interval: 1000 } // 轮询间隔(毫秒)
);
// 需要时停止处理
stopHandling();
分步方式
// 只轮询查询
const stopPolling = await oracle.pollQueries(
(query) => {
console.log('收到查询:', query);
},
{ interval: 1000 }
);
// 手动响应特定查询
await oracle.respondToQuery(queryId, '{"temperature": 27}');
4
延长预言机 TTL (Extend)
在预言机过期前延长其生命周期:
// 从当前过期高度再延长 500 个区块
await oracle.extend({
oracleTtlType: ORACLE_TTL_TYPES.delta,
oracleTtlValue: 500
});
获取状态
Oracle 和 OracleClient 都提供获取状态的方法:
| 方法 | 说明 |
|---|---|
getState() |
获取预言机状态(等同于 Node.getOracleByPubkey) |
getQuery(queryId) |
获取特定查询详情,包含解码后的查询和响应 |
getQueries() |
获取所有查询列表 |