Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Commit

Permalink
messaging
Browse files Browse the repository at this point in the history
  • Loading branch information
ankushKun committed Apr 15, 2024
1 parent f71def8 commit 48bac44
Show file tree
Hide file tree
Showing 12 changed files with 350 additions and 46 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/nextjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ jobs:
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
# run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
run: "npm install --legacy-peer-deps"
- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Upload artifact
Expand Down
182 changes: 156 additions & 26 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"ansi-to-react": "^6.1.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"next": "14.2.1",
Expand Down
111 changes: 94 additions & 17 deletions src/components/exercise.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
"use client";

import { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
import { Button } from "@/components/ui/button";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import Editor from "@monaco-editor/react";
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
import { connect, createDataItemSigner } from "@permaweb/aoconnect";
import { Separator } from "@/components/ui/separator";
import { Module, Scheduler } from "@/lib/ao";
import { TExerciseData } from "@/types";
import { toast } from "sonner";
import { useRouter } from "next/router";
import Editor from "@monaco-editor/react";
import { connect, createDataItemSigner } from "@permaweb/aoconnect";
import { PlayIcon, ReloadIcon } from "@radix-ui/react-icons";
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Markdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { toast } from "sonner";
import Ansi from "ansi-to-react";

declare global {
interface Window {
Expand All @@ -35,9 +36,56 @@ export default function Exercise({ data }: { data: TExerciseData }) {
const [address, setAddress] = useState("");
const [processId, setProcessId] = useState("");
const [spawning, setSpawning] = useState(false);
const [intrvl, setIntrvl] = useState<any>(0);
const [firstRun, setFirstRun] = useState(true);

const router = useRouter();

useEffect(() => {
if (!processId) return;
if (!window) return;
clearInterval(intrvl);
setIntrvl(
setInterval(async () => {
await connect()
.results({
process: processId,
from: localStorage.getItem("cursor") || "",
sort: "DESC",
limit: 25,
})
.then((r) => {
// console.log("checking inbox", r.edges);
if (r.edges.length > 0) {
r.edges.forEach((e: any) => {
const isPrint = e.node.Output.print;
const d = e.node.Output.data;
// console.log(d);
isPrint &&
localStorage.getItem("cursor") &&
typeof d == "string" &&
toast(
<Ansi className="bg-transparent p-1">
{d.replace("34m", "37m")}
</Ansi>,
);
// if (!isPrint) {
// try {
// const messageData = e.node.Messages[0].Data;
// console.log(messageData);
// } catch {
// console.log("No message data");
// }
// }
});
window && localStorage.setItem("cursor", r.edges[0].cursor);
}
});
}, 2500),
);
return () => clearInterval(intrvl);
}, [processId]);

useEffect(() => {
// console.log(router.query);
setCurrentCode(data.defaultCode);
Expand Down Expand Up @@ -105,6 +153,7 @@ export default function Exercise({ data }: { data: TExerciseData }) {
setRunning(true);
setOutputText("...");

const old_ts = new Date().getTime();
const r = await connect().message({
process: processId,
data: currentCode,
Expand All @@ -117,14 +166,37 @@ export default function Exercise({ data }: { data: TExerciseData }) {
process: processId,
});

console.log(Output.data.output);
setOutputText(Output.data.output);
if (Output.data.output == data.expectedResult) {
setPassed(true);
if (data.checkInbox) {
//check inbox for message output after 5s
setTimeout(async () => {
const r = await connect().message({
process: processId,
data: `json = require('json')
return json.encode(Inbox[#Inbox])`,
signer: createDataItemSigner(window.arweaveWallet),
tags: [{ name: "Action", value: "Eval" }],
});

const { Output } = await connect().result({
message: r,
process: processId,
});

const message = JSON.parse(Output.data.output);
const new_ts = message.Timestamp;
const valid = new_ts - old_ts > 0;
const from = data.fromId == "SELF" ? processId : data.fromId;
console.log(message);
setPassed(
message.Data == data.expectedResult && message.From == from && valid,
);
setRunning(false);
}, 5000);
} else {
setPassed(false);
setPassed(Output.data.output == data.expectedResult);
setRunning(false);
}
setRunning(false);
}

return (
Expand All @@ -145,7 +217,10 @@ export default function Exercise({ data }: { data: TExerciseData }) {
<ResizablePanelGroup direction="horizontal">
<ResizablePanel maxSize={45} minSize={15} className="p-3">
<div className="text-center text-3xl p-4 pb-7">{data.title}</div>
<Markdown className="markdown" remarkPlugins={markdownPlugins}>
<Markdown
className="markdown overflow-scroll max-h-[73vh]"
remarkPlugins={markdownPlugins}
>
{data.content}
</Markdown>
<div className="flex justify-between p-2 items-center">
Expand All @@ -156,6 +231,9 @@ export default function Exercise({ data }: { data: TExerciseData }) {
Previous
</Button>
<Button
disabled={
typeof data.allowNext == "boolean" ? !data.allowNext : !passed
}
variant="outline"
onClick={() => {
const nextable =
Expand Down Expand Up @@ -193,8 +271,7 @@ export default function Exercise({ data }: { data: TExerciseData }) {
<ResizablePanel maxSize={70} className="p-3">
<div className="flex justify-between">
<div>
Output{" "}
{outputText != "..." ? <>{passed ? "✅" : "❌"}</> : null}{" "}
Output {!running ? <>{passed ? "✅" : "❌"}</> : null}{" "}
</div>
<Button variant="ghost" disabled={running} onClick={runCode}>
{running ? (
Expand Down
3 changes: 3 additions & 0 deletions src/data/1.connect-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ In your first exercise, you will be connecting your wallet to this web applicati
This will allow you to interact with the blockchain and perform various tasks.
---
# TASK
Your task is to click on the Connect button on the top right of your screen,
this will open a popup of the ArConnect wallet, where you need to type your
password and allow the wallet to connect to this page.
---
`,
defaultCode: `-- You will be writing lua code here soon ;)`,
expectedResult: ``,
Expand Down
3 changes: 3 additions & 0 deletions src/data/2.spawn-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ All the lua code that you write will be executed on your process.
Processes can interact with each other by sending messages, which we will try out in upcoming exercises
---
# TASK
Your task is to click on the spawn process button on the top and wait for a process id to show up
Once the process id appears, you may move to the next exercise
---
`,
defaultCode: `-- You will be writing lua code here soon ;)`,
expectedResult: ``,
Expand Down
6 changes: 5 additions & 1 deletion src/data/3.hello-ao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ export default {
In the previous exercise, you spawned a process. Now it's time to write some code for it.
---
# TASK
Your goal is to modify the lua code from \`print("Hello World")\` to \`print("Hello AO!")\` and run it.`,
Your goal is to modify the lua code from \`print("Hello World")\` to \`print("Hello AO!")\` and run it.
---
`,
defaultCode: `--change this
print("Hello World")`,
expectedResult: "Hello AO!",
Expand Down
5 changes: 4 additions & 1 deletion src/data/4.calculate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default {
content: `
Just like we printed something before, we can also do mathematical operations on AO using LUA
---
# TASK
Your task is to find out the solution of the following equation:
Expand All @@ -14,10 +15,12 @@ Your task is to find out the solution of the following equation:
(6×7)−(12÷2)+(9×2)-12
~~~
---
Hint: Just type this expression with code compatible characters
`,
defaultCode: "1+1",
expectedResult: `42`,
nextRoute: "#",
nextRoute: "5-messaging",
prevRoute: "3-hello-ao",
} as TExerciseData;
34 changes: 34 additions & 0 deletions src/data/5.variables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TExerciseData } from "@/types";

export default {
route: "5-variables",
title: "Variables 📦",
content: `
Variables are used to store data that can be used later in the program.
To declare a variable, you need to use the \`=\` operator. The \`=\` operator assigns a value to a variable.
- **Name**: The Name is the name of the variable.
Here is an example of how to declare a variable:
~~~
Name = "Melon Musk"
~~~
In this example, the variable Name is assigned the value "Melon Musk".
---
# TASK
Your task is to fix the variable Name so that it contains the correct name "Elon Musk" and then print it
---
`,
defaultCode: `Name = "Melon Musk"
return Name`,
expectedResult: `Elon Musk`,
nextRoute: "6-messaging",
prevRoute: "4-calculate",
} as TExerciseData;
44 changes: 44 additions & 0 deletions src/data/6.messaging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { TExerciseData } from "@/types";

export default {
route: "6-messaging",
title: "Sending Messages 💬",
content: `
Now that you know how to print stuff, do basic calculations and make variables,
let's move on to the next step. In this exercise, you will learn how to send messages to a process.
To send a message, you need to use the \`Send\` function. The \`Send\` function takes a table containing data for whom and what to send.
- **Send**: The Send function is globally available in the aos interactive environment.
- **Target**: The Target field is a string containing the process ID of the process you want to send the message to.
- **Data**: The Data is the text message you want received by the receiving process. In this example, the message is "Hello World!".
Here is an example of how to send a message to a process:
~~~
Send({ Target = "process ID", Data = "Hello World!" })
~~~
---
# TASK
Your task is to send a message to yourself with the text "Hello World!".
Your own process ID is stored in the global variable \`ao.id\`.
You can either copy and paste the process ID as a string or use the global variable \`ao.id\` in Target.
---
`,
defaultCode: `Send({
Target = "process ID",
Data = "Hello World!"
})`,
expectedResult: `Hello World!`,
checkInbox: true,
fromId: "SELF",
nextRoute: "#",
prevRoute: "4-calculate",
} as TExerciseData;
2 changes: 2 additions & 0 deletions src/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export default {
"2-spawn-process": require("@/data/2.spawn-process").default,
"3-hello-ao": require("@/data/3.hello-ao").default,
"4-calculate": require("@/data/4.calculate").default,
"5-variables": require("@/data/5.variables").default,
"6-messaging": require("@/data/6.messaging").default,
} as { [foo: string]: TExerciseData };
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export interface TExerciseData {
defaultCode: string;
expectedResult: string;
allowNext?: boolean;
checkInbox?: boolean;
fromId: "SELF" | string;
}

0 comments on commit 48bac44

Please sign in to comment.