@xyo-network/react-chain-network 1.19.9 → 1.19.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/browser/components/broadcast/Drawer.d.ts +5 -2
  2. package/dist/browser/components/broadcast/Drawer.d.ts.map +1 -1
  3. package/dist/browser/components/broadcast/details/Card.d.ts +3 -2
  4. package/dist/browser/components/broadcast/details/Card.d.ts.map +1 -1
  5. package/dist/browser/components/broadcast/details/SummaryStack.d.ts +2 -0
  6. package/dist/browser/components/broadcast/details/SummaryStack.d.ts.map +1 -1
  7. package/dist/browser/components/broadcast/details/SummaryStack.stories.d.ts +8 -0
  8. package/dist/browser/components/broadcast/details/SummaryStack.stories.d.ts.map +1 -0
  9. package/dist/browser/components/broadcast/usePaginatedEventPairs.d.ts +13 -0
  10. package/dist/browser/components/broadcast/usePaginatedEventPairs.d.ts.map +1 -0
  11. package/dist/browser/context/network/settings/types.d.ts +1 -1
  12. package/dist/browser/context/network/settings/types.d.ts.map +1 -1
  13. package/dist/browser/hooks/provider/UseViewerInPage.stories.d.ts.map +1 -1
  14. package/dist/browser/hooks/provider/useRpcBroadcastListener.d.ts +3 -2
  15. package/dist/browser/hooks/provider/useRpcBroadcastListener.d.ts.map +1 -1
  16. package/dist/browser/index.mjs +468 -337
  17. package/dist/browser/index.mjs.map +1 -1
  18. package/dist/browser/model/BroadcastRpc.d.ts +3 -0
  19. package/dist/browser/model/BroadcastRpc.d.ts.map +1 -1
  20. package/package.json +11 -10
  21. package/src/components/broadcast/Drawer.tsx +66 -14
  22. package/src/components/broadcast/details/Card.tsx +25 -9
  23. package/src/components/broadcast/details/SummaryStack.stories.tsx +36 -0
  24. package/src/components/broadcast/details/SummaryStack.tsx +41 -3
  25. package/src/components/broadcast/usePaginatedEventPairs.ts +64 -0
  26. package/src/context/network/settings/types.ts +1 -1
  27. package/src/hooks/provider/UseViewerInPage.stories.tsx +10 -8
  28. package/src/hooks/provider/useRpcBroadcastListener.ts +36 -6
  29. package/src/model/BroadcastRpc.ts +4 -0
  30. package/dist/browser/components/broadcast/helpers/formatEvents.d.ts +0 -7
  31. package/dist/browser/components/broadcast/helpers/formatEvents.d.ts.map +0 -1
  32. package/dist/browser/components/broadcast/helpers/index.d.ts +0 -2
  33. package/dist/browser/components/broadcast/helpers/index.d.ts.map +0 -1
  34. package/src/components/broadcast/helpers/formatEvents.ts +0 -40
  35. package/src/components/broadcast/helpers/index.ts +0 -1
@@ -0,0 +1,64 @@
1
+ import type { ChangeEvent } from 'react'
2
+ import {
3
+ useCallback, useMemo, useState,
4
+ } from 'react'
5
+
6
+ import type { RpcRequestResponsePairsById } from '../../model/index.ts'
7
+
8
+ export const usePaginatedEventPairs = (
9
+ formattedEvents: RpcRequestResponsePairsById,
10
+ numberOfVisiblePairs: number,
11
+ onClearEvents?: () => void,
12
+ ) => {
13
+ const [currentPage, setCurrentPage] = useState(0)
14
+
15
+ const allEventEntries = useMemo(() => {
16
+ return Object.entries(formattedEvents ?? {})
17
+ }, [formattedEvents])
18
+
19
+ const totalPages = useMemo(() => {
20
+ return Math.ceil(allEventEntries.length / numberOfVisiblePairs)
21
+ }, [allEventEntries.length, numberOfVisiblePairs])
22
+
23
+ // Clamp current page to valid range
24
+ const effectiveCurrentPage = useMemo(() => {
25
+ if (totalPages === 0) return 0
26
+ return Math.min(currentPage, totalPages - 1)
27
+ }, [currentPage, totalPages])
28
+
29
+ const visibleEvents = useMemo(() => {
30
+ const startIndex = effectiveCurrentPage * numberOfVisiblePairs
31
+ const endIndex = startIndex + numberOfVisiblePairs
32
+ return allEventEntries.slice(startIndex, endIndex)
33
+ }, [allEventEntries, effectiveCurrentPage, numberOfVisiblePairs])
34
+
35
+ const handlePreviousPage = useCallback(() => {
36
+ setCurrentPage(prev => Math.max(0, prev - 1))
37
+ }, [])
38
+
39
+ const handleNextPage = useCallback(() => {
40
+ setCurrentPage(prev => Math.min(totalPages - 1, prev + 1))
41
+ }, [totalPages])
42
+
43
+ const handleClearEvents = useCallback(() => {
44
+ setCurrentPage(0)
45
+ onClearEvents?.()
46
+ }, [onClearEvents])
47
+
48
+ // Compatible with TablePagination's onPageChange signature
49
+ // Accepts 1-indexed page, converts to 0-indexed internally
50
+ const handlePageChange = useCallback((_event: ChangeEvent<unknown>, page: number) => {
51
+ setCurrentPage(page - 1)
52
+ }, [])
53
+
54
+ return {
55
+ allEventEntries,
56
+ visibleEvents,
57
+ effectiveCurrentPage: effectiveCurrentPage + 1, // Return 1-indexed page
58
+ totalPages,
59
+ handlePreviousPage,
60
+ handleNextPage,
61
+ handleClearEvents,
62
+ handlePageChange,
63
+ }
64
+ }
@@ -1,7 +1,7 @@
1
1
  import type { GatewayName } from '@xyo-network/xl1-sdk'
2
2
 
3
3
  export type NetworkSetting = {
4
- proxy: true
4
+ proxy: boolean
5
5
  }
6
6
 
7
7
  export type ChainNetworkSettings = Record<GatewayName, NetworkSetting>
@@ -14,11 +14,7 @@ import type { HydratedBlock, NetworkId } from '@xyo-network/xl1-sdk'
14
14
  import {
15
15
  LocalNetwork, MainNetwork, SequenceNetwork,
16
16
  } from '@xyo-network/xl1-sdk'
17
- import React, {
18
- useCallback,
19
- useEffect,
20
- useState,
21
- } from 'react'
17
+ import React, { useCallback, useState } from 'react'
22
18
 
23
19
  import { BroadcastedRpcCallsDrawer } from '../../components/index.ts'
24
20
  import type { ChainNetworkSettings } from '../../context/index.ts'
@@ -67,7 +63,7 @@ const UseViewerInPageStoryTemplate: React.FC = () => {
67
63
  const [result, setResult] = useState<HydratedBlock | null | undefined>()
68
64
  const [loading, setLoading] = useState(false)
69
65
  const [drawerOpen, setDrawerOpen] = useState(false)
70
- const { events } = useRpcBroadcastListener()
66
+ const { clearEvents, events } = useRpcBroadcastListener()
71
67
 
72
68
  const handleClick = useCallback(async () => {
73
69
  if (isDefinedNotNull(viewer)) {
@@ -107,8 +103,13 @@ const UseViewerInPageStoryTemplate: React.FC = () => {
107
103
  No wallet extension found. Please install the Xyo Wallet Chrome Extension.
108
104
  </Alert>
109
105
  )}
110
- <BroadcastedRpcCallsDrawer open={drawerOpen} events={events} onClose={() => setDrawerOpen(false)} />
111
- <ButtonEx disabled={events.length === 0} variant="contained" onClick={() => setDrawerOpen(true)}>
106
+ <BroadcastedRpcCallsDrawer
107
+ open={drawerOpen}
108
+ events={events}
109
+ onClearEvents={clearEvents}
110
+ onClose={() => setDrawerOpen(false)}
111
+ />
112
+ <ButtonEx disabled={Object.keys(events).length === 0} variant="contained" onClick={() => setDrawerOpen(true)}>
112
113
  Show Broadcasted RPC Calls
113
114
  </ButtonEx>
114
115
  <ButtonEx loading={loading} variant="contained" onClick={() => void handleClick()} disabled={!isDefined(viewer)}>
@@ -138,6 +139,7 @@ export default {
138
139
  const Template: StoryFn<typeof UseViewerInPageStoryTemplate> = args => <UseViewerInPageStoryTemplate {...args} />
139
140
 
140
141
  const Default = Template.bind({})
142
+ Default.decorators = [UseViewerInPageStoryDecorator]
141
143
  Default.args = {}
142
144
  const Proxy = Template.bind({})
143
145
  Proxy.decorators = [UseViewerInPageStoryProxyDecorator]
@@ -1,10 +1,30 @@
1
- import { isString } from '@xylabs/sdk-js'
1
+ import type { JsonRpcRequest, JsonRpcResponse } from '@metamask/utils'
2
+ import { isJsonRpcRequest, isJsonRpcResponse } from '@metamask/utils'
3
+ import { isDefined, isString } from '@xylabs/sdk-js'
2
4
  import { useEffect, useState } from 'react'
3
5
 
4
- import type { BroadcastedRpcCall } from '../../model/index.ts'
6
+ import type {
7
+ BroadcastedRpcCall, RpcRequestResponsePairs, RpcRequestResponsePairsById,
8
+ } from '../../model/index.ts'
9
+
10
+ const parseRpcCall = (acc: RpcRequestResponsePairsById, event: BroadcastedRpcCall) => {
11
+ if (isJsonRpcResponse(event.rpcCall)) {
12
+ const castedEvent = event as BroadcastedRpcCall<JsonRpcResponse>
13
+ acc[castedEvent.rpcCall.id as string].result = castedEvent
14
+ } else if (isJsonRpcRequest(event.rpcCall)) {
15
+ const castedEvent = event as BroadcastedRpcCall<JsonRpcRequest>
16
+ acc[castedEvent.rpcCall.id as string].request = castedEvent
17
+ } else {
18
+ console.error('Unknown RPC call type', event)
19
+ }
20
+ acc[event.rpcCall.id as string].source = event.source
21
+
22
+ return acc
23
+ }
5
24
 
6
25
  export const useRpcBroadcastListener = () => {
7
- const [events, setEvents] = useState<BroadcastedRpcCall[]>([])
26
+ const [events, setEvents] = useState<RpcRequestResponsePairsById>({})
27
+ const clearEvents = () => setEvents({})
8
28
 
9
29
  useEffect(() => {
10
30
  const listener = (e: Event) => {
@@ -18,9 +38,19 @@ export const useRpcBroadcastListener = () => {
18
38
  const broadcastedRpcCall: BroadcastedRpcCall = {
19
39
  rpcCall,
20
40
  source,
21
- timestamp: e.timeStamp,
41
+ timestamp: Date.now(),
22
42
  }
23
- setEvents(prev => [broadcastedRpcCall, ...prev])
43
+ setEvents((prev) => {
44
+ const { id } = broadcastedRpcCall.rpcCall
45
+ const newState = { ...prev }
46
+ if (isDefined(newState[id as string])) {
47
+ parseRpcCall(newState, broadcastedRpcCall)
48
+ } else {
49
+ newState[id as string] = {} as RpcRequestResponsePairs
50
+ parseRpcCall(newState, broadcastedRpcCall)
51
+ }
52
+ return newState
53
+ })
24
54
  } catch (err) {
25
55
  console.error(err)
26
56
  }
@@ -36,5 +66,5 @@ export const useRpcBroadcastListener = () => {
36
66
  }
37
67
  }, [])
38
68
 
39
- return { events }
69
+ return { events, clearEvents }
40
70
  }
@@ -22,3 +22,7 @@ export type RpcRequestResponsePairs = {
22
22
  result?: BroadcastedRpcCall<JsonRpcResponse>
23
23
  source?: string
24
24
  }
25
+
26
+ export type RpcRequestResponsePairsById = {
27
+ [id: string]: RpcRequestResponsePairs
28
+ }
@@ -1,7 +0,0 @@
1
- import type { BroadcastedRpcCall, RpcRequestResponsePairs } from '../../../model/index.ts';
2
- type RpcRequestResponsePairsById = {
3
- [id: string]: RpcRequestResponsePairs;
4
- };
5
- export declare const formatEvents: (events: BroadcastedRpcCall[]) => RpcRequestResponsePairsById;
6
- export {};
7
- //# sourceMappingURL=formatEvents.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatEvents.d.ts","sourceRoot":"","sources":["../../../../../src/components/broadcast/helpers/formatEvents.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AAE1F,KAAK,2BAA2B,GAAG;IACjC,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAAA;CACtC,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,QAAQ,kBAAkB,EAAE,KAAG,2BA6B3D,CAAA"}
@@ -1,2 +0,0 @@
1
- export * from './formatEvents.ts';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/broadcast/helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA"}
@@ -1,40 +0,0 @@
1
- import type { JsonRpcRequest, JsonRpcResponse } from '@metamask/utils'
2
- import { isJsonRpcRequest, isJsonRpcResponse } from '@metamask/utils'
3
- import { isArray, isDefined } from '@xylabs/sdk-js'
4
-
5
- import type { BroadcastedRpcCall, RpcRequestResponsePairs } from '../../../model/index.ts'
6
-
7
- type RpcRequestResponsePairsById = {
8
- [id: string]: RpcRequestResponsePairs
9
- }
10
-
11
- export const formatEvents = (events: BroadcastedRpcCall[]): RpcRequestResponsePairsById => {
12
- if (!isArray(events) || events.length === 0) return {} as RpcRequestResponsePairsById
13
-
14
- const parseRpcCall = (acc: RpcRequestResponsePairsById, event: BroadcastedRpcCall) => {
15
- if (isJsonRpcResponse(event.rpcCall)) {
16
- const castedEvent = event as BroadcastedRpcCall<JsonRpcResponse>
17
- acc[castedEvent.rpcCall.id as string].result = castedEvent
18
- } else if (isJsonRpcRequest(event.rpcCall)) {
19
- const castedEvent = event as BroadcastedRpcCall<JsonRpcRequest>
20
- acc[castedEvent.rpcCall.id as string].request = castedEvent
21
- } else {
22
- console.error('Unknown RPC call type', event)
23
- }
24
- acc[event.rpcCall.id as string].source = event.source
25
-
26
- return acc
27
- }
28
-
29
- let acc: RpcRequestResponsePairsById = {}
30
- for (const event of events) {
31
- const { id } = event.rpcCall
32
- if (isDefined(acc[id as string])) {
33
- acc = parseRpcCall(acc, event)
34
- } else {
35
- acc[id as string] = {} as RpcRequestResponsePairs
36
- acc = parseRpcCall(acc, event)
37
- }
38
- }
39
- return acc
40
- }
@@ -1 +0,0 @@
1
- export * from './formatEvents.ts'