mirror of
https://github.com/fluencelabs/examples
synced 2025-06-24 07:11:35 +00:00
A little attempt to reorganize code
This commit is contained in:
@ -5,9 +5,14 @@ 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, put_file_size, remove_service, provideFile } from "@fluencelabs/ipfs-execution";
|
||||
import { Multiaddr, protocols } from 'multiaddr';
|
||||
const { create, globSource, urlSource, CID } = require('ipfs-http-client');
|
||||
import {
|
||||
deploy_service,
|
||||
put_file_size,
|
||||
remove_service,
|
||||
provideFile,
|
||||
} from "@fluencelabs/ipfs-execution";
|
||||
import { Multiaddr, protocols } from "multiaddr";
|
||||
const { create, globSource, urlSource, CID } = require("ipfs-http-client");
|
||||
|
||||
const relayNodes = [stage[0], stage[1], stage[2]];
|
||||
|
||||
@ -16,29 +21,37 @@ const copyToClipboard = (text: string) => {
|
||||
};
|
||||
|
||||
function fromOption<T>(opt: T | T[] | null): T | null {
|
||||
if (Array.isArray(opt)) {
|
||||
if (opt.length === 0) { return null; }
|
||||
|
||||
opt = opt[0];
|
||||
if (Array.isArray(opt)) {
|
||||
if (opt.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (opt === null) { return null; }
|
||||
|
||||
return opt;
|
||||
|
||||
opt = opt[0];
|
||||
}
|
||||
if (opt === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
function decapsulateP2P(rpcAddr: string): string {
|
||||
return new Multiaddr(rpcAddr).decapsulateCode(protocols.names.p2p.code).toString();
|
||||
return new Multiaddr(rpcAddr)
|
||||
.decapsulateCode(protocols.names.p2p.code)
|
||||
.toString();
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [client, setClient] = useState<FluenceClient | null>(null);
|
||||
const [serviceId, setServiceId] = useState<string | null>(null);
|
||||
|
||||
const [wasm, setWasm] = useState<string | null>("Qmf8fH2cDZXGKS9uDGBcHxv5uQ51ChrigdZKe3QxS2C1AF");
|
||||
const [rpcAddr, setRpcAddr] = useState<string | null>("");
|
||||
const [wasm, setWasm] = useState<string>(
|
||||
"Qmf8fH2cDZXGKS9uDGBcHxv5uQ51ChrigdZKe3QxS2C1AF"
|
||||
);
|
||||
const [rpcAddr, setRpcAddr] = useState<string>("");
|
||||
const [fileCID, setFileCID] = useState<string>("");
|
||||
const [fileSize, setFileSize] = useState<string | null>(null);
|
||||
const [fileSizeCID, setFileSizeCID] = useState<string | null>(null);
|
||||
const [fileSize, setFileSize] = useState<string>("");
|
||||
const [fileSizeCID, setFileSizeCID] = useState<string>("");
|
||||
|
||||
const isConnected = client !== null;
|
||||
const gotRpcAddr = rpcAddr !== null;
|
||||
@ -64,7 +77,7 @@ function App() {
|
||||
console.log("getRpcAddr result", result);
|
||||
let rpcAddr = result.multiaddr;
|
||||
setRpcAddr(decapsulateP2P(rpcAddr));
|
||||
}
|
||||
};
|
||||
|
||||
const deployService = async () => {
|
||||
console.log("wasm %s rpcAddr %s", wasm, rpcAddr);
|
||||
@ -72,10 +85,12 @@ function App() {
|
||||
return;
|
||||
}
|
||||
var service_id = await deploy_service(
|
||||
client,
|
||||
client.relayPeerId!, wasm, rpcAddr,
|
||||
(msg, value) => console.log(msg, value),
|
||||
{ ttl: 10000 }
|
||||
client,
|
||||
client.relayPeerId!,
|
||||
wasm,
|
||||
rpcAddr,
|
||||
(msg, value) => console.log(msg, value),
|
||||
{ ttl: 10000 }
|
||||
);
|
||||
service_id = fromOption(service_id);
|
||||
setServiceId(service_id);
|
||||
@ -87,9 +102,12 @@ function App() {
|
||||
}
|
||||
|
||||
var putResult = await put_file_size(
|
||||
client,
|
||||
client.relayPeerId!, fileCID, rpcAddr, serviceId,
|
||||
size => setFileSize(size.toString()),
|
||||
client,
|
||||
client.relayPeerId!,
|
||||
fileCID,
|
||||
rpcAddr,
|
||||
serviceId,
|
||||
(size) => setFileSize(size.toString()),
|
||||
(label, error) => setFileSize("Error: " + label + ": " + error),
|
||||
{ ttl: 10000 }
|
||||
);
|
||||
@ -109,238 +127,253 @@ function App() {
|
||||
return;
|
||||
}
|
||||
|
||||
await remove_service(client, client.relayPeerId!, serviceId, { ttl: 10000 });
|
||||
await remove_service(client, client.relayPeerId!, serviceId, {
|
||||
ttl: 10000,
|
||||
});
|
||||
setServiceId(null);
|
||||
};
|
||||
|
||||
console.log("isConnected gotRpcAddr deployed\n", isConnected, gotRpcAddr, deployed);
|
||||
console.log(
|
||||
"isConnected gotRpcAddr deployed\n",
|
||||
isConnected,
|
||||
gotRpcAddr,
|
||||
deployed
|
||||
);
|
||||
|
||||
if (!isConnected) {
|
||||
return (<div className="App">
|
||||
<header>
|
||||
<img src={logo} className="logo" alt="logo" />
|
||||
</header>
|
||||
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">
|
||||
{!isConnected && <ConnectionForm connect={connect} />}
|
||||
{isConnected && <Connected client={client!} />}
|
||||
{isConnected && gotRpcAddr && !deployed && (
|
||||
<IpfsForm
|
||||
rpcAddr={rpcAddr}
|
||||
setRpcAddr={setRpcAddr}
|
||||
wasm={wasm}
|
||||
setWasm={setWasm}
|
||||
deployService={deployService}
|
||||
/>
|
||||
)}
|
||||
{deployed && (
|
||||
<Deployed
|
||||
setRpcAddr={setRpcAddr}
|
||||
rpcAddr={rpcAddr}
|
||||
setFileCID={setFileCID}
|
||||
fileCID={fileCID}
|
||||
fileSize={fileSize}
|
||||
fileSizeCID={fileSizeCID}
|
||||
getFileSize={getFileSize}
|
||||
wasm={wasm}
|
||||
serviceId={serviceId}
|
||||
removeService={removeService}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
<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>
|
||||
</table>
|
||||
<div>
|
||||
<div className="row">
|
||||
<h2>Set IPFS RPC address:</h2>
|
||||
<p className="p">
|
||||
Specify IPFS to download process_files.wasm from
|
||||
</p>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
onChange={(e) => setRpcAddr(e.target.value)}
|
||||
value={rpcAddr!}
|
||||
/>
|
||||
</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 via IPFS 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>
|
||||
const Deployed = (props: {
|
||||
setRpcAddr: React.Dispatch<React.SetStateAction<string>>;
|
||||
rpcAddr: string;
|
||||
setFileCID: React.Dispatch<React.SetStateAction<string>>;
|
||||
fileCID: string;
|
||||
fileSize: string;
|
||||
fileSizeCID: string;
|
||||
getFileSize: () => Promise<void>;
|
||||
wasm: string;
|
||||
serviceId: string | null;
|
||||
removeService: () => {};
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<h2>Deployed</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td className="bold">process_files.wasm CID:</td>
|
||||
<td className="mono">{props.wasm}</td>
|
||||
<td>
|
||||
<button
|
||||
className="btn-clipboard"
|
||||
onClick={() => copyToClipboard(props.wasm)}
|
||||
>
|
||||
<i className="gg-clipboard"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="bold">ProcessFiles service ID:</td>
|
||||
<td className="mono">{props.serviceId}</td>
|
||||
<button
|
||||
className="btn-clipboard"
|
||||
onClick={() => props.removeService()}
|
||||
>
|
||||
<i className="gg-trash"></i>
|
||||
</button>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="bold">File Size:</td>
|
||||
<td className="mono">{props.fileSize}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div>
|
||||
<div className="row">
|
||||
<h2>Set IPFS RPC address:</h2>
|
||||
<p className="p">Specify IPFS to download file from</p>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
onChange={(e) => props.setRpcAddr(e.target.value)}
|
||||
value={props.rpcAddr}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
} else if (deployed) {
|
||||
return (
|
||||
<div className="App">
|
||||
<header>
|
||||
<img src={logo} className="logo" alt="logo" />
|
||||
</header>
|
||||
<h2>Get file size</h2>
|
||||
<p className="p">
|
||||
Upload any file to IPFS node
|
||||
<p>
|
||||
<b>{props.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) => props.setFileCID(e.target.value)}
|
||||
value={props.fileCID}
|
||||
/>
|
||||
</div>
|
||||
<div className="row">
|
||||
<button className="btn btn-hello" onClick={props.getFileSize}>
|
||||
get size
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<label className="label bold">File Size:</label>
|
||||
<label className="mono">{props.fileSize}</label>
|
||||
</div>
|
||||
<div className="row">
|
||||
<label className="label bold">
|
||||
File size is uploaded to IPFS as CID:
|
||||
</label>
|
||||
<label className="mono">{props.fileSizeCID}</label>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
<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>
|
||||
<div className="row">
|
||||
<h2>Set IPFS RPC address:</h2>
|
||||
<p className="p">
|
||||
Specify IPFS to download file from
|
||||
</p>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
onChange={(e) => setRpcAddr(e.target.value)}
|
||||
value={rpcAddr!}
|
||||
/>
|
||||
</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>
|
||||
<div className="row">
|
||||
<label className="label bold">File Size:</label>
|
||||
<label className="mono">{fileSize}</label>
|
||||
</div>
|
||||
<div className="row">
|
||||
<label className="label bold">File size is uploaded to IPFS as CID:</label>
|
||||
<label className="mono">{fileSizeCID}</label>
|
||||
</div>
|
||||
</>
|
||||
const IpfsForm = (props: {
|
||||
rpcAddr: string;
|
||||
setRpcAddr: React.Dispatch<React.SetStateAction<string>>;
|
||||
wasm: string;
|
||||
setWasm: React.Dispatch<React.SetStateAction<string>>;
|
||||
deployService: () => Promise<void>;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div className="row">
|
||||
<h2>Set IPFS RPC address:</h2>
|
||||
<p className="p">Specify IPFS to download process_files.wasm from</p>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
onChange={(e) => props.setRpcAddr(e.target.value)}
|
||||
value={props.rpcAddr}
|
||||
/>
|
||||
</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) => props.setWasm(e.target.value)}
|
||||
value={props.wasm}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className="App">
|
||||
<header>
|
||||
<img src={logo} className="logo" alt="logo" />
|
||||
</header>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Deploy ProcessFiles service</h2>
|
||||
<p className="p">
|
||||
process_files.wasm will be downloaded via IPFS 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={props.deployService}>
|
||||
deploy service
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
<div className="content">
|
||||
<>
|
||||
<h2>Unimplemented! isConnected {isConnected} deployed {deployed} wasm {wasm} </h2>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const ConnectionForm = (props: {
|
||||
connect: (multiaddr: string) => Promise<void>;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<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 props.connect(x.multiaddr)}
|
||||
>
|
||||
Connect
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Connected = (props: { client: FluenceClient }) => {
|
||||
return (
|
||||
<>
|
||||
<h1>Connected</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<td className="bold">Peer id:</td>
|
||||
<td className="mono">{props.client.selfPeerId}</td>
|
||||
<td>
|
||||
<button
|
||||
className="btn-clipboard"
|
||||
onClick={() => copyToClipboard(props.client.selfPeerId)}
|
||||
>
|
||||
<i className="gg-clipboard"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="bold">Relay peer id:</td>
|
||||
<td className="mono">{props.client.relayPeerId}</td>
|
||||
<td>
|
||||
<button
|
||||
className="btn-clipboard"
|
||||
onClick={() => copyToClipboard(props.client.relayPeerId!)}
|
||||
>
|
||||
<i className="gg-clipboard"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
Reference in New Issue
Block a user