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

V2 #112

Merged
merged 83 commits into from
Jun 3, 2024
Merged

V2 #112

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
e48f162
wip: Use updated property naming
carina-akaia Apr 25, 2024
a0bbc5f
Bump Naxios
carina-akaia Apr 26, 2024
e49284c
Merge branch 'main' of https://github.com/PotLock/nadabot-app into en…
carina-akaia Apr 30, 2024
547a8cf
wip: Sync contract field names
carina-akaia Apr 30, 2024
ab747c6
wip: Sync contract field names
carina-akaia Apr 30, 2024
581022d
wip
carina-akaia May 2, 2024
8c687c6
wip: Adjust styles
carina-akaia May 2, 2024
e215ddd
Implement expiry form logic
carina-akaia May 3, 2024
fd3875b
wip: Create provider settings form
carina-akaia May 4, 2024
1ceed00
Handle duration string parsing error
carina-akaia May 6, 2024
cb654f1
fix: Pass missing `type` prop
carina-akaia May 6, 2024
acf6a40
doc: Add JSDoc
carina-akaia May 6, 2024
20c374a
wip: Update admin settings form
carina-akaia May 6, 2024
879aecc
fix: Add missing change callback
carina-akaia May 6, 2024
bcda69d
wip: Show expiration period on stamps
carina-akaia May 6, 2024
0302b2d
fix: Force form reset upon successful update
carina-akaia May 7, 2024
0f2f663
wip: Update provider card and modal
carina-akaia May 7, 2024
0adb4f1
wip: Update provider admin settings UI
carina-akaia May 9, 2024
c69f877
Create Slider component
carina-akaia May 10, 2024
ffb175a
Update input component styles
carina-akaia May 10, 2024
68948bd
Update color palette
carina-akaia May 10, 2024
cbf3ac0
wip: Update provider card and admin settings UI
carina-akaia May 10, 2024
8d6ae52
wip: Extract stamp editor component & Create stamp edit page
carina-akaia May 12, 2024
c4875df
wip: Update stamp editing styles
carina-akaia May 12, 2024
61e828b
wip: Fix runtime errors and type mismatches
carina-akaia May 14, 2024
c0d7027
wip
carina-akaia May 16, 2024
1e34a86
wip
carina-akaia May 16, 2024
357a22d
Separate shared modules / assets from business logic
carina-akaia May 16, 2024
25b4bf3
fix: Provide non-prefixed rule for compatibility
carina-akaia May 16, 2024
4df2729
wip: Fix type mismatch
carina-akaia May 16, 2024
b7120b8
nit: Keep constants in `/common/constants`
carina-akaia May 16, 2024
e7cc692
Update theme
carina-akaia May 17, 2024
db72ec7
Update styles for shared components
carina-akaia May 17, 2024
277e411
Add Create Group section to admin dashboard
carina-akaia May 17, 2024
36b5e18
Create component for content-rich modals
carina-akaia May 17, 2024
19399f3
Implement group API bindings
carina-akaia May 17, 2024
fc8a0dd
wip
carina-akaia May 17, 2024
b73b9b5
wip
carina-akaia May 17, 2024
1d9fdff
wip
carina-akaia May 18, 2024
d357270
wip
carina-akaia May 18, 2024
bff9c95
wip
carina-akaia May 18, 2024
aa6a0fe
wip: Create group editor
carina-akaia May 19, 2024
98810d1
wip
carina-akaia May 19, 2024
63b9a5c
wip
carina-akaia May 19, 2024
70f3a5d
wip
carina-akaia May 19, 2024
3d97a22
wip: Fix stamp form submit handler
carina-akaia May 19, 2024
fe8e9d0
Attempt to fix `localStorage is not defined`
carina-akaia May 19, 2024
3880de5
Extract group form from group editor
carina-akaia May 19, 2024
b9ad591
wip: Fix security vulnerability & Create select component
carina-akaia May 20, 2024
ae0405e
wip: Update group editor
carina-akaia May 20, 2024
84d6d40
wip: Make group rule types type-safe
carina-akaia May 20, 2024
24ac3dd
Adjust styles for Select
carina-akaia May 20, 2024
43d70bb
wip: Improve error handling
carina-akaia May 20, 2024
eae2f0d
Adjust input styles
carina-akaia May 20, 2024
535d2cd
wip: Display group provider errors
carina-akaia May 20, 2024
1e5d58d
wip: Update group dialog content
carina-akaia May 21, 2024
993a2d3
fix: Attach default deposit for payable functions
carina-akaia May 21, 2024
d0ce72b
wip
carina-akaia May 21, 2024
37afb05
nit: Fix Markdown rule violation
carina-akaia May 22, 2024
8c3810e
wip: Create groups list & Fix threshold validation
carina-akaia May 22, 2024
5139935
wip
carina-akaia May 23, 2024
88356eb
wip
carina-akaia May 23, 2024
039984c
wip
carina-akaia May 23, 2024
69ad9e4
wip
carina-akaia May 23, 2024
a3c88a0
wip
carina-akaia May 23, 2024
eba6a29
wip: Fix form consistency issues
carina-akaia May 24, 2024
83f0d0d
wip: Fix form consistency issues
carina-akaia May 24, 2024
7ac21ec
wip: Fix form consistency issues
carina-akaia May 24, 2024
49367a8
Update group styles
carina-akaia May 24, 2024
c07a14b
Display stamp's related group list
carina-akaia May 24, 2024
c3ec0c0
Add project structure documentation
carina-akaia May 24, 2024
52947f8
Use Potlock app's naming & colocation conventions
carina-akaia May 28, 2024
554d220
Remove dead code
carina-akaia May 28, 2024
67f107c
Elevate complexity tier
carina-akaia May 28, 2024
9ecda4b
Elevate complexity tier
carina-akaia May 28, 2024
13aa687
Use Potlock app's naming & colocation conventions
carina-akaia May 28, 2024
5b435dc
Rename Rules -> Groups
carina-akaia May 28, 2024
4b45018
Adjust routing schema
carina-akaia May 28, 2024
df4df87
wip: Apply code review suggestions
carina-akaia May 29, 2024
1c74037
wip: Reload page after sign out
carina-akaia May 29, 2024
2968ad9
Update `/rules` link label
carina-akaia May 30, 2024
b6937d6
Display rule type tag in group editor
carina-akaia May 30, 2024
05164b3
Merge branch 'staging' of https://github.com/PotLock/nadabot-app into…
carina-akaia Jun 3, 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
23 changes: 19 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
{
"editor.formatOnSave": true,
"eslint.validate": ["typescript"],
"eslint.validate": [
"typescript"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll": "explicit"
}
}

},
"cSpell.words": [
"fontsource",
"LIGHTGRAY",
"nadabot",
"naxios",
"Roboto",
"SHADOWGRAY",
"Snackbars",
"Subtractor",
"Unflag",
"uuidv4",
"wpdas",
"zustand"
]
}
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# nadabot-app

Nada.bot application https://nada.bot
Nada.bot application <https://nada.bot>

## Getting Started

Expand Down Expand Up @@ -33,3 +33,56 @@ NEXT_PUBLIC_SOCIAL_DB_CONTRACT_ID=v1.social08.testnet
# Pinata JWT (ask Shot for the JWT Key)
PINATA_JWT=<jwt-code>
```

## Project structure

```sh

[ / ]
├── [ common ] <--- # Abstract implementation details, reusable assets, and primitives, used in layouts
│ │ # and business logic across the codebase, and MUST NOT contain business logic themselves.
│ │ # AKA "shared" ( see link 1. )
│ │
│ ├── constants.ts
│ ├── assets
│ ├── contexts
│ ├── lib
│ ├── services
│ ├── store
│ └── ui
├── [ modules ] <--- # Business logic units broken down into categories.
│ │ # Simply put, this is a collection of directories that contain code implementing specific
│ │ # groups of app use cases and are named after functionalities they provide.
│ │
│ ├── auth
│ │
│ ├── [ core ] <--- # Follows the same structure as any other module, but contains business logic,
│ │ │ # that is shared between all or some of the other modules
│ │ │
│ │ └── [ hooks ] <--- # Feature-specific React hooks
│ │
│ ├── groups
│ └── stamps
└── [ pages ] <--- # App's entry point. Follows Nextjs App routing specification ( see link 2. ),
# with additional Private Folders following Nextjs App routing conventions ( see link 3. ),
# that facilitate layout code-splitting and further migration to App Router ( see link 4. )

```

### Links

1. [Shared layer from Feature-Sliced Design methodology](https://feature-sliced.design/docs/reference/layers#shared)
2. [Nextjs Pages routing conventions](https://nextjs.org/docs/getting-started/project-structure#pages-routing-conventions)
3. [Nextjs App Private Folders](https://nextjs.org/docs/app/building-your-application/routing/colocation#private-folders)
4. [Nextjs App Router](https://nextjs.org/docs/app)
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Stack } from "@mui/material";
import Image from "next/image";

import useBreakPoints from "@nadabot/hooks/useBreakPoints";
import useBreakPoints from "@nadabot/common/ui/utils/useBreakPoints";

import nadabotIcon from "../images/nadabot-icon.png";

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
13 changes: 13 additions & 0 deletions constants.ts → common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const ONE_TENTH_NEAR = utils.format.parseNearAmount("0.1")!;
export const ONE_HUNDREDTH_NEAR = utils.format.parseNearAmount("0.01")!;
// 0.02 NEAR
export const TWO_HUNDREDTHS_NEAR = utils.format.parseNearAmount("0.02")!;
// 0.03 NEAR
export const THREE_HUNDREDTHS_NEAR = utils.format.parseNearAmount("0.03")!;
// 300 Gas (full)
export const FULL_TGAS = "300000000000000";
// 30 Gas
Expand All @@ -44,3 +46,14 @@ export const MAX_PROVIDER_DESCRIPTION_LENGTH = 256;
export const MAX_PROVIDER_EXTERNAL_URL_LENGTH = 256;
export const MAX_PROVIDER_ICON_URL_LENGTH = 256;
export const MAX_GAS = 100; //100_000_000_000_000;
export const DEFAULT_ACCOUNT_ID_ARG_NAME = "account_id";

export const Routes = {
HOME: "/",
HOME_WITH_FILTERED_CHECKS: (
filterType: "newly-created" | "active" | "deactivated" | "flagged",
) => `/?filterType=${filterType}`,
ADD_STAMP: "/stamp/create",
ACCOUNT_INFO: (accountId: string) => `/account-info?accountId=${accountId}`,
ADMIN_HOME: "/admin",
};
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IPFS_NEAR_SOCIAL_THUMBNAIL_URL } from "@nadabot/constants";
import { IPFS_NEAR_SOCIAL_THUMBNAIL_URL } from "@nadabot/common/constants";

const getNearSocialProfileAvatarImage = (image_ipfs_cid?: string) =>
image_ipfs_cid
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
ProviderExternal,
ProviderExternalWithIsHuman,
} from "@nadabot/services/contracts/sybil.nadabot/interfaces/providers";
} from "@nadabot/common/services/contracts/sybil.nadabot/interfaces/providers";

/**
* Inserts { is_user_a_human: boolean } to regular provider (ProviderExternal)
Expand Down
2 changes: 1 addition & 1 deletion utils/providerSorts.ts → common/lib/providerSorts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ProviderExternalWithIsHuman } from "@nadabot/services/contracts/sybil.nadabot/interfaces/providers";
import { ProviderExternalWithIsHuman } from "@nadabot/common/services/contracts/sybil.nadabot/interfaces/providers";

/**
* sort providers to show the most weight first
Expand Down
52 changes: 52 additions & 0 deletions common/lib/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Temporal } from "temporal-polyfill";

/**
* Converts a value in milliseconds to the equivalent number of days.
*
* @param {number | string | null} value - The value to convert,
* which can be a number of milliseconds, a string representing a number of milliseconds, or null.
*
* @return {number} The number of days equivalent to the input value.
* @throws {TypeError} If the input value cannot be converted to a number of milliseconds.
*/
export const millisecondsToDays = (value: number | string | null): number => {
try {
return Temporal.Duration.from({
milliseconds: typeof value === "string" ? parseInt(value) : value ?? 0,
}).total("days");
} catch {
const error = new TypeError(`Unable to convert \`${value}\` to days`);

console.error(error);
throw error;
}
};

/**
* Converts a value in days to the equivalent number of milliseconds.
*
* @param {number | string | null} value - The value to convert,
* which can be a number of days, a string representing a number of days, or null.
*
* @return {number} The number of milliseconds equivalent to the input value.
* @throws {TypeError} If the input value cannot be converted to a number of milliseconds.
*/
export const daysToMilliseconds = (value: number | string | null): number => {
try {
return Temporal.Duration.from({
days: typeof value === "string" ? parseInt(value) : value ?? 0,
}).total("milliseconds");
} catch {
const error = new TypeError(
`Unable to convert \`${value}\` to milliseconds`,
);

console.error(error);
throw error;
}
};

export const daysSinceTimestamp = (unixTimestampMs: number) =>
Temporal.Now.instant().since(
Temporal.Instant.fromEpochMilliseconds(unixTimestampMs),
).days;
File renamed without changes.
2 changes: 1 addition & 1 deletion hooks/useIsAdminPage.ts → common/lib/useIsAdminPage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

import { Routes } from "@nadabot/routes";
import { Routes } from "@nadabot/common/constants";

const useIsAdminPage = () => {
const router = useRouter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { setupWelldoneWallet } from "@near-wallet-selector/welldone-wallet";
import { setupXDEFI } from "@near-wallet-selector/xdefi";
import naxios from "@wpdas/naxios";

import { CONTRACT_ID, NETWORK } from "@nadabot/constants";
import { CONTRACT_ID, NETWORK } from "@nadabot/common/constants";

// Naxios (Contract/Wallet) Instance
export const naxiosInstance = new naxios({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StorageCache } from "@wpdas/naxios";

import { SOCIAL_DB_CONTRACT_ID } from "@nadabot/constants";
import { SOCIAL_DB_CONTRACT_ID } from "@nadabot/common/constants";

import { naxiosInstance } from "..";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import { Provider } from "near-api-js/lib/providers";
import {
FULL_TGAS,
ONE_HUNDREDTH_NEAR,
THREE_HUNDREDTHS_NEAR,
TWO_HUNDREDTHS_NEAR,
} from "@nadabot/constants";
} from "@nadabot/common/constants";

import {
CreateGroup,
GroupById,
GroupExternal,
UpdateGroup,
} from "./interfaces/groups";
import { GetHumanScoreInput, HumanScoreResponse } from "./interfaces/is-human";
import { Config } from "./interfaces/lib";
import {
ActivateProviderInput,
DeactivateProviderInput,
FlagProviderInput,
ProviderById,
ProviderExternal,
RegisterProviderInput,
UnflagProviderInput,
Expand Down Expand Up @@ -40,6 +48,16 @@ export const contractApi = naxiosInstance.contractApi({
*/
export const get_config = () => contractApi.view<{}, Config>("get_config");

/**
* Get Provider by its id
*/
export const get_provider = (args: ProviderById) =>
contractApi.view<object, ProviderExternal | undefined>(
"get_provider",
{ args },
{ useCache: true },
);

/**
* Get Providers
* @returns
Expand Down Expand Up @@ -172,6 +190,34 @@ export const admin_flag_provider = (args: FlagProviderInput) =>
* @returns
*/
export const admin_unflag_provider = (args: UnflagProviderInput) =>
contractApi.call<typeof args, Provider>("admin_unflag_provider", {
contractApi.call<typeof args, Provider>("admin_unflag_provider", { args });

export const create_group = (args: CreateGroup) =>
contractApi.call<typeof args, GroupExternal>("create_group", {
args,
deposit: THREE_HUNDREDTHS_NEAR,
});

export const update_group = (args: UpdateGroup) =>
contractApi.call<typeof args, GroupExternal>("update_group", {
args,
deposit: THREE_HUNDREDTHS_NEAR,
});

export const delete_group = (args: GroupById) =>
contractApi.call<typeof args, void>("delete_group", {
args,
deposit: ONE_HUNDREDTH_NEAR,
});

export const get_groups = () =>
contractApi.view<object, GroupExternal[]>("get_groups", undefined, {
useCache: true,
});

export const get_group = (args: GroupById) =>
contractApi.view<typeof args, GroupExternal | undefined>(
"get_group",
{ args },
{ useCache: true },
);
57 changes: 57 additions & 0 deletions common/services/contracts/sybil.nadabot/interfaces/groups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ProviderId } from "./providers";

export type GroupId = number;

export enum RulePrimitiveType {
Highest = "Highest",
Lowest = "Lowest",
}

export enum RuleGenericType {
Sum = "Sum",
DiminishingReturns = "DiminishingReturns",
IncreasingReturns = "IncreasingReturns",
}

export type RuleType =
| keyof typeof RulePrimitiveType
| keyof typeof RuleGenericType;

export type Rule =
| keyof typeof RulePrimitiveType
| {
/** Sum all scores with optional max value */
[RuleGenericType.Sum]: number | null | undefined;
}
| {
/** Sum with diminishing returns, factor in percentage (e.g., 10 for 10% reduction each) */
[RuleGenericType.DiminishingReturns]: number;
}
| {
/** Sum with increasing returns, factor in percentage (e.g., 10 for 10% increase each) */
[RuleGenericType.IncreasingReturns]: number;
};

export type Group = {
name: string;
rule: Rule;
};

export type GroupExternal = Group & {
id: GroupId;
providers: ProviderId[];
};

export interface GroupById {
group_id: GroupId;
}

export interface CreateGroup extends Pick<GroupExternal, "rule" | "providers"> {
group_name: GroupExternal["name"];
}

export interface UpdateGroup
extends GroupById,
Partial<Pick<GroupExternal, "rule" | "providers">> {
group_name?: GroupExternal["name"];
}
Loading