// the interface you already have
interface AggregatorV3 {
function latestRoundData() external view returns (
uint80 roundId, int256 answer, uint256 startedAt,
uint256 updatedAt, uint80 answeredInRound
);
}
contract Reader {
// TailFeed proxy — same shape as any Chainlink feed
AggregatorV3 internal constant CRM_USD =
AggregatorV3(0x4028E40d8596fB18870e63C3a9f1aa0109B96888);
function price() public view returns (int256) {
(, int256 ans,,,) = CRM_USD.latestRoundData();
return ans; // 21550718797 = $215.50718797, 8 decimals
}
}
// npm i tailfeed (or vendor one file — zero deps)
import TailFeed from 'tailfeed';
const tf = new TailFeed('https://rpc.testnet.chain.robinhood.com');
const feeds = await tf.list(); // every live feed + address
const crm = await tf.read('CRM');
console.log(crm.price); // 215.50718797
console.log(crm.round); // 13
console.log(crm.updatedAt); // Date — when the chain last heard
# read a feed with cast, right now:
$ cast call 0x4028E40d8596fB18870e63C3a9f1aa0109B96888 \
"latestRoundData()" --rpc-url \
https://rpc.testnet.chain.robinhood.com
# the registry that owns all feeds:
$ cast call 0x05128EC5a91Ee365e1E8b38f83157A84A5b7f2Af \
"getFeed(uint256)(uint80,int256,uint256,uint256,address)" 1 \
--rpc-url https://rpc.testnet.chain.robinhood.com