Skip to content

Commit

Permalink
test(bridge-ui-v2): minting logic (#14149)
Browse files Browse the repository at this point in the history
Co-authored-by: Korbinian <[email protected]>
  • Loading branch information
jscriptcoder and KorbinianK authored Jul 13, 2023
1 parent 40ec18c commit 5d856df
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
node_modules
coverage
/build
/.svelte-kit
/package
Expand Down
1 change: 1 addition & 0 deletions packages/bridge-ui-v2/.prettierignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
node_modules
coverage
/build
/.svelte-kit
/package
Expand Down
6 changes: 4 additions & 2 deletions packages/bridge-ui-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
"build": "vite build",
"preview": "vite preview",
"test:pw": "playwright test",
"test:unit": "vitest run",
"test:unit:coverage": "vitest run --coverage",
"test:unit": "vitest run --silent",
"test:unit:debug": "vitest run",
"test:unit:coverage": "vitest run --silent --coverage",
"test:unit:watch": "vitest",
"svelte:check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --ignore ./wagmi.config.ts",
"svelte:check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --ignore ./wagmi.config.ts --watch",
Expand All @@ -25,6 +26,7 @@
"@types/debug": "^4.1.7",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"@vitest/coverage-v8": "^0.33.0",
"@wagmi/cli": "^1.0.1",
"autoprefixer": "^10.4.14",
"daisyui": "3.1.7",
Expand Down
120 changes: 120 additions & 0 deletions packages/bridge-ui-v2/src/libs/token/checkMintable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {
type Chain,
getContract,
type GetContractResult,
getPublicClient,
getWalletClient,
type PublicClient,
type WalletClient,
} from '@wagmi/core';

import { checkMintable } from './checkMintable';
import { MintableError, type Token } from './types';

vi.mock('@wagmi/core', () => {
return {
getWalletClient: vi.fn(),
getPublicClient: vi.fn(),
getContract: vi.fn(),
};
});

const mockNetwork = { id: 1 } as Chain;

const mockToken = {
addresses: { 1: '0x123' },
} as unknown as Token;

const mockWalletClient = {
account: { address: '0x123' },
} as unknown as WalletClient;

const mockTokenContract = {
read: {
minters: vi.fn(),
},
estimateGas: {
mint: vi.fn(),
},
} as unknown as GetContractResult<readonly unknown[], unknown>;

const mockPublicClient = {
getGasPrice: vi.fn(),
getBalance: vi.fn(),
} as unknown as PublicClient;

describe('checkMintable', () => {
beforeAll(() => {
vi.mocked(getWalletClient).mockResolvedValue(mockWalletClient);
vi.mocked(getContract).mockReturnValue(mockTokenContract);
vi.mocked(getPublicClient).mockReturnValue(mockPublicClient);
});

it('should throw when wallet is not connected', async () => {
vi.mocked(getWalletClient).mockResolvedValueOnce(null);

try {
await checkMintable(mockToken, mockNetwork);
expect.fail('should have thrown');
} catch (error) {
const { cause } = error as Error;
expect(cause).toBe(MintableError.NOT_CONNECTED);
}
});

it('should throw when user has already minted', async () => {
vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(true);

try {
await checkMintable(mockToken, mockNetwork);
expect.fail('should have thrown');
} catch (error) {
const { cause } = error as Error;
expect(cause).toBe(MintableError.TOKEN_MINTED);
}
});

it('should throw when user has insufficient balance', async () => {
vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(false);

// Estimated gas to mint is 100
vi.mocked(mockTokenContract.estimateGas.mint).mockResolvedValueOnce(BigInt(100));

// Gas price is 2
vi.mocked(mockPublicClient.getGasPrice).mockResolvedValueOnce(BigInt(2));

// Estimated cost is 100 * 2 = 200

// User balance is 100 (less than 200)
vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(100));

try {
await checkMintable(mockToken, mockNetwork);
expect.fail('should have thrown');
} catch (error) {
const { cause } = error as Error;
expect(cause).toBe(MintableError.INSUFFICIENT_BALANCE);
}
});

it('should not throw', async () => {
vi.mocked(mockTokenContract.read.minters).mockResolvedValueOnce(false);

// Estimated gas to mint is 100
vi.mocked(mockTokenContract.estimateGas.mint).mockResolvedValueOnce(BigInt(100));

// Gas price is 2
vi.mocked(mockPublicClient.getGasPrice).mockResolvedValueOnce(BigInt(2));

// Estimated cost is 100 * 2 = 200

// User balance is 300 (more than 200)
vi.mocked(mockPublicClient.getBalance).mockResolvedValueOnce(BigInt(300));

try {
await checkMintable(mockToken, mockNetwork);
} catch (error) {
expect.fail('should not have thrown');
}
});
});
2 changes: 1 addition & 1 deletion packages/bridge-ui-v2/src/libs/token/checkMintable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function checkMintable(token: Token, network: Chain) {
const walletClient = await getWalletClient({ chainId });

if (!walletClient) {
throw new Error(`user is not connected to ${network.name}`, { cause: MintableError.NOT_CONNECTED });
throw Error(`user is not connected to ${network.name}`, { cause: MintableError.NOT_CONNECTED });
}

const tokenContract = getContract({
Expand Down
46 changes: 46 additions & 0 deletions packages/bridge-ui-v2/src/libs/token/mint.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { getContract, type GetContractResult, getWalletClient, type WalletClient } from '@wagmi/core';

import { mint } from './mint';
import type { Token } from './types';

vi.mock('@wagmi/core', () => {
return {
getWalletClient: vi.fn(),
getContract: vi.fn(),
};
});

const mockToken = {
symbol: 'MKT',
addresses: { 1: '0x123' },
} as unknown as Token;

const mockWalletClient = {
account: { address: '0x123' },
chain: { id: 1 },
} as unknown as WalletClient;

const mockTokenContract = {
write: {
mint: vi.fn(),
},
} as unknown as GetContractResult<readonly unknown[], WalletClient>;

describe('mint', () => {
beforeAll(() => {
vi.mocked(getWalletClient).mockResolvedValue(mockWalletClient);
vi.mocked(getContract).mockReturnValue(mockTokenContract);
});

it('should throw an error when minting', async () => {
vi.mocked(mockTokenContract.write.mint).mockRejectedValue(new Error('BAM!!'));

await expect(mint(mockToken, mockWalletClient)).rejects.toThrow(`found a problem minting ${mockToken.symbol}`);
});

it('should return a tx hash when minting', async () => {
vi.mocked(mockTokenContract.write.mint).mockResolvedValue('0x123');

await expect(mint(mockToken, mockWalletClient)).resolves.toEqual('0x123');
});
});
Loading

0 comments on commit 5d856df

Please sign in to comment.