-
Notifications
You must be signed in to change notification settings - Fork 572
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate out HTTP API calls as a dedicated file (#1058)
* asdf * asdf * asdf * separate out http stuff * swap * linkAPIUrl no need after init * cleanup * for each * constructor * consistency * tests * update jest config
- Loading branch information
Showing
4 changed files
with
193 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
115 changes: 115 additions & 0 deletions
115
packages/wallet-sdk/src/connection/WalletLinkHTTP.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { ServerMessageEvent } from './ServerMessage'; | ||
import { WalletLinkHTTP } from './WalletLinkHTTP'; | ||
|
||
describe('WalletLinkHTTP', () => { | ||
const linkAPIUrl = 'https://example.com'; | ||
const sessionId = '123'; | ||
const sessionKey = 'abc'; | ||
|
||
it('should construct a WalletLinkHTTP instance with auth header', () => { | ||
const walletLinkHTTP = new WalletLinkHTTP(linkAPIUrl, sessionId, sessionKey); | ||
|
||
expect((walletLinkHTTP as any).auth).toEqual('Basic MTIzOmFiYw=='); | ||
}); | ||
|
||
describe('fetchUnseenEvents', () => { | ||
let events: { | ||
id: string; | ||
event: 'Web3Request' | 'Web3Response' | 'Web3RequestCanceled'; | ||
data: string; | ||
}[]; | ||
|
||
global.fetch = jest.fn().mockResolvedValue({ | ||
ok: true, | ||
json: () => ({ | ||
events, | ||
timestamp: 123, | ||
}), | ||
}); | ||
|
||
beforeEach(() => { | ||
events = []; | ||
}); | ||
|
||
describe('fetchUnseenEvents', () => { | ||
it('should return an empty array if there are no unseen events', async () => { | ||
const walletLinkHTTP = new WalletLinkHTTP(linkAPIUrl, sessionId, sessionKey); | ||
jest.spyOn(walletLinkHTTP as any, 'markUnseenEventsAsSeen').mockImplementation(() => {}); | ||
|
||
const result = await walletLinkHTTP.fetchUnseenEvents(); | ||
|
||
expect(result).toEqual([]); | ||
}); | ||
|
||
it('should return an array of unseen events', async () => { | ||
events = [ | ||
{ | ||
id: '1', | ||
event: 'Web3Response', | ||
data: 'data 1', | ||
}, | ||
{ | ||
id: '2', | ||
event: 'Web3Response', | ||
data: 'data 2', | ||
}, | ||
]; | ||
|
||
const walletLinkHTTP = new WalletLinkHTTP(linkAPIUrl, sessionId, sessionKey); | ||
jest.spyOn(walletLinkHTTP as any, 'markUnseenEventsAsSeen').mockImplementation(() => {}); | ||
|
||
const result = await walletLinkHTTP.fetchUnseenEvents(); | ||
|
||
expect(result).toEqual([ | ||
{ | ||
type: 'Event', | ||
sessionId: '123', | ||
eventId: '1', | ||
event: 'Web3Response', | ||
data: 'data 1', | ||
}, | ||
{ | ||
type: 'Event', | ||
sessionId: '123', | ||
eventId: '2', | ||
event: 'Web3Response', | ||
data: 'data 2', | ||
}, | ||
]); | ||
}); | ||
}); | ||
|
||
describe('markUnseenEventsAsSeen', () => { | ||
it('should mark all unseen events as seen', () => { | ||
const walletLinkHTTP = new WalletLinkHTTP(linkAPIUrl, sessionId, sessionKey); | ||
const unseenEvents: ServerMessageEvent[] = [ | ||
{ | ||
type: 'Event', | ||
sessionId: '1', | ||
eventId: 'id-1', | ||
event: 'Web3Response', | ||
data: 'data 1', | ||
}, | ||
{ | ||
type: 'Event', | ||
sessionId: '2', | ||
eventId: 'id-2', | ||
event: 'Web3Response', | ||
data: 'data 2', | ||
}, | ||
]; | ||
|
||
// spy on fetch and verify that it was called with the correct arguments | ||
const fetchSpy = jest.spyOn(global, 'fetch'); | ||
|
||
(walletLinkHTTP as any).markUnseenEventsAsSeen(unseenEvents); | ||
|
||
const metadata = expect.objectContaining({ headers: expect.anything(), method: 'POST' }); | ||
|
||
expect(fetchSpy).toHaveBeenCalledWith('https://example.com/events/id-1/seen', metadata); | ||
expect(fetchSpy).toHaveBeenCalledWith('https://example.com/events/id-2/seen', metadata); | ||
expect(fetchSpy).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { ServerMessageEvent } from './ServerMessage'; | ||
|
||
export class WalletLinkHTTP { | ||
private readonly auth: string; | ||
|
||
constructor( | ||
private readonly linkAPIUrl: string, | ||
private readonly sessionId: string, | ||
sessionKey: string | ||
) { | ||
const credentials = `${sessionId}:${sessionKey}`; | ||
this.auth = `Basic ${btoa(credentials)}`; | ||
} | ||
|
||
// mark unseen events as seen | ||
private async markUnseenEventsAsSeen(events: ServerMessageEvent[]) { | ||
return Promise.all( | ||
events.map((e) => | ||
fetch(`${this.linkAPIUrl}/events/${e.eventId}/seen`, { | ||
method: 'POST', | ||
headers: { | ||
Authorization: this.auth, | ||
}, | ||
}) | ||
) | ||
).catch((error) => console.error('Unabled to mark event as failed:', error)); | ||
} | ||
|
||
async fetchUnseenEvents(): Promise<ServerMessageEvent[]> { | ||
const response = await fetch(`${this.linkAPIUrl}/events?unseen=true`, { | ||
headers: { | ||
Authorization: this.auth, | ||
}, | ||
}); | ||
|
||
if (response.ok) { | ||
const { events, error } = (await response.json()) as { | ||
events?: { | ||
id: string; | ||
event: 'Web3Request' | 'Web3Response' | 'Web3RequestCanceled'; | ||
data: string; | ||
}[]; | ||
timestamp: number; | ||
error?: string; | ||
}; | ||
|
||
if (error) { | ||
throw new Error(`Check unseen events failed: ${error}`); | ||
} | ||
|
||
const responseEvents: ServerMessageEvent[] = | ||
events | ||
?.filter((e) => e.event === 'Web3Response') | ||
.map((e) => ({ | ||
type: 'Event', | ||
sessionId: this.sessionId, | ||
eventId: e.id, | ||
event: e.event, | ||
data: e.data, | ||
})) ?? []; | ||
|
||
this.markUnseenEventsAsSeen(responseEvents); | ||
|
||
return responseEvents; | ||
} | ||
throw new Error(`Check unseen events failed: ${response.status}`); | ||
} | ||
} |