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

feat: EVM compatible games #216

Draft
wants to merge 29 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
19e59b6
feat: add wallet selector
Udit-takkar Nov 19, 2023
c0a3b85
chore: remove comment
Udit-takkar Nov 19, 2023
b786ad8
Merge branch 'master' of github.com:aufacicenta/pulsemarkets into fea…
netpoe Nov 25, 2023
86f15e1
feat: EVMWalletSelectorContext
netpoe Nov 25, 2023
71c49eb
fix: Footer, LocaleSelector layout issues
netpoe Nov 25, 2023
087a8f6
feat: use new wallet selector in mobile
Udit-takkar Nov 25, 2023
edb1469
chore: remove
Udit-takkar Nov 25, 2023
5ba641b
Merge pull request #211 from Udit-takkar/feat/wallet-selector
netpoe Nov 26, 2023
4b99088
chore: removes last NEAR wallet-selector modules
netpoe Nov 26, 2023
54e6ea6
Merge branch 'feat/wallet-selector' into EVM
netpoe Nov 26, 2023
d2b8a54
feat: typescript interface
Udit-takkar Dec 9, 2023
8893171
feat: ethers-v6 Market contract context
netpoe Dec 13, 2023
eea2651
chore: updates EVM hook name
netpoe Dec 13, 2023
e1683f4
chore: updates README to EVM instructions
netpoe Dec 13, 2023
f5e4aa3
chore: fix spelling
Udit-takkar Dec 16, 2023
d01971a
feat: add other methods
Udit-takkar Dec 16, 2023
a630d95
refactor: Solidity public flags methods
netpoe Dec 16, 2023
df3d995
chore: typechain public flags
netpoe Dec 16, 2023
0e2d09b
Merge pull request #218 from aufacicenta/refactor/solidity-public-met…
netpoe Dec 16, 2023
f4168dd
chore: fixes typechain merge errors
netpoe Dec 19, 2023
38a05c7
chore:add contract value
Udit-takkar Jan 13, 2024
f840380
chore
Udit-takkar Jan 13, 2024
5fb00d8
feat: add getOutcometoken
Udit-takkar Jan 13, 2024
b5cbbb2
fix: resolves NEAR to EVM type issues WIP
netpoe Jan 22, 2024
169d2be
feat: [email protected] and sub-dependencies WIP
netpoe Jan 23, 2024
f6e11f6
fix: fetches optimismSepolia contract values WIP
netpoe Jan 23, 2024
4903463
fix(ImgPromptCard): marketContractValues working
netpoe Jan 23, 2024
5235db9
fix(PromptInputCard): brings back as EVM compatible
netpoe Feb 5, 2024
4dc5bfb
Merge pull request #217 from Udit-takkar/feat/typescript-interface
netpoe Feb 5, 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
175 changes: 53 additions & 122 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,110 +1,43 @@
# AI File Agent

![AI File Agent screenshot](https://blockchainassetregistry.infura-ipfs.io/ipfs/bafybeigtxmjowf7efxar3lel3kw63hsnogkimmb6azwqcrli55ekswifr4/Screenshot%202023-10-15%20at%2011.52.51.png)

Analyze API and file data with natural language and a nice UI.

- [Features](#features)
- [Development](#development)
- [Launching-client](#launching-client)
- [Debugging](#debugging)
- [Contributing](#contributing)

<a name="features"/>

## Features

AI File Agent is not only another AI chat UI, it allows you to upload any file and create custom components to render with each message, for example:

```typescript
messageContext.updateMessage({
role: "assistant",
content: `File "${file.name}" uploaded successfully. What would you like to do with it?`,
beforeContentComponent: (
<Typography.Description>
NOTE: This file is assigned to a temporary account.{" "}
<Typography.Link href="#">Create an account</Typography.Link> to keep it.
</Typography.Description>
),
afterContentComponent: <MessageFileType.Options file={file} fieldName={FormFieldNames.message} />,
type: "file",
file,
id: messageContext.transformId(file.upload!.uuid),
});
```
# Prompt Wars

Then, in the `MessageFileType.tsx` component:

```tsx
export const MessageFileType = ({ message, className }: MessageFileTypeProps) => {
const isSimulationEnabled = message.role === "assistant" && !message.hasInnerHtml;

const { simulationEnded } = useTypingSimulation(message.content, isSimulationEnabled, `#${message.id}`);

const progress: number = useSubscription(0, message.file.progressObservable);

return (
<div className={clsx(styles["message-file-type"], className)}>
<div>
<div className={styles["message-file-type__avatar"]}>
<div className={styles["message-file-type__avatar-box"]}>
{progress === 100 ? (
<Icon name="icon-file-check" />
) : (
<CircularProgress color="#ffd74b" percentage={progress} fontSize="21px" />
)}
</div>
</div>
<div className={styles["message-file-type__content"]}>
{message.beforeContentComponent && simulationEnded && message.beforeContentComponent}

{!isSimulationEnabled ? (
<Typography.Text>{message.content}</Typography.Text>
) : (
<Typography.Text id={message.id} />
)}

{message.afterContentComponent && simulationEnded && message.afterContentComponent}
</div>
</div>
</div>
);
};
```
Originally branded as Pulse Markets and built for the NEAR Blockchain, Prompt Wars is now a decentralized game build for EVM compatible wallets.

The reasoning behind the game is simple:

> Submit a prompt that will render the image on display, compare all the prompt results with the source image and pay the rewards to the resulting image that is closest to the reference image.

### Plus

- ✅ Upload any file of any size, display a nice uploading animation all within the chat interface
- ✅ Standard GoogleAI and OpenAI choice responses. Should work with more LM's in the future
- ✅ Animated assistant replies (typing animation)
- ✅ Variable height `textarea`
- ✅ API authentication handler
- ✅ `function_call` message type handler to call server-side functions
- ✅ Custom `label` values to render TSX components upon a given AI reply
- ✅ Well-typed Typescript interfaces to keep your dev flow groovin'
- ✅ Mobile-first design
- ✅ Dark and Light theming
- ✅ i18n ready
- ✅ Optional Tailwind CSS components and optional Shadcn UI components
- ✅ Open-source with paid bounties! 🤑
![Prompt Wars screenshot](https://blockchainassetregistry.infura-ipfs.io/ipfs/bafybeidycxac3jfzxd6c66luugcfks2ghuo423ukphdwnet753wy7n7tam/Screenshot%202023-07-07%20at%2012.42.32.png)

Follow [docs.pulsemarkets.org](https://docs.pulsemarkets.org/pulse-markets/) for a broader understanding of the smart-contract Prediction Markets protocol on top of which Prompt Wars is built.

- [Prompt Wars](#prompt-wars)
- [Development](#development)
- [Launching the frontend client](#launching-the-frontend-client)
- [Solidity Development](#solidity-development)
- [Building contract Instructions](#building-contract-instructions)
- [Creating new games](#creating-new-games)
- [Contributing](#contributing)

<a name="development"/>

## Development

Follow `app/README.md` for a detailed explanation of launching the dev environment.
To launch your own instance of Prompt Wars, you can:

1. connect to our Testnet or Mainnet contracts, OR
2. connect to your own contracts

<a name="launching-client"/>

### Launching the frontend client

The client is a NextJS application.
The client is a NextJS application that connects to the NEAR Protocol Rust smart-contracts with `near-api-js`.

To launch on `localhost:3003`, first clone this repo and run:

```
[email protected]:aufacicenta/fileagent.git
cd fileagent
```bash
[email protected]:aufacicenta/pulsemarkets.git
cd pulsemarkets
yarn
cd app
yarn
Expand All @@ -117,49 +50,47 @@ You'll need these values in `app/.env`:
export NODE_ENV=test
export NEXT_PUBLIC_ORIGIN="http://localhost:3003"

export NEXT_PUBLIC_CHAT_AI_API="googleai" # "googleai" OR "openai"
export NEXT_PUBLIC_INFURA_ID="..." # get it from infura.io, works to upload prompt images to IPFS

# Uncomment when ready to prod
# export NEXT_PUBLIC_DEFAULT_NETWORK_ENV="mainnet"

export NEXT_PUBLIC_DEFAULT_NETWORK_ENV="testnet"

export NEAR_SIGNER_PRIVATE_KEY="..." # a private key of your NEAR wallet account. This wallet creates the games and determines the winner

# NANONETS, for OCR features: https://nanonets.com/
export NANONETS_API_KEY="..."
export REPLICATE_API_TOKEN="..." # get it from replicate.ai, this connects to Stable Diffusion to compare the images

# OPEANAI, if you switch NEXT_PUBLIC_CHAT_AI_API to "openai"
export OPENAI_API_KEY="..."
export NEXT_PUBLIC_WEBSOCKETS_PORT=8000
```

# SUPABASE, used to store file content after it's read once: https://supabase.com/
export NEXT_PUBLIC_SUPABASE_URL="..."
export NEXT_PUBLIC_SUPABASE_ANON_KEY="..."
<a name="solidity-development"/>

# DROPBOX, used for the Dropbox Sign API features: https://developers.hellosign.com/api/reference/signature-request/
export DROPBOX_CLIENT_ID="..."
export DROPBOX_CLIENT_SECRET="..."
export DROPBOX_REDIRECT_URI="..."
## Solidity Development

# SQUARE, used for the Square API features: https://developer.squareup.com/explorer/square
export SQUARE_APP_ID="..."
export SQUARE_APP_SECRET="..."
export SQUARE_ACCESS_TOKEN="..."
export SQUARE_OAUTH_ENDPOINT="..."
### Building contract Instructions

# GOOGLE, used for googleai authentication: https://cloud.google.com/docs/authentication/provide-credentials-adc
export GOOGLE_APPLICATION_CREDENTIALS="path to credentials"
export GOOGLE_PROJECT_ID="..."
Whenever you make changes to `solidity/prompt-wars` contracts and compile them either with `npx hardhat compile`, or `npx hardhat test`, you should execute this:

# DATABASE, used for the Supabase postgres instance
export POSTGRES_DB_NAME=postgres
export POSTGRES_DB_USERNAME=postgres
export POSTGRES_DB_PASSWORD=...
export POSTGRES_DB_HOST=...
export POSTGRES_DB_PORT=5432
```bash
yarn typechain --target=ethers-v6 --out-dir app/src/providers/evm/contracts/prompt-wars solidity/promptwars/artifacts/contracts/Market.sol/Market.json
```

<a name="debugging"/>
This command will generate the ethers-v6 typings used in the app.

<a name="api"/>

## Creating new games

### Optional VSCode debugging
This is done through the API endpoints:

Instead of `yarn dev:debug`, hit the `F5` key, it should launch the VSCode Debugger in a new terminal session. You may create debug breakpoints on API endpoints, for example.
- `/api/prompt-wars/create` — create new games using the market factory contract (once this is called, it automates the next steps)
- `/api/prompt-wars/reveal` — compare the prompt results with the source image, store the results in the prompt wars market contract
- `/api/prompt-wars/resolve` — set the winner
- `/api/prompt-wars/self-destruct` — get the storage NEAR native balance back

<a name="contributing"/>

## Contributing

Check the paid issues in the [AI File Agent project board](https://github.com/orgs/aufacicenta/projects/3/views/1)!
Check the paid issues in the [Prompt Wars project board](https://github.com/orgs/aufacicenta/projects/2)!
1 change: 1 addition & 0 deletions app/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ module.exports = {
"unicorn/no-array-reduce": "off",
"unicorn/consistent-destructuring": "off",
"unicorn/no-array-for-each": "off",
"unicorn/no-abusive-eslint-disable": "off",

// a11y
"jsx-a11y/anchor-is-valid": "off",
Expand Down
5 changes: 4 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,18 @@
"@radix-ui/react-icons": "^1.3.0",
"@supabase/supabase-js": "^2.33.1",
"@types/js-cookie": "^3.0.3",
"@web3modal/wagmi": "^3.3.2",
"ag-grid-community": "^27.3.0",
"ag-grid-react": "^27.3.0",
"axios": "^1.5.0",
"bn.js": "^5.2.0",
"chart.js": "^3.8.2",
"chartjs-adapter-moment": "^1.0.0",
"clipboard": "^2.0.11",
"class-variance-authority": "^0.7.0",
"clipboard": "^2.0.11",
"clsx": "^2.0.0",
"dropzone": "^6.0.0-beta.2",
"ethers": "^6.9.0",
"filesize": "^10.1.0",
"final-form": "^4.20.4",
"final-form-arrays": "^3.0.2",
Expand Down Expand Up @@ -81,6 +83,7 @@
"tailwind-merge": "^1.14.0",
"tailwindcss-animate": "^1.0.7",
"uuid": "^9.0.0",
"wagmi": "^1.4.7",
"winston": "^3.9.0",
"ws": "^8.13.0"
},
Expand Down
2 changes: 1 addition & 1 deletion app/public/locales/en/prompt-wars.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"promptWars.marketCard.resolutionMechanism": "Resolution mechanism",
"promptWars.notifications.clearAll.": "Clear All",
"promptWars.closeIcon.crossedLines": "Crossed lines",
"promptWars.footer.madeByAufacicenta": "Made by Aufacicenta,",
"promptWars.footer.madeByAufacicenta": "Made by Aufacicenta",
"promptWars.footer.poweredByPulseProtocol": "powered by Pulse Protocol",
"promptWars.OutcomeTokensPosition.miniDescription": "Connect wallet to load balances",
"promptWars.walletSelector.nativeBalance": "Native Balance",
Expand Down
2 changes: 1 addition & 1 deletion app/public/locales/es/prompt-wars.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"promptWars.marketCard.resolutionMechanism": "Mecanismo de resolución",
"promptWars.notifications.clearAll.": "Borrar todo",
"promptWars.closeIcon.crossedLines": "Lineas cruzadas",
"promptWars.footer.madeByAufacicenta": "Hecho por Aufacicenta,",
"promptWars.footer.madeByAufacicenta": "Hecho por Aufacicenta",
"promptWars.footer.poweredByPulseProtocol": "Impulsado por Pulse Protocol",
"promptWars.OutcomeTokensPosition.miniDescription": "Conecta tu wallet para cargar los balances",
"promptWars.walletSelector.nativeBalance": "Balance Nativo",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import clsx from "clsx";
import { useEffect } from "react";
import Countdown from "react-countdown";
import { useAccount } from "wagmi";

import { useNearMarketContractContext } from "context/near/market-contract/useNearMarketContractContext";
import { Typography } from "ui/typography/Typography";
import { useWalletStateContext } from "context/wallet/state/useWalletStateContext";
import currency from "providers/currency";
import { useRoutes } from "hooks/useRoutes/useRoutes";

import { PriceMarketTableRowProps } from "./PriceMarketTableRow.types";
import styles from "./PriceMarketTableRow.module.scss";

export const PriceMarketTableRow: React.FC<PriceMarketTableRowProps> = ({ className }) => {
const walletState = useWalletStateContext();
const { isConnected } = useAccount();
const routes = useRoutes();

const {
Expand All @@ -33,7 +33,7 @@ export const PriceMarketTableRow: React.FC<PriceMarketTableRowProps> = ({ classN
}, [marketContractValues]);

const getOutcomeTokensPosition = () => {
if (!walletState.isConnected) {
if (!isConnected) {
return "connect wallet";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import clsx from "clsx";
import { useEffect } from "react";
import { useTranslation } from "next-i18next";
import { useAccount } from "wagmi";

import { useNearMarketContractContext } from "context/near/market-contract/useNearMarketContractContext";
import { useWalletStateContext } from "context/wallet/state/useWalletStateContext";
import { Typography } from "ui/typography/Typography";
import { Card } from "ui/card/Card";
import currency from "providers/currency";
Expand All @@ -12,14 +12,14 @@ import styles from "./OutcomeTokensPosition.module.scss";
import { OutcomeTokensPositionProps } from "./OutcomeTokensPosition.types";

export const OutcomeTokensPosition: React.FC<OutcomeTokensPositionProps> = ({ className }) => {
const walletState = useWalletStateContext();
const { isConnected } = useAccount();

const { marketContractValues, calculateTotalOutcomeTokensPosition, outcomeTokensExtended } =
useNearMarketContractContext();

useEffect(() => {
calculateTotalOutcomeTokensPosition();
}, [marketContractValues, walletState.isConnected]);
}, [marketContractValues, isConnected]);

const { t } = useTranslation(["prompt-wars"]);

Expand Down
Loading
Loading