Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map error type to message #1782

Merged
merged 4 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions components/account/WalletSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ const WalletSelect = () => {
)}
{hasError && (
<div className="text-vermilion ml-auto text-ztg-12-120 w-ztg-275">
{error.type === "NoAccounts"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this actually change? Since error type should only be one of two types it seems like the old code should cover all cases?

Copy link
Member Author

@Robiquet Robiquet Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect the types are probably wrong and not all errors are accounted for. Even so, I don't think the previous code is good practice as it assumes that there will only ever be 2 error types

? "No accounts on this wallet. Please add account in wallet extension."
: "Not allowed to interact with extension. Please change permission settings."}
{error.type === "NoAccounts" &&
"No accounts on this wallet. Please add account in wallet extension."}
{error.type === "InteractionDenied" &&
"Not allowed to interact with extension. Please change permission settings."}
</div>
)}
</div>
Expand Down
6 changes: 3 additions & 3 deletions lib/state/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { cryptoWaitReady } from "@polkadot/util-crypto";
import { InjectedAccount } from "@polkadot/extension-inject/types";
import { isPresent } from "lib/types";
import { PollingTimeout, poll } from "@zeitgeistpm/avatara-util";
import { PollingTimeout, poll } from "lib/util/poll";

const DAPP_NAME = "zeitgeist";

Expand Down Expand Up @@ -225,15 +225,15 @@ const enableWallet = async (walletId: string) => {
}

const enablePoll = async (): Promise<void> => {
await cryptoWaitReady();
try {
const extension = await poll(
async () => {
await cryptoWaitReady();
await wallet.enable(DAPP_NAME);
return wallet;
},
{
intervall: 66,
interval: 66,
timeout: 10_000,
},
);
Expand Down
34 changes: 34 additions & 0 deletions lib/util/poll.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { poll, PollingTimeout } from "./poll";

describe("poll", () => {
test("should only call input function once if it succeeds", async () => {
const testFn = jest.fn(async () => {
return new Promise((resolve) => {
resolve("foo");
});
});

const res = await poll(testFn, {
interval: 50,
timeout: 1000,
});

expect(res).toEqual("foo");
expect(testFn).toHaveBeenCalledTimes(1);
});

test("should call function at least twice and timeout", async () => {
const testFn = jest.fn(async () => {
throw new Error("1) What");
});

const res = await poll(testFn, {
interval: 1,
timeout: 100,
});

expect(res).toEqual(PollingTimeout);
expect(testFn).toHaveBeenNthCalledWith(1);
expect(testFn).toHaveBeenNthCalledWith(2);
});
});
49 changes: 49 additions & 0 deletions lib/util/poll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { delay } from "./delay";

/**
* Static literal symbol for a timed out polling try.
*/
export const PollingTimeout = "timeout";
export type PollingTimeout = typeof PollingTimeout;

/**
* @generic T type of the returned value
* @param fn () => Promise T - the fn called to poll for values
* @param opts.timeout number - how long to try total from start to finish.
* @param opts.interval number - the time between tries.
* @param opts.retries number - number of retries.
* @param opts.validator (value: T) => Promise<boolean> - check the value returned from the fn
* @returns Promise T | PollingTimeout | null
*/
export const poll = async <T>(
fn: () => Promise<T | null | PollingTimeout>,
opts: {
timeout: number;
interval: number;
validator?: (value: T | null | PollingTimeout) => Promise<boolean>;
},
): Promise<T | null | PollingTimeout> => {
if (opts.timeout <= 0) {
return PollingTimeout;
}

const start = Date.now();

try {
const value = await fn();
if (value && (!opts.validator || (await opts.validator(value)))) {
return value;
}
} catch {
await delay(opts.interval);

const end = Date.now();

return poll<T>(fn, { ...opts, timeout: opts.timeout - (end - start) });
}
await delay(opts.interval);

const end = Date.now();

return poll<T>(fn, { ...opts, timeout: opts.timeout - (end - start) });
};