305 lines
9.8 KiB
TypeScript
Raw Normal View History

2021-07-21 11:37:25 +03:00
import React, { useState } from "react";
import logo from "./logo.svg";
import "./App.scss";
import { createClient, FluenceClient } from "@fluencelabs/fluence";
import { get_external_api_multiaddr } from "@fluencelabs/aqua-ipfs";
import { stage } from "@fluencelabs/fluence-network-environment";
import { deploy_service, get_file_size, remove_service, provideFile } from "@fluencelabs/ipfs-execution";
const { create, globSource, urlSource, CID } = require('ipfs-http-client');
const relayNodes = [stage[0], stage[1], stage[2]];
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text);
};
function App() {
const [client, setClient] = useState<FluenceClient | null>(null);
const [serviceId, setServiceId] = useState<string | null>(null);
const [peerIdInput, setPeerIdInput] = useState<string>("");
const [relayPeerIdInput, setRelayPeerIdInput] = useState<string>("");
const [wasm, setWasm] = useState<string | null>("QmVg9EnanAbwTuEqjjuc1R2uf3AdtEkrNagSifQMkHfyNU");
const [rpcAddr, setRpcAddr] = useState<string | null>("");
const [fileCID, setFileCID] = useState<string>("");
const [fileSize, setFileSize] = useState<string | null>(null);
const isConnected = client !== null;
const gotRpcAddr = rpcAddr !== null;
const deployed = serviceId !== null;
const connect = async (relayPeerId: string) => {
try {
let client = await createClient(relayPeerId);
setClient(client);
await getRpcAddr(client);
} catch (err) {
console.log("Client initialization failed", err);
}
};
const getRpcAddr = async (client: FluenceClient) => {
if (client === null) {
console.log("getRpcAddr client is null");
return;
}
let result = await get_external_api_multiaddr(client, client.relayPeerId!);
console.log("getRpcAddr result", result);
let rpcAddr = result.multiaddr;
setRpcAddr(rpcAddr);
}
const deployService = async () => {
console.log("wasm %s rpcAddr %s", wasm, rpcAddr);
if (client === null || wasm === null || rpcAddr === null) {
return;
}
let service_id = await deploy_service(
client,
client.relayPeerId!, wasm, rpcAddr,
(msg, value) => console.log(msg, value),
{ ttl: 10000 }
);
setServiceId(service_id);
};
const getFileSize = async () => {
if (client === null || serviceId === null || rpcAddr === null) {
return;
}
let size = await get_file_size(client, client.relayPeerId!, fileCID, rpcAddr, serviceId, { ttl: 10000 });
if (size.success) {
setFileSize(size.size.toString());
} else {
setFileSize("Error: " + size.error);
}
};
const removeService = async () => {
if (client === null || serviceId === null) {
return;
}
await remove_service(client, client.relayPeerId!, serviceId, { ttl: 10000 });
setServiceId(null);
};
console.log("isConnected gotRpcAddr deployed\n", isConnected, gotRpcAddr, deployed);
if (!isConnected) {
return (<div className="App">
<header>
<img src={logo} className="logo" alt="logo" />
</header>
<div className="content">
<>
<h1>Pick a relay</h1>
<ul>
{relayNodes.map((x) => (
<li key={x.peerId}>
<span className="mono">{x.peerId}</span>
<button className="btn" onClick={async () => await connect(x.multiaddr)}>
Connect
</button>
</li>
))}
</ul>
</>
</div>
</div>
);
} else if (isConnected && gotRpcAddr && !deployed) {
return (
<div className="App">
<header>
<img src={logo} className="logo" alt="logo" />
</header>
<div className="content">
<>
<h1>Connected</h1>
<table>
<tr>
<td className="bold">Peer id:</td>
<td className="mono">{client!.selfPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client!.selfPeerId)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">Relay peer id:</td>
<td className="mono">{client!.relayPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client!.relayPeerId!)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">IPFS RPC:</td>
<td className="mono">{rpcAddr?.substring(0, 49) + "..."}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(rpcAddr!)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
</table>
<div>
<div className="row">
<h2>Set process_files.wasm module CID</h2>
<p className="p">
To deploy a service, specify CID of WebAssembly module.
</p>
<input
className="input"
type="text"
onChange={(e) => setWasm(e.target.value)}
value={wasm!}
/>
</div>
</div>
<div>
<h2>Deploy ProcessFiles service</h2>
<p className="p">
process_files.wasm will be downloaded to the Fluence node,
and then a service will be dynamically created from it!
After that, you will be able to use that service to get sizes of IPFS files!
</p>
<div className="row">
<button className="btn btn-hello" onClick={deployService}>
deploy service
</button>
</div>
</div>
</>
</div>
</div>
)
} else if (deployed) {
return (
<div className="App">
<header>
<img src={logo} className="logo" alt="logo" />
</header>
<div className="content">
<>
<h1>Deployed</h1>
<table>
<tr>
<td className="bold">Peer id:</td>
<td className="mono">{client!.selfPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client!.selfPeerId)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">Relay peer id:</td>
<td className="mono">{client!.relayPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client!.relayPeerId!)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">process_files.wasm CID:</td>
<td className="mono">{wasm}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(wasm!)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">ProcessFiles service ID:</td>
<td className="mono">{serviceId}</td>
<button
className="btn-clipboard"
onClick={() => removeService()}
>
<i className="gg-trash"></i>
</button>
</tr>
<tr>
<td className="bold">File Size:</td>
<td className="mono">{fileSize}</td>
</tr>
</table>
<div>
<h2>Get file size</h2>
<p className="p">
Upload any file to IPFS node
<p><b>{ rpcAddr }</b></p>
paste CID here and get the size of that file via ProcessFiles service you have just deployed
</p>
<div className="row">
<label className="label bold">IPFS CID</label>
<input
className="input"
type="text"
onChange={(e) => setFileCID(e.target.value)}
value={fileCID}
/>
</div>
<div className="row">
<button className="btn btn-hello" onClick={getFileSize} >
get size
</button>
</div>
<div className="row">
<label className="label bold">File Size:</label>
<label className="mono"> {fileSize}</label>
</div>
</div>
</>
</div>
</div>
)
} else {
return (
<div className="App">
<header>
<img src={logo} className="logo" alt="logo" />
</header>
<div className="content">
<>
<h2>Unimplemented! isConnected {isConnected} deployed {deployed} wasm {wasm} </h2>
</>
</div>
</div>
)
}
}
export default App;