diff --git a/src/handlers/wallet.handlers.spec.ts b/src/handlers/wallet.handlers.spec.ts new file mode 100644 index 00000000..8685da13 --- /dev/null +++ b/src/handlers/wallet.handlers.spec.ts @@ -0,0 +1,73 @@ +import {retryRequestStatus} from './wallet.handlers'; + +describe('Wallet handlers', () => { + const testId = '1234_test'; + + let popup: Window; + let isReady: () => boolean; + + beforeEach(() => { + vi.useFakeTimers(); + + popup = { + postMessage: vi.fn() + } as unknown as Window; + }); + + afterEach(() => { + vi.useRealTimers(); + vi.clearAllMocks(); + }); + + describe('Success', () => { + beforeEach(() => { + let counter = 0; + isReady = vi.fn(() => { + counter++; + return counter > 1; + }); + }); + + it('should call icrc29_status postMessage and returns ready', async () => + // eslint-disable-next-line @typescript-eslint/return-await + new Promise((resolve) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + retryRequestStatus({popup, isReady, id: testId}).then((result) => { + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(popup.postMessage).toHaveBeenCalledWith( + { + id: testId, + jsonrpc: '2.0', + method: 'icrc29_status' + }, + '*' + ); + + expect(result).toEqual('ready'); + + resolve(); + }); + + vi.advanceTimersByTime(1000); + })); + }); + + describe('Failure', () => { + beforeEach(() => { + isReady = vi.fn(() => false); + }); + + it('should timeout after 30 seconds', async () => + // eslint-disable-next-line @typescript-eslint/return-await, no-async-promise-executor, @typescript-eslint/no-misused-promises + new Promise(async (resolve) => { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + retryRequestStatus({popup, isReady, id: testId}).then((result) => { + expect(result).toEqual('timeout'); + + resolve(); + }); + + await vi.advanceTimersByTimeAsync(60 * 500); + })); + }); +}); diff --git a/src/handlers/wallet.handlers.ts b/src/handlers/wallet.handlers.ts new file mode 100644 index 00000000..89daf9c3 --- /dev/null +++ b/src/handlers/wallet.handlers.ts @@ -0,0 +1,31 @@ +import {ICRC29_STATUS} from '../types/icrc'; +import type {IcrcWalletStatusRequestType} from '../types/icrc-requests'; +import {JSON_RPC_VERSION_2, type RpcIdType} from '../types/rpc'; +import {retryUntilReady} from '../utils/timeout.utils'; + +export const retryRequestStatus = async ({ + popup, + isReady, + id +}: { + popup: Window; + isReady: () => boolean; + id: RpcIdType; +}): Promise<'ready' | 'timeout'> => { + const requestStatus = (): void => { + const msg: IcrcWalletStatusRequestType = { + jsonrpc: JSON_RPC_VERSION_2, + id, + method: ICRC29_STATUS + }; + + popup.postMessage(msg, '*'); + }; + + return await retryUntilReady({ + // TODO: extract a variable and default value for the Wallet + retries: 60, // 30 seconds + isReady, + fn: requestStatus + }); +};