Skip to content

Commit

Permalink
Merge branch 'laboratory-v2' of https://github.com/stellar/laboratory
Browse files Browse the repository at this point in the history
…into v2-explore-endpoints-pages-1
  • Loading branch information
quietbits committed Mar 29, 2024
2 parents 5ce66cd + 083d0cb commit a1c35fc
Show file tree
Hide file tree
Showing 11 changed files with 521 additions and 47 deletions.
12 changes: 7 additions & 5 deletions src/app/(sidebar)/account/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function CreateAccount() {
const generateKeypair = () => {
let keypair = Keypair.random();

account.update(keypair.publicKey());
account.updatePublicKey(keypair.publicKey());
setSecretKey(keypair.secret());
};

Expand Down Expand Up @@ -54,10 +54,12 @@ export default function CreateAccount() {
</div>

<ExpandBox isExpanded={Boolean(account.publicKey)} offsetTop="xl">
<GenerateKeypair
publicKey={account.publicKey}
secretKey={secretKey}
/>
<div className="Account__result">
<GenerateKeypair
publicKey={account.publicKey}
secretKey={secretKey}
/>
</div>
</ExpandBox>
</div>
</Card>
Expand Down
7 changes: 4 additions & 3 deletions src/app/(sidebar)/account/fund/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useEffect, useState } from "react";
import { Alert, Card, Input, Text, Button } from "@stellar/design-system";

import { shortenStellarAddress } from "@/helpers/shortenStellarAddress";
import { validatePublicKey } from "@/helpers/validatePublicKey";
import { useFriendBot } from "@/query/useFriendBot";
import { useStore } from "@/store/useStore";

import { validate } from "@/validate";

import "../styles.scss";

export default function FundAccount() {
Expand Down Expand Up @@ -52,8 +53,8 @@ export default function FundAccount() {
onChange={(e) => {
setGeneratedPublicKey(e.target.value);

const error = validatePublicKey(e.target.value);
setInlineErrorMessage(error);
const error = validate.publicKey(e.target.value);
setInlineErrorMessage(error || "");
}}
placeholder="Ex: GCEXAMPLE5HWNK4AYSTEQ4UWDKHTCKADVS2AHF3UI2ZMO3DPUSM6Q4UG"
error={inlineErrorMessage}
Expand Down
181 changes: 180 additions & 1 deletion src/app/(sidebar)/account/muxed-create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,184 @@
"use client";

import { useState } from "react";
import { Alert, Button, Card, Input, Text } from "@stellar/design-system";

import { useStore } from "@/store/useStore";

import { ExpandBox } from "@/components/ExpandBox";
import { MuxedAccountResult } from "@/components/MuxedAccountResult";
import { PubKeyPicker } from "@/components/FormElements/PubKeyPicker";
import { SdsLink } from "@/components/SdsLink";

import { muxedAccount } from "@/helpers/muxedAccount";

import { validate } from "@/validate";

import "../styles.scss";

export default function CreateMuxedAccount() {
return <div>Create Muxed Account</div>;
const { account } = useStore();

const [baseAddress, setBaseAddress] = useState<string>(
account.generatedMuxedAccountInput?.baseAddress || "",
);
const [muxedId, setMuxedId] = useState<string>(
account.generatedMuxedAccountInput?.id || "",
);
const [baseFieldErrorMessage, setBaseFieldErrorMessage] =
useState<string>("");
const [muxedFieldError, setMuxedFieldError] = useState<string>("");
const [sdkError, setSdkError] = useState<string>("");

const [isReset, setReset] = useState<boolean>(false);

const generateMuxedAccount = () => {
const result = muxedAccount.generate({
baseAddress,
muxedAccountId: muxedId,
});

const { error, muxedAddress } = result;

if (muxedAddress) {
setReset(false);
account.updateGeneratedMuxedAccount({
id: muxedId,
baseAddress,
muxedAddress,
});

account.updateGeneratedMuxedAccountInput({
id: muxedId,
baseAddress,
});

setSdkError("");
return;
}

if (error) {
setSdkError(error);
return;
}
};

return (
<div className="Account">
<Card>
<div className="Account__card">
<div className="CardText">
<Text size="lg" as="h1" weight="medium">
Create Multiplexed Account
</Text>

<Text size="sm" as="p">
A muxed (or multiplexed) account (defined in{" "}
<SdsLink href="https://github.com/stellar/stellar-protocol/blob/master/core/cap-0027.md">
CAP-27
</SdsLink>{" "}
and briefly{" "}
<SdsLink href="https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0023.md">
SEP-23
</SdsLink>
) is one that resolves a single Stellar G...account to many
different underlying IDs.
</Text>
</div>

<PubKeyPicker
id="muxed-public-key"
label="Base Account G Address"
value={baseAddress}
onChange={(e) => {
setReset(true);
setBaseAddress(e.target.value);

let error = "";

if (!e.target.value.startsWith("G")) {
error = "Base account address should start with G";
} else {
error = validate.publicKey(e.target.value) || "";
}

setBaseFieldErrorMessage(error);
}}
error={baseFieldErrorMessage}
copyButton={{
position: "right",
}}
/>

<Input
id="muxed-account-iD"
fieldSize="md"
placeholder="Ex: 1"
label="Muxed Account ID"
value={muxedId}
onChange={(e) => {
setReset(true);
setMuxedId(e.target.value);

const error = validate.positiveInt(e.target.value);
setMuxedFieldError(error || "");
}}
error={muxedFieldError}
copyButton={{
position: "right",
}}
/>

<div className="Account__CTA">
<Button
disabled={
!baseAddress ||
!muxedId ||
Boolean(baseFieldErrorMessage || muxedFieldError)
}
size="md"
variant={"secondary"}
onClick={generateMuxedAccount}
>
Create
</Button>
</div>

<ExpandBox
offsetTop="xl"
isExpanded={
!isReset && Boolean(account.generatedMuxedAccount.muxedAddress)
}
>
<MuxedAccountResult
baseAddress={account.generatedMuxedAccount.baseAddress ?? ""}
muxedAddress={account.generatedMuxedAccount.muxedAddress ?? ""}
muxedId={account.generatedMuxedAccount.id ?? ""}
/>
</ExpandBox>
</div>
</Card>

<Alert
placement="inline"
variant="warning"
title="Muxed accounts are uncommon"
>
Don’t use in a production environment unless you know what you’re doing.
</Alert>

{Boolean(sdkError) && (
<Alert
placement="inline"
variant="error"
onClose={() => {
setSdkError("");
}}
title={sdkError}
>
{""}
</Alert>
)}
</div>
);
}
142 changes: 141 additions & 1 deletion src/app/(sidebar)/account/muxed-parse/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,145 @@
"use client";

import { useState } from "react";
import { Alert, Card, Text, Button } from "@stellar/design-system";

import { useStore } from "@/store/useStore";

import { ExpandBox } from "@/components/ExpandBox";
import { PubKeyPicker } from "@/components/FormElements/PubKeyPicker";
import { MuxedAccountResult } from "@/components/MuxedAccountResult";

import { muxedAccount } from "@/helpers/muxedAccount";

import { validate } from "@/validate";

import "../styles.scss";

export default function ParseMuxedAccount() {
return <div>Parse Muxed Account</div>;
const { account } = useStore();
const parsedMuxedAccount = account.parsedMuxedAccount;

const [muxedAddress, setMuxedAddress] = useState<string>(
account.parsedMuxedAccountInput || "",
);

const [muxedFieldError, setMuxedFieldError] = useState<string>("");
const [sdkError, setSdkError] = useState<string>("");

const [isReset, setReset] = useState<boolean>(false);

const parseMuxedAccount = () => {
const result = muxedAccount.parse({
muxedAddress,
});

const { error, id, baseAddress } = result;

if (baseAddress && id) {
setReset(false);
account.updateParsedMuxedAccount({
id,
baseAddress,
muxedAddress,
});
account.updateParsedMuxedAccountInput(muxedAddress);

setSdkError("");
return;
}

if (error) {
setSdkError(error);
return;
}
};

return (
<div className="Account">
<Card>
<div className="Account__card">
<div className="CardText">
<Text size="lg" as="h1" weight="medium">
Get Muxed Account from M address
</Text>
</div>

<PubKeyPicker
id="muxed-account-address"
label="Muxed Account M Address"
placeholder="Ex: MBRWSVNURRYVIYSWLRFQ5AAAUWPKOZZNZVVVIXHFGUSGIRVKLVIDYAAAAAAAAAAD5GJ4U"
value={muxedAddress}
error={muxedFieldError}
copyButton={{
position: "right",
}}
onChange={(e) => {
setReset(true);
setMuxedAddress(e.target.value);

let error = "";

if (!e.target.value.startsWith("M")) {
error = "Muxed account address should start with M";
} else {
error = validate.publicKey(e.target.value) || "";
}

setMuxedFieldError(error);
}}
/>

<div className="Account__CTA">
<Button
disabled={!muxedAddress || Boolean(muxedFieldError)}
size="md"
variant={"secondary"}
onClick={parseMuxedAccount}
>
Parse
</Button>
</div>

<ExpandBox
offsetTop="xl"
isExpanded={
!isReset &&
Boolean(
parsedMuxedAccount?.baseAddress &&
parsedMuxedAccount?.id &&
parsedMuxedAccount?.muxedAddress,
)
}
>
<MuxedAccountResult
baseAddress={parsedMuxedAccount.baseAddress ?? ""}
muxedId={parsedMuxedAccount.id ?? ""}
muxedAddress={parsedMuxedAccount.muxedAddress ?? ""}
/>
</ExpandBox>
</div>
</Card>

<Alert
placement="inline"
variant="warning"
title="Muxed accounts are uncommon"
>
Don’t use in a production environment unless you know what you’re doing.
</Alert>

{Boolean(sdkError) && (
<Alert
placement="inline"
variant="error"
onClose={() => {
setSdkError("");
}}
title={sdkError}
>
{""}
</Alert>
)}
</div>
);
}
9 changes: 9 additions & 0 deletions src/app/(sidebar)/account/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,13 @@
cursor: pointer;
}
}

&__result {
display: flex;
flex-direction: column;
gap: pxToRem(16px);
background-color: var(--sds-clr-gray-03);
border-radius: pxToRem(8px);
padding: pxToRem(16px);
}
}
Loading

0 comments on commit a1c35fc

Please sign in to comment.