Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
303 changes: 184 additions & 119 deletions seedelf-platform/seedelf-cli/src/commands/sweep.rs

Large diffs are not rendered by default.

16 changes: 15 additions & 1 deletion seedelf-platform/seedelf-core/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ pub struct Asset {
pub amount: u64,
}

impl Default for Asset {
fn default() -> Self {
let blank = Hash::new([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
Self {
policy_id: blank,
token_name: blank.to_vec(),
amount: 0,
}
}
}

impl Asset {
/// Creates a new `Asset` instance.
///
Expand All @@ -25,7 +38,8 @@ impl Asset {
pub fn new(policy_id: String, token_name: String, amount: u64) -> Result<Self> {
Ok(Self {
policy_id: Hash::new(
hex::decode(policy_id)?
hex::decode(policy_id)
.unwrap_or_default()
.as_slice()
.try_into()
.map_err(|e| anyhow::anyhow!("{e}"))?,
Expand Down
32 changes: 18 additions & 14 deletions seedelf-platform/seedelf-gui/index.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<style>
html,body{background:#121212}
</style>
<meta charset="UTF-8" />
<link rel="icon" href="favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Seedelf</title>

</head>
<head>
<style>
html,
body {
background: #121212
}
</style>
<meta charset="UTF-8" />
<link rel="icon" href="favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Seedelf</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

</html>
37 changes: 37 additions & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/commands/extract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// core named this sweep, but in the gui it will be extract
use crate::session;
use seedelf_cli::commands::sweep::{SweepSeedelfOutput, build_sweep_seedelf};
use seedelf_core::assets::Assets;
use seedelf_core::constants::{Config, VARIANT, get_config};

#[tauri::command(async)]
pub async fn extract_seedelf(
network_flag: bool,
address: String,
lovelace: u64,
send_all: bool,
) -> String {
let config: Config = match get_config(VARIANT, network_flag) {
Some(c) => c,
None => {
return String::new();
}
};
let SweepSeedelfOutput { tx_hash, .. } = match session::with_key(|sk| {
build_sweep_seedelf(
config,
network_flag,
address,
lovelace,
Assets::new(),
None,
*sk,
send_all,
)
}) {
Ok(v) => v.await,
_ => return String::new(),
};

tx_hash
}
1 change: 1 addition & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod create;
pub mod extract;
pub mod fund;
pub mod remove;
pub mod send;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// core named this transfer, but in the gui it will send
// core named this transfer, but in the gui it will be send
use crate::session;
use seedelf_cli::commands::transfer::{TransferSeedelfOutput, build_transfer_seedelf};
use seedelf_core::assets::Assets;
Expand Down
1 change: 1 addition & 0 deletions seedelf-platform/seedelf-gui/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn run() {
commands::remove::remove_seedelf,
commands::fund::fund_seedelf,
commands::send::send_seedelf,
commands::extract::extract_seedelf,
// constants
constants::get_seedelf_policy_id,
// webserver.rs
Expand Down
191 changes: 187 additions & 4 deletions seedelf-platform/seedelf-gui/src/pages/Wallet/Extract.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,193 @@
// extract funds from the wallet
import { useState } from "react";
import {
ShowNotification,
NotificationVariant,
} from "@/components/ShowNotification";
import { ConfirmationModal } from "@/components/ConfirmationModal";
import { ExplorerLinkModal } from "@/components/ExplorerLinkModal";
import { useNetwork } from "@/types/network";
import { TextField } from "@/components/TextField";
import { NumberField } from "@/components/NumberField";
import { Checkbox } from "@/components/Checkbox";
import { SearchCheck } from "lucide-react";
import { extractSeedelf } from "./transactions";
import { colorClasses } from "./colors";
import { isNotAScript } from "./api";

import { useOutletContext } from "react-router";
import { OutletContextType } from "@/types/layout";

export function Extract() {
const [message, setMessage] = useState<string | null>(null);
const [variant, setVariant] = useState<NotificationVariant>("error");

const [address, setAddress] = useState("");
const [ada, setAda] = useState(0);

const { network } = useNetwork();
const [addressValid, setAddressValid] = useState<boolean>(false);
const [submitting, setSubmitting] = useState(false);
const [isSendAll, setIsSendAll] = useState<boolean>(false);

const { lovelace } = useOutletContext<OutletContextType>();

const [txHash, setTxHash] = useState("");

const [showConfirmationModal, setShowConfirmationModal] = useState(false);
const [showExplorerLinkModal, setShowExplorerLinkModal] =
useState<boolean>(false);

const handleAddressValid = async (a: string) => {
setVariant("error");
if (!a.trim()) return setMessage("Wallet address is required.");
if (network == "mainnet" && !a.includes("addr1"))
return setMessage("Incorrect Mainnet Address Format");
if (network == "preprod" && !a.includes("addr_test1"))
return setMessage("Incorrect Pre-Production Address Format");
const notScript = await isNotAScript(a);
if (!notScript) return setMessage("Address Is A Script");
setVariant("info");
setMessage("Address is valid");
setAddressValid(true);
};

const handleClear = () => {
setAddress("");
setAddressValid(false);
setAda(0);
setIsSendAll(false);
};

const handleSubmit = async () => {
setVariant("error");
const lovelace = ada * 1_000_000;

// should be good to run the build tx function now
try {
setVariant("info");
setMessage("Building Extract Seedelf Transaction");
const _txHash = await extractSeedelf(
network,
address,
lovelace,
isSendAll,
);
if (_txHash) {
setTxHash(_txHash);
setShowExplorerLinkModal(true);
handleClear();
}
} catch (e: any) {
setVariant("error");
setMessage(e as string);
} finally {
setSubmitting(false);
}
};

return (
<div className="p-6">
<h1 className="text-2xl font-bold">Extract</h1>
<p className="mt-4 text-gray-700">Remove some funds from the wallet</p>
<div className="p-6 w-full">
<h1 className="text-xl font-semibold text-center">
Extract From A Seedelf
</h1>

<ShowNotification
message={message}
setMessage={setMessage}
variant={variant}
/>

<ExplorerLinkModal
open={showExplorerLinkModal}
txHash={txHash}
onClose={() => {
setShowExplorerLinkModal(false);
}}
/>

<ConfirmationModal
open={showConfirmationModal}
onConfirm={() => {
handleSubmit();
setShowConfirmationModal(false);
}}
onCancel={() => {
setShowConfirmationModal(false);
}}
/>

<div className="my-4 w-full">
<div className="relative mx-auto w-full max-w-5/8">
<TextField
label="Address"
value={address}
onChange={(e) => {
const next = e.target.value;
setAddress(next);
handleAddressValid(next);
}}
disabled={submitting}
maxLength={108}
/>

<button
type="button"
title="Verify the seedelf exists"
className={`absolute bottom-0 right-0 translate-x-full ml-2 flex items-center justify-center p-2 ${address ? (addressValid ? colorClasses.green.text : colorClasses.red.text) : ""}`}
disabled
>
<SearchCheck />
</button>
</div>
</div>

<div className="my-4 max-w-5/8 mx-auto w-full">
<NumberField label="Ada" value={ada} onChange={setAda} min={0} />
</div>

<div className="grid grid-cols-3 items-center my-4 max-w-5/8 mx-auto w-full">
<Checkbox
label="Send All?"
checked={isSendAll}
onCheckedChange={() => {
if (isSendAll) {
setAddress("");
setAddressValid(false);
setIsSendAll(false);
} else {
setAddress(address);
setAda(lovelace);
setIsSendAll(true);
}
}}
baseColor={colorClasses.green.text}
/>
<div className="flex items-center justify-center gap-2 my-4 max-w-5/8 mx-auto w-full">
<button
type="button"
title="Fund an existing seedelf"
onClick={() => {
setShowConfirmationModal(true);
}}
className={`rounded ${colorClasses.sky.bg} px-4 py-2 text-sm text-white disabled:opacity-50`}
disabled={submitting || !address || !ada || !confirm}
>
Extract
</button>

{(address.length != 0 || ada > 0) && (
<button
type="button"
title="Clear all fields"
onClick={handleClear}
className={`rounded ${colorClasses.slate.bg} px-4 py-2 text-sm text-white disabled:opacity-50`}
disabled={submitting || !confirm}
>
Clear
</button>
)}
</div>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion seedelf-platform/seedelf-gui/src/pages/Wallet/Send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function Send() {
// should be good to run the build tx function now
try {
setVariant("info");
setMessage("Building Fund Seedelf Transaction");
setMessage("Building Send Seedelf Transaction");
const _txHash = await sendSeedelf(network, seedelf, lovelace);
if (_txHash) {
setTxHash(_txHash);
Expand Down
15 changes: 15 additions & 0 deletions seedelf-platform/seedelf-gui/src/pages/Wallet/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,18 @@ export async function sendSeedelf(
lovelace: lovelace,
});
}

export async function extractSeedelf(
network: Network,
address: string,
lovelace: number,
sendAll: boolean,
): Promise<string> {
const flag = castNetwork(network);
return await invoke<string>("extract_seedelf", {
networkFlag: flag,
address: address,
lovelace: lovelace,
sendAll: sendAll,
});
}