-
-
-
-
- {handle ? `@${handle}` : truncateAddress(userAddress)}{" "}
-
+ <>
+
+
+
+
+
+ {handle ? `@${handle}` : truncateAddress(userAddress)}{" "}
+
+
+
+
+ {commentLength}/{maxLength}
+
-
-
+
-
-
+
+
+
-
+
+
+ {errorMessage}
+
+ >
);
}
diff --git a/components/bounty/create-bounty/token-amount/controller.tsx b/components/bounty/create-bounty/token-amount/controller.tsx
index 1c83fc1642..d19c2bfd1e 100644
--- a/components/bounty/create-bounty/token-amount/controller.tsx
+++ b/components/bounty/create-bounty/token-amount/controller.tsx
@@ -1,6 +1,7 @@
import {useEffect, useState} from "react";
import {NumberFormatValues} from "react-number-format";
+import { fromSmartContractDecimals, toSmartContractDecimals } from "@taikai/dappkit/dist/src/utils/numbers";
import BigNumber from "bignumber.js";
import {useDebouncedCallback} from "use-debounce";
@@ -14,7 +15,7 @@ import {useUserStore} from "x-hooks/stores/user/user.store";
import CreateBountyTokenAmountView from "./view";
-const ZeroNumberFormatValues = {
+export const ZeroNumberFormatValues = {
value: "",
formattedValue: "",
floatValue: 0,
@@ -101,8 +102,8 @@ export default function CreateBountyTokenAmount({
}
const handleNumberFormat = (v: BigNumber) => ({
- value: v.decimalPlaces(5, 0).toFixed(),
- floatValue: v.toNumber(),
+ value: v.decimalPlaces(Math.min(10, decimals), 0).toFixed(),
+ floatValue: +v.decimalPlaces(Math.min(10, decimals), 0).toFixed(),
formattedValue: v.decimalPlaces(Math.min(10, decimals), 0).toFixed()
});
@@ -139,15 +140,22 @@ export default function CreateBountyTokenAmount({
return;
}
- const amountOfType =
+ let totalAmount =
BigNumber(type === "reward"
? _calculateTotalAmountFromGivenReward(value)
: value);
+
+ const contractTotalAmount = +toSmartContractDecimals(totalAmount.toString(), decimals);
+
+ if (contractTotalAmount % 100 !== 0) {
+ const adjustedContractTotalAmount = Math.ceil(contractTotalAmount / 100) * 100;
+ totalAmount = BigNumber(fromSmartContractDecimals(adjustedContractTotalAmount, decimals));
+ }
const initialDistributions = calculateDistributedAmounts( chain.closeFeePercentage,
mergeCreatorFeeShare,
proposerFeeShare,
- amountOfType,
+ totalAmount,
[
{
recipient: currentUser?.walletAddress,
@@ -166,24 +174,32 @@ export default function CreateBountyTokenAmount({
const _distributions = { totalServiceFees, ...initialDistributions}
if(type === 'reward'){
- const total = BigNumber(_calculateTotalAmountFromGivenReward(value));
- updateIssueAmount(handleNumberFormat(total))
- if (amountIsGtBalance(total.toNumber(), tokenBalance) && !isFunding) {
+ updateIssueAmount(handleNumberFormat(totalAmount))
+ const rewardValue = BigNumber(calculateRewardAmountGivenTotalAmount(totalAmount.toNumber()));
+
+ if (rewardValue !== value) {
+ setPreviewAmount(handleNumberFormat(rewardValue));
+ }
+
+ if (amountIsGtBalance(totalAmount.toNumber(), tokenBalance) && !isFunding) {
setInputError("bounty:errors.exceeds-allowance");
sethasAmountError(true);
}
}
if(type === 'total'){
- const rewardValue = BigNumber(calculateRewardAmountGivenTotalAmount(value));
+ const rewardValue = BigNumber(calculateRewardAmountGivenTotalAmount(totalAmount.toNumber()));
setPreviewAmount(handleNumberFormat(rewardValue));
+ if (totalAmount.toFixed() !== value.toString()) {
+ updateIssueAmount(handleNumberFormat(totalAmount));
+ }
+
if (rewardValue.isLessThan(BigNumber(currentToken?.minimum))) {
setInputError("bounty:errors.exceeds-minimum-amount");
sethasAmountError(true);
}
}
-
setDistributions(_distributions);
}
@@ -223,8 +239,8 @@ export default function CreateBountyTokenAmount({
setInputError("");
sethasAmountError(false);
}
- debouncedDistributionsUpdater(values.value, type);
setType(handleNumberFormat(BigNumber(values.value)));
+ debouncedDistributionsUpdater(values.value, type);
}
}
diff --git a/components/pages/task/create-task/controller.tsx b/components/pages/task/create-task/controller.tsx
index 91a845196c..8e2bd57164 100644
--- a/components/pages/task/create-task/controller.tsx
+++ b/components/pages/task/create-task/controller.tsx
@@ -466,7 +466,11 @@ export default function CreateTaskPage({
function handleUpdateToken(e: Token, type: 'transactional' | 'reward') {
const ERC20 = type === 'transactional' ? transactionalERC20 : rewardERC20
const setToken = type === 'transactional' ? setTransactionalToken : setRewardToken
- setToken(e)
+ setToken(e);
+ setIssueAmount(ZeroNumberFormatValues);
+ setRewardAmount(ZeroNumberFormatValues);
+ setPreviewAmount(ZeroNumberFormatValues);
+ setDistributions(undefined);
ERC20.setAddress(e.address)
}
diff --git a/components/profile/notification-form/controller.tsx b/components/profile/notification-form/controller.tsx
index baee356732..8907f72e81 100644
--- a/components/profile/notification-form/controller.tsx
+++ b/components/profile/notification-form/controller.tsx
@@ -11,6 +11,7 @@ import { lowerCaseCompare } from "helpers/string";
import { isValidEmail } from "helpers/validators/email";
import { CustomSession } from "interfaces/custom-session";
+import { EmailConfirmationErrors } from "interfaces/enums/Errors";
import { NotificationSettings } from "interfaces/user-notification";
import { useUpdateEmail } from "x-hooks/api/user";
@@ -90,8 +91,12 @@ export default function NotificationForm() {
const sessionUser = (sessionData as CustomSession)?.user;
const userEmail = sessionUser?.email || "";
const isConfirmationPending = !!userEmail && !sessionUser?.isEmailConfirmed;
+ const isEmailConfirmed = !!userEmail && !!sessionUser?.isEmailConfirmed;
const isSameEmail = lowerCaseCompare(userEmail, inputEmail);
- const emailVerificationError = query?.emailVerificationError?.toString()?.replace("Error: ", "");
+ const emailVerification = query?.emailVerification?.toString();
+ const emailVerificationError = !isEmailConfirmed && emailVerification && emailVerification !== "success" ?
+ emailVerification : null;
+ const canResend = !!emailVerificationError && emailVerification !== EmailConfirmationErrors.ALREADY_CONFIRMED;
function handleEmailChange(e) {
setInputEmail(e.target.value);
@@ -105,7 +110,7 @@ export default function NotificationForm() {
function onResend() {
updateEmail(userEmail, {
onSuccess: () => {
- goToProfilePage("dashboard", { emailVerificationError: "" });
+ goToProfilePage("dashboard", { emailVerification: "" });
}
});
}
@@ -151,7 +156,9 @@ export default function NotificationForm() {
isInvalid={isEmailInvalid}
isConfirmationPending={isConfirmationPending}
isExecuting={isExecutingEmail}
+ isEmailConfirmed={isEmailConfirmed}
emailVerificationError={emailVerificationError}
+ canResend={canResend}
notificationSettings={userNotificationSettings || {}}
toggleNotificationItem={toggleNotificationItem}
onChange={handleEmailChange}
diff --git a/components/profile/notification-form/view.tsx b/components/profile/notification-form/view.tsx
index 5efcd13795..9df61ce063 100644
--- a/components/profile/notification-form/view.tsx
+++ b/components/profile/notification-form/view.tsx
@@ -2,6 +2,7 @@ import React from "react";
import {useTranslation} from "next-i18next";
+import DoneIcon from "assets/icons/done-icon";
import InfoIconEmpty from "assets/icons/info-icon-empty";
import Button from "components/button";
@@ -19,6 +20,8 @@ interface NotificationFormViewProps {
isInvalid: boolean;
isConfirmationPending: boolean;
isExecuting: boolean;
+ isEmailConfirmed: boolean;
+ canResend: boolean;
emailVerificationError: string;
notificationSettings: Partial
;
onChange: (e) => void;
@@ -36,6 +39,8 @@ export default function NotificationFormView({
isInvalid,
isConfirmationPending,
isExecuting,
+ isEmailConfirmed,
+ canResend,
emailVerificationError,
notificationSettings,
onChange,
@@ -78,7 +83,7 @@ export default function NotificationFormView({
@@ -99,22 +104,24 @@ export default function NotificationFormView({
-
+
{t(`profile:email-errors.${emailVerificationError}`)}
-
-
-
+
+
+
+
+
@@ -127,6 +134,19 @@ export default function NotificationFormView({
+
+
+
+
+
+
+
+
+ {t("profile:notifications-form.email-confirmed")}
+
+
+
+
diff --git a/contexts/wagmi-provider.tsx b/contexts/wagmi-provider.tsx
index 751e37b866..c48e548d52 100644
--- a/contexts/wagmi-provider.tsx
+++ b/contexts/wagmi-provider.tsx
@@ -1,11 +1,26 @@
-import {ReactNode} from "react";
+import { ReactNode } from "react";
-import {getDefaultConfig} from "@rainbow-me/rainbowkit";
+import { getDefaultConfig } from "@rainbow-me/rainbowkit";
import getConfig from "next/config";
-import {parseCookies} from "nookies";
-import {defineChain} from "viem";
-import {aurora, auroraTestnet, mainnet, moonbeam, polygon, polygonAmoy, polygonMumbai, base} from "viem/chains";
-import {cookieStorage, cookieToInitialState, createStorage, WagmiProvider} from "wagmi";
+import { parseCookies } from "nookies";
+import { defineChain } from "viem";
+import {
+ aurora,
+ auroraTestnet,
+ mainnet,
+ moonbeam,
+ polygon,
+ polygonAmoy,
+ polygonMumbai,
+ localhost,
+ base,
+} from "viem/chains";
+import {
+ cookieStorage,
+ cookieToInitialState,
+ createStorage,
+ WagmiProvider,
+} from "wagmi";
interface WagmiProps {
children?: ReactNode;
@@ -15,44 +30,59 @@ const { publicRuntimeConfig } = getConfig();
const coinEx = defineChain({
id: 52,
- name: 'CoinEx',
- nativeCurrency: { name: 'CoinEx Chain Native Token', symbol: 'CET', decimals: 18 },
+ name: "CoinEx",
+ nativeCurrency: {
+ name: "CoinEx Chain Native Token",
+ symbol: "CET",
+ decimals: 18,
+ },
rpcUrls: {
default: {
- http: ['https://rpc.coinex.net'],
+ http: ["https://rpc.coinex.net"],
},
},
blockExplorers: {
default: {
- name: 'CoinEx Smart Chain Explorer',
- url: 'https://www.coinex.net/',
+ name: "CoinEx Smart Chain Explorer",
+ url: "https://www.coinex.net/",
},
- }
+ },
+});
+
+const ganache = defineChain({
+ ...localhost,
+ blockExplorers: {
+ default: {
+ name: "Local",
+ url: "http://127.0.0.1:8545",
+ },
+ },
});
const config = getDefaultConfig({
- appName: "BEPRO",
- projectId: publicRuntimeConfig?.walletConnectProjectId || "bc2288336095f20ebf8653a1ab670566",
- chains: [
- polygon,
- polygonAmoy,
- polygonMumbai,
- aurora,
- auroraTestnet,
- moonbeam,
- coinEx,
- mainnet,
- base,
- ],
- ssr: true,
- storage: createStorage({
- storage: cookieStorage,
- }),
+ appName: "BEPRO",
+ projectId:
+ publicRuntimeConfig?.walletConnectProjectId ||
+ "bc2288336095f20ebf8653a1ab670566",
+ chains: [
+ polygon,
+ aurora,
+ moonbeam,
+ coinEx,
+ mainnet,
+ polygonAmoy,
+ polygonMumbai,
+ auroraTestnet,
+ base,
+ ...(publicRuntimeConfig?.isProduction ? [] : [ganache]),
+ ],
+ ssr: true,
+ storage: createStorage({
+ storage: cookieStorage,
+ }),
});
-export default function Wagmi ({
- children
-}: WagmiProps) {
+export default function Wagmi({ children }: WagmiProps) {
const cookies = parseCookies();
const initialState = cookieToInitialState(config, JSON.stringify(cookies));
@@ -61,4 +91,4 @@ export default function Wagmi ({
{children}
);
-}
\ No newline at end of file
+}
diff --git a/helpers/analytic-events.ts b/helpers/analytic-events.ts
index e42ea71c43..1609ef7dd4 100644
--- a/helpers/analytic-events.ts
+++ b/helpers/analytic-events.ts
@@ -11,4 +11,5 @@ export const analyticEvents: AnalyticEvents = {
create_task_approve_amount: [analytic("ga4")],
create_pre_task: [analytic("ga4")],
created_task: [analytic("ga4")],
+ user_logged_in: [analytic("ga4")],
}
\ No newline at end of file
diff --git a/helpers/constants.ts b/helpers/constants.ts
index 6534273066..50190204a8 100644
--- a/helpers/constants.ts
+++ b/helpers/constants.ts
@@ -199,4 +199,6 @@ export const SPAM_TERMS = [
/^\./, /\.\w{0,3}$/, /robots/
]
-export const UNSUBSCRIBE_EVENT = typeof window === "undefined" ? null : new CustomEvent("task-unsubscribe");
\ No newline at end of file
+export const UNSUBSCRIBE_EVENT = typeof window === "undefined" ? null : new CustomEvent("task-unsubscribe");
+
+export const COMMENT_MAX_LENGTH = 1000;
\ No newline at end of file
diff --git a/helpers/object.ts b/helpers/object.ts
new file mode 100644
index 0000000000..d2d011f63a
--- /dev/null
+++ b/helpers/object.ts
@@ -0,0 +1,12 @@
+export function stringifyArrayValues(obj: object) {
+ const result = { ...obj };
+
+ for (const key in result) {
+ if (Array.isArray(result[key]))
+ result[key] = { array_value: JSON.stringify(result[key]) };
+ else if (typeof result[key] === "object")
+ result[key] = stringifyArrayValues(result[key]);
+ }
+
+ return result
+}
diff --git a/middleware/log-access.ts b/middleware/log-access.ts
index c7f76c0e68..226b56f058 100644
--- a/middleware/log-access.ts
+++ b/middleware/log-access.ts
@@ -1,9 +1,12 @@
import {NextApiHandler, NextApiRequest, NextApiResponse} from "next";
+import getConfig from "next/config";
import {error, info, warn} from "services/logging";
import {elasticLoggerMaker} from "../services/elastic-logger";
+const { serverRuntimeConfig } = getConfig();
+
export const LogAccess = (handler: NextApiHandler) => {
return async (req: NextApiRequest, res: NextApiResponse) => {
const {
@@ -22,16 +25,17 @@ export const LogAccess = (handler: NextApiHandler) => {
... (query ? { query } : {}),
... (body ? { body } : {})
};
-
- elasticLoggerMaker(`bepro-access-logs`)
- .log(`debug`, ["Access", [{
- _type: "access",
- payload: { data: JSON.stringify(payload) },
- method,
- pathname,
- headers: { ...req?.headers, cookie: "removed" },
- connection: { xForwarded, remoteAddress, cfConnectingIp }
- }]])
+
+ if (serverRuntimeConfig?.accessLogsEnabled)
+ elasticLoggerMaker(`bepro-access-logs`)
+ .log(`debug`, ["Access", [{
+ _type: "access",
+ payload,
+ method,
+ pathname,
+ headers: { ...req?.headers, cookie: "removed" },
+ connection: { xForwarded, remoteAddress, cfConnectingIp }
+ }]]);
try {
info(`access`, {pathname, payload, method,});
diff --git a/next.config.js b/next.config.js
index 4bd8d93d85..030d53cfb2 100644
--- a/next.config.js
+++ b/next.config.js
@@ -32,7 +32,7 @@ const publicRuntimeConfig = {
},
walletConnectProjectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID,
defaultChain: {
- id: process.env.NEXT_PUBLIC_NEEDS_CHAIN_ID,
+ id: +process.env.NEXT_PUBLIC_NEEDS_CHAIN_ID || 137,
name: process.env.NEXT_PUBLIC_NEEDS_CHAIN_NAME,
nativeToken: process.env.NEXT_PUBLIC_NATIVE_TOKEN_NAME,
blockscan: process.env.NEXT_PUBLIC_BLOCKSCAN_LINK,
@@ -100,7 +100,8 @@ const serverRuntimeConfig = {
imgProxy: {
salt: process.env.IMGPROXY_SALT,
key: process.env.IMGPROXY_KEY,
- }
+ },
+ accessLogsEnabled: process.env.ACCESS_LOGS_ENABLED === "true",
}
module.exports = () => removeImports({
diff --git a/pages/_app.tsx b/pages/_app.tsx
index f58a425313..8c754f592a 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -8,7 +8,6 @@ import {appWithTranslation} from "next-i18next";
import getConfig from "next/config";
import {useRouter} from "next/router";
import {GoogleAnalytics} from "nextjs-google-analytics";
-import {polygon} from "viem/chains";
import ConsentCookie from "components/consent-cokie";
import Loading from "components/loading";
@@ -43,7 +42,7 @@ function App({ Component, pageProps: { session, seoData, ...pageProps } }) {
-
+
diff --git a/pages/api/search/users/[...action].ts b/pages/api/search/users/[...action].ts
index 49a58358da..2d8644af12 100644
--- a/pages/api/search/users/[...action].ts
+++ b/pages/api/search/users/[...action].ts
@@ -18,22 +18,29 @@ import {UserRoleUtils} from "server/utils/jwt";
const {serverRuntimeConfig} = getConfig();
async function post(req: NextApiRequest) {
-
const {
action: [action]
} = req.query;
+ const { address, handle } = req.body;
+
+ const addressWhere = Sequelize.where( Sequelize.fn("lower", Sequelize.col("user.address")),
+ Op.eq,
+ address?.toLowerCase());
+
+ const handleWhere = Sequelize.where(Sequelize.fn("lower", Sequelize.col("user.handle")),
+ Op.eq,
+ handle?.toLowerCase());
+
const whereCondition = {
all: {
[Op.or]: [
- {address: (req?.body[0]?.toLowerCase())},
- {handle: req?.body[1]}
+ addressWhere,
+ handleWhere,
]
},
- login: {handle: {[Op.in]: req.body || []}},
- address: Sequelize.where(Sequelize.fn("lower", Sequelize.col("user.address")),
- Op.in,
- Sequelize.literal(`('${(req.body || []).map((s) => s?.toLowerCase()).join("','")}')`))
+ login: handleWhere,
+ address: addressWhere,
};
const queryOptions = {
@@ -50,17 +57,15 @@ async function post(req: NextApiRequest) {
const isAdmin = UserRoleUtils.hasAdminRole(token);
const isGovernor = UserRoleUtils.hasGovernorRole(token);
- const isSameUser = !!token?.address && lowerCaseCompare(token?.address, req?.body[0]) ||
- !!token?.login && lowerCaseCompare(token?.login, req?.body[1]);
+ const isSameUser = !!token?.address && lowerCaseCompare(token?.address, address) ||
+ !!token?.login && lowerCaseCompare(token?.login, handle);
if (isAdmin)
scope = UserTableScopes.admin;
else if (isGovernor || isSameUser)
scope = UserTableScopes.ownerOrGovernor;
-
- return models.user.scope(scope).findAll(paginate(queryOptions, req.body));
-
+ return models.user.scope(scope).findAll(paginate(queryOptions));
}
async function SearchUsers(req: NextApiRequest, res: NextApiResponse) {
diff --git a/pages/api/user/connect/confirm-email.ts b/pages/api/user/connect/confirm-email.ts
index b33423ced8..5de9d6df47 100644
--- a/pages/api/user/connect/confirm-email.ts
+++ b/pages/api/user/connect/confirm-email.ts
@@ -1,22 +1,40 @@
-import {NextApiRequest, NextApiResponse} from "next";
+import { NextApiRequest, NextApiResponse } from "next";
-import {withCORS} from "middleware";
+import { withCORS } from "middleware";
-import {get} from "server/common/user/email";
+import { Logger } from "services/logging";
+
+import { get } from "server/common/user/email";
+import { HttpBadRequestError, HttpConflictError } from "server/errors/http-errors";
async function handler(req: NextApiRequest, res: NextApiResponse) {
+ const url = "/dashboard?emailVerification=";
switch (req.method.toLowerCase()) {
case "get":
- await get(req)
- res.redirect("/profile?emailVerification=success");
+ try {
+ await get(req);
+ res.redirect(`${url}success`);
+ } catch(error) {
+ Logger.error(error, "Failed to confirm email", {
+ query: req.query,
+ url: req.url,
+ method: req.method,
+ cookies: req.cookies,
+ headers: req.headers
+ });
+
+ if (error instanceof HttpBadRequestError || error instanceof HttpConflictError) {
+ res.redirect(`${url}${error.message}`);
+ } else
+ res.redirect(`${url}server-error`);
+ }
break;
default:
res.status(405);
}
-
res.end();
}
diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index 18ac401e3b..dd139bb525 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -430,7 +430,10 @@
"failed-load-network": "failed to load marketplace",
"file-size-exceeded": "Maximum file size exceeded",
"file-not-supported": "File type not supported",
- "accepted-types": "Accepted types are {{types}}"
+ "accepted-types": "Accepted types are {{types}}",
+ "comment": {
+ "max-length": "Comment must have a maximum of {{max}} characters."
+ }
},
"warnings": {
"await-load-network": "await for a loading marketplace"
diff --git a/public/locales/en/profile.json b/public/locales/en/profile.json
index dd6b872548..cd362b6db1 100644
--- a/public/locales/en/profile.json
+++ b/public/locales/en/profile.json
@@ -49,12 +49,13 @@
"update-handle": "Error update handle"
}
},
- "notifications-form": {
+ "notifications-form": {
"title": "Notifications",
"message": "Allow Bepro Marketplace to send you updates in-app and via email. These can include updates to tasks, app updates, etc.",
"invalid-email": "Invalid email",
"re-send-email": "A confirmation email was sent, please check your inbox and spam box.",
"re-send": "Re-send",
+ "email-confirmed": "Email verified",
"success-toast": {
"title": "Success",
"content": "Email confirmed",
@@ -65,14 +66,15 @@
}
},
"email-errors": {
- "invalid-link": "Invalid confirmation link",
- "already-confirmed": "Email already confirmed",
+ "invalid-link": "Invalid confirmation link.",
+ "already-confirmed": "Email already confirmed.",
"expired-link": "This confirmation link is expired. Try re-sending another email.",
- "failed-to-update": "Failed to update email",
+ "failed-to-update": "Failed to update email.",
"try-again-later": "Something went wrong, try again later",
- "email-already-in-use": "Email already in use",
+ "email-already-in-use": "Email already in use.",
"invalid-email": "Invalid email",
- "nothing-to-change": "Nothing to change"
+ "nothing-to-change": "Nothing to change",
+ "server-error": "Something went wrong, please try re-send the email or send us a message on our discord."
},
"take-back-success": "Take back",
"take-back-fail": "Failed to take back",
diff --git a/scripts/deploy-multichain.js b/scripts/deploy-multichain.js
index 4470187cc3..7d84ac0844 100644
--- a/scripts/deploy-multichain.js
+++ b/scripts/deploy-multichain.js
@@ -260,9 +260,9 @@ async function main(option = 0) {
isDefault: false,
color: "#29b6af",
lockAmountForNetworkCreation: DEPLOY_LOCK_AMOUNT_FOR_NETWORK_CREATION,
- networkCreationFeePercentage: DEPLOY_LOCK_FEE_PERCENTAGE || DEFAULT_LOCK_FEE_PERCENTAGE / DIVISOR,
- closeFeePercentage: DEPLOY_CLOSE_BOUNTY_FEE || DEFAULT_LOCK_FEE_PERCENTAGE / DIVISOR,
- cancelFeePercentage: DEPLOY_CANCEL_BOUNTY_FEE || DEFAULT_LOCK_FEE_PERCENTAGE / DIVISOR,
+ networkCreationFeePercentage: (+DEPLOY_LOCK_FEE_PERCENTAGE || DEFAULT_LOCK_FEE_PERCENTAGE) / DIVISOR,
+ closeFeePercentage: (+DEPLOY_CLOSE_BOUNTY_FEE || DEFAULT_CLOSE_BOUNTY_FEE) / DIVISOR,
+ cancelFeePercentage: (+DEPLOY_CANCEL_BOUNTY_FEE || DEFAULT_CANCEL_BOUNTY_FEE) / DIVISOR,
icon: "QmZ8dSeJp9pZn2TFy2gp7McfMj9HapqnPW3mwnnrDLKtZs",
}
});
diff --git a/server/common/comments/post.ts b/server/common/comments/post.ts
index 54479f6235..76163facfc 100644
--- a/server/common/comments/post.ts
+++ b/server/common/comments/post.ts
@@ -3,6 +3,7 @@ import {IncludeOptions, Op, Sequelize, WhereOptions} from "sequelize";
import models from "db/models";
+import { COMMENT_MAX_LENGTH } from "helpers/constants";
import { truncateAddress } from "helpers/truncate-address";
import {HttpBadRequestError, HttpConflictError, HttpNotFoundError} from "server/errors/http-errors";
@@ -27,10 +28,12 @@ export default async function post(req: NextApiRequest, res: NextApiResponse) {
const foundOrValid = (v) => v ? 'found' : 'valid';
+ if (comment?.length > COMMENT_MAX_LENGTH)
+ throw new HttpBadRequestError(`Comment exceeds max length of ${COMMENT_MAX_LENGTH} characters`);
+
if (!["issue", "deliverable", "proposal", "review"].includes(type))
throw new HttpBadRequestError("type does not exist")
-
if (!issueId || !isValidNumber(issueId))
throw new HttpNotFoundError(`issueId not ${foundOrValid(!issueId)}`);
@@ -40,7 +43,6 @@ export default async function post(req: NextApiRequest, res: NextApiResponse) {
if (type === "proposal" && (!proposalId || !isValidNumber(proposalId)))
throw new HttpNotFoundError(`proposalId not ${foundOrValid(!proposalId)}`)
-
const user = context.user;
if (!user)
diff --git a/services/elastic-logger.ts b/services/elastic-logger.ts
index d8face1e1f..4c8181dae8 100644
--- a/services/elastic-logger.ts
+++ b/services/elastic-logger.ts
@@ -6,7 +6,6 @@ const {
NEXT_ELASTIC_SEARCH_USERNAME: username,
NEXT_ELASTIC_SEARCH_PASSWORD: password,
NEXT_LOG_APP_NAME: index = "webnetwork-logs",
- NEXT_LOG_TO_ELASTIC,
} = process.env;
export const elasticLoggerMaker = (index_name: any = `bepro-app-logs`): LoggerPlugin => ({
@@ -22,23 +21,22 @@ export const elasticLoggerMaker = (index_name: any = `bepro-app-logs`): LoggerPl
(typeof _params === "string" || typeof _params === "number")
? {value: _params}
: Array.isArray(_params)
- ? {value_array: _params}
+ ? {value_array: JSON.stringify(_params) }
: _params;
- if (NEXT_LOG_TO_ELASTIC)
- new Client({node, auth: {username, password}})
- .index({
- index: `${index_name}-${index}`,
- document: {
- level,
- message: contents[0],
- params,
- createdAt: new Date().toISOString(),
- }
- })
- .catch(e => {
- console.log(`Failed to log on elastic`, e);
- });
+ new Client({node, auth: {username, password}})
+ .index({
+ index: `${index_name}-${index}`,
+ document: {
+ level,
+ message: contents[0],
+ params,
+ createdAt: new Date().toISOString(),
+ }
+ })
+ .catch(e => {
+ console.log(`Failed to log on elastic`, e);
+ });
}
})
diff --git a/x-hooks/api/user/use-get-user-by-address.ts b/x-hooks/api/user/use-get-user-by-address.ts
index d3192d66a3..d6919b3386 100644
--- a/x-hooks/api/user/use-get-user-by-address.ts
+++ b/x-hooks/api/user/use-get-user-by-address.ts
@@ -4,6 +4,6 @@ import { api } from "services/api";
export async function useGetUserByAddress(address: string): Promise {
return api
- .post("/search/users/address/", [address])
+ .post("/search/users/address/", { address })
.then(({ data }) => data[0]);
}
\ No newline at end of file
diff --git a/x-hooks/api/user/use-get-user-by-login.ts b/x-hooks/api/user/use-get-user-by-login.ts
index 0140f03522..eeffab470a 100644
--- a/x-hooks/api/user/use-get-user-by-login.ts
+++ b/x-hooks/api/user/use-get-user-by-login.ts
@@ -4,6 +4,6 @@ import { api } from "services/api";
export async function useGetUserByLogin(login: string): Promise {
return api
- .post("/search/users/login/", [login])
+ .post("/search/users/login/", { handle: login })
.then(({ data }) => data[0]);
}
\ No newline at end of file