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

Wiz Merge #306

Merged
merged 41 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
78001ec
basic function calling in place
zackrw Sep 11, 2023
bbfe347
Add basic UI element for Wiz
zackrw Sep 11, 2023
ef5e38e
Update scripts
zackrw Sep 11, 2023
83fe9c9
Add handler for input
zackrw Sep 11, 2023
4fe1d62
Update copyright
zackrw Sep 11, 2023
9a90aa0
function calling is working as intended on the backend
zackrw Sep 11, 2023
505d89d
It works.
zackrw Sep 12, 2023
9ab50c0
Improve icon for closing the window
zackrw Sep 12, 2023
dd7685b
Fix height issue
zackrw Sep 12, 2023
f87483d
Change openai import
zackrw Sep 12, 2023
274443f
Remove some function calls
zackrw Sep 12, 2023
2a89d08
Updates for performance, usability, safety, and bugfixes
zackrw Oct 20, 2023
f35009c
Extra files
zackrw Oct 20, 2023
a369add
Upgrade to 5.0 and other improvements
zackrw Oct 20, 2023
fd57ede
Update to GPT-4, add expansion and other tweaks
zackrw Nov 12, 2023
316114a
All files
zackrw Nov 12, 2023
3227861
Merge branch 'master' of https://github.com/openzeppelin/contracts-wi…
zackrw Nov 13, 2023
ffbadf7
Merge pull request #1 from zackrw/master
zackrw Nov 13, 2023
0484f0d
Merge in latest master branch
zackrw Nov 13, 2023
7a1f565
Redeploy
zackrw Nov 13, 2023
1722d20
Experiment with redis
zackrw Nov 14, 2023
23a6fcf
Redeploy
zackrw Nov 14, 2023
85ea823
Verified logging
zackrw Nov 14, 2023
c82034d
Update styles to be screen height instead of 1020px or more
zackrw Nov 23, 2023
ec3bc9f
Merge pull request #2 from zackrw/upstash
zackrw Nov 29, 2023
f405aac
Update screenshot.png and README.md
zackrw Nov 29, 2023
19b0286
Remove query-ai script
zackrw Nov 29, 2023
de6af85
Update .gitignore
zackrw Nov 29, 2023
c86183b
Update packages/core/package.json
zackrw Nov 29, 2023
b1a28d8
Update package.json
zackrw Nov 29, 2023
a763a02
Remove .vscode/settings.json
zackrw Nov 29, 2023
2d650a8
Remove package-lock.json
zackrw Nov 29, 2023
7034be6
Re-add yarn.lock
zackrw Nov 29, 2023
606836c
Add LICENSE for Feather and Lucide in icons
zackrw Nov 29, 2023
dcda8e1
Remove .netlify
zackrw Nov 29, 2023
bff87f1
Remove dependencies
zackrw Nov 29, 2023
c8ebf7e
Update yarn.lock
zackrw Nov 29, 2023
7d1cfa6
ISC License for icons
zackrw Nov 29, 2023
99cf8fd
Remove console logs
zackrw Nov 30, 2023
044649b
No changes to yarn.lock
zackrw Nov 30, 2023
80dec64
Apply revisions
zackrw Nov 30, 2023
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
dist
*.tsbuildinfo
node_modules


.env
.env.local
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Install dependencies with `yarn install`.

`packages/ui` is the interface built in Svelte. `yarn dev` spins up a local server to develop the UI.

You'll need to supply your own environment variables if you want to enable Wizard AI Assistant (OPENAI_API_KEY) and/or logging (REDIS_URL, REDIS_TOKEN).

## Embedding

To embed Contracts Wizard on your site, first include the script tag:
Expand Down
6 changes: 6 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[build]
command = "yarn --cwd packages/ui build"
publish = "packages/ui/public"

edge_functions = "packages/ui/api"

[[edge_functions]]
path = "/ai"
function = "ai"
77 changes: 77 additions & 0 deletions packages/ui/api/ai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import OpenAI from 'https://esm.sh/openai@4.11.0'
import { OpenAIStream, StreamingTextResponse } from 'https://esm.sh/ai@2.2.16'
import { erc20Function, erc721Function, erc1155Function, governorFunction, customFunction } from '../src/wiz-functions.ts'
import { Redis } from 'https://esm.sh/@upstash/redis@1.25.1'
zackrw marked this conversation as resolved.
Show resolved Hide resolved

export default async (req: Request) => {
try {
const data = await req.json()
const apiKey = Deno.env.get('OPENAI_API_KEY')

const redisUrl = Deno.env.get('REDIS_URL')
const redisToken = Deno.env.get('REDIS_TOKEN')

if (!redisUrl || !redisToken) { throw new Error('missing redis credentials') }

const redis = new Redis({
url: redisUrl,
token: redisToken,
})

const openai = new OpenAI({
apiKey: apiKey
})

const validatedMessages = data.messages.filter((message: { role: string, content: string }) => {
return message.content.length < 500
})

const messages = [{
role: 'system',
content: `
The current options are ${JSON.stringify(data.currentOpts)}.
Please be kind and concise. Keep responses to <100 words.
`.trim()
}, ...validatedMessages]

const response = await openai.chat.completions.create({
model: 'gpt-4-1106-preview',
messages,
functions: [
erc20Function, erc721Function, erc1155Function, governorFunction, customFunction
],
temperature: 0.7,
stream: true
})

const stream = OpenAIStream(response, {
async onCompletion(completion) {
const id = data.chatId
const updatedAt = Date.now()
const payload = {
id,
updatedAt,
messages: [
...messages,
{
content: completion,
role: 'assistant'
}
]
}
const exists = await redis.exists(`chat:${id}`)
if (!exists) {
// @ts-ignore redis types seem to require [key: string]
payload.createdAt = updatedAt
}
await redis.hset(`chat:${id}`, payload)
}
});
return new StreamingTextResponse(stream);

} catch (e) {
return Response.json({
error: 'Could not retrieve results.'
})
}
}
2 changes: 1 addition & 1 deletion packages/ui/public/cairo.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
</div>

<footer>
<p>© <a href="https://openzeppelin.com" target="_blank" rel="noopener noreferrer">OpenZeppelin</a> 2022 |&nbsp;<a href="https://openzeppelin.com/privacy" target="_blank" rel="noopener noreferrer">Privacy</a> |&nbsp;<a href="https://openzeppelin.com/tos" target="_blank" rel="noopener noreferrer">Terms of Service</a></p>
<p>© <a href="https://openzeppelin.com" target="_blank" rel="noopener noreferrer">OpenZeppelin</a> 2022-2023 |&nbsp;<a href="https://openzeppelin.com/privacy" target="_blank" rel="noopener noreferrer">Privacy</a> |&nbsp;<a href="https://openzeppelin.com/tos" target="_blank" rel="noopener noreferrer">Terms of Service</a></p>
</footer>

<!-- Start of HubSpot Embed Code -->
Expand Down
37 changes: 33 additions & 4 deletions packages/ui/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import Dropdown from './Dropdown.svelte';
import OverflowMenu from './OverflowMenu.svelte';
import Tooltip from './Tooltip.svelte';
import Wiz from './Wiz.svelte';

import type { KindedOptions, Kind, Contract, OptionsErrorMessages } from '@openzeppelin/wizard';
import { ContractBuilder, buildGeneric, printContract, sanitizeKind, OptionsError } from '@openzeppelin/wizard';
Expand All @@ -41,6 +42,8 @@

let contract: Contract = new ContractBuilder('MyToken');

$: functionCall && applyFunctionCall()

$: opts = allOpts[tab];

$: {
Expand Down Expand Up @@ -119,9 +122,36 @@
await postConfig(opts, 'download-foundry', language);
}
};

const nameMap = {
erc20: 'ERC20',
erc721: 'ERC721',
erc1155: 'ERC1155',
governor: 'Governor',
custom: 'Custom',
}

let functionCall: {
name?: string,
opts?: any
} = {}

const applyFunctionCall = () => {
if (functionCall.name) {
const name = functionCall.name as keyof typeof nameMap
tab = sanitizeKind(nameMap[name])

allOpts[tab] = {
...allOpts[tab],
...functionCall.opts
}
}
}
</script>

<div class="container flex flex-col gap-4 p-4">
<Wiz bind:functionCall={functionCall} bind:currentOpts={opts}></Wiz>

<div class="header flex flex-row justify-between">
<div class="tab overflow-hidden">
<OverflowMenu>
Expand Down Expand Up @@ -219,7 +249,7 @@
</div>

<div class="flex flex-row gap-4 grow">
<div class="controls w-64 flex flex-col shrink-0 justify-between">
<div class="controls w-64 flex flex-col shrink-0 justify-between h-[calc(100vh-84px)] overflow-auto">
<div class:hidden={tab !== 'ERC20'}>
<ERC20Controls bind:opts={allOpts.ERC20} />
</div>
Expand All @@ -237,8 +267,8 @@
</div>
</div>

<div class="output flex flex-col grow overflow-auto">
<pre class="flex flex-col grow basis-0 overflow-auto"><code class="hljs grow overflow-auto p-4">{@html highlightedCode}</code></pre>
<div class="output flex flex-col grow overflow-auto h-[calc(100vh-84px)]">
<pre class="flex flex-col grow basis-0 overflow-auto"><code class="hljs grow overflow-auto p-4">{@html highlightedCode}</code></pre>
</div>
</div>
</div>
Expand All @@ -249,7 +279,6 @@
border: 1px solid var(--gray-2);
border-radius: 10px;
min-width: 32rem;
min-height: 53rem;
}

.header {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/CustomControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import UpgradeabilitySection from './UpgradeabilitySection.svelte';
import InfoSection from './InfoSection.svelte';

export const opts: Required<KindedOptions['Custom']> = {
export let opts: Required<KindedOptions['Custom']> = {
kind: 'Custom',
...custom.defaults,
info: { ...infoDefaults }, // create new object since Info is nested
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/ERC1155Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import UpgradeabilitySection from './UpgradeabilitySection.svelte';
import InfoSection from './InfoSection.svelte';

export const opts: Required<KindedOptions['ERC1155']> = {
export let opts: Required<KindedOptions['ERC1155']> = {
kind: 'ERC1155',
...erc1155.defaults,
info: { ...infoDefaults }, // create new object since Info is nested
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/ERC20Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import UpgradeabilitySection from './UpgradeabilitySection.svelte';
import InfoSection from './InfoSection.svelte';

export const opts: Required<KindedOptions['ERC20']> = {
export let opts: Required<KindedOptions['ERC20']> = {
kind: 'ERC20',
...erc20.defaults,
premint: '', // default to empty premint in UI instead of 0
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/ERC721Controls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import UpgradeabilitySection from './UpgradeabilitySection.svelte';
import InfoSection from './InfoSection.svelte';

export const opts: Required<KindedOptions['ERC721']> = {
export let opts: Required<KindedOptions['ERC721']> = {
kind: 'ERC721',
...erc721.defaults,
info: { ...infoDefaults }, // create new object since Info is nested
Expand Down
25 changes: 25 additions & 0 deletions packages/ui/src/ExperimentalTooltip.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import Tooltip from './Tooltip.svelte';

export let link: string | undefined = undefined;
export let align: 'right' | undefined = undefined;
export let placement: 'top' | 'bottom' | 'left' | 'right' = 'right';
</script>

<Tooltip let:trigger interactive placement={placement} theme="light-yellow border" maxWidth="15em">
<div
use:trigger
class="tooltip bg-blue-300 uppercase text-xs font-semibold px-2 py-1 rounded-md text-white hover:bg-blue-400"
class:ml-auto={align === 'right'}
>
ALPHA
</div>

<div slot="content">
<slot></slot>
{#if link}
<br>
<a target="_blank" rel="noopener noreferrer" href={link}>Read more.</a>
{/if}
</div>
</Tooltip>
2 changes: 1 addition & 1 deletion packages/ui/src/GovernorControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

const defaults = governor.defaults;

export const opts: Required<KindedOptions['Governor']> = {
export let opts: Required<KindedOptions['Governor']> = {
kind: 'Governor',
...defaults,
proposalThreshold: '', // default to empty in UI
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/HelpTooltip.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

export let link: string | undefined = undefined;
export let align: 'right' | undefined = undefined;
export let placement: 'top' | 'bottom' | 'left' | 'right' = 'right';
</script>

<Tooltip let:trigger interactive placement="right" theme="light-yellow border" maxWidth="15em">
<Tooltip let:trigger interactive placement={placement} theme="light-yellow border" maxWidth="15em">
<svg
use:trigger
class="tooltip"
Expand Down
Loading
Loading