Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ describe('UnifiedWavesList', () => {
render(
<UnifiedWavesList
waves={[]}
activeWaveId={null}
fetchNextPage={jest.fn()}
hasNextPage={false}
isFetching={false}
Expand Down Expand Up @@ -87,7 +86,6 @@ describe('UnifiedWavesList', () => {
render(
<UnifiedWavesList
waves={[createMockMinimalWave({ id: '1', isPinned: false })]}
activeWaveId={null}
fetchNextPage={fetchNextPage}
hasNextPage={true}
isFetching={false}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react';
import SnapshotExcludeComponentWinners from '@/components/distribution-plan-tool/build-phases/build-phase/form/component-config/SnapshotExcludeComponentWinners';
import type { PhaseGroupSnapshotConfig } from '@/components/distribution-plan-tool/build-phases/build-phase/form/BuildPhaseFormConfigModal';
import { DistributionPlanToolContext } from '@/components/distribution-plan-tool/DistributionPlanToolContext';

jest.mock('@/components/distribution-plan-tool/build-phases/build-phase/form/component-config/ComponentConfigNextBtn', () => ({
Expand Down Expand Up @@ -37,11 +38,23 @@ const phases = [
{ id: 'p1', name: 'Phase1', components: [{ id: 'c1', name: 'Comp1' }] },
] as any;

const baseConfig: PhaseGroupSnapshotConfig = {
groupSnapshotId: 'g1',
snapshotId: 's1',
snapshotType: null,
snapshotSchema: null,
excludeComponentWinners: [],
excludeSnapshots: [],
topHoldersFilter: null,
tokenIds: null,
uniqueWalletsCount: null,
};

test('shows error toast when nothing selected', () => {
const setToasts = jest.fn();
render(
<DistributionPlanToolContext.Provider value={{ setToasts } as any}>
<SnapshotExcludeComponentWinners phases={phases} onNextStep={jest.fn()} onSelectExcludeComponentWinners={jest.fn()} title="t" onClose={jest.fn()} />
<SnapshotExcludeComponentWinners config={baseConfig} phases={phases} onNextStep={jest.fn()} onSelectExcludeComponentWinners={jest.fn()} title="t" onClose={jest.fn()} />
</DistributionPlanToolContext.Provider>
);
fireEvent.click(screen.getByTestId('next'));
Expand All @@ -50,10 +63,14 @@ test('shows error toast when nothing selected', () => {

test('returns selected component ids on next', () => {
const onSelect = jest.fn();
const config: PhaseGroupSnapshotConfig = {
...baseConfig,
uniqueWalletsCount: 42,
};
render(
<SnapshotExcludeComponentWinners phases={phases} onNextStep={jest.fn()} onSelectExcludeComponentWinners={onSelect} title="t" onClose={jest.fn()} />, { wrapper: Wrapper }
<SnapshotExcludeComponentWinners config={config} phases={phases} onNextStep={jest.fn()} onSelectExcludeComponentWinners={onSelect} title="t" onClose={jest.fn()} />, { wrapper: Wrapper }
);
fireEvent.click(screen.getByTestId('opt-c1'));
fireEvent.click(screen.getByTestId('next'));
expect(onSelect).toHaveBeenCalledWith({ excludeComponentWinners: ['c1'], uniqueWalletsCount: null });
expect(onSelect).toHaveBeenCalledWith({ excludeComponentWinners: ['c1'], uniqueWalletsCount: 42 });
});
2 changes: 1 addition & 1 deletion components/app-wallets/AppWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export default function AppWalletComponent(
url: result.uri,
dialogTitle: "Share or Save File",
});
} catch (_error) {
} catch {
alert("Unable to write file");
}
};
Expand Down
187 changes: 99 additions & 88 deletions components/app-wallets/AppWalletsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import React, {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
Expand Down Expand Up @@ -53,7 +54,7 @@ export const AppWalletsProvider: React.FC<{ children: React.ReactNode }> = ({
const capacitor = useCapacitor();
const { isCapacitor } = capacitor;

const fetchAppWallets = async () => {
const fetchAppWallets = useCallback(async () => {
if (!appWalletsSupported) {
setFetchingAppWallets(false);
setAppWallets([]);
Expand All @@ -66,7 +67,7 @@ export const AppWalletsProvider: React.FC<{ children: React.ReactNode }> = ({

setAppWallets(wallets);
setFetchingAppWallets(false);
};
}, [appWalletsSupported]);

useEffect(() => {
let cancelled = false;
Expand Down Expand Up @@ -112,97 +113,107 @@ export const AppWalletsProvider: React.FC<{ children: React.ReactNode }> = ({
};
}, [isCapacitor]);

const createAppWallet = async (
name: string,
pass: string
): Promise<boolean> => {
if (!appWalletsSupported) return false;

const wallet = ethers.Wallet.createRandom();
const encryptedAddress = await encryptData(
wallet.address,
wallet.address,
pass
);
const encryptedMnemonic = await encryptData(
wallet.address,
wallet.mnemonic?.phrase ?? "",
pass
);
const encryptedPrivateKey = await encryptData(
wallet.address,
wallet.privateKey,
pass
);

const appWallet: AppWallet = {
name,
created_at: Time.now().toSeconds(),
address: wallet.address,
address_hashed: encryptedAddress,
mnemonic: encryptedMnemonic,
private_key: encryptedPrivateKey,
imported: false,
};

const result = await SecureStoragePlugin.set({
key: `${WALLET_KEY_PREFIX}${wallet.address}`,
value: JSON.stringify(appWallet),
});

await fetchAppWallets();

return result.value;
};

const importAppWallet = async (
walletName: string,
walletPass: string,
address: string,
mnemonic: string,
privateKey: string
): Promise<boolean> => {
if (!appWalletsSupported) return false;

const encryptedAddress = await encryptData(address, address, walletPass);
const encryptedMnemonic = await encryptData(address, mnemonic, walletPass);
const encryptedPrivateKey = await encryptData(
address,
privateKey,
walletPass
);

const wallet: AppWallet = {
name: walletName,
created_at: Time.now().toSeconds(),
address,
address_hashed: encryptedAddress,
mnemonic: encryptedMnemonic,
private_key: encryptedPrivateKey,
imported: true,
};

const result = await SecureStoragePlugin.set({
key: `${WALLET_KEY_PREFIX}${address}`,
value: JSON.stringify(wallet),
});

await fetchAppWallets();
const createAppWallet = useCallback(
async (name: string, pass: string): Promise<boolean> => {
if (!appWalletsSupported) return false;

const wallet = ethers.Wallet.createRandom();
const encryptedAddress = await encryptData(
wallet.address,
wallet.address,
pass
);
const encryptedMnemonic = await encryptData(
wallet.address,
wallet.mnemonic?.phrase ?? "",
pass
);
const encryptedPrivateKey = await encryptData(
wallet.address,
wallet.privateKey,
pass
);

const appWallet: AppWallet = {
name,
created_at: Time.now().toSeconds(),
address: wallet.address,
address_hashed: encryptedAddress,
mnemonic: encryptedMnemonic,
private_key: encryptedPrivateKey,
imported: false,
};

const result = await SecureStoragePlugin.set({
key: `${WALLET_KEY_PREFIX}${wallet.address}`,
value: JSON.stringify(appWallet),
});

await fetchAppWallets();

return result.value;
},
[appWalletsSupported, fetchAppWallets]
);

return result.value;
};
const importAppWallet = useCallback(
async (
walletName: string,
walletPass: string,
address: string,
mnemonic: string,
privateKey: string
): Promise<boolean> => {
if (!appWalletsSupported) return false;

const encryptedAddress = await encryptData(address, address, walletPass);
const encryptedMnemonic = await encryptData(
address,
mnemonic,
walletPass
);
const encryptedPrivateKey = await encryptData(
address,
privateKey,
walletPass
);

const wallet: AppWallet = {
name: walletName,
created_at: Time.now().toSeconds(),
address,
address_hashed: encryptedAddress,
mnemonic: encryptedMnemonic,
private_key: encryptedPrivateKey,
imported: true,
};

const result = await SecureStoragePlugin.set({
key: `${WALLET_KEY_PREFIX}${address}`,
value: JSON.stringify(wallet),
});

await fetchAppWallets();

return result.value;
},
[appWalletsSupported, fetchAppWallets]
);

const deleteAppWallet = async (address: string): Promise<boolean> => {
if (!appWalletsSupported) return false;
const deleteAppWallet = useCallback(
async (address: string): Promise<boolean> => {
if (!appWalletsSupported) return false;

const result = await SecureStoragePlugin.remove({
key: `${WALLET_KEY_PREFIX}${address}`,
});
const result = await SecureStoragePlugin.remove({
key: `${WALLET_KEY_PREFIX}${address}`,
});

await fetchAppWallets();
await fetchAppWallets();

return result.value;
};
return result.value;
},
[appWalletsSupported, fetchAppWallets]
);

const value = useMemo(
() => ({
Expand Down
21 changes: 7 additions & 14 deletions components/block-picker/advanced/BlockPickerAdvancedItemBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"use client";

import Link from "next/link";
import { faCopy } from "@fortawesome/free-regular-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useState } from "react";
import { useCopyToClipboard } from "react-use";

Expand Down Expand Up @@ -35,7 +37,7 @@ export default function BlockPickerAdvancedItemBlock({
parts.push(number.substring(lastIndex));
}

const [copyState, copyToClipboard] = useCopyToClipboard();
const [, copyToClipboard] = useCopyToClipboard();
const [coping, setCoping] = useState(false);

const copy = () => {
Expand All @@ -46,20 +48,11 @@ export default function BlockPickerAdvancedItemBlock({

return (
<div>
<svg
<FontAwesomeIcon
onClick={copy}
className="tw-h-5 tw-cursor-pointer tw-w-5 tw-mr-2.5 tw-text-iron-300 hover:tw-text-white tw-transition tw-duration-300 tw-ease-out"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M5 15C4.06812 15 3.60218 15 3.23463 14.8478C2.74458 14.6448 2.35523 14.2554 2.15224 13.7654C2 13.3978 2 12.9319 2 12V5.2C2 4.0799 2 3.51984 2.21799 3.09202C2.40973 2.71569 2.71569 2.40973 3.09202 2.21799C3.51984 2 4.0799 2 5.2 2H12C12.9319 2 13.3978 2 13.7654 2.15224C14.2554 2.35523 14.6448 2.74458 14.8478 3.23463C15 3.60218 15 4.06812 15 5M12.2 22H18.8C19.9201 22 20.4802 22 20.908 21.782C21.2843 21.5903 21.5903 21.2843 21.782 20.908C22 20.4802 22 19.9201 22 18.8V12.2C22 11.0799 22 10.5198 21.782 10.092C21.5903 9.71569 21.2843 9.40973 20.908 9.21799C20.4802 9 19.9201 9 18.8 9H12.2C11.0799 9 10.5198 9 10.092 9.21799C9.71569 9.40973 9.40973 9.71569 9.21799 10.092C9 10.5198 9 11.0799 9 12.2V18.8C9 19.9201 9 20.4802 9.21799 20.908C9.40973 21.2843 9.71569 21.5903 10.092 21.782C10.5198 22 11.0799 22 12.2 22Z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
className="tw-h-5 tw-w-5 tw-cursor-pointer tw-mr-2.5 tw-text-iron-300 hover:tw-text-white tw-transition tw-duration-300 tw-ease-out"
icon={faCopy}
/>
{coping ? (
"Copied"
) : (
Expand Down
Loading