Compare commits
15 Commits
feat/add-l
...
feat/templ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
027b2c8ed4 | ||
|
|
b4ca360661 | ||
|
|
ad947be0bc | ||
|
|
f739d4da34 | ||
|
|
fdb1eb01a4 | ||
|
|
920d359966 | ||
|
|
9e1dbc8765 | ||
|
|
10ea77fd8d | ||
|
|
50de7ebf15 | ||
|
|
7db07e3f92 | ||
|
|
6ad7c67672 | ||
|
|
10f279a6b4 | ||
|
|
792c093cfd | ||
|
|
a11a641608 | ||
|
|
8ac7e82221 |
@@ -70,7 +70,7 @@ const StyledTitle = styled(DialogPrimitive.Title, {
|
||||
});
|
||||
|
||||
const StyledDescription = styled(DialogPrimitive.Description, {
|
||||
margin: "10px 0 20px",
|
||||
margin: "10px 0 10px",
|
||||
color: "$mauve11",
|
||||
fontSize: 15,
|
||||
lineHeight: 1.5,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import {
|
||||
Plus,
|
||||
Share,
|
||||
@@ -26,11 +26,7 @@ import NewWindow from "react-new-window";
|
||||
import { signOut, useSession } from "next-auth/react";
|
||||
import { useSnapshot } from "valtio";
|
||||
|
||||
import {
|
||||
createNewFile,
|
||||
syncToGist,
|
||||
updateEditorSettings,
|
||||
} from "../state/actions";
|
||||
import { createNewFile, syncToGist, updateEditorSettings, downloadAsZip } from "../state/actions";
|
||||
import state from "../state";
|
||||
import Box from "./Box";
|
||||
import Button from "./Button";
|
||||
@@ -46,6 +42,7 @@ import {
|
||||
import Flex from "./Flex";
|
||||
import Stack from "./Stack";
|
||||
import Input from "./Input";
|
||||
import Text from "./Text";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
AlertDialog,
|
||||
@@ -55,11 +52,22 @@ import {
|
||||
AlertDialogCancel,
|
||||
AlertDialogAction,
|
||||
} from "./AlertDialog";
|
||||
import { styled } from "../stitches.config";
|
||||
|
||||
const DEFAULT_EXTENSION = ".c";
|
||||
|
||||
const ErrorText = styled(Text, {
|
||||
color: "$red9",
|
||||
mt: "$1",
|
||||
display: "block",
|
||||
});
|
||||
|
||||
const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
const snap = useSnapshot(state);
|
||||
const [createNewAlertOpen, setCreateNewAlertOpen] = useState(false);
|
||||
const [editorSettingsOpen, setEditorSettingsOpen] = useState(false);
|
||||
const [isNewfileDialogOpen, setIsNewfileDialogOpen] = useState(false);
|
||||
const [newfileError, setNewfileError] = useState<string | null>(null);
|
||||
const [filename, setFilename] = useState("");
|
||||
const { data: session, status } = useSession();
|
||||
const [popup, setPopUp] = useState(false);
|
||||
@@ -69,6 +77,36 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
setPopUp(false);
|
||||
}
|
||||
}, [session, popup]);
|
||||
|
||||
// when filename changes, reset error
|
||||
useEffect(() => {
|
||||
setNewfileError(null);
|
||||
}, [filename, setNewfileError]);
|
||||
|
||||
const validateFilename = useCallback(
|
||||
(filename: string): { error: string | null } => {
|
||||
if (snap.files.find(file => file.name === filename)) {
|
||||
return { error: "Filename already exists." };
|
||||
}
|
||||
// More checks in future
|
||||
return { error: null };
|
||||
},
|
||||
[snap.files]
|
||||
);
|
||||
const handleConfirm = useCallback(() => {
|
||||
// add default extension in case omitted
|
||||
let _filename = filename.includes(".") ? filename : filename + DEFAULT_EXTENSION;
|
||||
const chk = validateFilename(_filename);
|
||||
if (chk.error) {
|
||||
setNewfileError(`Error: ${chk.error}`);
|
||||
return;
|
||||
}
|
||||
|
||||
setIsNewfileDialogOpen(false);
|
||||
createNewFile(_filename);
|
||||
setFilename("");
|
||||
}, [filename, setIsNewfileDialogOpen, setFilename, validateFilename]);
|
||||
|
||||
const files = snap.files;
|
||||
return (
|
||||
<Flex css={{ flexShrink: 0, gap: "$0" }}>
|
||||
@@ -101,9 +139,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
return (
|
||||
<Button
|
||||
size="sm"
|
||||
outline={
|
||||
showWat ? snap.activeWat !== index : snap.active !== index
|
||||
}
|
||||
outline={showWat ? snap.activeWat !== index : snap.active !== index}
|
||||
onClick={() => (state.active = index)}
|
||||
key={file.name + index}
|
||||
css={{
|
||||
@@ -138,8 +174,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
// If deleted file is behind active tab
|
||||
// we keep the current state otherwise
|
||||
// select previous file on the list
|
||||
state.active =
|
||||
index > snap.active ? snap.active : snap.active - 1;
|
||||
state.active = index > snap.active ? snap.active : snap.active - 1;
|
||||
}}
|
||||
>
|
||||
<X size="9px" weight="bold" />
|
||||
@@ -149,15 +184,10 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
);
|
||||
})}
|
||||
{!showWat && (
|
||||
<Dialog>
|
||||
<Dialog open={isNewfileDialogOpen} onOpenChange={setIsNewfileDialogOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
ghost
|
||||
size="sm"
|
||||
css={{ alignItems: "center", px: "$2", mr: "$3" }}
|
||||
>
|
||||
<Plus size="16px" />{" "}
|
||||
{snap.files.length === 0 && "Add new file"}
|
||||
<Button ghost size="sm" css={{ alignItems: "center", px: "$2", mr: "$3" }}>
|
||||
<Plus size="16px" /> {snap.files.length === 0 && "Add new file"}
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
@@ -166,8 +196,14 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
<label>Filename</label>
|
||||
<Input
|
||||
value={filename}
|
||||
onChange={(e) => setFilename(e.target.value)}
|
||||
onChange={e => setFilename(e.target.value)}
|
||||
onKeyPress={e => {
|
||||
if (e.key === "Enter") {
|
||||
handleConfirm();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ErrorText>{newfileError}</ErrorText>
|
||||
</DialogDescription>
|
||||
|
||||
<Flex
|
||||
@@ -180,18 +216,12 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
<DialogClose asChild>
|
||||
<Button outline>Cancel</Button>
|
||||
</DialogClose>
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
createNewFile(filename);
|
||||
// reset
|
||||
setFilename("");
|
||||
}}
|
||||
>
|
||||
Create file
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={handleConfirm}
|
||||
>
|
||||
Create file
|
||||
</Button>
|
||||
</Flex>
|
||||
<DialogClose asChild>
|
||||
<Box css={{ position: "absolute", top: "$3", right: "$3" }}>
|
||||
@@ -211,9 +241,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
<Container
|
||||
css={{ width: "unset", display: "flex", alignItems: "center" }}
|
||||
>
|
||||
<Container css={{ width: "unset", display: "flex", alignItems: "center" }}>
|
||||
{status === "authenticated" ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -246,15 +274,10 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem disabled onClick={() => signOut()}>
|
||||
<User size="16px" /> {session?.user?.username} (
|
||||
{session?.user.name})
|
||||
<User size="16px" /> {session?.user?.username} ({session?.user.name})
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() =>
|
||||
window.open(
|
||||
`http://gist.github.com/${session?.user.username}`
|
||||
)
|
||||
}
|
||||
onClick={() => window.open(`http://gist.github.com/${session?.user.username}`)}
|
||||
>
|
||||
<ArrowSquareOut size="16px" />
|
||||
Go to your Gist
|
||||
@@ -268,12 +291,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<Button
|
||||
outline
|
||||
size="sm"
|
||||
css={{ mr: "$3" }}
|
||||
onClick={() => setPopUp(true)}
|
||||
>
|
||||
<Button outline size="sm" css={{ mr: "$3" }} onClick={() => setPopUp(true)}>
|
||||
<GithubLogo size="16px" /> Login
|
||||
</Button>
|
||||
)}
|
||||
@@ -312,7 +330,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Button outline size="sm" css={{ alignItems: "center" }}>
|
||||
<Button isLoading={snap.zipLoading} onClick={downloadAsZip} outline size="sm" css={{ alignItems: "center" }}>
|
||||
<DownloadSimple size="16px" />
|
||||
</Button>
|
||||
<Button
|
||||
@@ -320,9 +338,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
size="sm"
|
||||
css={{ alignItems: "center" }}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
`${window.location.origin}/develop/${snap.gistId}`
|
||||
);
|
||||
navigator.clipboard.writeText(`${window.location.origin}/develop/${snap.gistId}`);
|
||||
toast.success("Copied share link to clipboard!");
|
||||
}}
|
||||
>
|
||||
@@ -352,7 +368,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem>
|
||||
<DropdownMenuItem disabled={snap.zipLoading} onClick={downloadAsZip}>
|
||||
<DownloadSimple size="16px" /> Download as ZIP
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
@@ -367,9 +383,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
Copy share link to clipboard
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
disabled={
|
||||
session?.user.username !== snap.gistOwner || !snap.gistId
|
||||
}
|
||||
disabled={session?.user.username !== snap.gistOwner || !snap.gistId}
|
||||
onClick={() => {
|
||||
syncToGist(session);
|
||||
}}
|
||||
@@ -395,21 +409,15 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
</DropdownMenu>
|
||||
</Stack>
|
||||
|
||||
{popup && !session ? (
|
||||
<NewWindow center="parent" url="/sign-in" />
|
||||
) : null}
|
||||
{popup && !session ? <NewWindow center="parent" url="/sign-in" /> : null}
|
||||
</Container>
|
||||
</Flex>
|
||||
<AlertDialog
|
||||
open={createNewAlertOpen}
|
||||
onOpenChange={(value) => setCreateNewAlertOpen(value)}
|
||||
>
|
||||
<AlertDialog open={createNewAlertOpen} onOpenChange={value => setCreateNewAlertOpen(value)}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action will create new <strong>public</strong> Github Gist from
|
||||
your current saved files. You can delete gist anytime from your
|
||||
GitHub Gists page.
|
||||
This action will create new <strong>public</strong> Github Gist from your current saved
|
||||
files. You can delete gist anytime from your GitHub Gists page.
|
||||
</AlertDialogDescription>
|
||||
<Flex css={{ justifyContent: "flex-end", gap: "$3" }}>
|
||||
<AlertDialogCancel asChild>
|
||||
@@ -443,8 +451,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
type="number"
|
||||
min="1"
|
||||
value={editorSettings.tabSize}
|
||||
onChange={(e) =>
|
||||
setEditorSettings((curr) => ({
|
||||
onChange={e =>
|
||||
setEditorSettings(curr => ({
|
||||
...curr,
|
||||
tabSize: Number(e.target.value),
|
||||
}))
|
||||
@@ -454,18 +462,12 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
|
||||
|
||||
<Flex css={{ marginTop: 25, justifyContent: "flex-end", gap: "$3" }}>
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
outline
|
||||
onClick={() => updateEditorSettings(editorSettings)}
|
||||
>
|
||||
<Button outline onClick={() => updateEditorSettings(editorSettings)}>
|
||||
Cancel
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<DialogClose asChild>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => updateEditorSettings(editorSettings)}
|
||||
>
|
||||
<Button variant="primary" onClick={() => updateEditorSettings(editorSettings)}>
|
||||
Save changes
|
||||
</Button>
|
||||
</DialogClose>
|
||||
|
||||
@@ -11,6 +11,7 @@ import Container from "./Container";
|
||||
import dark from "../theme/editor/amy.json";
|
||||
import light from "../theme/editor/xcode_default.json";
|
||||
import { saveFile } from "../state/actions";
|
||||
import { apiHeaderFiles } from "../state/constants";
|
||||
import state from "../state";
|
||||
|
||||
import EditorNavigation from "./EditorNavigation";
|
||||
@@ -26,12 +27,26 @@ loader.config({
|
||||
},
|
||||
});
|
||||
|
||||
const validateWritability = (editor: monaco.editor.IStandaloneCodeEditor) => {
|
||||
const currPath = editor.getModel()?.uri.path;
|
||||
if (apiHeaderFiles.find(h => currPath?.endsWith(h))) {
|
||||
editor.updateOptions({ readOnly: true });
|
||||
} else {
|
||||
editor.updateOptions({ readOnly: false });
|
||||
}
|
||||
};
|
||||
|
||||
const HooksEditor = () => {
|
||||
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
|
||||
const subscriptionRef = useRef<ReconnectingWebSocket | null>(null);
|
||||
const snap = useSnapshot(state);
|
||||
const router = useRouter();
|
||||
const { theme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
if (editorRef.current) validateWritability(editorRef.current);
|
||||
}, [snap.active]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
subscriptionRef?.current?.close();
|
||||
@@ -58,9 +73,9 @@ const HooksEditor = () => {
|
||||
language={snap.files?.[snap.active]?.language}
|
||||
path={`file://tmp/c/${snap.files?.[snap.active]?.name}`}
|
||||
defaultValue={snap.files?.[snap.active]?.content}
|
||||
beforeMount={(monaco) => {
|
||||
beforeMount={monaco => {
|
||||
if (!snap.editorCtx) {
|
||||
snap.files.forEach((file) =>
|
||||
snap.files.forEach(file =>
|
||||
monaco.editor.createModel(
|
||||
file.content,
|
||||
file.language,
|
||||
@@ -86,7 +101,7 @@ const HooksEditor = () => {
|
||||
// listen when the web socket is opened
|
||||
listen({
|
||||
webSocket: webSocket as WebSocket,
|
||||
onConnection: (connection) => {
|
||||
onConnection: connection => {
|
||||
// create and start the language client
|
||||
const languageClient = createLanguageClient(connection);
|
||||
const disposable = languageClient.start();
|
||||
@@ -125,12 +140,10 @@ const HooksEditor = () => {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
editor.addCommand(
|
||||
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS,
|
||||
() => {
|
||||
saveFile();
|
||||
}
|
||||
);
|
||||
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
|
||||
saveFile();
|
||||
});
|
||||
validateWritability(editor)
|
||||
}}
|
||||
theme={theme === "dark" ? "dark" : "light"}
|
||||
/>
|
||||
@@ -148,9 +161,7 @@ const HooksEditor = () => {
|
||||
<Box css={{ display: "inline-flex", pl: "35px" }}>
|
||||
<ArrowBendLeftUp size={30} />
|
||||
</Box>
|
||||
<Box
|
||||
css={{ pl: "0px", pt: "15px", flex: 1, display: "inline-flex" }}
|
||||
>
|
||||
<Box css={{ pl: "0px", pt: "15px", flex: 1, display: "inline-flex" }}>
|
||||
<Text
|
||||
css={{
|
||||
fontSize: "14px",
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
DialogTrigger,
|
||||
} from "./Dialog";
|
||||
import PanelBox from "./PanelBox";
|
||||
import { templateFileIds } from '../state/constants';
|
||||
|
||||
const Navigation = () => {
|
||||
const router = useRouter();
|
||||
@@ -82,12 +83,8 @@ const Navigation = () => {
|
||||
<Spinner />
|
||||
) : (
|
||||
<>
|
||||
<Heading css={{ lineHeight: 1 }}>
|
||||
{snap.files?.[0]?.name || "XRPL Hooks"}
|
||||
</Heading>
|
||||
<Text
|
||||
css={{ fontSize: "$xs", color: "$mauve10", lineHeight: 1 }}
|
||||
>
|
||||
<Heading css={{ lineHeight: 1 }}>{snap.files?.[0]?.name || "XRPL Hooks"}</Heading>
|
||||
<Text css={{ fontSize: "$xs", color: "$mauve10", lineHeight: 1 }}>
|
||||
{snap.files.length > 0 ? "Gist: " : "Playground"}
|
||||
<Text css={{ color: "$mauve12" }}>
|
||||
{snap.files.length > 0 &&
|
||||
@@ -99,10 +96,7 @@ const Navigation = () => {
|
||||
</Flex>
|
||||
{router.isReady && (
|
||||
<ButtonGroup css={{ marginLeft: "auto" }}>
|
||||
<Dialog
|
||||
open={snap.mainModalOpen}
|
||||
onOpenChange={(open) => (state.mainModalOpen = open)}
|
||||
>
|
||||
<Dialog open={snap.mainModalOpen} onOpenChange={open => (state.mainModalOpen = open)}>
|
||||
<DialogTrigger asChild>
|
||||
<Button outline>
|
||||
<FolderOpen size="15px" />
|
||||
@@ -163,12 +157,9 @@ const Navigation = () => {
|
||||
mb: "$7",
|
||||
}}
|
||||
>
|
||||
Hooks add smart contract functionality to the XRP
|
||||
Ledger.
|
||||
Hooks add smart contract functionality to the XRP Ledger.
|
||||
</Text>
|
||||
<Flex
|
||||
css={{ flexDirection: "column", gap: "$2", mt: "$2" }}
|
||||
>
|
||||
<Flex css={{ flexDirection: "column", gap: "$2", mt: "$2" }}>
|
||||
<Text
|
||||
css={{
|
||||
display: "inline-flex",
|
||||
@@ -253,43 +244,29 @@ const Navigation = () => {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<PanelBox
|
||||
as="a"
|
||||
href="/develop/be088224fb37c0075e84491da0e602c1"
|
||||
>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.starter}`}>
|
||||
<Heading>Starter</Heading>
|
||||
<Text>
|
||||
Just an empty starter with essential imports
|
||||
</Text>
|
||||
<Text>Just an empty starter with essential imports</Text>
|
||||
</PanelBox>
|
||||
<PanelBox
|
||||
as="a"
|
||||
href="/develop/be088224fb37c0075e84491da0e602c1"
|
||||
>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.starter}`}>
|
||||
<Heading>Firewall</Heading>
|
||||
<Text>
|
||||
This Hook essentially checks a blacklist of accounts
|
||||
</Text>
|
||||
<Text>This Hook essentially checks a blacklist of accounts</Text>
|
||||
</PanelBox>
|
||||
<PanelBox
|
||||
as="a"
|
||||
href="/develop/be088224fb37c0075e84491da0e602c1"
|
||||
>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.accept}`}>
|
||||
<Heading>Accept</Heading>
|
||||
<Text>
|
||||
This hook just accepts any transaction coming through
|
||||
it
|
||||
</Text>
|
||||
<Text>This hook just accepts any transaction coming through it</Text>
|
||||
</PanelBox>
|
||||
<PanelBox
|
||||
as="a"
|
||||
href="/develop/be088224fb37c0075e84491da0e602c1"
|
||||
>
|
||||
<Heading>Accept</Heading>
|
||||
<Text>
|
||||
This hook just accepts any transaction coming through
|
||||
it
|
||||
</Text>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.notary}`}>
|
||||
<Heading>Notary</Heading>
|
||||
<Text>Collecting signatures for multi-sign transactions</Text>
|
||||
</PanelBox>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.carbon}`}>
|
||||
<Heading>Carbon</Heading>
|
||||
<Text>Send a percentage of sum to an address</Text>
|
||||
</PanelBox>
|
||||
<PanelBox as="a" href={`/develop/${templateFileIds.peggy}`}>
|
||||
<Heading>Peggy</Heading>
|
||||
<Text>An oracle based stabe coin hook</Text>
|
||||
</PanelBox>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -336,42 +313,18 @@ const Navigation = () => {
|
||||
}}
|
||||
>
|
||||
<ButtonGroup>
|
||||
<Link
|
||||
href={gistId ? `/develop/${gistId}` : "/develop"}
|
||||
passHref
|
||||
shallow
|
||||
>
|
||||
<Button
|
||||
as="a"
|
||||
outline={!router.pathname.includes("/develop")}
|
||||
uppercase
|
||||
>
|
||||
<Link href={gistId ? `/develop/${gistId}` : "/develop"} passHref shallow>
|
||||
<Button as="a" outline={!router.pathname.includes("/develop")} uppercase>
|
||||
Develop
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
href={gistId ? `/deploy/${gistId}` : "/deploy"}
|
||||
passHref
|
||||
shallow
|
||||
>
|
||||
<Button
|
||||
as="a"
|
||||
outline={!router.pathname.includes("/deploy")}
|
||||
uppercase
|
||||
>
|
||||
<Link href={gistId ? `/deploy/${gistId}` : "/deploy"} passHref shallow>
|
||||
<Button as="a" outline={!router.pathname.includes("/deploy")} uppercase>
|
||||
Deploy
|
||||
</Button>
|
||||
</Link>
|
||||
<Link
|
||||
href={gistId ? `/test/${gistId}` : "/test"}
|
||||
passHref
|
||||
shallow
|
||||
>
|
||||
<Button
|
||||
as="a"
|
||||
outline={!router.pathname.includes("/test")}
|
||||
uppercase
|
||||
>
|
||||
<Link href={gistId ? `/test/${gistId}` : "/test"} passHref shallow>
|
||||
<Button as="a" outline={!router.pathname.includes("/test")} uppercase>
|
||||
Test
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
"@radix-ui/react-dropdown-menu": "^0.1.1",
|
||||
"@radix-ui/react-id": "^0.1.1",
|
||||
"@stitches/react": "^1.2.6-0",
|
||||
"file-saver": "^2.0.5",
|
||||
"jszip": "^3.7.1",
|
||||
"base64-js": "^1.5.1",
|
||||
"dinero.js": "^1.9.1",
|
||||
"monaco-editor": "^0.30.1",
|
||||
@@ -45,9 +47,10 @@
|
||||
"vscode-uri": "^3.0.2",
|
||||
"wabt": "1.0.16",
|
||||
"xrpl-accountlib": "^1.2.3",
|
||||
"xrpl-client": "^1.9.2"
|
||||
"xrpl-client": "^1.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/file-saver": "^2.0.4",
|
||||
"@types/dinero.js": "^1.9.0",
|
||||
"@types/pako": "^1.0.2",
|
||||
"@types/react": "17.0.31",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Router from "next/router";
|
||||
import toast from "react-hot-toast";
|
||||
import state, { FaucetAccountRes } from '../index';
|
||||
|
||||
@@ -31,30 +32,35 @@ export const addFaucetAccount = async (showToast: boolean = false) => {
|
||||
if (state.accounts.length > 4) {
|
||||
return toast.error("You can only have maximum 5 accounts");
|
||||
}
|
||||
const toastId = showToast ? toast.loading("Creating account") : "";
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_SITE_URL}/api/faucet`, {
|
||||
method: "POST",
|
||||
});
|
||||
const json: FaucetAccountRes | { error: string } = await res.json();
|
||||
if ("error" in json) {
|
||||
if (showToast) {
|
||||
return toast.error(json.error, { id: toastId });
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (showToast) {
|
||||
toast.success("New account created", { id: toastId });
|
||||
}
|
||||
state.accounts.push({
|
||||
name: names[state.accounts.length],
|
||||
xrp: (json.xrp || 0 * 1000000).toString(),
|
||||
address: json.address,
|
||||
secret: json.secret,
|
||||
sequence: 1,
|
||||
hooks: [],
|
||||
isLoading: false,
|
||||
if (typeof window !== 'undefined') {
|
||||
|
||||
|
||||
const toastId = showToast ? toast.loading("Creating account") : "";
|
||||
console.log(Router)
|
||||
const res = await fetch(`${window.location.origin}/api/faucet`, {
|
||||
method: "POST",
|
||||
});
|
||||
const json: FaucetAccountRes | { error: string } = await res.json();
|
||||
if ("error" in json) {
|
||||
if (showToast) {
|
||||
return toast.error(json.error, { id: toastId });
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (showToast) {
|
||||
toast.success("New account created", { id: toastId });
|
||||
}
|
||||
state.accounts.push({
|
||||
name: names[state.accounts.length],
|
||||
xrp: (json.xrp || 0 * 1000000).toString(),
|
||||
address: json.address,
|
||||
secret: json.secret,
|
||||
sequence: 1,
|
||||
hooks: [],
|
||||
isLoading: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
19
state/actions/downloadAsZip.ts
Normal file
19
state/actions/downloadAsZip.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { createZip } from '../../utils/zip';
|
||||
import { guessZipFileName } from '../../utils/helpers';
|
||||
import state from '..'
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
export const downloadAsZip = async () => {
|
||||
try {
|
||||
state.zipLoading = true
|
||||
// TODO do something about file/gist loading state
|
||||
const files = state.files.map(({ name, content }) => ({ name, content }));
|
||||
const zipped = await createZip(files);
|
||||
const zipFileName = guessZipFileName(files);
|
||||
zipped.saveFile(zipFileName);
|
||||
} catch (error) {
|
||||
toast.error('Error occured while creating zip file, try again later')
|
||||
} finally {
|
||||
state.zipLoading = false
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Octokit } from "@octokit/core";
|
||||
import Router from "next/router";
|
||||
import state from '../index';
|
||||
import { templateFileIds } from '../constants';
|
||||
|
||||
|
||||
const octokit = new Octokit();
|
||||
|
||||
@@ -17,6 +19,17 @@ export const fetchFiles = (gistId: string) => {
|
||||
|
||||
octokit
|
||||
.request("GET /gists/{gist_id}", { gist_id: gistId })
|
||||
.then(res => {
|
||||
if (!Object.values(templateFileIds).includes(gistId)) {
|
||||
return res
|
||||
}
|
||||
// in case of templates, fetch header file(s) and append to res
|
||||
return octokit.request("GET /gists/{gist_id}", { gist_id: templateFileIds.headers }).then(({ data: { files: headerFiles } }) => {
|
||||
const files = { ...res.data.files, ...headerFiles }
|
||||
res.data.files = files
|
||||
return res
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.data.files && Object.keys(res.data.files).length > 0) {
|
||||
const files = Object.keys(res.data.files).map((filename) => ({
|
||||
@@ -44,6 +57,7 @@ export const fetchFiles = (gistId: string) => {
|
||||
state.loading = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
// console.error(err)
|
||||
state.loading = false;
|
||||
state.logs.push({
|
||||
type: "error",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { importAccount } from "./importAccount";
|
||||
import { saveFile } from "./saveFile";
|
||||
import { syncToGist } from "./syncToGist";
|
||||
import { updateEditorSettings } from "./updateEditorSettings";
|
||||
import { downloadAsZip } from "./downloadAsZip";
|
||||
|
||||
export {
|
||||
addFaucetAccount,
|
||||
@@ -17,5 +18,6 @@ export {
|
||||
importAccount,
|
||||
saveFile,
|
||||
syncToGist,
|
||||
updateEditorSettings
|
||||
updateEditorSettings,
|
||||
downloadAsZip
|
||||
};
|
||||
1
state/constants/index.ts
Normal file
1
state/constants/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './templates'
|
||||
11
state/constants/templates.ts
Normal file
11
state/constants/templates.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export const templateFileIds = {
|
||||
'starter': '1d14e51e2e02dc0a508cb0733767a914', // TODO currently same as accept
|
||||
'accept': '1d14e51e2e02dc0a508cb0733767a914',
|
||||
'firewall': 'bcd6d0c0fcbe52545ddb802481ff9d26',
|
||||
'notary': 'a789c75f591eeab7932fd702ed8cf9ea',
|
||||
'carbon': '43925143fa19735d8c6505c34d3a6a47',
|
||||
'peggy': 'ceaf352e2a65741341033ab7ef05c448',
|
||||
'headers': '9b448e8a55fab11ef5d1274cb59f9cf3'
|
||||
}
|
||||
|
||||
export const apiHeaderFiles = ['hookapi.h', 'sfcodes.h', 'hookmacro.h']
|
||||
@@ -45,6 +45,7 @@ export interface IState {
|
||||
activeWat: number;
|
||||
loading: boolean;
|
||||
gistLoading: boolean;
|
||||
zipLoading: boolean;
|
||||
compiling: boolean;
|
||||
logs: ILog[];
|
||||
deployLogs: ILog[];
|
||||
@@ -59,7 +60,7 @@ export interface IState {
|
||||
}
|
||||
|
||||
// let localStorageState: null | string = null;
|
||||
let initialState = {
|
||||
let initialState: IState = {
|
||||
files: [],
|
||||
active: 0,
|
||||
activeWat: 0,
|
||||
@@ -72,6 +73,7 @@ let initialState = {
|
||||
gistOwner: undefined,
|
||||
gistName: undefined,
|
||||
gistLoading: false,
|
||||
zipLoading: false,
|
||||
editorSettings: {
|
||||
tabSize: 2,
|
||||
},
|
||||
|
||||
9
utils/helpers.ts
Normal file
9
utils/helpers.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
interface File {
|
||||
name: string
|
||||
}
|
||||
|
||||
export const guessZipFileName = (files: File[]) => {
|
||||
let parts = (files.filter(f => f.name.endsWith('.c'))[0]?.name || 'hook').split('.')
|
||||
parts = parts.length > 1 ? parts.slice(0, -1) : parts
|
||||
return parts.join('')
|
||||
}
|
||||
32
utils/zip.ts
Normal file
32
utils/zip.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import JSZip, { JSZipFileOptions } from 'jszip'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
interface File {
|
||||
name: string
|
||||
content: any
|
||||
options?: JSZipFileOptions
|
||||
}
|
||||
|
||||
interface Zipped {
|
||||
saveFile: (filename: string) => void
|
||||
data: Blob
|
||||
}
|
||||
|
||||
export const createZip = async (files: File[]): Promise<Zipped> => {
|
||||
const zip = new JSZip()
|
||||
|
||||
files.forEach(({ name, content, options }) => {
|
||||
zip.file(name, content, options)
|
||||
})
|
||||
|
||||
const data = await zip.generateAsync({ type: "blob" })
|
||||
|
||||
return {
|
||||
saveFile: (filename: string) =>
|
||||
saveAs(data, filename),
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
86
yarn.lock
86
yarn.lock
@@ -809,6 +809,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/dinero.js/-/dinero.js-1.9.0.tgz#e11356764339e3d361d38bd54910282b106dc321"
|
||||
integrity sha512-H2XdE6N/A2wJ/TJhGqeHDMUhCaey2R/Lcq9ichGBncKsFGvqrroXZWPNdDkCcgQOBPoCD4n9QuSBUC/35wuJiw==
|
||||
|
||||
"@types/file-saver@^2.0.4":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.4.tgz#aaf9b96296150d737b2fefa535ced05ed8013d84"
|
||||
integrity sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
@@ -1516,6 +1521,11 @@ core-js@^2.4.0:
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
|
||||
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
|
||||
|
||||
create-ecdh@^4.0.0:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
|
||||
@@ -2157,6 +2167,11 @@ file-entry-cache@^6.0.1:
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
file-saver@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
|
||||
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
@@ -2481,6 +2496,11 @@ image-size@1.0.0:
|
||||
dependencies:
|
||||
queue "6.0.2"
|
||||
|
||||
immediate@~3.0.5:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
|
||||
|
||||
import-fresh@^3.0.0, import-fresh@^3.2.1:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
@@ -2700,6 +2720,11 @@ is-wsl@^2.1.1:
|
||||
dependencies:
|
||||
is-docker "^2.0.0"
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
@@ -2790,6 +2815,16 @@ jsonwebtoken@^8.5.1:
|
||||
array-includes "^3.1.3"
|
||||
object.assign "^4.1.2"
|
||||
|
||||
jszip@^3.7.1:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9"
|
||||
integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==
|
||||
dependencies:
|
||||
lie "~3.3.0"
|
||||
pako "~1.0.2"
|
||||
readable-stream "~2.3.6"
|
||||
set-immediate-shim "~1.0.1"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
@@ -2834,6 +2869,13 @@ levn@^0.4.1:
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
lie@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
|
||||
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
|
||||
dependencies:
|
||||
immediate "~3.0.5"
|
||||
|
||||
loader-utils@1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||
@@ -3365,7 +3407,7 @@ pako@^2.0.4:
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d"
|
||||
integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==
|
||||
|
||||
pako@~1.0.5:
|
||||
pako@~1.0.2, pako@~1.0.5:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||
@@ -3523,6 +3565,11 @@ pretty-format@^3.8.0:
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385"
|
||||
integrity sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
process@0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
@@ -3712,6 +3759,19 @@ readable-stream@^3.5.0, readable-stream@^3.6.0:
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
readable-stream@~2.3.6:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readdirp@~3.5.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
|
||||
@@ -3927,7 +3987,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2,
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
||||
safe-buffer@~5.1.1:
|
||||
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
@@ -3962,6 +4022,11 @@ semver@^7.2.1, semver@^7.3.4, semver@^7.3.5:
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
set-immediate-shim@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
|
||||
integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
|
||||
|
||||
setimmediate@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||
@@ -4152,6 +4217,13 @@ string_decoder@1.3.0, string_decoder@^1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
@@ -4428,7 +4500,7 @@ utf-8-validate@^5.0.2:
|
||||
dependencies:
|
||||
node-gyp-build "^4.3.0"
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
@@ -4642,10 +4714,10 @@ xrpl-accountlib@^1.2.3:
|
||||
xrpl-secret-numbers "^0.3.3"
|
||||
xrpl-sign-keypairs "^2.0.0"
|
||||
|
||||
xrpl-client@^1.9.2:
|
||||
version "1.9.2"
|
||||
resolved "https://registry.yarnpkg.com/xrpl-client/-/xrpl-client-1.9.2.tgz#c018510b050e678e09b8640533a57c50d4e586e9"
|
||||
integrity sha512-foFrFqfYxpkj8La9k1G9ZJEbVOHJpvIIt0koNaw/3nlTUUnbyTENtr112CnHEh+z2JMqJxBB9JpmZavGDhMlKg==
|
||||
xrpl-client@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/xrpl-client/-/xrpl-client-1.9.3.tgz#1f2c17f7677d271a854e74d6035d6334cacf1629"
|
||||
integrity sha512-TouyBeXuDXZWvO+4HrlvfrVtoXXyi9ny4+vpZoMCd2EbljsdFFTU6ujAqu81BvujkathKMTHiB81cR1bTL8ypw==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
websocket "^1.0.34"
|
||||
|
||||
Reference in New Issue
Block a user