Act·two-phase async
ᛚ
Long-running HTTP
Polling + JQ extract
Long-poll workflows with built-in JQ extraction. Minutes to hours.
0x0000000000000000000000000000000000000805Explorer
Two-phase async. Three sub-requests: initial submit (returns task ID via JQ), poll until status JQ matches, then optional result fetch. Settles via
onLongRunningResult.click 'auto' (capability = 7)
≤ 500
blocks
block #
submit & extract taskId
1 header(s)
JQ path
min escrow: 0.0500 RITUALyou have: — RITUAL
Connect your wallet to submit a real transaction.
to: 0x0000000000000000000000000000000000000805chainId 1979 · two-phase · 35 fields
Output
Click Validate to encode the 35-field long-running request.
poll every 5 blk · max 10000
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";
contract LongRunningJob is PrecompileConsumer {
address constant LONG_HTTP = address(0x805);
address constant ASYNC_DELIVERY = 0x5A16214fF555848411544b005f7Ac063742f39F6;
event JobSubmitted(bytes32 indexed jobId, address indexed sender);
event JobReady(bytes32 indexed jobId, uint16 status, bytes body);
event JobFailed(bytes32 indexed jobId, string error);
/// @notice Submit a long-running job. Three HTTP requests:
/// 1. initial — kick off the task, returns task ID via JQ path
/// 2. poll — check status (executor repeats until JQ path matches)
/// 3. result — fetch final result (optional — empty url uses poll body)
function submitJob(address executor) external {
bytes memory encoded = abi.encode(
executor,
new bytes[](0), uint256(500), new bytes[](0), bytes(""),
uint64(5), // pollIntervalBlocks
uint64(block.number + 10000), // maxPollBlock
"{{TASK_ID}}", // taskIdMarker
address(this), this.onLongRunningResult.selector,
uint256(300000), uint256(1_000_000_000),
uint256(100_000_000), uint256(0),
// ... 18 more fields for the 3 HTTP sub-requests
// see /playground/long-http for the full encoding
uint256(0), uint8(0), false
);
(bool ok,) = LONG_HTTP.call(encoded);
require(ok, "long-http submit failed");
}
/// @notice Phase 2 callback — only AsyncDelivery may call.
function onLongRunningResult(bytes32 jobId, bytes calldata result) external {
require(msg.sender == ASYNC_DELIVERY, "unauth");
// Decode using HTTP response shape: (uint16 status, string[] keys, string[] vals, bytes body, string err)
(uint16 status, , , bytes memory body, string memory err) =
abi.decode(result, (uint16, string[], string[], bytes, string));
if (bytes(err).length != 0) {
emit JobFailed(jobId, err);
} else {
emit JobReady(jobId, status, body);
}
}
}