IPcl.globalPeriodicVolume
globalPeriodicVolume(
address user,
string calldata asset,
uint64 resetPeriodSeconds,
bool resolveAgentOwners
) external view returns (PeriodicVolume[] memory statuses) 요청한 (asset, resetPeriodSeconds) 쌍에 해당하는 모든 전역 주기 거래량 카운터를 user에 대해 반환합니다. 전역 PERIODIC_VOLUME_POLICY 중 해당 (자산, 주기) 튜플과 일치하는 정책이 없으면 빈 배열을 반환합니다. 그렇지 않으면 등록된 각 한도마다 하나씩 PeriodicVolume 항목을 담습니다. 동일한 주기에 서로 다른 maxAmount 값이 여러 개 등록될 수 있으며, 호출자가 그중 가장 엄격한 한도를 선택할 수 있도록 모두 반환합니다. resolveAgentOwners를 true로 설정하면 조회 주소가 소유한 모든 에이전트의 거래량을 합산합니다.
파라미터
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
user | address | ✓ | 누적 거래량을 조회할 계정 주소입니다. |
asset | string | ✓ | PeriodicVolumePolicy.tokens 배열에 선언된 자산 식별자입니다(보통 base denom, 예: "aokrw"). 서버에서 정규화됩니다. |
resetPeriodSeconds | uint64 | ✓ | 조회할 카운터를 식별하는 초 단위 주기 길이입니다(예: 24시간 윈도는 86400). 등록된 주기가 이 값과 정확히 일치하는 항목만 반환됩니다. |
resolveAgentOwners | bool | ✓ | true이면 소유자가 user인 모든 에이전트의 거래량을 합산합니다. false이면 user 자신의 카운터만 조회합니다. |
반환값
타입:
PeriodicVolume[] PeriodicVolume { uint256 amount; uint256 maxAmount; uint64 resetPeriodSeconds; uint64 resetAt; } 배열입니다. (자산, 주기) 튜플과 일치하는 등록 한도마다 하나씩 항목이 담깁니다. 빈 배열은 해당 튜플에 등록된 정책이 없다는 뜻입니다.
예제
사용자에게 적용되는 모든 전역 일일 OKRW 한도 조회
동일한 (자산, 주기) 튜플에 여러 한도가 공존할 수 있으므로, 단일 레코드를 가정하지 말고 반환 배열을 순회하여 결합해야 합니다. 보통은 남은 여유(remaining headroom)의 최솟값을 취합니다.
import { createPublicClient, http } from "viem";
const PCL = "0x1000000000000000000000000000000000000005" as const;
const pclAbi = [{
name: "globalPeriodicVolume", type: "function", stateMutability: "view",
inputs: [
{ name: "user", type: "address" },
{ name: "asset", type: "string" },
{ name: "resetPeriodSeconds", type: "uint64" },
{ name: "resolveAgentOwners", type: "bool" },
],
outputs: [{
type: "tuple[]",
components: [
{ name: "amount", type: "uint256" },
{ name: "maxAmount", type: "uint256" },
{ name: "resetPeriodSeconds", type: "uint64" },
{ name: "resetAt", type: "uint64" },
],
}],
}] as const;
const client = createPublicClient({ transport: http("https://rpc-testnet.maroo.io") });
// TODO: replace with the real end-user address before production.
const statuses = await client.readContract({
address: PCL,
abi: pclAbi,
functionName: "globalPeriodicVolume",
args: ["0x8f3aC2b1D9e74C05a6B18Fe27dC4913E5A0f7b62", "aokrw", 86_400n, false],
});
if (statuses.length === 0) {
console.log("no periodic-volume policy is currently registered for this (asset, period)");
} else {
// Pick the tightest applicable cap — remaining headroom is min(maxAmount - amount) across entries.
const headroom = statuses.reduce<bigint>((min, s) => {
const left = s.maxAmount - s.amount;
return left < min ? left : min;
}, statuses[0].maxAmount - statuses[0].amount);
console.log(`tightest remaining headroom: ${headroom} aokrw`);
} Solidity에서 동일한 카운터 조회
Solidity view가 메모리 배열을 반환하므로, 컨트랙트가 추가 RPC 호출 없이 순회하며 가장 엄격한 한도를 선택할 수 있습니다.
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;
import "@maroo-chain/contracts/precompiles/pcl/IPcl.sol";
contract HeadroomView {
IPcl constant pcl = IPcl(0x1000000000000000000000000000000000000005);
/// @return tightest Minimum remaining headroom across every registered
/// global periodic-volume limit for the (aokrw, 24h) counter.
function remainingDailyHeadroom(address user) external view returns (uint256 tightest) {
PeriodicVolume[] memory rows =
pcl.globalPeriodicVolume(user, "aokrw", 86_400, false);
if (rows.length == 0) {
return type(uint256).max; // no policy → unbounded
}
tightest = type(uint256).max;
for (uint256 i = 0; i < rows.length; ++i) {
uint256 left = rows[i].maxAmount - rows[i].amount;
if (left < tightest) tightest = left;
}
}
}