@@ -166,14 +166,23 @@ func (c *BaseClient) GetNodeVersionInfo(ctx context.Context, opts ...grpc.CallOp
166166 return nil , newRPCError (err )
167167 }
168168
169+ var compRange * flow.CompatibleRange
169170 info := res .GetInfo ()
171+ if info != nil {
172+ compRange = & flow.CompatibleRange {
173+ StartHeight : info .CompatibleRange .GetStartHeight (),
174+ EndHeight : info .CompatibleRange .GetEndHeight (),
175+ }
176+ }
177+
170178 return & flow.NodeVersionInfo {
171179 Semver : info .Semver ,
172180 Commit : info .Commit ,
173181 SporkId : flow .BytesToID (info .SporkId ),
174182 ProtocolVersion : info .ProtocolVersion ,
175183 SporkRootBlockHeight : info .SporkRootBlockHeight ,
176184 NodeRootBlockHeight : info .NodeRootBlockHeight ,
185+ CompatibleRange : compRange ,
177186 }, nil
178187}
179188
@@ -1369,6 +1378,145 @@ func receiveBlocksFromClient[Client interface {
13691378 }
13701379}
13711380
1381+ func (c * BaseClient ) SubscribeBlockHeadersFromStartBlockID (
1382+ ctx context.Context ,
1383+ startBlockID flow.Identifier ,
1384+ blockStatus flow.BlockStatus ,
1385+ opts ... grpc.CallOption ,
1386+ ) (<- chan flow.BlockHeader , <- chan error , error ) {
1387+ status := convert .BlockStatusToEntity (blockStatus )
1388+ if status == entities .BlockStatus_BLOCK_UNKNOWN {
1389+ return nil , nil , newRPCError (errors .New ("unknown block status" ))
1390+ }
1391+
1392+ request := & access.SubscribeBlockHeadersFromStartBlockIDRequest {
1393+ StartBlockId : startBlockID .Bytes (),
1394+ BlockStatus : status ,
1395+ }
1396+
1397+ subscribeClient , err := c .rpcClient .SubscribeBlockHeadersFromStartBlockID (ctx , request , opts ... )
1398+ if err != nil {
1399+ return nil , nil , newRPCError (err )
1400+ }
1401+
1402+ blockHeaderChan := make (chan flow.BlockHeader )
1403+ errChan := make (chan error )
1404+
1405+ go func () {
1406+ defer close (blockHeaderChan )
1407+ defer close (errChan )
1408+ receiveBlockHeadersFromClient (ctx , subscribeClient , blockHeaderChan , errChan )
1409+ }()
1410+
1411+ return blockHeaderChan , errChan , nil
1412+ }
1413+
1414+ func (c * BaseClient ) SubscribeBlockHeadersFromStartHeight (
1415+ ctx context.Context ,
1416+ startHeight uint64 ,
1417+ blockStatus flow.BlockStatus ,
1418+ opts ... grpc.CallOption ,
1419+ ) (<- chan flow.BlockHeader , <- chan error , error ) {
1420+ status := convert .BlockStatusToEntity (blockStatus )
1421+ if status == entities .BlockStatus_BLOCK_UNKNOWN {
1422+ return nil , nil , newRPCError (errors .New ("unknown block status" ))
1423+ }
1424+
1425+ request := & access.SubscribeBlockHeadersFromStartHeightRequest {
1426+ StartBlockHeight : startHeight ,
1427+ BlockStatus : status ,
1428+ }
1429+
1430+ subscribeClient , err := c .rpcClient .SubscribeBlockHeadersFromStartHeight (ctx , request , opts ... )
1431+ if err != nil {
1432+ return nil , nil , newRPCError (err )
1433+ }
1434+
1435+ blockHeaderChan := make (chan flow.BlockHeader )
1436+ errChan := make (chan error )
1437+
1438+ go func () {
1439+ defer close (blockHeaderChan )
1440+ defer close (errChan )
1441+ receiveBlockHeadersFromClient (ctx , subscribeClient , blockHeaderChan , errChan )
1442+ }()
1443+
1444+ return blockHeaderChan , errChan , nil
1445+ }
1446+
1447+ func (c * BaseClient ) SubscribeBlockHeadersFromLatest (
1448+ ctx context.Context ,
1449+ blockStatus flow.BlockStatus ,
1450+ opts ... grpc.CallOption ,
1451+ ) (<- chan flow.BlockHeader , <- chan error , error ) {
1452+ status := convert .BlockStatusToEntity (blockStatus )
1453+ if status == entities .BlockStatus_BLOCK_UNKNOWN {
1454+ return nil , nil , newRPCError (errors .New ("unknown block status" ))
1455+ }
1456+
1457+ request := & access.SubscribeBlockHeadersFromLatestRequest {
1458+ BlockStatus : status ,
1459+ }
1460+
1461+ subscribeClient , err := c .rpcClient .SubscribeBlockHeadersFromLatest (ctx , request , opts ... )
1462+ if err != nil {
1463+ return nil , nil , newRPCError (err )
1464+ }
1465+
1466+ blockHeaderChan := make (chan flow.BlockHeader )
1467+ errChan := make (chan error )
1468+
1469+ go func () {
1470+ defer close (blockHeaderChan )
1471+ defer close (errChan )
1472+ receiveBlockHeadersFromClient (ctx , subscribeClient , blockHeaderChan , errChan )
1473+ }()
1474+
1475+ return blockHeaderChan , errChan , nil
1476+ }
1477+
1478+ func receiveBlockHeadersFromClient [Client interface {
1479+ Recv () (* access.SubscribeBlockHeadersResponse , error )
1480+ }](
1481+ ctx context.Context ,
1482+ client Client ,
1483+ blockHeadersChan chan <- flow.BlockHeader ,
1484+ errChan chan <- error ,
1485+ ) {
1486+ sendErr := func (err error ) {
1487+ select {
1488+ case <- ctx .Done ():
1489+ case errChan <- err :
1490+ }
1491+ }
1492+
1493+ for {
1494+ // Receive the next blockHeader response
1495+ blockHeaderResponse , err := client .Recv ()
1496+ if err != nil {
1497+ if err == io .EOF {
1498+ // End of stream, return gracefully
1499+ return
1500+ }
1501+
1502+ sendErr (fmt .Errorf ("error receiving blockHeader: %w" , err ))
1503+ return
1504+ }
1505+
1506+ blockHeader , err := convert .MessageToBlockHeader (blockHeaderResponse .GetHeader ())
1507+ if err != nil {
1508+ sendErr (fmt .Errorf ("error converting message to block header: %w" , err ))
1509+ return
1510+ }
1511+
1512+ select {
1513+ case <- ctx .Done ():
1514+ return
1515+ case blockHeadersChan <- blockHeader :
1516+ }
1517+ }
1518+ }
1519+
13721520func (c * BaseClient ) SubscribeAccountStatusesFromStartHeight (
13731521 ctx context.Context ,
13741522 startHeight uint64 ,
0 commit comments