11import { useState , useEffect , useRef } from 'react' ;
2- import { RequestQuery , OfferOptions , contractConfig , serverAddress } from '../../shared/index.js' ;
3- import {
4- Client ,
5- ClientOptions ,
6- RequestRecord ,
7- createClient ,
8- storage ,
9- utils ,
10- } from '../../../src/index.js' ; //@windingtree /sdk
2+ import { Client , ClientOptions , createClient , storage } from '../../../src/index.js' ; // @windingtree /sdk
3+ import { RequestQuery , OfferOptions , chainConfig , serverAddress } from '../../shared/index.js' ;
4+ import { OfferData } from '../../../src/shared/types.js' ;
5+ import { useWallet } from './providers/WalletProvider/WalletProviderContext.js' ;
6+ import { AccountWidget } from './providers/WalletProvider/AccountWidget.js' ;
7+ import { FormValues , RequestForm } from './components/RequestForm.js' ;
8+ import { Tabs , TabPanel } from './components/Tabs.js' ;
9+ import { Requests , RequestsRegistryRecord } from './components/Requests.js' ;
10+ import { MakeDeal } from './components/MakeDeal.js' ;
11+ import { Offers } from './components/Offers.js' ;
12+ import { Deals , DealsRegistryRecord } from './components/Deals.js' ;
1113
1214/** Default request expiration time */
1315const defaultExpire = '30s' ;
1416
1517/** Default topic to publish requests the same as for the supplier node */
1618const defaultTopic = 'hello' ;
1719
18- type RequestsRegistryRecord = Required < RequestRecord < RequestQuery , OfferOptions > > ;
19-
20- interface FormValues {
21- topic : string ;
22- message : string ;
23- }
24-
25- interface RequestFormProps {
26- connected : boolean ;
27- onSubmit ( query : FormValues ) : void ;
28- }
29-
30- interface RequestsProps {
31- requests : RequestsRegistryRecord [ ] ;
32- subscribed ?: ( id : string ) => boolean ;
33- onClear ( ) : void ;
34- onCancel ( id : string ) : void ;
35- }
36-
37- /**
38- * Accepts user input
39- */
40- export const RequestForm = ( { connected, onSubmit } : RequestFormProps ) => {
41- const [ topic , setTopic ] = useState < string > ( defaultTopic ) ;
42- const [ message , setMessage ] = useState < string > ( '' ) ;
43-
44- if ( ! connected ) {
45- return null ;
46- }
47-
48- return (
49- < div style = { { marginTop : 20 } } >
50- < form
51- onSubmit = { ( e ) => {
52- e . preventDefault ( ) ;
53- if ( message === '' ) {
54- return ;
55- }
56- onSubmit ( {
57- topic,
58- message,
59- } ) ;
60- } }
61- >
62- < div style = { { marginBottom : 20 } } >
63- < div >
64- < strong > Topic:</ strong >
65- </ div >
66- < div style = { { marginBottom : 5 } } >
67- < input value = { topic } onChange = { ( e ) => setTopic ( e . target . value ) } />
68- </ div >
69- < div >
70- < strong > Request:</ strong >
71- </ div >
72- < div >
73- < input value = { message } onChange = { ( e ) => setMessage ( e . target . value ) } />
74- </ div >
75- < div style = { { display : 'flex' , alignItems : 'center' , marginTop : 10 } } >
76- < div >
77- < button type = "submit" > Send</ button >
78- </ div >
79- </ div >
80- </ div >
81- </ form >
82- </ div >
83- ) ;
84- } ;
85-
8620/**
87- * Published requests table
21+ * Main application component
8822 */
89- export const Requests = ( { requests, subscribed, onClear, onCancel } : RequestsProps ) => {
90- if ( requests . length === 0 ) {
91- return null ;
92- }
93-
94- return (
95- < div style = { { marginTop : 20 } } >
96- < table border = { 1 } cellPadding = { 5 } >
97- < thead >
98- < tr >
99- < td > Topic</ td >
100- < td > Id</ td >
101- < td > Query</ td >
102- < td > Subscribed</ td >
103- < td > Expired</ td >
104- < td > Offers</ td >
105- < td > Cancel</ td >
106- </ tr >
107- </ thead >
108- < tbody >
109- { requests . map ( ( r , index ) => (
110- < tr key = { index } >
111- < td > { r . data . topic } </ td >
112- < td > { r . data . id } </ td >
113- < td > { JSON . stringify ( r . data . query ) } </ td >
114- < td > { subscribed && subscribed ( r . data . id ) ? '✅' : 'no' } </ td >
115- < td > { utils . isExpired ( r . data . expire ) || r . cancelled ? '✅' : 'no' } </ td >
116- < td > { r . offers . length } </ td >
117- < td >
118- { ! r . cancelled && ! utils . isExpired ( r . data . expire ) ? (
119- < button
120- onClick = { ( ) => {
121- onCancel ( r . data . id ) ;
122- } }
123- >
124- Cancel
125- </ button >
126- ) : (
127- 'cancelled'
128- ) }
129- </ td >
130- </ tr >
131- ) ) }
132- </ tbody >
133- </ table >
134- < div style = { { marginTop : 10 } } >
135- < button
136- onClick = { ( e ) => {
137- e . preventDefault ( ) ;
138- onClear ( ) ;
139- } }
140- >
141- Clear
142- </ button >
143- </ div >
144- </ div >
145- ) ;
146- } ;
147-
14823export const App = ( ) => {
14924 const client = useRef < Client < RequestQuery , OfferOptions > | undefined > ( ) ;
25+ const { publicClient } = useWallet ( ) ;
15026 const [ connected , setConnected ] = useState < boolean > ( false ) ;
27+ const [ selectedTab , setSelectedTab ] = useState < number > ( 0 ) ;
15128 const [ requests , setRequests ] = useState < RequestsRegistryRecord [ ] > ( [ ] ) ;
29+ const [ deals , setDeals ] = useState < DealsRegistryRecord [ ] > ( [ ] ) ;
30+ const [ offers , setOffers ] = useState < OfferData < RequestQuery , OfferOptions > [ ] | undefined > ( ) ;
31+ const [ offer , setOffer ] = useState < OfferData < RequestQuery , OfferOptions > | undefined > ( ) ;
15232 const [ error , setError ] = useState < string | undefined > ( ) ;
15333
15434 /** This hook starts the client that will be available via `client.current` */
@@ -158,21 +38,35 @@ export const App = () => {
15838 setError ( undefined ) ;
15939
16040 const options : ClientOptions = {
161- contractConfig ,
41+ chain : chainConfig ,
16242 serverAddress,
16343 storageInitializer : storage . localStorage . createInitializer ( {
164- session : true ,
44+ session : false , // session or local storage
16545 } ) ,
166- requestRegistryPrefix : 'requestsRegistry' ,
46+ dbKeysPrefix : 'wt_' ,
47+ publicClient,
48+ } ;
49+
50+ const updateRequests = ( ) => {
51+ if ( client . current ) {
52+ setRequests ( client . current . requests . getAll ( ) ) ;
53+ }
54+ } ;
55+
56+ const updateDeals = ( ) => {
57+ if ( client . current ) {
58+ client . current . deals . getAll ( ) . then ( ( newDeals ) => {
59+ setDeals ( newDeals ) ;
60+ } ) . catch ( console . error ) ;
61+ }
16762 } ;
16863
16964 client . current = createClient < RequestQuery , OfferOptions > ( options ) ;
17065
17166 client . current . addEventListener ( 'start' , ( ) => {
17267 console . log ( '🚀 Client started at:' , new Date ( ) . toISOString ( ) ) ;
173- if ( client . current ) {
174- setRequests ( client . current . requests . getAll ( ) ) ;
175- }
68+ updateRequests ( ) ;
69+ updateDeals ( ) ;
17670 } ) ;
17771
17872 client . current . addEventListener ( 'stop' , ( ) => {
@@ -189,14 +83,7 @@ export const App = () => {
18983 console . log ( '🔌 Client disconnected from server at:' , new Date ( ) . toISOString ( ) ) ;
19084 } ) ;
19185
192- const updateRequests = ( ) => {
193- if ( ! client . current ) {
194- return ;
195- }
196- setRequests ( client . current . requests . getAll ( ) ) ;
197- } ;
198-
199- /** Listening for requests events and update the table */
86+ /** Listening for requests events and update tables */
20087 client . current . addEventListener ( 'request:create' , updateRequests ) ;
20188 client . current . addEventListener ( 'request:subscribe' , updateRequests ) ;
20289 client . current . addEventListener ( 'request:publish' , updateRequests ) ;
@@ -206,6 +93,7 @@ export const App = () => {
20693 client . current . addEventListener ( 'request:delete' , updateRequests ) ;
20794 client . current . addEventListener ( 'request:offer' , updateRequests ) ;
20895 client . current . addEventListener ( 'request:clear' , updateRequests ) ;
96+ client . current . addEventListener ( 'deal:changed' , updateDeals ) ;
20997
21098 await client . current . start ( ) ;
21199 } catch ( error ) {
@@ -215,7 +103,7 @@ export const App = () => {
215103 } ;
216104
217105 startClient ( ) ;
218- } , [ ] ) ;
106+ } , [ publicClient ] ) ;
219107
220108 /** Publishing of request */
221109 const sendRequest = async ( { topic, message } : FormValues ) => {
@@ -229,7 +117,7 @@ export const App = () => {
229117 const request = await client . current . requests . create ( {
230118 topic,
231119 expire : defaultExpire ,
232- nonce : 1 ,
120+ nonce : BigInt ( 1 ) ,
233121 query : {
234122 greeting : message ,
235123 } ,
@@ -244,26 +132,59 @@ export const App = () => {
244132
245133 return (
246134 < >
135+ < div style = { { display : 'flex' , flexDirection : 'row' , alignItems : 'center' } } >
136+ < div style = { { flex : 1 } } >
137+ < h1 > Client</ h1 >
138+ </ div >
139+ < AccountWidget />
140+ </ div >
247141 { client . current && < div > ✅ Client started</ div > }
248142 { connected && < div > ✅ Connected to the coordination server</ div > }
249- < RequestForm connected = { connected } onSubmit = { sendRequest } />
250- < Requests
251- requests = { requests }
252- subscribed = { ( id ) => {
253- console . log ( '###' , id ) ;
254- return client . current ?. requests . subscribed ( id ) || false ;
255- } }
256- onClear = { ( ) => {
257- if ( client . current ) {
258- client . current ?. requests . clear ( ) ;
259- }
260- } }
261- onCancel = { ( id ) => {
262- if ( client . current ) {
263- client . current . requests . cancel ( id ) ;
264- }
265- } }
143+ < RequestForm connected = { connected } onSubmit = { sendRequest } defaultTopic = { defaultTopic } />
144+ < Tabs
145+ tabs = { [
146+ {
147+ id : 0 ,
148+ title : 'Requests' ,
149+ active : true ,
150+ } ,
151+ {
152+ id : 1 ,
153+ title : 'Deals' ,
154+ } ,
155+ ] }
156+ onChange = { setSelectedTab }
266157 />
158+ < TabPanel id = { 0 } activeTab = { selectedTab } >
159+ < Requests
160+ requests = { requests }
161+ subscribed = { ( id ) => client . current ?. requests . subscribed ( id ) || false }
162+ onClear = { ( ) => {
163+ if ( client . current ) {
164+ client . current ?. requests . clear ( ) ;
165+ }
166+ } }
167+ onCancel = { ( id ) => {
168+ if ( client . current ) {
169+ client . current . requests . cancel ( id ) ;
170+ }
171+ } }
172+ onOffers = { setOffers }
173+ />
174+ < Offers
175+ offers = { offers }
176+ onAccept = { setOffer }
177+ onClose = { ( ) => {
178+ setOffer ( undefined ) ;
179+ setOffers ( undefined ) ;
180+ } }
181+ />
182+ < MakeDeal offer = { offer } client = { client . current } />
183+ </ TabPanel >
184+ < TabPanel id = { 1 } activeTab = { selectedTab } >
185+ < Deals deals = { deals } client = { client . current } />
186+ </ TabPanel >
187+
267188 { error && < div style = { { marginTop : 20 } } > 🚨 { error } </ div > }
268189 </ >
269190 ) ;
0 commit comments