From 90ae1a1cb28cd2fd9df3cba92d6ccc589f591682 Mon Sep 17 00:00:00 2001 From: "zapaz.eth" Date: Sun, 27 Oct 2024 11:41:23 +0100 Subject: [PATCH 01/16] optimize Svelte5 write contract --- .vscode/settings.json | 8 +++ .../src/lib/onchain-ai/components/Chat.svelte | 2 +- .../src/lib/onchain-ai/components/Form.svelte | 33 +++--------- ...vents.svelte.ts => interactions.svelte.ts} | 0 .../src/lib/onchain-ai/runes/write.svelte.ts | 50 +++++++++++++++++++ svelte5/src/routes/events/+page.svelte | 2 +- svelte5/turbo.json | 2 +- 7 files changed, 69 insertions(+), 28 deletions(-) rename svelte5/src/lib/onchain-ai/runes/{events.svelte.ts => interactions.svelte.ts} (100%) create mode 100644 svelte5/src/lib/onchain-ai/runes/write.svelte.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 57d7631..df7afd0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,6 +17,14 @@ { "filePath": "svelte5/src/lib/onchain-ai/components/Events.svelte", "group": "Default" + }, + { + "filePath": "svelte5/src/lib/onchain-ai", + "group": "Default" + }, + { + "filePath": "svelte5/src/routes/+page.svelte", + "group": "Default" } ] } diff --git a/svelte5/src/lib/onchain-ai/components/Chat.svelte b/svelte5/src/lib/onchain-ai/components/Chat.svelte index 4a151d3..cf67ded 100644 --- a/svelte5/src/lib/onchain-ai/components/Chat.svelte +++ b/svelte5/src/lib/onchain-ai/components/Chat.svelte @@ -1,6 +1,6 @@ diff --git a/svelte5/src/lib/onchain-ai/runes/events.svelte.ts b/svelte5/src/lib/onchain-ai/runes/interactions.svelte.ts similarity index 100% rename from svelte5/src/lib/onchain-ai/runes/events.svelte.ts rename to svelte5/src/lib/onchain-ai/runes/interactions.svelte.ts diff --git a/svelte5/src/lib/onchain-ai/runes/write.svelte.ts b/svelte5/src/lib/onchain-ai/runes/write.svelte.ts new file mode 100644 index 0000000..a554ba6 --- /dev/null +++ b/svelte5/src/lib/onchain-ai/runes/write.svelte.ts @@ -0,0 +1,50 @@ +import { createWriteContract } from "wagmi-svelte"; +import { createOnchainAI } from "./contract.svelte"; +import { createTransactor, type TransactionFunc } from "$lib/runes/transactor.svelte"; + +const createOnchainAIWrite = ({ + functionName, + args = [], + value = 0n +}: { + functionName: string; + args?: string[]; + value?: bigint; +}) => { + const lastResponse: string | undefined = $state(); + + let lastTxHash: string | undefined = $state(); + + const { chainId, address, abi } = $derived.by(createOnchainAI); + + let contractWrite = $derived.by(createWriteContract()); + let writeTx: TransactionFunc = $derived.by(createTransactor()); + + const send = async () => { + try { + const makeWriteWithParams = () => + contractWrite.writeContractAsync({ + chainId, + address, + abi, + functionName, + args, + value + }); + lastTxHash = await writeTx?.(makeWriteWithParams); + } catch (e: unknown) { + console.error("⚡️ send ~ error", e); + } + + return lastTxHash; + }; + + return { + get lastTxHash() { + return lastTxHash; + }, + send + }; +}; + +export { createOnchainAIWrite }; diff --git a/svelte5/src/routes/events/+page.svelte b/svelte5/src/routes/events/+page.svelte index 08015e4..6eb49dc 100644 --- a/svelte5/src/routes/events/+page.svelte +++ b/svelte5/src/routes/events/+page.svelte @@ -1,6 +1,6 @@ {#if interactionsCount != 0} -
+
{#each interactions as interaction} -
+
{interaction.prompt}
-
+
{#if interaction.response} {interaction.response} {:else} @@ -33,10 +30,6 @@
{/each}
- -
- -
{/if} diff --git a/svelte5/src/lib/onchain-ai/components/Interaction.svelte b/svelte5/src/lib/onchain-ai/components/Interaction.svelte new file mode 100644 index 0000000..3a53dec --- /dev/null +++ b/svelte5/src/lib/onchain-ai/components/Interaction.svelte @@ -0,0 +1,43 @@ + + +{#if interaction} +
+ {interaction.prompt} +
+
+ {#if interaction.response} + {interaction.response} + {:else} +
...
+ {/if} +
+ +
+ +
+{/if} + + diff --git a/svelte5/src/lib/onchain-ai/components/LastInteraction.svelte b/svelte5/src/lib/onchain-ai/components/LastInteraction.svelte new file mode 100644 index 0000000..2087eb7 --- /dev/null +++ b/svelte5/src/lib/onchain-ai/components/LastInteraction.svelte @@ -0,0 +1,15 @@ + + +
+ +
diff --git a/svelte5/src/lib/onchain-ai/components/index.ts b/svelte5/src/lib/onchain-ai/components/index.ts index 5fcab20..7a19b4e 100644 --- a/svelte5/src/lib/onchain-ai/components/index.ts +++ b/svelte5/src/lib/onchain-ai/components/index.ts @@ -1,3 +1,5 @@ export { default as Chat } from "./Chat.svelte"; export { default as Explorer } from "./Explorer.svelte"; export { default as Form } from "./Form.svelte"; +export { default as Interaction } from "./Interaction.svelte"; +export { default as LastInteraction } from "./LastInteraction.svelte"; diff --git a/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts b/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts index a8f00ea..d710f58 100644 --- a/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts +++ b/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts @@ -7,18 +7,20 @@ import { createPublicClient, createAccount } from "$lib/wagmi/runes"; const createOnchainAI = () => { const client = $derived.by(createPublicClient()); - const { targetNetworkId } = $derived.by(createTargetNetworkId); - const { address, abi } = $derived(readDeployments(targetNetworkId)?.OnChainAIv1); + const { targetNetworkId: chainId } = $derived.by(createTargetNetworkId); + const { address, abi } = $derived(readDeployments(chainId)?.OnChainAIv1); const { account } = $derived(createAccount()); const { address: acountAddress } = $derived(account); - const config = $derived(readConfig(targetNetworkId)); + const config = $derived(readConfig(chainId)); + // $inspect("createOnchainAI chainId", chainId) + return { get client() { return client; }, get chainId() { - return targetNetworkId; + return chainId; }, get address() { return address as Address; diff --git a/svelte5/src/lib/onchain-ai/runes/index.ts b/svelte5/src/lib/onchain-ai/runes/index.ts index bfc52f4..1072371 100644 --- a/svelte5/src/lib/onchain-ai/runes/index.ts +++ b/svelte5/src/lib/onchain-ai/runes/index.ts @@ -1,4 +1,5 @@ export * from "./contract.svelte"; export * from "./interactions.svelte"; +export * from "./lastInteraction.svelte"; export * from "./read.svelte"; export * from "./write.svelte"; diff --git a/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts b/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts new file mode 100644 index 0000000..b025085 --- /dev/null +++ b/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts @@ -0,0 +1,34 @@ +import type { Address } from "viem"; +import { createReadOnchainAI } from "$lib/onchain-ai/runes"; +import type { InteractionType, InteractionTypeTuple } from "$lib/onchain-ai/ts"; +import { createBlockNumber } from "$lib/wagmi/runes"; + +const createLastInteraction = (account: Address) => { + const { blockNumber } = $derived(createBlockNumber()); + $effect(() => { + blockNumber; + fetch && fetch(); + }) + + const { data: interactionTuple, fetch } = $derived.by(() => { + if (!account) return { data: null, fetch: null }; + + return createReadOnchainAI({ functionName: "lastInteraction", args: [account] }); + }); + + + const lastInteraction = $derived.by(() => { + if (!interactionTuple) return null; + + + const [requestId, sender, prompt, response] = interactionTuple as InteractionTypeTuple; + return { requestId, sender, prompt, response }; + + }) as InteractionType | null; + + return { + get lastInteraction() { return lastInteraction; } + }; +}; + +export { createLastInteraction }; diff --git a/svelte5/src/lib/onchain-ai/ts/types.ts b/svelte5/src/lib/onchain-ai/ts/types.ts index 4e0cddd..31bd61b 100644 --- a/svelte5/src/lib/onchain-ai/ts/types.ts +++ b/svelte5/src/lib/onchain-ai/ts/types.ts @@ -1,27 +1,15 @@ import type { Address, Log } from "viem"; -type EntriesToObject = { - [K in E[number] as K[0]]: K[1]; +type InteractionTypeTuple = [string, Address, string, string] +type InteractionType = { + requestId: string, + sender: Address, + prompt: string, + response: string, + isResponse?: boolean }; -type EntriesToTuple = { - [I in keyof E]: E[I][1]; -} extends infer U - ? { [K in keyof U]: U[K] } - : never; - -type InteractionTypeOrdered = [ - ["requestId", string], - ["sender", Address], - ["isResponse", boolean], - ["prompt", string], - ["response", string] -]; -type InteractionType = EntriesToObject; -type InteractionTypeTuple = EntriesToTuple; - type InteractionLogWithArgs = Log & { args: InteractionType; index: number }; - type InteractionLogsParamsType = { address: Address; abi: any; diff --git a/svelte5/src/lib/wagmi/runes/blocks.svelte.ts b/svelte5/src/lib/wagmi/runes/blocks.svelte.ts index 419479f..28129f6 100644 --- a/svelte5/src/lib/wagmi/runes/blocks.svelte.ts +++ b/svelte5/src/lib/wagmi/runes/blocks.svelte.ts @@ -2,8 +2,8 @@ import { getBlockNumber, watchBlockNumber } from "@wagmi/core"; import { createConfig } from "./config.svelte"; import { createTargetNetworkId } from "$lib/scaffold-eth/runes/global.svelte"; -const createBlockNumber = (params: { chainId?: number; watch?: boolean }) => { - let { chainId, watch } = params; +const createBlockNumber = (params?: { chainId?: number; watch?: boolean }) => { + let { chainId, watch } = params || {} watch ??= true; const config = $derived.by(createConfig()); @@ -20,7 +20,7 @@ const createBlockNumber = (params: { chainId?: number; watch?: boolean }) => { }; fetch(); - let unwatch = (): void => {}; + let unwatch = (): void => { }; $effect(() => { unwatch(); unwatch = watchBlockNumber(config, { diff --git a/svelte5/src/lib/wagmi/runes/read.svelte.ts b/svelte5/src/lib/wagmi/runes/read.svelte.ts index 96b75a6..981b0f7 100644 --- a/svelte5/src/lib/wagmi/runes/read.svelte.ts +++ b/svelte5/src/lib/wagmi/runes/read.svelte.ts @@ -36,7 +36,9 @@ const createReadContract = ({ isFetching = true; try { - data = await readContract(config, { address, abi, functionName, args }); + const newData = await readContract(config, { address, abi, functionName, args }); + if (JSON.stringify($state.snapshot(data)) == JSON.stringify(newData)) return; + data = newData; } catch (e: unknown) { console.error("createReadContract ERROR", e); } @@ -46,7 +48,7 @@ const createReadContract = ({ }; if (onStart) fetch(); - $inspect("createReadContract", { address, abi, functionName, args }); + // $inspect("createReadContract data", data); return { fetch, get isFetching() { diff --git a/svelte5/src/routes/tests/last/+page.svelte b/svelte5/src/routes/tests/last/+page.svelte index 623f941..1e7fbf6 100644 --- a/svelte5/src/routes/tests/last/+page.svelte +++ b/svelte5/src/routes/tests/last/+page.svelte @@ -1,19 +1,9 @@ -
- {#if lastInteraction} - `{lastInteraction.prompt}` => `{lastInteraction.response}` - {/if} -
+ From ed071887d176f740f469b830a81faae75fae673a Mon Sep 17 00:00:00 2001 From: "zapaz.eth" Date: Mon, 4 Nov 2024 15:44:00 +0100 Subject: [PATCH 16/16] deployments of final V1 version --- foundry/addresses.json | 4 ++-- pnpm-lock.yaml | 10 +++++----- svelte5/package.json | 2 +- svelte5/src/lib/deployments.json | 4 ++-- svelte5/src/lib/onchain-ai/components/Chat.svelte | 2 -- svelte5/src/lib/onchain-ai/runes/contract.svelte.ts | 2 +- .../lib/onchain-ai/runes/lastInteraction.svelte.ts | 9 ++++----- svelte5/src/lib/onchain-ai/ts/types.ts | 12 ++++++------ svelte5/src/lib/scaffold.config.ts | 2 +- svelte5/src/lib/wagmi/runes/blocks.svelte.ts | 4 ++-- svelte5/src/lib/wagmi/runes/read.svelte.ts | 5 ++--- svelte5/src/routes/tests/+page.svelte | 1 - 12 files changed, 26 insertions(+), 31 deletions(-) diff --git a/foundry/addresses.json b/foundry/addresses.json index 6898a36..c26ab1f 100644 --- a/foundry/addresses.json +++ b/foundry/addresses.json @@ -2,7 +2,7 @@ "11155420": { "Counter": "0x8354Ef7b78012151c276f51F8d19147FF8C47288", "OnChainAI": "0xd1ca741de2d2975822ADf4646Cf0A8AE3Df51c78", - "OnChainAIv1": "0xa043949B6984D8704501EC64519E2b6e00a4329A", + "OnChainAIv1": "0x879ae6BC9a6173A14111FE204ec0E14DCB619e9E", "chainName": "optimism-sepolia" }, "31337": { @@ -13,7 +13,7 @@ }, "8453": { "OnChainAI": "0xd798E6E526d7893e4F7aCED9F56DF69643bCf1B6", - "OnChainAIv1": "0x1F4666E268Ec7F1Fc46C467A8CdAF6b01f88B935", + "OnChainAIv1": "0x5095f726C40D0AE7360c6307B7cE57620ae8594c", "chainName": "base" }, "84532": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ca2792..1c6ca93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -156,8 +156,8 @@ importers: specifier: ^2.46.0 version: 2.46.0(eslint@9.14.0(jiti@2.4.0))(svelte@5.1.9)(ts-node@10.9.2(@types/node@22.8.7)(typescript@5.6.3)) globals: - specifier: ^15.11.0 - version: 15.11.0 + specifier: ^15.12.0 + version: 15.12.0 postcss: specifier: ^8.4.47 version: 8.4.47 @@ -3820,8 +3820,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.11.0: - resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==} + globals@15.12.0: + resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} engines: {node: '>=18'} globalyzer@0.1.0: @@ -11730,7 +11730,7 @@ snapshots: globals@14.0.0: {} - globals@15.11.0: {} + globals@15.12.0: {} globalyzer@0.1.0: {} diff --git a/svelte5/package.json b/svelte5/package.json index fb4b3a1..3a98ec8 100644 --- a/svelte5/package.json +++ b/svelte5/package.json @@ -29,7 +29,7 @@ "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.46.0", - "globals": "^15.11.0", + "globals": "^15.12.0", "postcss": "^8.4.47", "postcss-load-config": "^6.0.1", "prettier": "^3.3.3", diff --git a/svelte5/src/lib/deployments.json b/svelte5/src/lib/deployments.json index e707879..4107238 100644 --- a/svelte5/src/lib/deployments.json +++ b/svelte5/src/lib/deployments.json @@ -1,7 +1,7 @@ { "8453": { "OnChainAIv1": { - "address": "0x1F4666E268Ec7F1Fc46C467A8CdAF6b01f88B935", + "address": "0x5095f726C40D0AE7360c6307B7cE57620ae8594c", "abi": [ { "type": "constructor", @@ -1495,7 +1495,7 @@ ] }, "OnChainAIv1": { - "address": "0xa043949B6984D8704501EC64519E2b6e00a4329A", + "address": "0x879ae6BC9a6173A14111FE204ec0E14DCB619e9E", "abi": [ { "type": "constructor", diff --git a/svelte5/src/lib/onchain-ai/components/Chat.svelte b/svelte5/src/lib/onchain-ai/components/Chat.svelte index 63bff3f..2a7f91a 100644 --- a/svelte5/src/lib/onchain-ai/components/Chat.svelte +++ b/svelte5/src/lib/onchain-ai/components/Chat.svelte @@ -49,5 +49,3 @@
{interactionsCount}/{interactionsMax}
- - diff --git a/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts b/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts index d710f58..0b25217 100644 --- a/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts +++ b/svelte5/src/lib/onchain-ai/runes/contract.svelte.ts @@ -14,7 +14,7 @@ const createOnchainAI = () => { const config = $derived(readConfig(chainId)); // $inspect("createOnchainAI chainId", chainId) - + return { get client() { return client; diff --git a/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts b/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts index b025085..aa5fc4d 100644 --- a/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts +++ b/svelte5/src/lib/onchain-ai/runes/lastInteraction.svelte.ts @@ -8,7 +8,7 @@ const createLastInteraction = (account: Address) => { $effect(() => { blockNumber; fetch && fetch(); - }) + }); const { data: interactionTuple, fetch } = $derived.by(() => { if (!account) return { data: null, fetch: null }; @@ -16,18 +16,17 @@ const createLastInteraction = (account: Address) => { return createReadOnchainAI({ functionName: "lastInteraction", args: [account] }); }); - const lastInteraction = $derived.by(() => { if (!interactionTuple) return null; - const [requestId, sender, prompt, response] = interactionTuple as InteractionTypeTuple; return { requestId, sender, prompt, response }; - }) as InteractionType | null; return { - get lastInteraction() { return lastInteraction; } + get lastInteraction() { + return lastInteraction; + } }; }; diff --git a/svelte5/src/lib/onchain-ai/ts/types.ts b/svelte5/src/lib/onchain-ai/ts/types.ts index 31bd61b..cc8de91 100644 --- a/svelte5/src/lib/onchain-ai/ts/types.ts +++ b/svelte5/src/lib/onchain-ai/ts/types.ts @@ -1,12 +1,12 @@ import type { Address, Log } from "viem"; -type InteractionTypeTuple = [string, Address, string, string] +type InteractionTypeTuple = [string, Address, string, string]; type InteractionType = { - requestId: string, - sender: Address, - prompt: string, - response: string, - isResponse?: boolean + requestId: string; + sender: Address; + prompt: string; + response: string; + isResponse?: boolean; }; type InteractionLogWithArgs = Log & { args: InteractionType; index: number }; diff --git a/svelte5/src/lib/scaffold.config.ts b/svelte5/src/lib/scaffold.config.ts index 1a475c5..1dd627b 100644 --- a/svelte5/src/lib/scaffold.config.ts +++ b/svelte5/src/lib/scaffold.config.ts @@ -17,7 +17,7 @@ const { PUBLIC_ALCHEMY_API_KEY, PUBLIC_WALLET_CONNECT_PROJECT_ID } = env as { const scaffoldConfig = { // The networks on which your DApp is live - targetNetworks: [chains.baseSepolia, chains.anvil, chains.optimismSepolia, chains.base], + targetNetworks: [chains.base, chains.baseSepolia, chains.optimismSepolia, chains.anvil], // The interval at which your front-end polls the RPC servers for new data // it has no effect if you only target the local network (default is 4000) diff --git a/svelte5/src/lib/wagmi/runes/blocks.svelte.ts b/svelte5/src/lib/wagmi/runes/blocks.svelte.ts index 28129f6..e2e1fde 100644 --- a/svelte5/src/lib/wagmi/runes/blocks.svelte.ts +++ b/svelte5/src/lib/wagmi/runes/blocks.svelte.ts @@ -3,7 +3,7 @@ import { createConfig } from "./config.svelte"; import { createTargetNetworkId } from "$lib/scaffold-eth/runes/global.svelte"; const createBlockNumber = (params?: { chainId?: number; watch?: boolean }) => { - let { chainId, watch } = params || {} + let { chainId, watch } = params || {}; watch ??= true; const config = $derived.by(createConfig()); @@ -20,7 +20,7 @@ const createBlockNumber = (params?: { chainId?: number; watch?: boolean }) => { }; fetch(); - let unwatch = (): void => { }; + let unwatch = (): void => {}; $effect(() => { unwatch(); unwatch = watchBlockNumber(config, { diff --git a/svelte5/src/lib/wagmi/runes/read.svelte.ts b/svelte5/src/lib/wagmi/runes/read.svelte.ts index 981b0f7..25576ad 100644 --- a/svelte5/src/lib/wagmi/runes/read.svelte.ts +++ b/svelte5/src/lib/wagmi/runes/read.svelte.ts @@ -1,6 +1,6 @@ import type { Abi, AbiFunction, AbiParameter } from "abitype"; import type { Address } from "viem"; -import { type ReadContractReturnType, readContract } from "@wagmi/core"; +import { type ReadContractReturnType, readContract, deepEqual } from "@wagmi/core"; import { createConfig } from "$lib/wagmi/runes"; const createReadContract = ({ @@ -37,8 +37,7 @@ const createReadContract = ({ try { const newData = await readContract(config, { address, abi, functionName, args }); - if (JSON.stringify($state.snapshot(data)) == JSON.stringify(newData)) return; - data = newData; + if (!deepEqual($state.snapshot(data), newData)) data = newData; } catch (e: unknown) { console.error("createReadContract ERROR", e); } diff --git a/svelte5/src/routes/tests/+page.svelte b/svelte5/src/routes/tests/+page.svelte index 3397ea6..f12994d 100644 --- a/svelte5/src/routes/tests/+page.svelte +++ b/svelte5/src/routes/tests/+page.svelte @@ -2,7 +2,6 @@

Tests