diff --git a/packages/taikoon-ui/src/components/sections/index.ts b/packages/taikoon-ui/src/components/sections/index.ts
index e3b6b0efaf4..e9a1d7747b3 100644
--- a/packages/taikoon-ui/src/components/sections/index.ts
+++ b/packages/taikoon-ui/src/components/sections/index.ts
@@ -1,5 +1,6 @@
export { default as CollapsibleSection } from './Collapsible.section.svelte';
export { default as CountdownSection } from './Countdown.section.svelte';
+export { default as FaqSection } from './Faq.section.svelte';
export { default as FooterSection } from './Footer.section.svelte';
export { default as HeadingSection } from './Heading.section.svelte';
export { default as InformationSection } from './Information.section.svelte';
diff --git a/packages/taikoon-ui/src/generated/abi/index.ts b/packages/taikoon-ui/src/generated/abi/index.ts
index fae30cd3856..276d4ce8e72 100644
--- a/packages/taikoon-ui/src/generated/abi/index.ts
+++ b/packages/taikoon-ui/src/generated/abi/index.ts
@@ -3,7 +3,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
- * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0)
+ * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0xfDbaA6d6c382A2555856bFaB315D5E6F3CDA1393)
* -
*/
export const taikoonTokenAbi = [
@@ -544,16 +544,16 @@ export const taikoonTokenAbi = [
] as const;
/**
- * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0)
+ * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0xfDbaA6d6c382A2555856bFaB315D5E6F3CDA1393)
* -
*/
export const taikoonTokenAddress = {
- 17000: '0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0',
- 31337: '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82',
+ 17000: '0xfDbaA6d6c382A2555856bFaB315D5E6F3CDA1393',
+ 31337: '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512',
} as const;
/**
- * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0)
+ * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0xfDbaA6d6c382A2555856bFaB315D5E6F3CDA1393)
* -
*/
export const taikoonTokenConfig = {
diff --git a/packages/taikoon-ui/src/i18n/en.json b/packages/taikoon-ui/src/i18n/en.json
index 3c77860da7e..d37c3d0f072 100644
--- a/packages/taikoon-ui/src/i18n/en.json
+++ b/packages/taikoon-ui/src/i18n/en.json
@@ -16,7 +16,7 @@
},
"buttons": {
"mintNow": "Mint Now",
- "learnMore": "Learn More",
+ "learnMore": "FAQs",
"mint": "Mint",
"etherscan": "View on Etherscan",
"share": "Share",
@@ -28,7 +28,7 @@
"mint": {
"title": "Taikoons",
"text": "Taikoons are the genesis NFT collection for the Taiko Layer 2 ecosystem.",
- "mintsLeft": "Mints left: {mintsLeft}",
+ "eligibleLabel": "You are eligible to mint:",
"toast": {
"clipboardCopy": "Link copied to clipboard"
},
@@ -72,19 +72,23 @@
"entries": [
{
"title": "What is the total supply of the NFTs in this collection?",
- "text": "The total supply of the NFTs in this collection is 888."
+ "text": "There are 888 Taikoons — not more, not less! Always double check if the official collection when minting/trading."
},
{
"title": "How can I use my Taikoons?",
- "text": "You can use your Taikoons to participate in the Taiko Layer 2 ecosystem."
+ "text": "Taikoons are primarily a PFP collection, meaning its purpose is to give you a sense of identity in the Taiko community. However, since the Taikoons you hold are your property, you can do with them whatever you want! Trade, print, or just hold them — they're yours!
Also, keep in mind that there are no financial incentives attached to Taikoons."
},
{
"title": "What is the minting process?",
- "text": "The minting process is as follows:"
+ "text": "One time genesis mint of all 888 nfts targeted May 2024"
},
{
- "title": "How does the daily auction work?",
- "text": "The daily auction works as follows:"
+ "title": "What is the official Taikoons contract?",
+ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tincidunt lorem eros, in bibendum lectus mollis laoreet. Praesent luctus odio rhoncus nisi pulvinar pharetra. Aliquam volutpat bibendum nisl, vitae elementum mauris egestas eget. Etiam ex felis, porttitor nec elementum vitae, mattis at felis. In cursus, augue vel pulvinar aliquet, orci sapien aliquam ipsum, non sollicitudin purus nulla ac risus."
+ },
+ {
+ "title": "What are the traits?",
+ "text": "(tbc) Nouns are generated randomly based Ethereum block hashes. There are no 'if' statements or other rules governing Noun trait scarcity, which makes all Nouns equally rare. As of this writing, Nouns are made up of: -backgrounds (2) -bodies (30) -accessories (140) -heads (242) -glasses (23)"
}
]
},
@@ -96,7 +100,7 @@
"text": "The most developer-friendly and secure Ethereum scaling solution."
},
"subscribe": {
- "stayUpdated": "Stay updated! \nDive into the latest Taiko developer news",
+ "stayUpdated": "Stay updated! Dive into the latest Taiko developer news",
"subscribe": "Subscribe",
"email": "Email"
},
diff --git a/packages/taikoon-ui/src/lib/connect/web3modal.ts b/packages/taikoon-ui/src/lib/connect/web3modal.ts
index 24760545662..5978bf69d58 100644
--- a/packages/taikoon-ui/src/lib/connect/web3modal.ts
+++ b/packages/taikoon-ui/src/lib/connect/web3modal.ts
@@ -7,7 +7,7 @@ import { config } from '$wagmi-config';
import { getChainImages } from '../../lib/chain';
-const projectId = PUBLIC_WALLETCONNECT_PROJECT_ID || '';
+const projectId = PUBLIC_WALLETCONNECT_PROJECT_ID || 'walletconnect-project-id';
const chainImages = getChainImages();
export const chainId = readable(getChainId(config), (set) => watchChainId(config, { onChange: set }));
@@ -24,7 +24,7 @@ export const provider = readable(undefined, (set) =>
);
export const web3modal = createWeb3Modal({
- wagmiConfig: config,
+ wagmiConfig: config || { projectId, chains: [], connectors: [] },
projectId,
featuredWalletIds: [],
allowUnsupportedChain: true,
diff --git a/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts b/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts
index 82901bfb61f..3f6ef3d772d 100644
--- a/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts
+++ b/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts
@@ -9,10 +9,9 @@ import { totalWhitelistMintCount } from '../user/totalWhitelistMintCount';
import estimateContractGas from '../wagmi/estimateContractGas';
import { canMint } from './canMint';
-export async function estimateMintGasCost({ freeMintCount }: { freeMintCount: number }): Promise {
- if (freeMintCount === 0) return 0;
+export async function estimateMintGasCost(): Promise {
const { selectedNetworkId } = web3modal.getState();
- if (!selectedNetworkId) return -1;
+ if (!selectedNetworkId) return 0;
const chainId = selectedNetworkId as IChainId;
const freeMintLeft = await totalWhitelistMintCount();
diff --git a/packages/taikoon-ui/src/lib/util/balance.test.ts b/packages/taikoon-ui/src/lib/util/balance.test.ts
index 7de2ae95d19..b70b9418927 100644
--- a/packages/taikoon-ui/src/lib/util/balance.test.ts
+++ b/packages/taikoon-ui/src/lib/util/balance.test.ts
@@ -3,7 +3,7 @@ import { renderBalance, renderEthBalance } from './balance';
vi.mock('@wagmi/core');
test('renderBalance lib', () => {
- expect(renderBalance(null)).toBe('0.00');
+ expect(renderBalance()).toBe('0.00');
expect(
renderBalance({
decimals: 18,
diff --git a/packages/taikoon-ui/src/lib/util/balance.ts b/packages/taikoon-ui/src/lib/util/balance.ts
index c3625a2b9ed..107bbd975d5 100644
--- a/packages/taikoon-ui/src/lib/util/balance.ts
+++ b/packages/taikoon-ui/src/lib/util/balance.ts
@@ -3,7 +3,7 @@ import { formatEther } from 'viem';
import { truncateString } from '../../lib/util/truncateString';
-export function renderBalance(balance: Maybe) {
+export function renderBalance(balance?: GetBalanceReturnType) {
if (!balance) return '0.00';
// if (typeof balance === 'bigint') return balance.toString();
const maxlength = Number(balance.formatted) < 0.000001 ? balance.decimals : 6;
diff --git a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts
deleted file mode 100644
index 0ee1ab6764d..00000000000
--- a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { readContract } from '@wagmi/core';
-import { get } from 'svelte/store';
-
-import { bridgePausedModal } from '$stores/modal';
-
-import { checkForPausedContracts } from './checkForPausedContracts';
-
-vi.mock('@wagmi/core');
-vi.mock('viem');
-
-vi.mock('$bridgeConfig', () => ({
- routingContractsMap: {
- 1: {
- 2: {
- erc20VaultAddress: '0x00001',
- bridgeAddress: '0x00002',
- erc721VaultAddress: '0x00003',
- erc1155VaultAddress: '0x00004',
- crossChainSyncAddress: '0x00005',
- signalServiceAddress: '0x00006',
- },
- },
- 2: {
- 1: {
- erc20VaultAddress: '0x00007',
- bridgeAddress: '0x00008',
- erc721VaultAddress: '0x00009',
- erc1155VaultAddress: '0x00010',
- crossChainSyncAddress: '0x00011',
- signalServiceAddress: '0x00012',
- },
- },
- 3: {
- 2: {
- erc20VaultAddress: '0x00007',
- bridgeAddress: '0x00008',
- erc721VaultAddress: '0x00009',
- erc1155VaultAddress: '0x00010',
- crossChainSyncAddress: '0x00011',
- signalServiceAddress: '0x00012',
- },
- },
- },
-}));
-
-describe('checkForPausedContracts', () => {
- beforeEach(() => {
- vi.resetAllMocks();
- });
-
- test('should return false if no contracts are paused', async () => {
- // when
- await checkForPausedContracts();
-
- // then
- expect(readContract).toHaveBeenCalledTimes(3);
- expect(get(bridgePausedModal)).toBe(false);
- });
-
- test('should return true if at least one contract is paused', async () => {
- // given
- vi.mocked(readContract).mockResolvedValueOnce(true);
-
- // when
- await checkForPausedContracts();
-
- // then
- expect(readContract).toHaveBeenCalledTimes(3);
- expect(get(bridgePausedModal)).toBe(true);
- });
-
- test('should handle errors', async () => {
- // given
- vi.mocked(readContract).mockRejectedValueOnce(new Error('some error'));
-
- // when
- await checkForPausedContracts();
-
- // then
- expect(get(bridgePausedModal)).toBe(true);
- expect(readContract).toHaveBeenCalledTimes(3);
- });
-});
diff --git a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts
deleted file mode 100644
index 8451e79ce57..00000000000
--- a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export const isBridgePaused = async () => {
- return await checkForPausedContracts();
-};
-
-export const checkForPausedContracts = async () => {
- return true;
-};
diff --git a/packages/taikoon-ui/src/lib/util/classNames.ts b/packages/taikoon-ui/src/lib/util/classNames.ts
index 4a60c3b72bf..64c687e9396 100644
--- a/packages/taikoon-ui/src/lib/util/classNames.ts
+++ b/packages/taikoon-ui/src/lib/util/classNames.ts
@@ -1,3 +1,3 @@
-export function classNames(...classes: Array>) {
+export function classNames(...classes: Array) {
return classes.filter(Boolean).join(' ');
}
diff --git a/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts b/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts
deleted file mode 100644
index 5a9edcd4ae8..00000000000
--- a/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { Hash } from 'viem';
-
-import { chains } from '$libs/chain';
-
-export async function fetchTransactionReceipt(transactionHash: Hash, chainId: number) {
- try {
- const nodeUrl = chains.find((c) => c.id === chainId)?.rpcUrls?.default?.http[0];
- if (!nodeUrl) {
- throw new Error('Node URL not found');
- }
-
- const response = await fetch(nodeUrl, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- jsonrpc: '2.0',
- method: 'eth_getTransactionReceipt',
- params: [transactionHash],
- id: 1,
- }),
- });
-
- const data = await response.json();
- return data.result;
- } catch (error) {
- console.error('Error fetching transaction receipt:', error);
- throw error;
- }
-}
diff --git a/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts b/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts
deleted file mode 100644
index f42cda0f29b..00000000000
--- a/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-describe('getConnectedWallet', () => {
- it('TODO', () => {
- expect(true).toBeTruthy();
- });
-});
diff --git a/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts b/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts
deleted file mode 100644
index 3f042f9acbc..00000000000
--- a/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { getWalletClient } from '@wagmi/core';
-
-import { NotConnectedError } from '$libs/error';
-import { config } from '$libs/wagmi';
-
-export async function getConnectedWallet(chainId?: number) {
- const walletClient = await getWalletClient(config, { chainId });
-
- if (!walletClient) {
- throw new NotConnectedError('wallet is not connected');
- }
-
- return walletClient;
-}
diff --git a/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts b/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts
deleted file mode 100644
index bf873aeab6c..00000000000
--- a/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { NFT } from '../token/types';
-
-export function groupNFTByCollection(nfts: NFT[]): Record {
- const grouped: Record = {};
- nfts.forEach((nft) => {
- const addressKey = Object.values(nft.addresses).join('-');
- if (!grouped[addressKey]) {
- grouped[addressKey] = [];
- }
- grouped[addressKey].push(nft);
- });
- return grouped;
-}
diff --git a/packages/taikoon-ui/src/lib/util/isCountdownActive.ts b/packages/taikoon-ui/src/lib/util/isCountdownActive.ts
new file mode 100644
index 00000000000..cff30d478c1
--- /dev/null
+++ b/packages/taikoon-ui/src/lib/util/isCountdownActive.ts
@@ -0,0 +1,6 @@
+import { PUBLIC_LAUNCH_DATE } from '$env/static/public';
+
+export default function isCountdownActive(): boolean {
+ const launchDate = new Date(PUBLIC_LAUNCH_DATE);
+ return Date.now() < launchDate.getTime();
+}
diff --git a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts
deleted file mode 100644
index 7dd57bb5825..00000000000
--- a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { jsonParseWithDefault } from './jsonParseWithDefault';
-
-describe('jsonToArray', () => {
- it('should return default value when input is null or empty string', () => {
- expect(jsonParseWithDefault(null, [])).toEqual([]);
- expect(jsonParseWithDefault('', 5)).toEqual(5);
- });
-
- it('should return default value when input is not a valid JSON', () => {
- expect(jsonParseWithDefault(undefined, true)).toEqual(true);
- expect(jsonParseWithDefault('not a valid JSON', '')).toEqual('');
- });
-
- it('should return parsed JSON when input is a valid JSON', () => {
- const strJson = '{"person": "Fran", "age": "Unknown"}';
- expect(jsonParseWithDefault(strJson, null)).toEqual(JSON.parse(strJson));
- });
-});
diff --git a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts
deleted file mode 100644
index 69acdcd8670..00000000000
--- a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export function jsonParseWithDefault(strJson: Maybe, defaultValue: T): T {
- try {
- // Keep in mind that strJson could be null or empty string
- // JSON.parse would not throw an error in those cases
- return strJson ? JSON.parse(strJson) : defaultValue;
- } catch (e) {
- return defaultValue;
- }
-}
diff --git a/packages/taikoon-ui/src/lib/util/logger.ts b/packages/taikoon-ui/src/lib/util/logger.ts
deleted file mode 100644
index 204f4ae8ed0..00000000000
--- a/packages/taikoon-ui/src/lib/util/logger.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import debug from 'debug';
-
-export function getLogger(namespace: string) {
- return debug(`nft-lab:${namespace}`);
-}
diff --git a/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts b/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts
deleted file mode 100644
index f6d2b4130a1..00000000000
--- a/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-import type { Address, Hex } from 'viem';
-
-import { type BridgeTransaction, MessageStatus } from '$libs/bridge';
-import type { TokenType } from '$libs/token';
-import { mergeAndCaptureOutdatedTransactions } from '$libs/util/mergeTransactions';
-
-function setupMocks() {
- vi.mock('@wagmi/core');
- vi.mock('@web3modal/wagmi');
- vi.mock('$customToken', () => {
- return {
- customToken: [
- {
- name: 'Bull Token',
- addresses: {
- '31336': '0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0',
- '167002': '0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE',
- },
- symbol: 'BLL',
- decimals: 18,
- type: 'ERC20',
- logoURI: 'ipfs://QmezMTpT6ovJ3szb3SKDM9GVGeQ1R8DfjYyXG12ppMe2BY',
- mintable: true,
- },
- {
- name: 'Horse Token',
- addresses: {
- '31336': '0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e',
- '167002': '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1',
- },
- symbol: 'HORSE',
- decimals: 18,
- type: 'ERC20',
- logoURI: 'ipfs://QmU52ZxmSiGX24uDPNUGG3URyZr5aQdLpACCiD6tap4Mgc',
- mintable: true,
- },
- ],
- };
- });
-}
-
-describe('mergeUniqueTransactions', () => {
- beforeEach(() => {
- setupMocks();
- });
-
- // Given
- const localTxs: BridgeTransaction[] = [
- {
- hash: 'hash1' as Hex,
- from: 'address1' as Address,
- amount: BigInt(1000),
- symbol: 'symbol1',
- decimals: 2,
- srcChainId: BigInt(1),
- destChainId: BigInt(2),
- status: MessageStatus.DONE,
- msgHash: 'msg1' as Hex,
- receipt: undefined,
- tokenType: 'ERC20' as TokenType,
- },
- {
- hash: 'hash2' as Hex,
- from: 'address2' as Address,
- amount: BigInt(2000),
- symbol: 'symbol2',
- decimals: 2,
- srcChainId: BigInt(1),
- destChainId: BigInt(2),
- status: MessageStatus.DONE,
- msgHash: 'msg2' as Hex,
- receipt: undefined,
- tokenType: 'ERC20' as TokenType,
- },
- ];
-
- const relayerTx: BridgeTransaction[] = [
- {
- hash: 'hash3' as Hex,
- from: 'address3' as Address,
- amount: BigInt(3000),
- symbol: 'symbol3',
- decimals: 2,
- srcChainId: BigInt(1),
- destChainId: BigInt(2),
- status: MessageStatus.DONE,
- msgHash: 'msg3' as Hex,
- receipt: undefined,
- tokenType: 'ERC20' as TokenType,
- },
- {
- hash: 'hash4' as Hex,
- from: 'address4' as Address,
- amount: BigInt(4000),
- symbol: 'symbol4',
- decimals: 2,
- srcChainId: BigInt(1),
- destChainId: BigInt(2),
- status: MessageStatus.DONE,
- msgHash: 'msg4' as Hex,
- receipt: undefined,
- tokenType: 'ERC20' as TokenType,
- },
- ];
-
- it('should merge transactions when no outdated local ones', () => {
- // When
- const result = mergeAndCaptureOutdatedTransactions(localTxs, relayerTx);
-
- // Then
- expect(extractHashes(result.mergedTransactions)).toEqual(extractHashes([...localTxs, ...relayerTx]));
- expect(result.outdatedLocalTransactions).toEqual([]);
- });
-
- it('should identify and capture outdated local transactions', () => {
- // Given
- const outdatedTx = relayerTx[0];
- const localWithOutdated = [...localTxs, outdatedTx];
-
- // When
- const result = mergeAndCaptureOutdatedTransactions(localWithOutdated, relayerTx);
-
- // Then
- expect(extractHashes(result.mergedTransactions)).toEqual(extractHashes([...localTxs, ...relayerTx]));
- expect(result.outdatedLocalTransactions).toEqual([outdatedTx]);
- });
-
- it('should merge transactions and capture outdated ones, complex', () => {
- // Given
-
- const localWithOutdated = [
- ...localTxs,
- {
- hash: 'hash3' as Hex,
- from: 'address2' as Address,
- amount: BigInt(2000),
- symbol: 'symbol2',
- decimals: 2,
- srcChainId: BigInt(1),
- destChainId: BigInt(2),
- status: MessageStatus.DONE,
- msgHash: 'msg2' as Hex,
- receipt: undefined,
- tokenType: 'ERC20' as TokenType,
- },
- ];
-
- const expectedMergedHashes = extractHashes([...localTxs, ...relayerTx]);
- const expectedOutdatedHashes = ['hash3' as Hex];
-
- // When
- const result = mergeAndCaptureOutdatedTransactions(localWithOutdated, relayerTx);
-
- // Then
- expect(extractHashes(result.mergedTransactions)).toEqual(expectedMergedHashes);
- expect(extractHashes(result.outdatedLocalTransactions)).toEqual(expectedOutdatedHashes);
- });
-});
-
-function extractHashes(transactions: BridgeTransaction[]): Hex[] {
- return transactions.map((tx) => tx.hash);
-}
diff --git a/packages/taikoon-ui/src/lib/util/mergeTransactions.ts b/packages/taikoon-ui/src/lib/util/mergeTransactions.ts
deleted file mode 100644
index 42805471ed3..00000000000
--- a/packages/taikoon-ui/src/lib/util/mergeTransactions.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { BridgeTransaction } from '$libs/bridge';
-
-type MergeResult = {
- mergedTransactions: BridgeTransaction[];
- outdatedLocalTransactions: BridgeTransaction[];
-};
-
-export const mergeAndCaptureOutdatedTransactions = (
- localTxs: BridgeTransaction[],
- relayerTx: BridgeTransaction[],
-): MergeResult => {
- const relayerTxMap: Map = new Map();
- relayerTx.forEach((tx) => relayerTxMap.set(tx.hash, tx));
-
- const outdatedLocalTransactions: BridgeTransaction[] = [];
- const mergedTransactions: BridgeTransaction[] = [];
-
- for (const tx of localTxs) {
- if (!relayerTxMap.has(tx.hash)) {
- mergedTransactions.push(tx);
- } else {
- outdatedLocalTransactions.push(tx);
- }
- }
-
- for (const tx of relayerTx) {
- mergedTransactions.push(tx);
- }
-
- return { mergedTransactions, outdatedLocalTransactions };
-};
diff --git a/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts b/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts
deleted file mode 100644
index 21cf5fcfc5c..00000000000
--- a/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import axios, { AxiosError, type AxiosResponse } from 'axios';
-
-import { apiService } from '$config';
-import { type NFT, type NFTMetadata, TokenType } from '$libs/token';
-import { safeParseUrl } from '$libs/util/safeParseUrl';
-
-import { checkForAdblocker } from './checkForAdblock';
-import { extractIPFSCidFromUrl } from './extractIPFSCidFromUrl';
-import { getLogger } from './logger';
-
-const log = getLogger('libs:token:parseNFTMetadata');
-
-export const parseNFTMetadata = async (token: NFT): Promise => {
- if (token.type !== TokenType.ERC721 && token.type !== TokenType.ERC1155) throw new Error('Not a NFT');
-
- log(`fetching metadata for ${token.name} id: ${token.tokenId}`);
-
- if (!token.uri) throw new Error('No token URI found');
-
- if (token.uri.includes('{id}')) {
- token.uri = token.uri.replace('{id}', token.tokenId.toString());
- }
-
- const url = safeParseUrl(token.uri);
- if (!url) throw new Error(`Invalid token URI: ${token.uri}`);
-
- let json;
-
- try {
- json = await axios.get(url, { timeout: apiService.timeout });
- } catch (err) {
- const error = err as AxiosError;
- log(`error fetching metadata for ${token.name} id: ${token.tokenId}`, error);
- //todo: handle different error scenarios?
- json = await retry(url, token.tokenId);
- }
- if (!json) {
- const isBlocked = await checkForAdblocker(url);
- if (isBlocked) {
- log(`The resource at ${url} is blocked by an adblocker`);
- json = await retry(url, token.tokenId);
- } else {
- throw new Error(`No metadata found for ${token.name} id: ${token.tokenId}`);
- }
- }
-
- if (!json || json instanceof Error) {
- // Handle error
- throw new Error(`No metadata found for ${token.name} id: ${token.tokenId}`);
- }
- const metadata = {
- description: json.data.description || '',
- external_url: json.data.external_url || '',
- image: json.data.image || '',
- name: json.data.name || '',
- };
-
- log(`fetched metadata for ${token.name} id: ${token.tokenId}`, metadata);
- return metadata;
-};
-
-// TODO: we could retry several times with different gateways
-const retry = async (url: string, tokenId: number): Promise => {
- let newUrl;
- tokenId !== undefined && tokenId !== null ? (newUrl = useGateway(url, tokenId)) : (newUrl = useGateway(url, tokenId));
- if (newUrl) {
- const result = await retryRequest(newUrl);
- if (result instanceof Error) {
- return result;
- }
- return result;
- }
- return new Error(`No metadata found for ${url}`);
-};
-
-const retryRequest = async (newUrl: string): Promise => {
- try {
- log(`retrying with ${newUrl}`);
- return await axios.get(newUrl);
- } catch (error) {
- log('retrying failed', error);
- throw new Error(`No metadata found for ${newUrl}`);
- }
-};
-
-//TODO: make this configurable via the config system?
-const useGateway = (url: string, tokenId: number) => {
- const { cid } = extractIPFSCidFromUrl(url);
- let gateway: string;
- if (tokenId !== undefined && tokenId !== null && cid) {
- gateway = `https://ipfs.io/ipfs/${cid}/${tokenId}.json`;
- } else {
- log(`no valid CID found in ${url}`);
- return null;
- }
- return gateway;
-};
diff --git a/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts b/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts
deleted file mode 100644
index 2943c667496..00000000000
--- a/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { positionElementByTarget } from './positionElementByTarget';
-
-const targetElement = {
- offsetHeight: 10,
- offsetWidth: 10,
-} as HTMLElement;
-
-const elementToPosition = {
- style: {
- top: '',
- bottom: '',
- left: '',
- right: '',
- transform: '',
- },
- offsetHeight: 100,
- offsetWidth: 100,
-} as HTMLElement;
-
-describe('positionElementByTarget', () => {
- it('should position element to the top', () => {
- positionElementByTarget(elementToPosition, targetElement, 'top', 15);
-
- expect(elementToPosition.style.top).toBe('');
- expect(elementToPosition.style.bottom).toBe('25px'); // 10 + 15
- expect(elementToPosition.style.left).toBe('50%');
- expect(elementToPosition.style.right).toBe('');
- expect(elementToPosition.style.transform).toBe('translateX(-50%)');
- });
-
- it('should position element to the bottom', () => {
- positionElementByTarget(elementToPosition, targetElement, 'bottom', 20);
-
- expect(elementToPosition.style.top).toBe('30px'); // 10 + 20
- expect(elementToPosition.style.bottom).toBe('');
- expect(elementToPosition.style.left).toBe('50%');
- expect(elementToPosition.style.right).toBe('');
- expect(elementToPosition.style.transform).toBe('translateX(-50%)');
- });
-
- it('should position element to the left', () => {
- positionElementByTarget(elementToPosition, targetElement, 'left', 25);
-
- expect(elementToPosition.style.top).toBe('50%');
- expect(elementToPosition.style.bottom).toBe('');
- expect(elementToPosition.style.left).toBe('auto');
- expect(elementToPosition.style.right).toBe('35px'); // 10 + 25
- expect(elementToPosition.style.transform).toBe('translateY(-50%)');
- });
-
- it('should position element to the right', () => {
- positionElementByTarget(elementToPosition, targetElement, 'right', 30);
-
- expect(elementToPosition.style.top).toBe('50%');
- expect(elementToPosition.style.bottom).toBe('');
- expect(elementToPosition.style.left).toBe('40px'); // 10 + 30
- expect(elementToPosition.style.right).toBe('auto');
- expect(elementToPosition.style.transform).toBe('translateY(-50%)');
- });
-});
diff --git a/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts b/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts
deleted file mode 100644
index d61bbea5fff..00000000000
--- a/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-// TODO: add support for other positions: 'top-left', 'bottom-right', etc...
-export function positionElementByTarget(
- elementToPosition: HTMLElement,
- targetElement: HTMLElement,
- position: Position = 'top',
- gap = 10,
-) {
- const { style } = elementToPosition;
-
- // Reset styles.
- style.top = '';
- style.bottom = '';
- style.left = '';
- style.right = '';
- style.transform = '';
-
- switch (position) {
- case 'top':
- case 'top-right':
- case 'top-left':
- style.bottom = `${targetElement.offsetHeight + gap}px`;
- style.left = '50%';
- style.transform = 'translateX(-50%)';
- break;
- case 'bottom':
- case 'bottom-right':
- case 'bottom-left':
- style.top = `${targetElement.offsetHeight + gap}px`;
- style.left = '50%';
- style.transform = 'translateX(-50%)';
- break;
- case 'left':
- style.left = 'auto';
- style.right = `${targetElement.offsetWidth + gap}px`;
- style.top = '50%';
- style.transform = 'translateY(-50%)';
- break;
- case 'right':
- style.right = 'auto';
- style.left = `${targetElement.offsetWidth + gap}px`;
- style.top = '50%';
- style.transform = 'translateY(-50%)';
- break;
- }
-}
diff --git a/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts b/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts
deleted file mode 100644
index d1c72c5c144..00000000000
--- a/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import axios, { type AxiosRequestConfig } from 'axios';
-
-import { ipfsConfig } from '$config';
-import { PUBLIC_IPFS_GATEWAYS } from '$env/static/public';
-import { ConfigError, IpfsError } from '$libs/error';
-
-const gateways = PUBLIC_IPFS_GATEWAYS.split(',') || [];
-
-const axiosConfig: AxiosRequestConfig = {
- timeout: ipfsConfig.gatewayTimeout,
-};
-
-export async function resolveIPFSUri(uri: string): Promise {
- const cid = uri.replace('ipfs://', '');
- let elapsedTime = 0;
- if (gateways.length === 0) throw new ConfigError('No IPFS gateways configured');
- for (const gateway of gateways) {
- const start = Date.now();
- try {
- const url = `${gateway}/ipfs/${cid}`;
- await axios.head(url, axiosConfig);
- return url; // Return the first successful gateway URL
- } catch (error) {
- elapsedTime += Date.now() - start;
- if (elapsedTime > ipfsConfig.overallTimeout) {
- break;
- }
- }
- }
- throw new IpfsError('Failed to retrieve metadata from IPFS gateways');
-}
diff --git a/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts b/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts
deleted file mode 100644
index 85df57956ca..00000000000
--- a/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { readContract } from '@wagmi/core';
-import { zeroAddress } from 'viem';
-
-import { safeReadContract } from './safeReadContract';
-
-vi.mock('@wagmi/core');
-
-describe('safeReadContract', () => {
- it('should return contract data on success', async () => {
- const mockData = { data: 'mockData' };
- vi.mocked(readContract).mockResolvedValue(mockData);
-
- const result = await safeReadContract({
- address: zeroAddress,
- abi: [],
- functionName: 'functionName',
- chainId: 1,
- });
-
- expect(result).toEqual(mockData);
- });
-
- it('should return null on failure', async () => {
- vi.mocked(readContract).mockRejectedValue(new Error('mockError'));
-
- const result = await safeReadContract({
- address: zeroAddress,
- abi: [],
- functionName: 'functionName',
- chainId: 1,
- });
-
- expect(result).toBeNull();
- });
-});
diff --git a/packages/taikoon-ui/src/lib/util/safeReadContract.ts b/packages/taikoon-ui/src/lib/util/safeReadContract.ts
deleted file mode 100644
index 072c97c7787..00000000000
--- a/packages/taikoon-ui/src/lib/util/safeReadContract.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { readContract } from '@wagmi/core';
-import type { Abi, Address } from 'viem';
-
-import { config } from '$libs/wagmi';
-
-import { getLogger } from './logger';
-
-const log = getLogger('libs:util:safeReadContract');
-
-type ReadContractParams = {
- address: Address;
- abi: Abi;
- functionName: string;
- args?: unknown[];
- chainId: number;
-};
-
-/*
- * Safely read a contract, returning null if it fails
- * useful when trying to access a non standard, non mandatory function
- */
-export async function safeReadContract(params: ReadContractParams): Promise {
- try {
- return await readContract(config, params);
- } catch (error) {
- log(`Safely failed to read contract: ${error}`);
- return null;
- }
-}
diff --git a/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts b/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts
deleted file mode 100644
index e7181058e50..00000000000
--- a/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { shortenAddress } from './shortenAddress';
-
-it('should return string with prefix and suffix', () => {
- const dummyAddress = '0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377';
-
- expect(shortenAddress(dummyAddress)).toStrictEqual('0x63Fa…D377');
- expect(shortenAddress(dummyAddress, 10, 10)).toStrictEqual('0x63FaC920…52fe3BD377');
-});
-
-it('should return 0x if empty', () => {
- expect(shortenAddress('')).toBe('0x');
-});
diff --git a/packages/taikoon-ui/src/lib/util/shortenAddress.ts b/packages/taikoon-ui/src/lib/util/shortenAddress.ts
index d30beb3f364..4d3b693278b 100644
--- a/packages/taikoon-ui/src/lib/util/shortenAddress.ts
+++ b/packages/taikoon-ui/src/lib/util/shortenAddress.ts
@@ -2,7 +2,7 @@ import type { IAddress } from '../../types';
import { web3modal } from '../connect';
import { getName } from '../ens';
-export async function shortenAddress(address: IAddress, charsStart = 6, charsEnd = 4, sep = '…'): Promise {
+export async function shortenAddress(address: IAddress, charsStart = 5, charsEnd = 3, sep = '…'): Promise {
if (!address) return '0x';
const shortened = [address.slice(0, charsStart), address.slice(-charsEnd)].join(sep);
diff --git a/packages/taikoon-ui/src/lib/wagmi/watcher.ts b/packages/taikoon-ui/src/lib/wagmi/watcher.ts
index 819d7b2e9aa..9af9d86f4fd 100644
--- a/packages/taikoon-ui/src/lib/wagmi/watcher.ts
+++ b/packages/taikoon-ui/src/lib/wagmi/watcher.ts
@@ -4,24 +4,18 @@ import { config } from '$wagmi-config';
import { isSupportedChain } from '../../lib/chain';
import { refreshUserBalance } from '../../lib/util/balance';
-import { checkForPausedContracts } from '../../lib/util/checkForPausedContracts';
-import { getLogger } from '../../lib/util/logger';
import { account } from '../../stores/account';
import { switchChainModal } from '../../stores/modal';
import { connectedSourceChain } from '../../stores/network';
-const log = getLogger('wagmi:watcher');
let isWatching = false;
let unWatchAccount: () => void;
export async function startWatching() {
- checkForPausedContracts();
-
if (!isWatching) {
unWatchAccount = watchAccount(config, {
onChange(data) {
- checkForPausedContracts();
- log('Account changed', data);
+ console.warn('Account changed', data);
account.set(data);
refreshUserBalance();
const { chain } = data;
@@ -29,7 +23,7 @@ export async function startWatching() {
// We need to check if the chain is supported, and if not
// we present the user with a modal to switch networks.
if (chain && !isSupportedChain(Number(chain.id))) {
- log('Unsupported chain', chain);
+ console.warn('Unsupported chain', chain);
switchChainModal.set(true);
return;
} else if (chain) {
diff --git a/packages/taikoon-ui/src/routes/+layout.svelte b/packages/taikoon-ui/src/routes/+layout.svelte
index 0c77630d904..5c7d8bb12c8 100644
--- a/packages/taikoon-ui/src/routes/+layout.svelte
+++ b/packages/taikoon-ui/src/routes/+layout.svelte
@@ -7,7 +7,7 @@
import { zeroAddress } from 'viem';
import { ResponsiveController } from '$components/core/ResponsiveController';
- import { MintConfirmationModal, TaikoonDetailModal } from '$components/modals';
+ import { MintConfirmationModal, PostMintModal, TaikoonDetailModal } from '$components/modals';
import { mint } from '$stores/mint';
import { taikoonDetail } from '$stores/taikoonDetail';
@@ -26,6 +26,7 @@
tokenIds: [],
address: zeroAddress,
totalMintCount: 0,
+ txHash: '',
});
const taikoonDetailState = taikoonDetail;
@@ -36,7 +37,16 @@
setContext('mint', mintState);
setContext('taikoonDetail', taikoonDetailState);
- const containerClasses = classNames('z-0', 'w-full', 'h-full', 'flex', 'flex-col', 'items-center', 'justify-evenly');
+ const containerClasses = classNames(
+ 'z-0',
+ 'w-full',
+ 'h-full',
+ 'flex',
+ 'flex-col',
+ 'relative',
+ 'items-center',
+ 'justify-evenly',
+ );
let windowSize: 'sm' | 'md' | 'lg' = 'md';
@@ -61,7 +71,9 @@
-
+
+
+
{#if windowSize === 'sm'}
diff --git a/packages/taikoon-ui/src/routes/+page.svelte b/packages/taikoon-ui/src/routes/+page.svelte
index e9aa539d50d..e9dfe7eb9aa 100644
--- a/packages/taikoon-ui/src/routes/+page.svelte
+++ b/packages/taikoon-ui/src/routes/+page.svelte
@@ -2,19 +2,16 @@
import { t } from 'svelte-i18n';
import {
- CollapsibleSection,
CountdownSection,
+ FaqSection,
FooterSection,
HeadingSection,
InformationSection,
} from '$components/sections';
+ import isCountdownActive from '$lib/util/isCountdownActive';
import { Button } from '$ui/Button';
import { SectionContainer } from '$ui/Section';
- $: currentPage = 'teaser';
-
- $: faqOptions = $t('content.sections.faq.entries');
-
let scrollTarget: HTMLElement | undefined = undefined;
function scrollToFaq() {
@@ -28,7 +25,7 @@
- {#if currentPage === 'teaser'}
+ {#if isCountdownActive()}