// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;
import {IFeed} from "./interfaces/IFeed.sol";
import {ISubscriptionRegistry} from "./interfaces/ISubscriptionRegistry.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract PriceFeedConsumer {
IFeed public immutable feed;
ISubscriptionRegistry public immutable subscriptionRegistry;
IERC20 public immutable usdc;
uint256 public lastPrice;
uint256 public lastUpdate;
event PriceUpdated(uint256 price, uint256 timestamp);
constructor(
address _feed,
address _subscriptionRegistry,
address _usdc
) {
feed = IFeed(_feed);
subscriptionRegistry = ISubscriptionRegistry(_subscriptionRegistry);
usdc = IERC20(_usdc);
}
/// @notice Subscribe this contract to the feed
/// @param duration Subscription duration in seconds
function subscribe(uint256 duration) external {
uint256 dueTime = block.timestamp + duration;
uint256 pricePerSecond = subscriptionRegistry.getConsumerPricePerSecondScaled(address(feed));
uint256 totalPrice = pricePerSecond * duration;
require(usdc.approve(address(subscriptionRegistry), totalPrice), "Approve failed");
address[] memory consumers = new address[](1);
consumers[0] = address(this);
subscriptionRegistry.subscribe(address(feed), dueTime, consumers);
}
/// @notice Get the latest price from the feed
/// @return price The latest price as uint256
/// @return timestamp The timestamp of the price update
function getLatestPrice() external view returns (uint256 price, uint256 timestamp) {
(bytes memory data, uint256 ts) = feed.getLatest();
require(data.length >= 32, "Invalid data");
assembly {
price := mload(add(data, 32))
}
return (price, ts);
}
/// @notice Update stored price (only callable by contract itself or EOA)
function updatePrice() external {
(uint256 price, uint256 timestamp) = this.getLatestPrice();
lastPrice = price;
lastUpdate = timestamp;
emit PriceUpdated(price, timestamp);
}
/// @notice Check if subscription is still valid
function isSubscribed() external view returns (bool) {
uint256 lastUpdateTime = feed.getLastUpdated();
// If feed was updated recently and we can read it, subscription is active
// This is a simple check - you may want more sophisticated validation
try feed.getLatest() returns (bytes memory, uint256) {
return true;
} catch {
return false;
}
}
}