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

feat: increase test coverage #46

Merged
merged 42 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d650065
feat: block error tests
marcomariscal Mar 29, 2024
8addbe8
chore: remove unused
marcomariscal Mar 29, 2024
a87688a
feat: improve getAnnouncementsForUser test coverage
marcomariscal Mar 29, 2024
941f9c4
feat: getStealthMetaAddress improve coverage
marcomariscal Mar 29, 2024
0935765
fix: use process announcements directly
marcomariscal Mar 29, 2024
4edb850
feat: getAnnouncementsForUser error class tests
marcomariscal Apr 3, 2024
bb22ba9
feat: setupTestEnv coverage improvements
marcomariscal Apr 4, 2024
7c8eaac
fix: fetchChainId dry
marcomariscal Apr 4, 2024
55867c1
feat: improve setupTestWallet coverage
marcomariscal Apr 4, 2024
8e1658c
chore: remove unused
marcomariscal Apr 4, 2024
9a4ab7d
chore: remove unused
marcomariscal Apr 4, 2024
8b0ecd6
feat: move chain error throwing logic to func
marcomariscal Apr 4, 2024
41c8ae3
feat: improve createStealthClient test coverage
marcomariscal Apr 4, 2024
058a3bc
feat: improve coverage for getViewTagFromMetadata
marcomariscal Apr 4, 2024
22ed14e
chore: remove unused
marcomariscal Apr 4, 2024
f29ed17
feat: inc test coverage for genStealthAddress
marcomariscal Apr 4, 2024
628b81b
chore: remove unused
marcomariscal Apr 4, 2024
268c0c8
Merge branch 'main' into feat/increase-test-coverage
marcomariscal Apr 4, 2024
cb12486
feat: handle prepare error
marcomariscal Apr 4, 2024
1a770c0
feat: improve coverage
marcomariscal Apr 4, 2024
4237793
feat: coverage threshold
marcomariscal Apr 12, 2024
a7f1765
chore: remove unnecessary
marcomariscal Apr 12, 2024
654bdd8
feat: coverage to .98
marcomariscal Apr 12, 2024
7880e2e
fix: lint errors
marcomariscal Apr 12, 2024
a2b9c89
package: update viem
marcomariscal Apr 12, 2024
34287b2
fix: move contract writing to beforeall
marcomariscal Apr 12, 2024
1b75e23
fix: remove async from describe
marcomariscal Apr 12, 2024
cfa3afc
chore: clarity
marcomariscal Apr 12, 2024
0a35537
fix: lint
marcomariscal Apr 12, 2024
40ee5b1
chore: log to test gh action
marcomariscal Apr 12, 2024
857daff
fix: handle block is null/pending
marcomariscal Apr 12, 2024
2322065
fix: revert
marcomariscal Apr 12, 2024
b965ef6
chore: log
marcomariscal Apr 12, 2024
edb9838
chore: log
marcomariscal Apr 12, 2024
5d0857a
fix: use latest
marcomariscal Apr 12, 2024
56c0053
feat: remove unused error handling
marcomariscal Apr 12, 2024
e95e1a5
chore: remove unused imports
marcomariscal Apr 12, 2024
bd3a9b4
chore: threshold to .8
marcomariscal Apr 12, 2024
07d5cb4
fix: remove unused mock restore
marcomariscal Apr 15, 2024
70ec3ab
chore: remove unused imports
marcomariscal Apr 15, 2024
db60a07
Update src/lib/helpers/test/setupTestWallet.test.ts
marcomariscal Apr 16, 2024
f0ad178
feat: beforeAll test funcs (#54)
marcomariscal May 2, 2024
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
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion bunfig.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[test]
coverageSkipTestFiles = true
coverageThreshold = 0
coverageThreshold = 0.8
root = "./src"
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"anvil-fork": "make anvil-fork",
"test-fork": "make test-fork",
"test": "bun test src",
"test": "bun test",
"build": "bun tsc",
"format": "prettier --write .",
"watch": "bun test --watch src"
Expand All @@ -21,6 +21,6 @@
},
"dependencies": {
"@noble/secp256k1": "^2.0.0",
"viem": "^2.7.19"
"viem": "^2.9.16"
}
}
56 changes: 34 additions & 22 deletions src/lib/actions/getAnnouncements/getAnnouncements.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, test, expect } from 'bun:test';
import { describe, test, expect, beforeAll } from 'bun:test';
import ERC556AnnouncerAbi from '../../abi/ERC5564Announcer';
import {
VALID_SCHEME_ID,
Expand All @@ -7,39 +7,51 @@ import {
} from '../../..';
import setupTestEnv from '../../helpers/test/setupTestEnv';
import setupTestWallet from '../../helpers/test/setupTestWallet';
import type { StealthActions } from '../../stealthClient/types';
import type { SuperWalletClient } from '../../helpers/types';
import type { Address } from 'viem';

describe('getAnnouncements', async () => {
const { stealthClient, ERC5564DeployBlock, ERC5564Address } =
await setupTestEnv();
const walletClient = await setupTestWallet();
describe('getAnnouncements', () => {
let stealthClient: StealthActions;
let walletClient: SuperWalletClient;
let fromBlock: bigint;
let ERC5564Address: Address;

// Set up stealth address details
const schemeId = VALID_SCHEME_ID.SCHEME_ID_1;
const { stealthMetaAddressURI } = generateRandomStealthMetaAddress();
const fromBlock = ERC5564DeployBlock;

// Set up stealth address details
const { stealthAddress, viewTag, ephemeralPublicKey } =
generateStealthAddress({
stealthMetaAddressURI,
schemeId,
});

// Announce the stealth address, ephemeral public key, and view tag
const hash = await walletClient.writeContract({
address: ERC5564Address,
functionName: 'announce',
args: [BigInt(schemeId), stealthAddress, ephemeralPublicKey, viewTag],
abi: ERC556AnnouncerAbi,
chain: walletClient.chain,
account: walletClient.account!,
});
// Set up the test environment and announce the stealth address
beforeAll(async () => {
const {
stealthClient: client,
ERC5564Address,
ERC5564DeployBlock,
} = await setupTestEnv();
walletClient = await setupTestWallet();
stealthClient = client;
fromBlock = ERC5564DeployBlock;

// Announce the stealth address, ephemeral public key, and view tag
const hash = await walletClient.writeContract({
address: ERC5564Address,
functionName: 'announce',
args: [BigInt(schemeId), stealthAddress, ephemeralPublicKey, viewTag],
abi: ERC556AnnouncerAbi,
chain: walletClient.chain,
account: walletClient.account!,
});

console.log('Waiting for announcement transaction to be mined...');
// Wait for the transaction to be mined
const res = await walletClient.waitForTransactionReceipt({
hash,
// Wait for the transaction to be mined
await walletClient.waitForTransactionReceipt({
hash,
});
});
console.log('Announcement transaction mined:', res.transactionHash);

test('fetches announcements successfully', async () => {
const announcements = await stealthClient.getAnnouncements({
Expand Down
30 changes: 13 additions & 17 deletions src/lib/actions/getAnnouncements/getAnnouncements.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { BlockType } from '../types';

import { type PublicClient, parseAbiItem } from 'viem';
import { getBlock, getLogs } from 'viem/actions';
import { getBlock, getBlockNumber, getLogs } from 'viem/actions';
import { handleViemPublicClient } from '../../stealthClient/createStealthClient';
import type {
AnnouncementLog,
GetAnnouncementsParams,
GetAnnouncementsReturnType,
import {
type AnnouncementLog,
type GetAnnouncementsParams,
type GetAnnouncementsReturnType,
} from './types';

/**
Expand Down Expand Up @@ -98,10 +98,6 @@ const fetchLogsInChunks = async ({
block: toBlock ?? 'latest',
});

if (!resolvedToBlock) {
throw new Error('Failed to resolve toBlock');
}

let currentBlock = resolvedFromBlock;
const allLogs = [];

Expand Down Expand Up @@ -134,25 +130,25 @@ const fetchLogsInChunks = async ({
* @param {Object} params - Parameters for resolving the block number.
* - `publicClient`: An instance of the viem `PublicClient`.
* - `block`: The block number or tag to resolve.
* @returns {Promise<bigint | null>} The resolved block number as a bigint or null.
* @returns {Promise<bigint>} The resolved block number as a bigint or null.
*/
async function resolveBlockNumber({
export async function resolveBlockNumber({
publicClient,
block,
}: {
publicClient: PublicClient;
block?: BlockType;
}): Promise<bigint | null> {
}): Promise<bigint> {
if (typeof block === 'bigint') {
return block;
}

try {
const res = await getBlock(publicClient, { blockTag: block });
return res.number;
} catch (error) {
throw new Error(`Failed to resolve block number: ${error}.`);
const { number } = await getBlock(publicClient, { blockTag: block });
// Get the latest block number if null, since it is the pending block
if (!number) {
return getBlockNumber(publicClient);
}
return number;
}

export default getAnnouncements;
173 changes: 130 additions & 43 deletions src/lib/actions/getAnnouncementsForUser/getAnnouncementsForUser.test.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,85 @@
import { expect, test, describe } from 'bun:test';
import { expect, test, describe, beforeAll } from 'bun:test';
import setupTestEnv from '../../helpers/test/setupTestEnv';
import setupTestWallet from '../../helpers/test/setupTestWallet';
import setupTestStealthKeys from '../../helpers/test/setupTestStealthKeys';
import { VALID_SCHEME_ID, generateStealthAddress } from '../../../utils/crypto';
import { ERC5564AnnouncerAbi } from '../../abi';

describe('getAnnouncementsForUser', async () => {
const { stealthClient, ERC5564Address, ERC5564DeployBlock } =
await setupTestEnv();
const walletClient = await setupTestWallet();
const schemeId = VALID_SCHEME_ID.SCHEME_ID_1;
const { stealthMetaAddressURI, spendingPublicKey, viewingPrivateKey } =
setupTestStealthKeys(schemeId);
const fromBlock = ERC5564DeployBlock;

// Set up stealth address details
const { stealthAddress, ephemeralPublicKey, viewTag } =
generateStealthAddress({
import type { AnnouncementLog } from '..';
import { FromValueNotFoundError, TransactionHashRequiredError } from './types';
import {
getTransactionFrom,
processAnnouncement,
} from './getAnnouncementsForUser';
import { type PublicClient } from 'viem';
import { getViewTagFromMetadata } from '../../..';
import type { HexString } from '../../../utils/crypto/types';
import type { StealthActions } from '../../stealthClient/types';
import type { SuperWalletClient } from '../../helpers/types';

describe('getAnnouncementsForUser', () => {
let stealthClient: StealthActions;
let walletClient: SuperWalletClient;

let stealthAddress: HexString,
ephemeralPublicKey: HexString,
viewTag: HexString;
let spendingPublicKey: HexString,
viewingPrivateKey: HexString,
stealthMetaAddressURI: string;

let announcements: AnnouncementLog[] = [];

beforeAll(async () => {
// Set up the test environment
const {
stealthClient: client,
ERC5564Address,
ERC5564DeployBlock,
} = await setupTestEnv();
walletClient = await setupTestWallet();
stealthClient = client;

// Set up the stealth keys and generate a stealth address
const schemeId = VALID_SCHEME_ID.SCHEME_ID_1;
({ stealthMetaAddressURI, spendingPublicKey, viewingPrivateKey } =
setupTestStealthKeys(schemeId));

({ stealthAddress, ephemeralPublicKey, viewTag } = generateStealthAddress({
stealthMetaAddressURI,
schemeId,
schemeId: VALID_SCHEME_ID.SCHEME_ID_1,
}));

// Announce the stealth address, ephemeral public key, and view tag
const hash = await walletClient.writeContract({
address: ERC5564Address,
functionName: 'announce',
args: [BigInt(schemeId), stealthAddress, ephemeralPublicKey, viewTag],
abi: ERC5564AnnouncerAbi,
chain: walletClient.chain,
account: walletClient.account!,
});

// Announce the stealth address, ephemeral public key, and view tag
const hash = await walletClient.writeContract({
address: ERC5564Address,
functionName: 'announce',
args: [BigInt(schemeId), stealthAddress, ephemeralPublicKey, viewTag],
abi: ERC5564AnnouncerAbi,
chain: walletClient.chain,
account: walletClient.account!,
});

console.log('Waiting for announcement transaction to be mined...');
// Wait for the transaction to be mined
const res = await walletClient.waitForTransactionReceipt({
hash,
});
console.log('Announcement transaction mined:', res.transactionHash);

// Fetch relevant announcements to check against
console.log('fetching announcements...');
const announcements = await stealthClient.getAnnouncements({
ERC5564Address,
args: {
schemeId: BigInt(schemeId),
stealthAddress,
caller: walletClient.account?.address, // Just an example; the caller is the address of the wallet since it called announce
},
fromBlock,
console.log('Waiting for announcement transaction to be mined...');
// Wait for the transaction to be mined
const res = await walletClient.waitForTransactionReceipt({
hash,
});
console.log('Announcement transaction mined:', res.transactionHash);

// Fetch relevant announcements to check against
console.log('fetching announcements...');
announcements = await stealthClient.getAnnouncements({
ERC5564Address,
args: {
schemeId: BigInt(schemeId),
stealthAddress,
caller: walletClient.account?.address, // Just an example; the caller is the address of the wallet since it called announce
},
fromBlock: ERC5564DeployBlock,
toBlock: 'latest',
});
console.log('relevant announcements fetched for testing');
});
console.log('relevant announcements fetched for testing');

test('filters announcements correctly for the user', async () => {
// Fetch announcements for the specific user
Expand Down Expand Up @@ -162,4 +192,61 @@ describe('getAnnouncementsForUser', async () => {
`Processed ${largeNumberOfAnnouncements} announcements in ${endTime - startTime} milliseconds.`
);
});

test('throws TransactionHashRequiredError when transactionHash is null', async () => {
const announcementWithoutHash: AnnouncementLog = {
...announcements[0],
transactionHash: null,
};

expect(
processAnnouncement(
announcementWithoutHash,
walletClient as PublicClient,
{
spendingPublicKey,
viewingPrivateKey,
excludeList: new Set([]),
includeList: new Set([]),
}
)
).rejects.toBeInstanceOf(TransactionHashRequiredError);
});

test('throws FromValueNotFoundError when the "from" value is not found', async () => {
const invalidHash = '0xinvalidhash';

expect(
getTransactionFrom({
publicClient: walletClient as PublicClient,
hash: invalidHash,
})
).rejects.toBeInstanceOf(FromValueNotFoundError);
});

test('throws error if view tag does not start with 0x', () => {
const metadata = 'invalidmetadata';
expect(() => getViewTagFromMetadata(metadata as HexString)).toThrow(
'Invalid metadata format'
);
});
});

describe('getAnnouncementsForUser error class tests', () => {
test('TransactionHashRequiredError should have the correct message', () => {
const errorMessage = 'The transaction hash is required.';
const error = new TransactionHashRequiredError();

expect(error.message).toBe(errorMessage);
expect(error.name).toBe('TransactionHashRequiredError');
});

test('FromValueNotFoundError should have the correct message', () => {
const errorMessage =
'The "from" value could not be retrieved for a transaction.';
const error = new FromValueNotFoundError();

expect(error.message).toBe(errorMessage);
expect(error.name).toBe('FromValueNotFoundError');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ async function getAnnouncementsForUser({
* - `includeList`: Addresses to specifically include in the results.
* @returns {Promise<ProcessAnnouncementReturnType>} A promise that resolves to the processed announcement if it is relevant, or null otherwise.
*/
async function processAnnouncement(
export async function processAnnouncement(
announcement: AnnouncementLog,
publicClient: PublicClient,
{
Expand Down Expand Up @@ -173,7 +173,7 @@ async function shouldIncludeAnnouncement({
* @returns {Promise<`0x${string}`>} A promise that resolves to the transaction sender address.
* @throws {FromValueNotFoundError} If the transaction or sender address cannot be fetched, indicating a potential issue with the transaction lookup.
*/
async function getTransactionFrom({
export async function getTransactionFrom({
publicClient,
hash,
}: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
VALID_SCHEME_ID,
generateRandomStealthMetaAddress,
} from '../../..';
import { GetStealthMetaAddressError } from './types';

describe('getStealthMetaAddress', async () => {
const { stealthClient, ERC6538Address } = await setupTestEnv();
Expand Down Expand Up @@ -41,4 +42,16 @@ describe('getStealthMetaAddress', async () => {

expect(result).toEqual(stealthMetaAddress);
});

test('should throw an error if the stealth meta address cannot be fetched', async () => {
const invalidRegistrant = '0xInvalidRegistrant';

expect(
stealthClient.getStealthMetaAddress({
ERC6538Address,
registrant: invalidRegistrant,
schemeId: VALID_SCHEME_ID.SCHEME_ID_1,
})
).rejects.toBeInstanceOf(GetStealthMetaAddressError);
});
});
Loading