initial sketch: filecoin deal UI and scene

This commit is contained in:
@wwwjim 2020-09-22 15:01:36 -07:00
parent d72d2147b0
commit 6b7e547b06
8 changed files with 176 additions and 3 deletions

View File

@ -149,6 +149,12 @@ export const generate = ({ library = [], slates = [] }) => [
},
],
},
{
id: "V1_NAVIGATION_FILECOIN_STORAGE_DEAL",
decorator: "MAKE_DEAL",
name: "Storage deal",
pageTitle: "Make a one-off Filecoin storage deal",
},
{
id: "V1_NAVIGATION_PROFILE_EDIT",
decorator: "EDIT_ACCOUNT",

View File

@ -1,5 +1,7 @@
import * as Constants from "~/common/constants";
import { FilecoinNumber, Converter } from "@openworklabs/filecoin-number";
const MINUTE = 60;
const HOUR = MINUTE * 60;
const DAY = HOUR * 24;
@ -69,8 +71,10 @@ export const getCIDFromIPFS = (url) => {
};
export const formatAsFilecoinConversion = (number) => {
number = number / Math.pow(10, 18);
return `${formatAsFilecoin(number)}`;
const filecoinNumber = new FilecoinNumber(`${number}`, "attofil");
//const inAttoFil = filecoinNumber.toAttoFil();
const inFil = filecoinNumber.toFil();
return `${formatAsFilecoin(inFil)}`;
};
export const formatAsFilecoin = (number) => {

View File

@ -423,6 +423,7 @@ export const Deals = (props) => (
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
>
<path d="m23.5 22-1-1.934v-4.566c.042-1.778-2.081-3.363-4-5" />
<path d="m20.019 17.5-2.551-2.607.00000002.00000002c-.476378-.495833-1.26451-.511603-1.76034-.035225-.495833.476378-.511603 1.26451-.035225 1.76034.00382974.00398614.00768599.00794673.0115685.0118815l2.816 2.87v1.5l-.00000021-.0000012c.153133.894577.493939 1.74659 1 2.5" />

View File

@ -30,6 +30,7 @@ import SceneSentinel from "~/scenes/SceneSentinel";
import ScenePublicProfile from "~/scenes/ScenePublicProfile";
import ScenePublicSlate from "~/scenes/ScenePublicSlate";
import SceneArchive from "~/scenes/SceneArchive";
import SceneMakeFilecoinDeal from "~/scenes/SceneMakeFilecoinDeal";
// NOTE(jim):
// Sidebars each have a decorator and can be shown to with _handleAction
@ -88,6 +89,7 @@ const SCENES = {
NETWORK: <SceneSentinel />,
DIRECTORY: <SceneDirectory />,
FILECOIN: <SceneArchive />,
MAKE_DEAL: <SceneMakeFilecoinDeal />,
};
export default class ApplicationPage extends React.Component {

View File

@ -14,6 +14,7 @@ const IconMap = {
FOLDER: <SVG.Folder height="20px" />,
WALLET: <SVG.OldWallet height="20px" />,
DEALS: <SVG.Deals height="20px" />,
MAKE_DEAL: <SVG.Deals height="20px" />,
SLATES: <SVG.Layers height="20px" />,
SLATE: <SVG.Slate height="20px" />,
LOCAL_DATA: <SVG.HardDrive height="20px" />,

View File

@ -45,6 +45,7 @@
"@emotion/react": "11.0.0-next.12",
"@emotion/server": "11.0.0-next.12",
"@improbable-eng/grpc-web": "^0.13.0",
"@openworklabs/filecoin-number": "0.0.10",
"@react-hook/window-size": "^3.0.7",
"@slack/webhook": "^5.0.3",
"@textile/grpc-transport": "0.0.3",

View File

@ -0,0 +1,158 @@
import * as React from "react";
import * as Strings from "~/common/strings";
import * as Constants from "~/common/constants";
import * as System from "~/components/system";
import { css } from "@emotion/react";
import { createState } from "~/scenes/SceneSettings";
import { LoaderSpinner } from "~/components/system/components/Loaders";
import { FilecoinNumber, Converter } from "@openworklabs/filecoin-number";
import Section from "~/components/core/Section";
import ScenePage from "~/components/core/ScenePage";
import ScenePageHeader from "~/components/core/ScenePageHeader";
const STYLES_SECTION_UPLOAD = css`
background: white;
display: flex;
align-items: center;
justify-content: center;
padding: 88px 48px 88px 48px;
border: 1px solid #ececec;
margin-top: 48px;
max-width: 688px;
font-family: ${Constants.font.semiBold};
`;
export default class SceneDeals extends React.Component {
state = {};
async componentDidMount() {
let networkViewer;
try {
const response = await fetch("/api/network");
const json = await response.json();
networkViewer = json.data;
} catch (e) {}
this.setState({
networkViewer,
...createState(networkViewer.powerInfo.defaultStorageConfig),
settings_cold_default_max_price: 1000000000000000,
});
}
_handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
render() {
let inFil = 0;
if (this.state.networkViewer) {
const filecoinNumber = new FilecoinNumber(
`${this.state.settings_cold_default_max_price}`,
"attofil"
);
inFil = filecoinNumber.toFil();
}
return (
<ScenePage>
<ScenePageHeader title="Make a one-off Flecoin Storage Deal">
This is a simple tool to upload data and make one-off storage deals in
the Filecoin network.
</ScenePageHeader>
{this.state.networkViewer ? (
<React.Fragment>
<div css={STYLES_SECTION_UPLOAD}>
Drag and drop a file here or&nbsp;<a href="#">click</a>&nbsp;to
upload.
</div>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Filecoin address (Read only)"
description="This is the Filecoin address your funds will come from."
name="settings_cold_default_duration"
readOnly
type="text"
value={this.state.settings_cold_default_address}
onChange={this._handleChange}
/>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Default Filecoin replication and availability factor"
description="How many times should we replicate this deal across your selected miners?"
name="settings_cold_default_replication_factor"
type="number"
value={this.state.settings_cold_default_replication_factor}
placeholder="Type in amount of miners"
onChange={this._handleChange}
/>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Default Filecoin deal duration"
description="Current deal duration is in epochs."
name="settings_cold_default_duration"
type="number"
value={this.state.settings_cold_default_duration}
placeholder="Type in epochs (~25 seconds)"
onChange={this._handleChange}
/>
<System.Input
containerStyle={{ marginTop: 24 }}
label="Max Filecoin price (attoFIL)"
type="number"
description={`Set the maximum Filecoin price you're willing to pay. The current price you have set is equivalent to ${inFil} FIL`}
name="settings_cold_default_max_price"
value={this.state.settings_cold_default_max_price}
placeholder="Type in amount of Filecoin (attoFIL)"
onChange={this._handleChange}
/>
<Section
title="Targeted miners"
style={{ marginTop: 48, maxWidth: 688, minWidth: "auto" }}
onAction={this.props.onAction}
buttons={[
{
name: "Add miner",
},
]}
>
<System.Table
data={{
columns: [
{
key: "miner",
name: "Miner ID",
width: "100%",
},
],
rows: this.state.settings_cold_default_trusted_miners.map(
(miner) => {
return {
miner,
};
}
),
}}
/>
</Section>
<System.ButtonPrimary style={{ marginTop: 48 }}>
Make storage deal
</System.ButtonPrimary>
</React.Fragment>
) : (
<LoaderSpinner style={{ marginTop: 48, height: 32, width: 32 }} />
)}
</ScenePage>
);
}
}

View File

@ -39,7 +39,7 @@ const STYLES_RIGHT = css`
flex-shrink: 0;
`;
const createState = (config) => {
export const createState = (config) => {
return {
settings_hot_enabled: config.hot.enabled,
settings_hot_allow_unfreeze: config.hot.allowUnfreeze,