diff --git a/batcher-ui/.husky/pre-commit b/batcher-ui/.husky/pre-commit index 36af2198..e6ee3eec 100755 --- a/batcher-ui/.husky/pre-commit +++ b/batcher-ui/.husky/pre-commit @@ -1,4 +1,5 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -npx lint-staged +# npx lint-staged +cd batcher-ui && npm run lint diff --git a/batcher-ui/.lintstagedrc.js b/batcher-ui/.lintstagedrc.js index f85c082b..e52dc808 100644 --- a/batcher-ui/.lintstagedrc.js +++ b/batcher-ui/.lintstagedrc.js @@ -5,6 +5,7 @@ const buildEslintCommand = filenames => .map(f => path.relative(process.cwd(), f)) .join(' --file ')}`; + module.exports = { '*.{js,jsx,ts,tsx}': [buildEslintCommand], }; diff --git a/batcher-ui/global.d.ts b/batcher-ui/global.d.ts index 2fb6c50d..aaf67f9f 100644 --- a/batcher-ui/global.d.ts +++ b/batcher-ui/global.d.ts @@ -1,7 +1,22 @@ declare global { namespace NodeJS { interface ProcessEnv { - SECRET: string; + NEXT_PUBLIC_BATCHER_CONTRACT_HASH: string; + NEXT_PUBLIC_MARKET_MAKER_CONTRACT_HASH: string; + NEXT_PUBLIC_TOKEN_MANAGER_CONTRACT_HASH: string; + NEXT_PUBLIC_TZBTC_VAULT_CONTRACT_HASH: string; + NEXT_PUBLIC_USDT_VAULT_CONTRACT_HASH: string; + NEXT_PUBLIC_EURL_VAULT_CONTRACT_HASH: string; + NEXT_PUBLIC_USDTZ_VAULT_CONTRACT_HASH: string; + NEXT_PUBLIC_BTCTZ_VAULT_CONTRACT_HASH: string; + + NEXT_PUBLIC_NETWORK_TARGET: string; + NEXT_PUBLIC_BATCHER_URI: string; + NEXT_PUBLIC_BATCHER_LOGO_PATH: string; + NEXT_PUBLIC_TEZOS_NODE_URI: string; + NEXT_PUBLIC_TZKT_API_URI: string; + NEXT_PUBLIC_LOCAL_STORAGE_KEY_STATE: string; + NEXT_PUBLIC_GA_TRACKING_ID: string; } } } diff --git a/batcher-ui/next.config.js b/batcher-ui/next.config.js index 91f9cb61..6704ca2a 100644 --- a/batcher-ui/next.config.js +++ b/batcher-ui/next.config.js @@ -1,15 +1,38 @@ /** @type {import('next').NextConfig} */ -const config = require('./src/config/env.ts'); const env = process.env.ENV; // 'mainnet' | 'ghostnet' +const config = require('./src/config/env.js'); +const contractsConfig = require('./src/config/contracts.js'); + +const contractHashes = contractsConfig[env]; +const envConfig = config[env]; + +if ( + !contractHashes || + !contractsConfig.isContractsWellConfigured(contractHashes) +) { + throw new Error( + 'Configuration error on contracts hashes. Please check in src/config/contracts.js file.' + ); +} + +if (!envConfig || !config.isConfigOK(envConfig)) { + throw new Error( + 'Configuration error on environment variables. Please check in src/config/env.js file.' + ); +} + console.info('🚀 Current env:', env); const nextConfig = { reactStrictMode: false, swcMinify: true, - env: config[env], + env: { + ...config.toEnvVar(envConfig), + ...contractsConfig.toEnvVar(contractHashes), + }, webpack: (config, { isServer, webpack }) => { if (!isServer) config.resolve.fallback['fs'] = false; diff --git a/batcher-ui/package.json b/batcher-ui/package.json index d11212f6..23a41fe0 100644 --- a/batcher-ui/package.json +++ b/batcher-ui/package.json @@ -13,7 +13,7 @@ "start": "ENV=mainnet next start -p 80", "start:ghostnet": "ENV=ghostnet next start -p 80", "build:ghostnet": "ENV=ghostnet next build", - "lint": "next lint" + "lint": "ENV=ghostnet next lint" }, "lint-staged": { "**/*.{js,jsx,tsx,ts,less,md,json}": [ diff --git a/batcher-ui/pages/_app.tsx b/batcher-ui/pages/_app.tsx index 105260cc..73ebe769 100644 --- a/batcher-ui/pages/_app.tsx +++ b/batcher-ui/pages/_app.tsx @@ -34,7 +34,7 @@ const App = ({ Component }: AppProps) => { { diff --git a/batcher-ui/src/config/contracts.js b/batcher-ui/src/config/contracts.js new file mode 100644 index 00000000..8c366cf4 --- /dev/null +++ b/batcher-ui/src/config/contracts.js @@ -0,0 +1,53 @@ +/** + * Regroup all contracts hash needed to Batcher works properly + * and provide functions to ensure all contracts hashes are setuped. + */ + +const CONTRACTS_NAMES = [ + 'batcher', + 'market_maker', + 'token_manager', + 'tzBTC_vault', + 'USDT_vault', + 'EURL_vault', + 'BTCtz_vault', + 'USDtz_vault', +]; + +const ghostnet = { + batcher: 'KT1LhTpwSGcFAUUM3JYjW8XW74UHP82YzERy', + market_maker: 'KT1BbDTB4BJWTH1CKfxYC5eB8TgrwB7WuNGF', + token_manager: 'KT19JLvQdDGUnssfL5n6rBozZpnaej3Xfvjy', + tzBTC_vault: 'KT1L4dArtU44J2uuneHHn1fjRfd7K6XDDuW3', + USDT_vault: 'KT18qMEmNgvSSPEUoChDnxkVCg7eEy9UoQfj', + USDtz_vault: 'KT1EFFWgmyu6npNZTRzB8zzuKBRnMaW8bpyN', + BTCtz_vault: 'KT1VUVHxMjXpdQYM38hVAncUSGCz9fv78ZnP', + EURL_vault: 'KT1RkAdLQtyKZQBCxYieH2ds4YbrLEsoDGGk', +}; + +const mainnet = { + batcher: 'KT1CoTu4CXcWoVk69Ukbgwx2iDK7ZA4FMSpJ', + market_maker: 'KT1TNX1YLCmPJN4rbwAUsUAdnqVYrZ5X5YNB', + token_manager: '', + tzBTC_vault: '', + USDT_vault: '', + USDtz_vault: '', + BTCtz_vault: '', + EURL_vault: '', +}; + +const toEnvVar = contracts => + Object.entries(contracts) + .map(([k, v]) => [`NEXT_PUBLIC_${k.toUpperCase()}_CONTRACT_HASH`, v]) + .reduce((acc, current) => ({ ...acc, [current[0]]: current[1] }), {}); + +const isContractsWellConfigured = contracts => { + return CONTRACTS_NAMES.every(name => Object.keys(contracts).includes(name)); +}; + +module.exports = { + ghostnet, + mainnet, + toEnvVar, + isContractsWellConfigured, +}; diff --git a/batcher-ui/src/config/env.js b/batcher-ui/src/config/env.js new file mode 100644 index 00000000..fe2f5b49 --- /dev/null +++ b/batcher-ui/src/config/env.js @@ -0,0 +1,47 @@ +const ENV_VARS = [ + 'network_target', + 'batcher_uri', + 'batcher_logo_path', // TODO attention + 'tezos_node_uri', + 'tzkt_api_uri', // tODO attention + 'local_storage_key_state', + 'ga_tracking_id', +]; + +const ghostnet = { + network_target: 'GHOSTNET', + batcher_uri: 'https://ghostnet.batcher.marigold.dev', + batcher_logo_path: + 'https://storage.googleapis.com/marigold-public-bucket/batcher-logo.png', + tezos_node_uri: 'https://ghostnet.tezos.marigold.dev/', + tzkt_api_uri: 'https://api.ghostnet.tzkt.io', + local_storage_key_state: 'batcher-state', + ga_tracking_id: 'G-2K59PEELC8', +}; + +const mainnet = { + network_target: 'MAINNET', + batcher_uri: 'https://batcher.marigold.dev', + batcher_logo_path: + 'https://storage.googleapis.com/marigold-public-bucket/batcher-logo.png', + tezos_node_uri: 'https://mainnet.tezos.marigold.dev/', + tzkt_api_uri: 'https://api.tzkt.io', + local_storage_key_state: 'batcher-state', + ga_tracking_id: 'G-2K59PEELC8', +}; + +const toEnvVar = vars => + Object.entries(vars) + .map(([k, v]) => [`NEXT_PUBLIC_${k.toUpperCase()}`, v]) + .reduce((acc, current) => ({ ...acc, [current[0]]: current[1] }), {}); + +const isConfigOK = vars => { + return ENV_VARS.every(name => Object.keys(vars).includes(name)); +}; + +module.exports = { + ghostnet, + mainnet, + toEnvVar, + isConfigOK, +}; diff --git a/batcher-ui/src/config/env.ts b/batcher-ui/src/config/env.ts deleted file mode 100644 index 24362694..00000000 --- a/batcher-ui/src/config/env.ts +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = { - ghostnet: { - NEXT_PUBLIC_NETWORK_TARGET: 'GHOSTNET', - NEXT_PUBLIC_BATCHER_URI: 'https://ghostnet.batcher.marigold.dev', - NEXT_PUBLIC_PATH_TO_BATCHER_LOGO: - 'https://storage.googleapis.com/marigold-public-bucket/batcher-logo.png', - NEXT_PUBLIC_TEZOS_NODE_URI: 'https://ghostnet.tezos.marigold.dev/', - NEXT_PUBLIC_TZKT_URI_API: 'https://api.ghostnet.tzkt.io', - NEXT_PUBLIC_BATCHER_CONTRACT_HASH: 'KT1LhTpwSGcFAUUM3JYjW8XW74UHP82YzERy', - NEXT_PUBLIC_MARKETMAKER_CONTRACT_HASH: - 'KT1XKvKiTTj8N6WKv3MhnZhFjZopFGQGBTdT', - NEXT_PUBLIC_LOCAL_STORAGE_KEY_STATE: 'batcher-state', - NEXT_PUBLIC_GA_TRACKING_ID: 'G-2K59PEELC8', - }, - mainnet: { - NEXT_PUBLIC_NETWORK_TARGET: 'MAINNET', - NEXT_PUBLIC_BATCHER_URI: 'https://batcher.marigold.dev', - NEXT_PUBLIC_PATH_TO_BATCHER_LOGO: - 'https://storage.googleapis.com/marigold-public-bucket/batcher-logo.png', - NEXT_PUBLIC_TEZOS_NODE_URI: 'https://mainnet.tezos.marigold.dev/', - NEXT_PUBLIC_TZKT_URI_API: 'https://api.tzkt.io', - NEXT_PUBLIC_BATCHER_CONTRACT_HASH: 'KT1CoTu4CXcWoVk69Ukbgwx2iDK7ZA4FMSpJ', - NEXT_PUBLIC_MARKETMAKER_CONTRACT_HASH: - 'KT1TNX1YLCmPJN4rbwAUsUAdnqVYrZ5X5YNB', - NEXT_PUBLIC_LOCAL_STORAGE_KEY_STATE: 'batcher-state', - NEXT_PUBLIC_GA_TRACKING_ID: 'G-2K59PEELC8', - }, -}; diff --git a/batcher-ui/src/contexts/events.tsx b/batcher-ui/src/contexts/events.tsx index d43ecd17..f040abc9 100644 --- a/batcher-ui/src/contexts/events.tsx +++ b/batcher-ui/src/contexts/events.tsx @@ -15,7 +15,7 @@ export const EventsProvider = ({ children }: { children: React.ReactNode }) => { useEffect(() => { const socket = new HubConnectionBuilder() - .withUrl(process.env.NEXT_PUBLIC_TZKT_URI_API + '/v1/ws') + .withUrl(process.env.NEXT_PUBLIC_TZKT_API_URI + '/v1/ws') .build(); setup(socket); // setSocket(socket); diff --git a/batcher-ui/src/types/config.ts b/batcher-ui/src/types/config.ts new file mode 100644 index 00000000..e69de29b diff --git a/batcher-ui/src/utils/utils.ts b/batcher-ui/src/utils/utils.ts index 6f5529b6..75fad055 100644 --- a/batcher-ui/src/utils/utils.ts +++ b/batcher-ui/src/utils/utils.ts @@ -140,7 +140,7 @@ export const TOKENS = ['USDT', 'EURL', 'TZBTC']; export const getTokensBalancesByAccount = (userAddress: string) => fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/tokens/balances?account=${userAddress}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/tokens/balances?account=${userAddress}` ).then(checkStatus); export const getBalances = async (userAddress: string): Promise => { @@ -165,7 +165,7 @@ export const getBalances = async (userAddress: string): Promise => { export const getStorage = (): Promise => fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/contracts/${process.env.NEXT_PUBLIC_BATCHER_CONTRACT_HASH}/storage` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/contracts/${process.env.NEXT_PUBLIC_BATCHER_CONTRACT_HASH}/storage` ).then(checkStatus); export const getBigMapByIdAndUserAddress = ( @@ -176,7 +176,7 @@ export const getBigMapByIdAndUserAddress = ( return Promise.reject('No address or no bigmap ID for order book.'); return ( fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigMapId}/keys/${userAddress}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigMapId}/keys/${userAddress}` ) // TODO: improve that by parseStatus function .then(response => checkStatus(response, { value: [] })) @@ -190,7 +190,7 @@ export const getBigMapByIdAndBatchNumber = ( const bigMapId: string | null = getByKey('batches'); if (!bigMapId) return Promise.reject('No bigmap ID for batches.'); return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigMapId}/keys/${batchNumber}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigMapId}/keys/${batchNumber}` ) .then(checkStatus) .then(r => r.value); @@ -203,7 +203,7 @@ export const getBigMapByIdAndTokenPair = ( if (!bigMapId) return Promise.reject('No bigmap ID for rates_current.'); return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigMapId}/keys` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigMapId}/keys` ) .then(checkStatus) .then(response => @@ -217,7 +217,7 @@ export const getTokensMetadata = async () => { return Promise.all( Object.values(validTokens).map(async token => { const icon = await fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/tokens?contract=${token.address}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/tokens?contract=${token.address}` ) .then(t => t.json()) .then(([t]) => @@ -690,7 +690,7 @@ const getDepositAmount = (depositAmount: number, decimals: number) => const getMarketMakerStorage = (): Promise => { return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/contracts/${process.env.NEXT_PUBLIC_MARKETMAKER_CONTRACT_HASH}/storage` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/contracts/${process.env.NEXT_PUBLIC_MARKETMAKER_CONTRACT_HASH}/storage` ).then(checkStatus); }; @@ -699,7 +699,7 @@ const getUserVaultFromBigmap = ( userKey: string ): Promise => { return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigmapId}/keys/${userKey}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigmapId}/keys/${userKey}` ).then(checkStatus); }; @@ -708,7 +708,7 @@ const getHoldingsVaultFromBigmap = ( key: string ): Promise => { return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigmapId}/keys/${key}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigmapId}/keys/${key}` ).then(checkStatus); }; const getVaultsFromBigmap = ( @@ -716,7 +716,7 @@ const getVaultsFromBigmap = ( tokenName: string ): Promise => { return fetch( - `${process.env.NEXT_PUBLIC_TZKT_URI_API}/v1/bigmaps/${bigmapId}/keys/${tokenName}` + `${process.env.NEXT_PUBLIC_TZKT_API_URI}/v1/bigmaps/${bigmapId}/keys/${tokenName}` ).then(checkStatus); };