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

Donation UI: Direct NEAR donation #64

Merged
merged 93 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
2e12bc9
Include projects overview component
carina-akaia Jun 3, 2024
d26310c
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 3, 2024
fa52cbf
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 4, 2024
7fb24d7
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 4, 2024
57accba
wip
carina-akaia Jun 6, 2024
5d43174
wip
carina-akaia Jun 6, 2024
697dd78
Generate API bindings directly from endpoint
carina-akaia Jun 6, 2024
697c953
chore: Enable autoformatting for generated API clients
carina-akaia Jun 6, 2024
37f46e2
Use SWR
carina-akaia Jun 6, 2024
7a365a0
fix: Use custom modal close callback
carina-akaia Jun 7, 2024
090fe07
wip: Update generated API bindings
carina-akaia Jun 9, 2024
cdb6726
fix: Add missing UnoCSS configuration & Resolve type errors
carina-akaia Jun 9, 2024
8e71bcd
feat: Create input field component
carina-akaia Jun 10, 2024
796cb6a
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 10, 2024
d6d7fe3
Rename to TextField and restrict type options
carina-akaia Jun 10, 2024
7a97c58
Barrel export named UI primitives
carina-akaia Jun 11, 2024
e453b16
wip: Update modals
carina-akaia Jun 11, 2024
acca086
api: Sync with backend schema
carina-akaia Jun 12, 2024
db306e9
Adjust TextField styles
carina-akaia Jun 12, 2024
3673b36
Update styles
carina-akaia Jun 12, 2024
94dbee7
wip: Update styles
carina-akaia Jun 12, 2024
2416719
wip: Update styles
carina-akaia Jun 12, 2024
2f987e4
wip: Update styles
carina-akaia Jun 12, 2024
b7b2acd
wip: Update styles
carina-akaia Jun 13, 2024
2c115c9
wip
carina-akaia Jun 13, 2024
66e15ad
wip
carina-akaia Jun 14, 2024
dd598ee
wip
carina-akaia Jun 14, 2024
7c985f0
Add Swagger UI URL to docs
carina-akaia Jun 14, 2024
31f7908
wip
carina-akaia Jun 14, 2024
ac018d4
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 14, 2024
9ef854c
fix: Provide Redux store to modals
carina-akaia Jun 14, 2024
640de81
wip
carina-akaia Jun 14, 2024
3874562
wip
carina-akaia Jun 14, 2024
e8d37b9
wip
carina-akaia Jun 15, 2024
74bacba
wip
carina-akaia Jun 15, 2024
7c91ecb
wip
carina-akaia Jun 15, 2024
1d13b98
wip
carina-akaia Jun 16, 2024
b8a7023
wip
carina-akaia Jun 16, 2024
476544f
wip
carina-akaia Jun 17, 2024
2b11b57
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 17, 2024
7b2bc46
wip: Use account balances from Pagoda EAPI
carina-akaia Jun 18, 2024
5fead6c
wip
carina-akaia Jun 18, 2024
ef5eddb
wip
carina-akaia Jun 18, 2024
6d11a71
wip: Restructure donation flow
carina-akaia Jun 18, 2024
1a58110
wip: Restructure donation flow
carina-akaia Jun 18, 2024
f7984a9
wip
carina-akaia Jun 18, 2024
93c1cc8
wip
carina-akaia Jun 18, 2024
86c2a18
wip
carina-akaia Jun 18, 2024
021764f
wip
carina-akaia Jun 19, 2024
f1d5337
wip
carina-akaia Jun 19, 2024
3a97423
Adjust button styles
carina-akaia Jun 19, 2024
645c26d
wip
carina-akaia Jun 19, 2024
06b3b92
wip
carina-akaia Jun 19, 2024
7d033e8
wip
carina-akaia Jun 19, 2024
bc635f3
wip
carina-akaia Jun 19, 2024
9553f4e
Fix api client issues & Add Pagoda EAPI client
carina-akaia Jun 19, 2024
acf7172
Delete Next artifacts
carina-akaia Jun 19, 2024
ff7de53
wip: Implement fee calculation
carina-akaia Jun 20, 2024
b9d6fde
wip: Implement fee calculation
carina-akaia Jun 20, 2024
303107f
wip: Implement fee calculation
carina-akaia Jun 20, 2024
8505d2b
Merge branch 'main' of https://github.com/PotLock/potlock-nextjs-app …
carina-akaia Jun 21, 2024
8faf9f6
wip: Implement fee calculation
carina-akaia Jun 21, 2024
6dcf15d
wip
carina-akaia Jun 21, 2024
2269e36
wip
carina-akaia Jun 21, 2024
4b29bd7
wip
carina-akaia Jun 21, 2024
019cb54
wip
carina-akaia Jun 22, 2024
1964e6a
wip: Improve UX
carina-akaia Jun 22, 2024
fb51588
wip: Improve UX
carina-akaia Jun 22, 2024
ded14f7
wip
carina-akaia Jun 23, 2024
ef476ed
wip
carina-akaia Jun 23, 2024
b2787ab
Refine validation
carina-akaia Jun 23, 2024
ca20b69
fix: Refine validation and fee calculation
carina-akaia Jun 23, 2024
9b66c46
wip
carina-akaia Jun 24, 2024
8e00af7
wip
carina-akaia Jun 24, 2024
33ffd76
fix: Adjust styles
carina-akaia Jun 24, 2024
6e0876c
wip
carina-akaia Jun 24, 2024
974c2a0
wip
carina-akaia Jun 24, 2024
8892ee8
chore: Remove dead code
carina-akaia Jun 24, 2024
855c415
feat: Implement random project donation
carina-akaia Jun 24, 2024
09ebb22
Merge branch 'staging' of https://github.com/PotLock/potlock-nextjs-a…
carina-akaia Jun 25, 2024
a718214
wip
carina-akaia Jun 25, 2024
f15b56c
Fix donation TX confirmation
carina-akaia Jun 25, 2024
dc999f1
wip: Adjust success screen
carina-akaia Jun 26, 2024
8d49bcf
Merge branch 'staging' of https://github.com/PotLock/potlock-nextjs-a…
carina-akaia Jun 26, 2024
a78f614
wip
carina-akaia Jun 26, 2024
d337a81
wip
carina-akaia Jun 26, 2024
857a75f
wip
carina-akaia Jun 26, 2024
0ebd832
wip
carina-akaia Jun 26, 2024
e2dd499
wip
carina-akaia Jun 26, 2024
96c59d5
fix: Adjust styles
carina-akaia Jun 26, 2024
587ca3a
fix: Adjust styles
carina-akaia Jun 26, 2024
62c5ec6
test: Set random donation button test timeout to 5s
carina-akaia Jun 26, 2024
e9408bb
chore: Format
carina-akaia Jun 26, 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
9 changes: 2 additions & 7 deletions src/app/_components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import Link from "next/link";
import { Button } from "@/common/ui/components";
import useWallet from "@/modules/auth/hooks/useWallet";
import useRegistration from "@/modules/core/hooks/useRegistration";
import { DonationRandomButton } from "@/modules/donation";

const Hero = () => {
const wallet = useWallet();
const accountId = wallet?.wallet?.accountId || "";

const { registration, loading } = useRegistration(accountId);

const isRegisteredProject = !!registration.id;

return (
Expand All @@ -23,12 +23,7 @@ const Hero = () => {
<br className="hidden md:block" /> participate in funding rounds.
</h1>
<div className="mt-6 flex items-center gap-4 text-sm max-md:flex-col md:mt-10 md:gap-8">
<Button
className="w-full md:w-[180px]"
// onClick={openDonateRandomlyModal}
>
Donate Randomly
</Button>
<DonationRandomButton />

{!loading && (
<Button
Expand Down
24 changes: 3 additions & 21 deletions src/app/_layout/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
"use client";

import { useCallback, useState } from "react";
import { useState } from "react";

import Image from "next/image";
import Link from "next/link";
import { usePathname } from "next/navigation";

import { walletApi } from "@/common/contracts";
import useIsClient from "@/common/lib/useIsClient";
import { Button } from "@/common/ui/components";
import { SignInButton } from "@/modules/auth";
import { useAuth } from "@/modules/auth/hooks/useAuth";
import routesPath from "@/modules/core/routes";

Expand Down Expand Up @@ -37,26 +36,9 @@ const AuthButton = () => {
const { isAuthenticated } = useAuth();
const isClient = useIsClient();

const loginHandler = useCallback(() => {
walletApi.signInModal();
}, []);

if (!isClient) return;

if (isAuthenticated) {
return <UserDropdown />;
}

return (
<Button
font="semibold"
variant="standard-filled"
onClick={loginHandler}
className="border-none bg-[#342823] shadow-none"
>
Sign In
</Button>
);
return isAuthenticated ? <UserDropdown /> : <SignInButton />;
};

const MobileMenuButton = ({ onClick }: { onClick: () => void }) => {
Expand Down
3 changes: 3 additions & 0 deletions src/app/_store/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ import { Models } from "@rematch/core";

import { auth } from "@/modules/auth/state";
import { core } from "@/modules/core/state";
import { donationModel } from "@/modules/donation";
import { navModel, profilesModel } from "@/modules/profile/models";

export interface RootModel extends Models<RootModel> {
auth: typeof auth;
donation: typeof donationModel;
profiles: typeof profilesModel;
nav: typeof navModel;
core: typeof core;
}

export const models: RootModel = {
auth,
donation: donationModel,
profiles: profilesModel,
nav: navModel,
core,
Expand Down
15 changes: 10 additions & 5 deletions src/app/tests.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { screen } from "@testing-library/react";
import { screen, waitFor } from "@testing-library/react";
import { expect, test } from "vitest";

import { renderWithStore } from "./_store/testEnv";
Expand All @@ -7,10 +7,15 @@ import Homepage from "./page";
renderWithStore(<Homepage />);

test("Homepage", async () => {
expect(
screen.getByText("Donate Randomly"),
"random donation button",
).toBeDefined();
await waitFor(
() =>
expect(
screen.getByText("Donate Randomly"),
"random donation button",
).toBeDefined(),

{ timeout: 5000 },
);

// await waitFor(
// () =>
Expand Down
47 changes: 43 additions & 4 deletions src/common/api/pagoda/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { PAGODA_REQUEST_CONFIG } from "@/common/constants";
import { NEAR_TOKEN_DENOM, PAGODA_REQUEST_CONFIG } from "@/common/constants";
import { walletApi } from "@/common/contracts";
import { ByAccountId, ByTokenId } from "@/common/types";

import { swrHooks } from "./generated";
import { ByAccountId } from "../potlock";

export const useNearAccountBalance = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useGetAccountsAccountIdBalancesNEAR(
Expand All @@ -10,7 +11,7 @@ export const useNearAccountBalance = ({ accountId }: ByAccountId) => {
PAGODA_REQUEST_CONFIG,
);

return { ...queryResult, data: queryResult.data?.data };
return { ...queryResult, data: queryResult.data?.data.balance };
};

export const useFtAccountBalances = ({ accountId }: ByAccountId) => {
Expand All @@ -20,5 +21,43 @@ export const useFtAccountBalances = ({ accountId }: ByAccountId) => {
PAGODA_REQUEST_CONFIG,
);

return { ...queryResult, data: queryResult.data?.data };
return { ...queryResult, data: queryResult.data?.data.balances };
};

export type TokenMetadataInputs = ByTokenId & {
disabled?: boolean;
};

export const useTokenMetadata = ({
tokenId,
disabled = false,
}: TokenMetadataInputs) => {
const nearQueryResult = swrHooks.useGetAccountsAccountIdBalancesNEAR(
walletApi.accountId ?? "unknown",
undefined,

{
...PAGODA_REQUEST_CONFIG,
swr: { enabled: !disabled && tokenId === NEAR_TOKEN_DENOM },
},
);

const ftQueryResult = swrHooks.useGetNep141MetadataContractAccountId(
tokenId,
undefined,

{
...PAGODA_REQUEST_CONFIG,
swr: { enabled: !disabled && tokenId !== NEAR_TOKEN_DENOM },
},
);

return {
...(tokenId === NEAR_TOKEN_DENOM ? nearQueryResult : ftQueryResult),

data:
tokenId === NEAR_TOKEN_DENOM
? nearQueryResult.data?.data.balance.metadata
: ftQueryResult.data?.data.metadata,
};
};
83 changes: 71 additions & 12 deletions src/common/api/potlock/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
import { POTLOCK_REQUEST_CONFIG } from "@/common/constants";
import { ByAccountId, ByListId, ConditionalExecution } from "@/common/types";

import { swrHooks } from "./generated";
import {
ByAccountId,
ByPotId,
V1AccountsPotApplicationsRetrieveParams,
V1ListsRandomRegistrationRetrieveParams,
} from "./types";

export const useAccounts = () => {
const queryResult = swrHooks.useV1AccountsRetrieve(POTLOCK_REQUEST_CONFIG);
/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_donate_contract_config_retrieve
*/
export const useDonationConfig = () => {
const queryResult = swrHooks.useV1DonateContractConfigRetrieve(
POTLOCK_REQUEST_CONFIG,
);

return { ...queryResult, data: queryResult.data?.data };
};

export const useAccount = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useV1AccountsRetrieve2(
accountId,
POTLOCK_REQUEST_CONFIG,
);
/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_retrieve
*/
export const useAccounts = (params?: ConditionalExecution) => {
const queryResult = swrHooks.useV1AccountsRetrieve({
...POTLOCK_REQUEST_CONFIG,
swr: { enabled: params?.enabled ?? true },
});

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_retrieve_2
*/
export const useAccount = ({ accountId }: Partial<ByAccountId>) => {
const queryResult = swrHooks.useV1AccountsRetrieve2(accountId ?? "unknown", {
...POTLOCK_REQUEST_CONFIG,
swr: { enabled: Boolean(accountId) },
});

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_active_pots_retrieve
*/
export const useAccountActivePots = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useV1AccountsActivePotsRetrieve(
accountId,
Expand All @@ -32,6 +56,9 @@ export const useAccountActivePots = ({ accountId }: ByAccountId) => {
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_pot_applications_retrieve
*/
export const useAccountPotApplications = ({
accountId,
status,
Expand All @@ -45,12 +72,18 @@ export const useAccountPotApplications = ({
return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_pots_retrieve
*/
export const usePots = () => {
const queryResult = swrHooks.useV1PotsRetrieve(POTLOCK_REQUEST_CONFIG);

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_accounts_donations_received_retrieve
*/
export const useAccountDonationsReceived = ({ accountId }: ByAccountId) => {
const queryResult = swrHooks.useV1AccountsDonationsReceivedRetrieve(
accountId,
Expand All @@ -60,10 +93,36 @@ export const useAccountDonationsReceived = ({ accountId }: ByAccountId) => {
return { ...queryResult, data: queryResult.data?.data };
};

export const usePot = ({ potId }: ByPotId) => {
const queryResult = swrHooks.useV1PotsRetrieve2(
potId,
POTLOCK_REQUEST_CONFIG,
/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_pots_retrieve_2
*/
export const usePot = ({ potId }: Partial<ByPotId>) => {
const queryResult = swrHooks.useV1PotsRetrieve2(potId ?? "unknown", {
...POTLOCK_REQUEST_CONFIG,
swr: { enabled: Boolean(potId) },
});

return { ...queryResult, data: queryResult.data?.data };
};

/**
* https://dev.potlock.io/api/schema/swagger-ui/#/v1/v1_lists_random_registration_retrieve
*
* Note: automatic refresh is disabled for optimization.
* Call `mutate()` for manual refresh.
*/
export const useRandomListRegistration = ({
listId,
status,
}: ByListId & V1ListsRandomRegistrationRetrieveParams) => {
const queryResult = swrHooks.useV1ListsRandomRegistrationRetrieve(
listId,
{ status },

{
...POTLOCK_REQUEST_CONFIG,
swr: { revalidateIfStale: false, revalidateOnFocus: false },
},
);

return { ...queryResult, data: queryResult.data?.data };
Expand Down
8 changes: 1 addition & 7 deletions src/common/api/potlock/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { Account, Pot } from "./generated/client";
import { Pot } from "./generated/client";

export * from "./generated/client";

export type AccountId = Account["id"];

export interface ByAccountId {
accountId: AccountId;
}

export type PotId = Pot["id"];

export interface ByPotId {
Expand Down
4 changes: 2 additions & 2 deletions src/common/assets/svgs/near-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const NearIcon = (props: any) => (
const NearIcon = ({ width = 16, height = 16, ...props }: any) => (
<svg
{...props}
style={{ width: 16 }}
style={{ width, height }}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
Expand Down
17 changes: 13 additions & 4 deletions src/common/assets/svgs/twitter.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { Icon } from "./styles";

const TwitterSvg = () => (
<Icon xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 17" fill="none">
const TwitterSvg = (props: any) => (
<Icon
xmlns="http://www.w3.org/2000/svg"
width="19"
height="18"
viewBox="0 0 19 18"
fill="none"
{...props}
>
<path
d="M20.92 2C20.15 2.35 19.32 2.58 18.46 2.69C19.34 2.16 20.02 1.32 20.34 0.31C19.51 0.81 18.59 1.16 17.62 1.36C16.83 0.5 15.72 0 14.46 0C12.11 0 10.19 1.92 10.19 4.29C10.19 4.63 10.23 4.96 10.3 5.27C6.74 5.09 3.57 3.38 1.46 0.79C1.09 1.42 0.88 2.16 0.88 2.94C0.88 4.43 1.63 5.75 2.79 6.5C2.08 6.5 1.42 6.3 0.84 6V6.03C0.84 8.11 2.32 9.85 4.28 10.24C3.65073 10.4122 2.9901 10.4362 2.35 10.31C2.62161 11.1625 3.15354 11.9084 3.87102 12.4429C4.5885 12.9775 5.45545 13.2737 6.35 13.29C4.83363 14.4904 2.954 15.1393 1.02 15.13C0.68 15.13 0.34 15.11 0 15.07C1.9 16.29 4.16 17 6.58 17C14.46 17 18.79 10.46 18.79 4.79C18.79 4.6 18.79 4.42 18.78 4.23C19.62 3.63 20.34 2.87 20.92 2Z"
fill="#7B7B7B"
fill-rule="evenodd"
clip-rule="evenodd"
d="M16.25 15.4041L10.9706 7.70919L10.9797 7.7164L15.7398 2.20117H14.1491L10.2713 6.69017L7.19196 2.20117H3.02012L7.9489 9.38538L7.94831 9.38477L2.75 15.4041H4.34071L8.65183 10.4098L12.0782 15.4041H16.25ZM6.56169 3.40143L13.969 14.2038H12.7084L5.29515 3.40143H6.56169Z"
fill="#DBDBDB"
/>
</Icon>
);
Expand Down
8 changes: 5 additions & 3 deletions src/common/contracts/potlock/donate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MemoryCache } from "@wpdas/naxios";
import { ChangeMethodArgs, MemoryCache } from "@wpdas/naxios";

import { POTLOCK_DONATE_CONTRACT_ID } from "@/common/constants";

Expand Down Expand Up @@ -53,9 +53,11 @@ export const getDonationsForDonor = (args: { donor_id: string }) =>

export const donateNearDirectly = (
args: DirectDonationArgs,
depositAmountFloat: number,
depositAmountYocto: string,
callbackUrl?: ChangeMethodArgs<DirectDonation>["callbackUrl"],
) =>
contractApi.call<typeof args, DirectDonation>("donate", {
args,
deposit: depositAmountFloat.toString(),
deposit: depositAmountYocto,
callbackUrl,
});
Loading
Loading