mirror of
https://github.com/fluencelabs/examples
synced 2025-04-25 02:32:16 +00:00
Intro: improve IPFS demo frontend (#16)
This commit is contained in:
parent
e5e0d59835
commit
41733278ac
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "ipfs-execution",
|
||||
"name": "@fluencelabs/ipfs-execution",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
@ -1275,7 +1275,7 @@
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"version": "npm:node-fetch@2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
@ -1414,7 +1414,7 @@
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"version": "npm:node-fetch@2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
@ -1566,7 +1566,7 @@
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "npm:@achingbrain/node-fetch@2.6.7",
|
||||
"version": "npm:node-fetch@2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g=="
|
||||
},
|
||||
|
@ -8,9 +8,9 @@
|
||||
"prebuild": "npm run compile-aqua",
|
||||
"build": "tsc",
|
||||
"prestart:local": "npm run build",
|
||||
"start:local": "node dist/index.js local",
|
||||
"start:local": "node dist/demo.js local",
|
||||
"prestart:remote": "npm run build",
|
||||
"start:remote": "node dist/index.js stage",
|
||||
"start:remote": "node dist/demo.js stage",
|
||||
"start": "npm run start:remote"
|
||||
},
|
||||
"keywords": [
|
||||
|
@ -1,7 +0,0 @@
|
||||
data SizeResult:
|
||||
size: u32
|
||||
success: bool
|
||||
error: string
|
||||
|
||||
service ProcessFiles:
|
||||
file_size(file_path: string) -> SizeResult
|
@ -19,7 +19,7 @@ import { set_timeout } from "@fluencelabs/aqua-ipfs";
|
||||
import {createClient, FluenceClient, setLogLevel} from "@fluencelabs/fluence";
|
||||
import {stage, krasnodar, Node, testNet} from "@fluencelabs/fluence-network-environment";
|
||||
import { provideFile, globSource, urlSource } from "./provider";
|
||||
import { deploy_service, get_file_size, remove_service } from "./process";
|
||||
import { deploy_service, put_file_size, remove_service } from "./process";
|
||||
|
||||
async function main(environment: Node[]) {
|
||||
// setLogLevel('DEBUG');
|
||||
@ -38,28 +38,49 @@ async function main(environment: Node[]) {
|
||||
await set_timeout(fluence, environment[2].peerId, 10);
|
||||
|
||||
console.log("\n\n📘 Will deploy ProcessFiles service");
|
||||
let service_id = await deploy_service(
|
||||
var service_id = await deploy_service(
|
||||
fluence,
|
||||
environment[2].peerId, file.cid.toString(), rpcAddr,
|
||||
(msg, value) => console.log(msg, value),
|
||||
(label, error) => { console.error("📕 deploy_service failed: ", label, error) },
|
||||
{ ttl: 10000 }
|
||||
)
|
||||
service_id = fromOption(service_id);
|
||||
if (service_id === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("📗 ProcessFiles service is now deployed and available as", service_id);
|
||||
|
||||
console.log("\n\n📘 Will upload file & calculate its size");
|
||||
let { file: newFile } = await provideFile(urlSource("https://i.imgur.com/NZgK6DB.png"), providerClient);
|
||||
let fileSize = await get_file_size(
|
||||
var putResult = await put_file_size(
|
||||
fluence,
|
||||
environment[2].peerId, newFile.cid.toString(), rpcAddr, service_id,
|
||||
fileSize => console.log("📗 Calculated file size:", fileSize),
|
||||
(label, error) => { console.error("📕 put_file_size failed: ", label, error) },
|
||||
{ ttl: 10000 }
|
||||
)
|
||||
console.log("📗 Calculated file size:", fileSize)
|
||||
putResult = fromOption(putResult);
|
||||
if (putResult !== null) {
|
||||
console.log("📗 File size is saved to IPFS:", putResult);
|
||||
}
|
||||
|
||||
let result = await remove_service(fluence, environment[2].peerId, service_id);
|
||||
console.log("📕 ProcessFiles service removed", result);
|
||||
console.log("📗 ProcessFiles service removed", result);
|
||||
return;
|
||||
}
|
||||
|
||||
function fromOption<T>(opt: T | T[] | null): T | null {
|
||||
if (Array.isArray(opt)) {
|
||||
if (opt.length === 0) { return null; }
|
||||
|
||||
opt = opt[0];
|
||||
}
|
||||
if (opt === null) { return null; }
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
let args = process.argv.slice(2);
|
||||
var environment: Node[];
|
||||
if (args.length >= 1 && args[0] == "testnet") {
|
||||
|
@ -16,28 +16,65 @@ service NewOp("op"):
|
||||
concat_strings(a: string, b: string) -> string
|
||||
array(s: string) -> []string
|
||||
|
||||
func deploy_service(relay: PeerId, cid: CID, provider_ipfs: Multiaddr, log: string, u32 -> ()) -> ServiceID:
|
||||
on relay:
|
||||
get_result <- Ipfs.get_from(cid, provider_ipfs)
|
||||
config <- NewDist.default_module_config("process_files")
|
||||
module_hash <- NewDist.add_module_from_vault(get_result.path, config)
|
||||
prefixed_hash <- NewOp.concat_strings("hash:", module_hash)
|
||||
dependencies <- NewOp.array(prefixed_hash)
|
||||
blueprint <- Dist.make_blueprint("process_files", dependencies)
|
||||
blueprint_id <- Dist.add_blueprint(blueprint)
|
||||
service_id <- Srv.create(blueprint_id)
|
||||
-- Add module to node
|
||||
func add_module(name: string, path: string) -> Hash:
|
||||
config <- NewDist.default_module_config(name)
|
||||
module_hash <- NewDist.add_module_from_vault(path, config)
|
||||
<- module_hash
|
||||
|
||||
-- Add service blueprint to node
|
||||
func add_blueprint(module_hash: Hash) -> string:
|
||||
prefixed_hash <- NewOp.concat_strings("hash:", module_hash)
|
||||
dependencies <- NewOp.array(prefixed_hash)
|
||||
blueprint <- Dist.make_blueprint("process_files", dependencies)
|
||||
blueprint_id <- Dist.add_blueprint(blueprint)
|
||||
<- blueprint_id
|
||||
|
||||
-- Download single .wasm module from IPFS and create a service from it
|
||||
func deploy_service(relay: PeerId, cid: CID, ipfs: Multiaddr, error: string, string -> ()) -> ?ServiceID:
|
||||
service_id: *ServiceID
|
||||
on relay:
|
||||
-- Download .wasm from IPFS to node
|
||||
get_result <- Ipfs.get_from(cid, ipfs)
|
||||
if get_result.success:
|
||||
module_hash <- add_module("process_files", get_result.path)
|
||||
blueprint_id <- add_blueprint(module_hash)
|
||||
service_id <- Srv.create(blueprint_id)
|
||||
else:
|
||||
co error("Ipfs.get_from failed", get_result.error)
|
||||
|
||||
ProcessFiles service_id
|
||||
size <- ProcessFiles.file_size(get_result.path)
|
||||
log("Size of the .wasm module is", size.size)
|
||||
<- service_id
|
||||
|
||||
func get_file_size(relay: PeerId, cid: CID, provider_ipfs: Multiaddr, service_id: ServiceID) -> SizeResult:
|
||||
-- Download file from IPFS, and write it's size to file in IPFS
|
||||
func put_file_size(
|
||||
relay: PeerId,
|
||||
cid: CID,
|
||||
ipfs: Multiaddr,
|
||||
service_id: ServiceID,
|
||||
logSize: u32 -> (),
|
||||
error: string, string -> ()
|
||||
) -> ?IpfsPutResult:
|
||||
result: *IpfsPutResult
|
||||
ProcessFiles service_id
|
||||
on relay:
|
||||
get_result <- Ipfs.get_from(cid, provider_ipfs)
|
||||
size <- ProcessFiles.file_size(get_result.path)
|
||||
<- size
|
||||
get <- Ipfs.get_from(cid, ipfs)
|
||||
if get.success:
|
||||
size <- ProcessFiles.file_size(get.path)
|
||||
if size.success:
|
||||
-- report file size in background
|
||||
co logSize(size.size)
|
||||
-- write file size to disk
|
||||
write <- ProcessFiles.write_file_size(size.size)
|
||||
if write.success:
|
||||
-- upload file to ipfs
|
||||
result <- Ipfs.put(write.path)
|
||||
else:
|
||||
co error("ProcessFiles.write_file_size failed", write.error)
|
||||
else:
|
||||
co error("ProcessFiles.file_size failed", size.error)
|
||||
else:
|
||||
co error("Ipfs.get_from failed", get.error)
|
||||
<- result
|
||||
|
||||
func remove_service(relay: PeerId, service_id: ServiceID) -> bool:
|
||||
on relay:
|
||||
|
@ -12,7 +12,7 @@ import { RequestFlow } from '@fluencelabs/fluence/dist/internal/RequestFlow';
|
||||
|
||||
|
||||
|
||||
export async function deploy_service(client: FluenceClient, relay: string, cid: string, provider_ipfs: string, log: (arg0: string, arg1: number) => void, config?: {ttl?: number}): Promise<string> {
|
||||
export async function add_blueprint(client: FluenceClient, module_hash: string, config?: {ttl?: number}): Promise<string> {
|
||||
let request: RequestFlow;
|
||||
const promise = new Promise<string>((resolve, reject) => {
|
||||
const r = new RequestFlowBuilder()
|
||||
@ -27,58 +27,22 @@ export async function deploy_service(client: FluenceClient, relay: string, cid:
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(call %init_peer_id% ("getDataSrv" "relay") [] relay)
|
||||
(call %init_peer_id% ("getDataSrv" "module_hash") [] module_hash)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "cid") [] cid)
|
||||
(call %init_peer_id% ("op" "concat_strings") ["hash:" module_hash] prefixed_hash)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "provider_ipfs") [] provider_ipfs)
|
||||
(call %init_peer_id% ("op" "array") [prefixed_hash] dependencies)
|
||||
)
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call relay ("ipfs-adapter" "get_from") [cid provider_ipfs] get_result)
|
||||
(call relay ("dist" "default_module_config") ["process_files"] config)
|
||||
)
|
||||
(call relay ("dist" "add_module_from_vault") [get_result.$.path! config] module_hash)
|
||||
)
|
||||
(call relay ("op" "concat_strings") ["hash:" module_hash] prefixed_hash)
|
||||
)
|
||||
(call relay ("op" "array") [prefixed_hash] dependencies)
|
||||
)
|
||||
(call relay ("dist" "make_blueprint") ["process_files" dependencies] blueprint)
|
||||
)
|
||||
(call relay ("dist" "add_blueprint") [blueprint] blueprint_id)
|
||||
)
|
||||
(call relay ("srv" "create") [blueprint_id] service_id)
|
||||
)
|
||||
(call relay (service_id "file_size") [get_result.$.path!] size)
|
||||
)
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "log") ["Size of the .wasm module is" size.$.size!])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
(call %init_peer_id% ("dist" "make_blueprint") ["process_files" dependencies] blueprint)
|
||||
)
|
||||
(call %init_peer_id% ("dist" "add_blueprint") [blueprint] blueprint_id)
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "response") [service_id])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
|
||||
(call %init_peer_id% ("callbackSrv" "response") [blueprint_id])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 4])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
|
||||
`,
|
||||
@ -87,10 +51,7 @@ export async function deploy_service(client: FluenceClient, relay: string, cid:
|
||||
h.on('getDataSrv', '-relay-', () => {
|
||||
return client.relayPeerId!;
|
||||
});
|
||||
h.on('getDataSrv', 'relay', () => {return relay;});
|
||||
h.on('getDataSrv', 'cid', () => {return cid;});
|
||||
h.on('getDataSrv', 'provider_ipfs', () => {return provider_ipfs;});
|
||||
h.on('callbackSrv', 'log', (args) => {log(args[0], args[1]); return {};});
|
||||
h.on('getDataSrv', 'module_hash', () => {return module_hash;});
|
||||
h.onEvent('callbackSrv', 'response', (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
@ -104,7 +65,7 @@ h.on('callbackSrv', 'log', (args) => {log(args[0], args[1]); return {};});
|
||||
})
|
||||
.handleScriptError(reject)
|
||||
.handleTimeout(() => {
|
||||
reject('Request timed out for deploy_service');
|
||||
reject('Request timed out for add_blueprint');
|
||||
})
|
||||
if(config && config.ttl) {
|
||||
r.withTTL(config.ttl)
|
||||
@ -117,9 +78,9 @@ h.on('callbackSrv', 'log', (args) => {log(args[0], args[1]); return {};});
|
||||
|
||||
|
||||
|
||||
export async function get_file_size(client: FluenceClient, relay: string, cid: string, provider_ipfs: string, service_id: string, config?: {ttl?: number}): Promise<{error:string;size:number;success:boolean}> {
|
||||
export async function put_file_size(client: FluenceClient, relay: string, cid: string, ipfs: string, service_id: string, logSize: (arg0: number) => void, error: (arg0: string, arg1: string) => void, config?: {ttl?: number}): Promise<{error:string;hash:string;success:boolean} | null> {
|
||||
let request: RequestFlow;
|
||||
const promise = new Promise<{error:string;size:number;success:boolean}>((resolve, reject) => {
|
||||
const promise = new Promise<{error:string;hash:string;success:boolean} | null>((resolve, reject) => {
|
||||
const r = new RequestFlowBuilder()
|
||||
.disableInjections()
|
||||
.withRawScript(
|
||||
@ -138,7 +99,7 @@ export async function get_file_size(client: FluenceClient, relay: string, cid: s
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "cid") [] cid)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "provider_ipfs") [] provider_ipfs)
|
||||
(call %init_peer_id% ("getDataSrv" "ipfs") [] ipfs)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "service_id") [] service_id)
|
||||
)
|
||||
@ -146,23 +107,104 @@ export async function get_file_size(client: FluenceClient, relay: string, cid: s
|
||||
)
|
||||
(xor
|
||||
(seq
|
||||
(call relay ("ipfs-adapter" "get_from") [cid provider_ipfs] get_result)
|
||||
(call relay (service_id "file_size") [get_result.$.path!] size)
|
||||
(call relay ("ipfs-adapter" "get_from") [cid ipfs] get)
|
||||
(xor
|
||||
(match get.$.success! true
|
||||
(xor
|
||||
(seq
|
||||
(call relay (service_id "file_size") [get.$.path!] size)
|
||||
(xor
|
||||
(match size.$.success! true
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(par
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "logSize") [size.$.size!])
|
||||
(seq
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
(call relay (service_id "write_file_size") [size.$.size!] write)
|
||||
)
|
||||
(xor
|
||||
(match write.$.success! true
|
||||
(xor
|
||||
(call relay ("ipfs-adapter" "put") [write.$.path!] $result)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
)
|
||||
)
|
||||
(par
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "error") ["ProcessFiles.write_file_size failed" write.$.error!])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 4])
|
||||
)
|
||||
)
|
||||
)
|
||||
(par
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "error") ["ProcessFiles.file_size failed" size.$.error!])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 5])
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 6])
|
||||
)
|
||||
)
|
||||
)
|
||||
(par
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "error") ["Ipfs.get_from failed" get.$.error!])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 7])
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 8])
|
||||
)
|
||||
)
|
||||
)
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "response") [size])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
(call %init_peer_id% ("callbackSrv" "response") [$result])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 9])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 10])
|
||||
)
|
||||
|
||||
`,
|
||||
@ -173,8 +215,10 @@ export async function get_file_size(client: FluenceClient, relay: string, cid: s
|
||||
});
|
||||
h.on('getDataSrv', 'relay', () => {return relay;});
|
||||
h.on('getDataSrv', 'cid', () => {return cid;});
|
||||
h.on('getDataSrv', 'provider_ipfs', () => {return provider_ipfs;});
|
||||
h.on('getDataSrv', 'ipfs', () => {return ipfs;});
|
||||
h.on('getDataSrv', 'service_id', () => {return service_id;});
|
||||
h.on('callbackSrv', 'logSize', (args) => {logSize(args[0]); return {};});
|
||||
h.on('callbackSrv', 'error', (args) => {error(args[0], args[1]); return {};});
|
||||
h.onEvent('callbackSrv', 'response', (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
@ -188,7 +232,7 @@ h.on('getDataSrv', 'service_id', () => {return service_id;});
|
||||
})
|
||||
.handleScriptError(reject)
|
||||
.handleTimeout(() => {
|
||||
reject('Request timed out for get_file_size');
|
||||
reject('Request timed out for put_file_size');
|
||||
})
|
||||
if(config && config.ttl) {
|
||||
r.withTTL(config.ttl)
|
||||
@ -272,3 +316,186 @@ h.on('getDataSrv', 'service_id', () => {return service_id;});
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export async function add_module(client: FluenceClient, name: string, path: string, config?: {ttl?: number}): Promise<string> {
|
||||
let request: RequestFlow;
|
||||
const promise = new Promise<string>((resolve, reject) => {
|
||||
const r = new RequestFlowBuilder()
|
||||
.disableInjections()
|
||||
.withRawScript(
|
||||
`
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(call %init_peer_id% ("getDataSrv" "name") [] name)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "path") [] path)
|
||||
)
|
||||
(call %init_peer_id% ("dist" "default_module_config") [name] config)
|
||||
)
|
||||
(call %init_peer_id% ("dist" "add_module_from_vault") [path config] module_hash)
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "response") [module_hash])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
|
||||
`,
|
||||
)
|
||||
.configHandler((h) => {
|
||||
h.on('getDataSrv', '-relay-', () => {
|
||||
return client.relayPeerId!;
|
||||
});
|
||||
h.on('getDataSrv', 'name', () => {return name;});
|
||||
h.on('getDataSrv', 'path', () => {return path;});
|
||||
h.onEvent('callbackSrv', 'response', (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
});
|
||||
|
||||
h.onEvent('errorHandlingSrv', 'error', (args) => {
|
||||
// assuming error is the single argument
|
||||
const [err] = args;
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
.handleScriptError(reject)
|
||||
.handleTimeout(() => {
|
||||
reject('Request timed out for add_module');
|
||||
})
|
||||
if(config && config.ttl) {
|
||||
r.withTTL(config.ttl)
|
||||
}
|
||||
request = r.build();
|
||||
});
|
||||
await client.initiateFlow(request!);
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export async function deploy_service(client: FluenceClient, relay: string, cid: string, ipfs: string, error: (arg0: string, arg1: string) => void, config?: {ttl?: number}): Promise<string | null> {
|
||||
let request: RequestFlow;
|
||||
const promise = new Promise<string | null>((resolve, reject) => {
|
||||
const r = new RequestFlowBuilder()
|
||||
.disableInjections()
|
||||
.withRawScript(
|
||||
`
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
|
||||
(call %init_peer_id% ("getDataSrv" "relay") [] relay)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "cid") [] cid)
|
||||
)
|
||||
(call %init_peer_id% ("getDataSrv" "ipfs") [] ipfs)
|
||||
)
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
(xor
|
||||
(seq
|
||||
(call relay ("ipfs-adapter" "get_from") [cid ipfs] get_result)
|
||||
(xor
|
||||
(match get_result.$.success! true
|
||||
(xor
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(seq
|
||||
(call relay ("dist" "default_module_config") ["process_files"] config)
|
||||
(call relay ("dist" "add_module_from_vault") [get_result.$.path! config] module_hash)
|
||||
)
|
||||
(call relay ("op" "concat_strings") ["hash:" module_hash] prefixed_hash)
|
||||
)
|
||||
(call relay ("op" "array") [prefixed_hash] dependencies)
|
||||
)
|
||||
(call relay ("dist" "make_blueprint") ["process_files" dependencies] blueprint)
|
||||
)
|
||||
(call relay ("dist" "add_blueprint") [blueprint] blueprint_id)
|
||||
)
|
||||
(call relay ("srv" "create") [blueprint_id] $service_id)
|
||||
)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
|
||||
)
|
||||
)
|
||||
)
|
||||
(par
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "error") ["Ipfs.get_from failed" get_result.$.error!])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
|
||||
)
|
||||
)
|
||||
(null)
|
||||
)
|
||||
)
|
||||
)
|
||||
(seq
|
||||
(call -relay- ("op" "noop") [])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3])
|
||||
)
|
||||
)
|
||||
)
|
||||
(call -relay- ("op" "noop") [])
|
||||
)
|
||||
(xor
|
||||
(call %init_peer_id% ("callbackSrv" "response") [$service_id])
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 4])
|
||||
)
|
||||
)
|
||||
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 5])
|
||||
)
|
||||
|
||||
`,
|
||||
)
|
||||
.configHandler((h) => {
|
||||
h.on('getDataSrv', '-relay-', () => {
|
||||
return client.relayPeerId!;
|
||||
});
|
||||
h.on('getDataSrv', 'relay', () => {return relay;});
|
||||
h.on('getDataSrv', 'cid', () => {return cid;});
|
||||
h.on('getDataSrv', 'ipfs', () => {return ipfs;});
|
||||
h.on('callbackSrv', 'error', (args) => {error(args[0], args[1]); return {};});
|
||||
h.onEvent('callbackSrv', 'response', (args) => {
|
||||
const [res] = args;
|
||||
resolve(res);
|
||||
});
|
||||
|
||||
h.onEvent('errorHandlingSrv', 'error', (args) => {
|
||||
// assuming error is the single argument
|
||||
const [err] = args;
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
.handleScriptError(reject)
|
||||
.handleTimeout(() => {
|
||||
reject('Request timed out for deploy_service');
|
||||
})
|
||||
if(config && config.ttl) {
|
||||
r.withTTL(config.ttl)
|
||||
}
|
||||
request = r.build();
|
||||
});
|
||||
await client.initiateFlow(request!);
|
||||
return promise;
|
||||
}
|
||||
|
@ -3,5 +3,11 @@ data SizeResult:
|
||||
success: bool
|
||||
error: string
|
||||
|
||||
data WriteResult:
|
||||
path: string
|
||||
success: bool
|
||||
error: string
|
||||
|
||||
service ProcessFiles:
|
||||
file_size(file_path: string) -> SizeResult
|
||||
write_file_size(size: u32) -> WriteResult
|
||||
|
@ -13,6 +13,7 @@ path = "src/main.rs"
|
||||
[dependencies]
|
||||
marine-rs-sdk = { version="0.6.11", features=["logger"] }
|
||||
log = "0.4.14"
|
||||
rand = "0.8.4"
|
||||
|
||||
[dev-dependencies]
|
||||
marine-rs-sdk-test = "0.1.11"
|
||||
|
@ -5,4 +5,4 @@ mkdir -p artifacts
|
||||
rm -f artifacts/*.wasm
|
||||
marine build --release
|
||||
cp target/wasm32-wasi/release/process_files.wasm artifacts/
|
||||
marine aqua artifacts/process_files.wasm >../aqua/process_files.aqua
|
||||
marine aqua artifacts/process_files.wasm >../aqua/src/process_files.aqua
|
||||
|
@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use marine_rs_sdk::{marine, module_manifest};
|
||||
use marine_rs_sdk::{marine, module_manifest, get_call_parameters};
|
||||
use std::path::{PathBuf, Path};
|
||||
use rand::Rng;
|
||||
use rand::distributions::Alphanumeric;
|
||||
|
||||
module_manifest!();
|
||||
|
||||
@ -35,3 +38,32 @@ pub fn file_size(file_path: String) -> SizeResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub struct WriteResult {
|
||||
pub path: String,
|
||||
pub success: bool,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub fn write_file_size(size: u32) -> WriteResult {
|
||||
let name: String = rand::thread_rng()
|
||||
.sample_iter(Alphanumeric)
|
||||
.take(16)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
|
||||
let file = vault_dir().join(&name);
|
||||
let file_str = file.to_string_lossy().to_string();
|
||||
match std::fs::write(&file, size.to_string()) {
|
||||
Ok(_) => WriteResult { path: file_str, success: true, error: String::new() },
|
||||
Err(err) => WriteResult { path: String::new(), success: false, error: err.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
fn vault_dir() -> PathBuf {
|
||||
let particle_id = get_call_parameters().particle_id;
|
||||
let vault = Path::new("/tmp").join("vault").join(particle_id);
|
||||
|
||||
vault
|
||||
}
|
689
intro/4-ipfs-code-execution/web/package-lock.json
generated
689
intro/4-ipfs-code-execution/web/package-lock.json
generated
@ -1295,6 +1295,122 @@
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz",
|
||||
"integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ=="
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cids": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/cids/-/cids-1.1.7.tgz",
|
||||
"integrity": "sha512-dlh+K0hMwFAFFjWQ2ZzxOhgGVNVREPdmk8cqHFui2U4sOodcemLMxdE5Ujga4cDcDQhWfldEPThkfu6KWBt1eA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashes": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
"integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1",
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"multicodec": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.1.0.tgz",
|
||||
"integrity": "sha512-f6d4DhbQ9a8WiJ/wpbKgeJSeR0/juP/1wnjbKdZ0KAWDkC/z7Lb3xOegMUG+uTcfwSYf6j1eTvFf8HDgqPRGmQ==",
|
||||
"requires": {
|
||||
"uint8arrays": "^2.1.5",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.2.tgz",
|
||||
"integrity": "sha512-xpx++1iZr4ZQHjN1mcrXS6904R36LWLxX/CBifczjtmrtCXEX623DMWOF1eiNSg+pFpiZDFVBgou/4v6ayCHSQ==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
|
||||
@ -12563,6 +12679,11 @@
|
||||
"pify": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"hamt_plus": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
|
||||
"integrity": "sha1-4hwlKWjH4zsg9qGwlM2FeHomVgE="
|
||||
},
|
||||
"handle-thing": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
|
||||
@ -16821,6 +16942,46 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
"integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1",
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz",
|
||||
"integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
@ -17022,6 +17183,37 @@
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"cids": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/cids/-/cids-1.1.7.tgz",
|
||||
"integrity": "sha512-dlh+K0hMwFAFFjWQ2ZzxOhgGVNVREPdmk8cqHFui2U4sOodcemLMxdE5Ujga4cDcDQhWfldEPThkfu6KWBt1eA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashes": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.2.tgz",
|
||||
"integrity": "sha512-xpx++1iZr4ZQHjN1mcrXS6904R36LWLxX/CBifczjtmrtCXEX623DMWOF1eiNSg+pFpiZDFVBgou/4v6ayCHSQ==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^5.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"it-length-prefixed": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-3.1.0.tgz",
|
||||
@ -17033,6 +17225,32 @@
|
||||
"varint": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
@ -17042,6 +17260,22 @@
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"multicodec": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.1.0.tgz",
|
||||
"integrity": "sha512-f6d4DhbQ9a8WiJ/wpbKgeJSeR0/juP/1wnjbKdZ0KAWDkC/z7Lb3xOegMUG+uTcfwSYf6j1eTvFf8HDgqPRGmQ==",
|
||||
"requires": {
|
||||
"uint8arrays": "^2.1.5",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-3.1.2.tgz",
|
||||
@ -17231,6 +17465,35 @@
|
||||
"private-ip": "^2.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"cids": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/cids/-/cids-1.1.7.tgz",
|
||||
"integrity": "sha512-dlh+K0hMwFAFFjWQ2ZzxOhgGVNVREPdmk8cqHFui2U4sOodcemLMxdE5Ujga4cDcDQhWfldEPThkfu6KWBt1eA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashes": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip-address": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-6.4.0.tgz",
|
||||
@ -17250,10 +17513,95 @@
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
|
||||
"integrity": "sha1-sBMHyym2GKHtJux56RH4A8TaAEA="
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
"integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1",
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"multicodec": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.1.0.tgz",
|
||||
"integrity": "sha512-f6d4DhbQ9a8WiJ/wpbKgeJSeR0/juP/1wnjbKdZ0KAWDkC/z7Lb3xOegMUG+uTcfwSYf6j1eTvFf8HDgqPRGmQ==",
|
||||
"requires": {
|
||||
"uint8arrays": "^2.1.5",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.2.tgz",
|
||||
"integrity": "sha512-xpx++1iZr4ZQHjN1mcrXS6904R36LWLxX/CBifczjtmrtCXEX623DMWOF1eiNSg+pFpiZDFVBgou/4v6ayCHSQ==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
|
||||
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -17276,15 +17624,136 @@
|
||||
"p-timeout": "^4.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cids": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/cids/-/cids-1.1.7.tgz",
|
||||
"integrity": "sha512-dlh+K0hMwFAFFjWQ2ZzxOhgGVNVREPdmk8cqHFui2U4sOodcemLMxdE5Ujga4cDcDQhWfldEPThkfu6KWBt1eA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashes": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"err-code": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz",
|
||||
"integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA=="
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"err-code": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
|
||||
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
"integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1",
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"multicodec": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.1.0.tgz",
|
||||
"integrity": "sha512-f6d4DhbQ9a8WiJ/wpbKgeJSeR0/juP/1wnjbKdZ0KAWDkC/z7Lb3xOegMUG+uTcfwSYf6j1eTvFf8HDgqPRGmQ==",
|
||||
"requires": {
|
||||
"uint8arrays": "^2.1.5",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.2.tgz",
|
||||
"integrity": "sha512-xpx++1iZr4ZQHjN1mcrXS6904R36LWLxX/CBifczjtmrtCXEX623DMWOF1eiNSg+pFpiZDFVBgou/4v6ayCHSQ==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"p-timeout": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
|
||||
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw=="
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -17488,6 +17957,122 @@
|
||||
"integrity": "sha512-wwZ5+PU0vQw10kwQRyZin1Z0dqVOp0BnYlX1xvXHS2fmLwrrQCfU1+3tlW5MRcihUwGz1virnVhbRAU1biKfiw==",
|
||||
"requires": {
|
||||
"multiaddr": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cids": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/cids/-/cids-1.1.7.tgz",
|
||||
"integrity": "sha512-dlh+K0hMwFAFFjWQ2ZzxOhgGVNVREPdmk8cqHFui2U4sOodcemLMxdE5Ujga4cDcDQhWfldEPThkfu6KWBt1eA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashes": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
"integrity": "sha512-bpklWHs70LO3smJUHOjcnzGceJJvn9ui0Vau6Za0B/GBepaXswmW8Ufea0uD9pROf/qCQ4N4lZ3sf3U+SNf0tw==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1",
|
||||
"web-encoding": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"multicodec": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-3.1.0.tgz",
|
||||
"integrity": "sha512-f6d4DhbQ9a8WiJ/wpbKgeJSeR0/juP/1wnjbKdZ0KAWDkC/z7Lb3xOegMUG+uTcfwSYf6j1eTvFf8HDgqPRGmQ==",
|
||||
"requires": {
|
||||
"uint8arrays": "^2.1.5",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-4.0.2.tgz",
|
||||
"integrity": "sha512-xpx++1iZr4ZQHjN1mcrXS6904R36LWLxX/CBifczjtmrtCXEX623DMWOF1eiNSg+pFpiZDFVBgou/4v6ayCHSQ==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^5.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-1.1.0.tgz",
|
||||
"integrity": "sha512-cLdlZ6jnFczsKf5IH1gPHTtcHtPGho5r4CvctohmQjw8K7Q3gFdfIGHxSTdTaCKrL4w09SsPRJTqRS0drYeszA==",
|
||||
"requires": {
|
||||
"multibase": "^3.0.0",
|
||||
"web-encoding": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"magic-string": {
|
||||
@ -18002,18 +18587,36 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-10.0.0.tgz",
|
||||
"integrity": "sha512-yP3LzFkM0GORZHNenS8Ok2spsaICRBhxLEohAfKKwwrgHIEWrDUhMRIkh/MONDBThNqaiGl7Ch1H7qblRDNHyg==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"err-code": "^3.0.1",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
"multiformats": "^9.0.2",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"err-code": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz",
|
||||
"integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA=="
|
||||
},
|
||||
"varint": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
|
||||
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiaddr-to-uri": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr-to-uri/-/multiaddr-to-uri-6.0.0.tgz",
|
||||
"integrity": "sha512-OjpkVHOXEmIKMO8WChzzQ7aZQcSQX8squxmvtDbRpy7/QNmJ3Z7jv6qyD74C28QtaeNie8O8ngW2AkeiMmKP7A==",
|
||||
"requires": {
|
||||
"multiaddr": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cids": {
|
||||
@ -18036,15 +18639,30 @@
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.5.tgz",
|
||||
"integrity": "sha512-CSR7AO+4AHUeSOnZ/NBNCElDeWfRh9bXtOck27083kc7SznmmHIhNEkEOCQOn0wvrIMjS3IH0TNLR16vuc46mA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1"
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiaddr": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr/-/multiaddr-8.1.2.tgz",
|
||||
"integrity": "sha512-r13IzW8+Sv9zab9Gt8RPMIN2WkptIPq99EpAzg4IbJ/zTELhiEwXWr9bAmEatSCI4j/LSA6ESJzvz95JZ+ZYXQ==",
|
||||
"requires": {
|
||||
"cids": "^1.0.0",
|
||||
"class-is": "^1.1.0",
|
||||
"dns-over-http-resolver": "^1.0.0",
|
||||
"err-code": "^2.0.3",
|
||||
"is-ip": "^3.1.0",
|
||||
"multibase": "^3.0.0",
|
||||
"uint8arrays": "^1.1.0",
|
||||
"varint": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-3.1.2.tgz",
|
||||
@ -18063,20 +18681,12 @@
|
||||
"varint": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"multibase": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-4.0.4.tgz",
|
||||
"integrity": "sha512-8/JmrdSGzlw6KTgAJCOqUBSGd1V6186i/X8dDCGy/lbCKrQ+1QB6f3HE+wPr7Tpdj4U3gutaj9jG2rNX6UpiJg==",
|
||||
"requires": {
|
||||
"@multiformats/base-x": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.5.tgz",
|
||||
"integrity": "sha512-CSR7AO+4AHUeSOnZ/NBNCElDeWfRh9bXtOck27083kc7SznmmHIhNEkEOCQOn0wvrIMjS3IH0TNLR16vuc46mA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1"
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
},
|
||||
"varint": {
|
||||
@ -18105,11 +18715,11 @@
|
||||
}
|
||||
},
|
||||
"uint8arrays": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.5.tgz",
|
||||
"integrity": "sha512-CSR7AO+4AHUeSOnZ/NBNCElDeWfRh9bXtOck27083kc7SznmmHIhNEkEOCQOn0wvrIMjS3IH0TNLR16vuc46mA==",
|
||||
"version": "2.1.7",
|
||||
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-2.1.7.tgz",
|
||||
"integrity": "sha512-k+yuEWEHQG/TuRaxL+JVEe8IBqyU5dhDkw+CISCDccOcW90dIju0A6i0Iwav0MK7kg73FZpowqOByS5e/B6GYA==",
|
||||
"requires": {
|
||||
"multibase": "^4.0.1"
|
||||
"multiformats": "^9.4.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18125,14 +18735,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiaddr-to-uri": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/multiaddr-to-uri/-/multiaddr-to-uri-6.0.0.tgz",
|
||||
"integrity": "sha512-OjpkVHOXEmIKMO8WChzzQ7aZQcSQX8squxmvtDbRpy7/QNmJ3Z7jv6qyD74C28QtaeNie8O8ngW2AkeiMmKP7A==",
|
||||
"requires": {
|
||||
"multiaddr": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"multibase": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz",
|
||||
@ -18187,6 +18789,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"multiformats": {
|
||||
"version": "9.4.3",
|
||||
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.4.3.tgz",
|
||||
"integrity": "sha512-sCNjBP/NPCeQu83Mst8IQZq9+HuR7Catvk/m7CeH0r/nupsU6gM7GINf5E1HCDRxDeU+Cgda/WPmcwQhYs3dyA=="
|
||||
},
|
||||
"multihashes": {
|
||||
"version": "0.4.21",
|
||||
"resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz",
|
||||
@ -21184,6 +21791,14 @@
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"recoil": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.3.1.tgz",
|
||||
"integrity": "sha512-KNA3DRqgxX4rRC8E7fc6uIw7BACmMPuraIYy+ejhE8tsw7w32CetMm8w7AMZa34wzanKKkev3vl3H7Z4s0QSiA==",
|
||||
"requires": {
|
||||
"hamt_plus": "1.0.2"
|
||||
}
|
||||
},
|
||||
"recursive-readdir": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||
|
@ -4,10 +4,9 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-ipfs": "0.1.8",
|
||||
"@fluencelabs/ipfs-execution": "file:../aqua",
|
||||
"@fluencelabs/fluence": "0.9.53",
|
||||
"@fluencelabs/fluence-network-environment": "1.0.10",
|
||||
"ipfs-http-client": "^50.1.2",
|
||||
"@fluencelabs/ipfs-execution": "file:../aqua",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
@ -15,9 +14,12 @@
|
||||
"@types/node": "^12.20.16",
|
||||
"@types/react": "^17.0.14",
|
||||
"@types/react-dom": "^17.0.9",
|
||||
"ipfs-http-client": "^50.1.2",
|
||||
"multiaddr": "^10.0.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "4.0.3",
|
||||
"recoil": "^0.3.1",
|
||||
"typescript": "^4.3.5",
|
||||
"web-vitals": "^1.1.2"
|
||||
},
|
||||
|
@ -3,7 +3,7 @@ $color2: rgb(214, 214, 214);
|
||||
$accent-color: rgb(225, 30, 90);
|
||||
|
||||
.logo {
|
||||
height: 15vmin;
|
||||
height: 10vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ $accent-color: rgb(225, 30, 90);
|
||||
}
|
||||
|
||||
header {
|
||||
margin-top: 10vmin;
|
||||
margin-top: 3vmin;
|
||||
}
|
||||
|
||||
header,
|
||||
@ -44,23 +44,13 @@ li {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.p {
|
||||
width: 550px;
|
||||
p {
|
||||
margin: 0.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $accent-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
.row {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@ -88,27 +78,49 @@ li {
|
||||
}
|
||||
}
|
||||
|
||||
.btn-hello {
|
||||
width: 200px;
|
||||
.btn-right {
|
||||
width: 250px;
|
||||
display: inline;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.btn-inline {
|
||||
background-color: transparent;
|
||||
margin: 5px;
|
||||
|
||||
display: inline;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
color: $accent-color;
|
||||
outline: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 70px;
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 500px;
|
||||
width: calc(70% - 15px);
|
||||
height: 26px;
|
||||
box-sizing: border-box;
|
||||
|
||||
margin: 5px;
|
||||
padding: 0 5px;
|
||||
border: 1px solid;
|
||||
border-color: $color2;
|
||||
|
||||
@ -125,78 +137,19 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
.gg-clipboard {
|
||||
.input-ro {
|
||||
display: inline;
|
||||
width: 500px;
|
||||
height: 26px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: block;
|
||||
transform: scale(var(--ggs, 1));
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 2px solid;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.gg-clipboard::after,
|
||||
.gg-clipboard::before {
|
||||
content: "";
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
border-radius: 2px;
|
||||
width: 10px;
|
||||
left: 2px;
|
||||
}
|
||||
.gg-clipboard::before {
|
||||
border: 2px solid;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
top: -2px;
|
||||
height: 6px;
|
||||
}
|
||||
.gg-clipboard::after {
|
||||
height: 2px;
|
||||
background: currentColor;
|
||||
box-shadow: 0 -4px 0 0;
|
||||
bottom: 2px;
|
||||
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.gg-trash {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: block;
|
||||
transform: scale(var(--ggs,1));
|
||||
width: 10px;
|
||||
height: 12px;
|
||||
border: 2px solid transparent;
|
||||
box-shadow:
|
||||
0 0 0 2px,
|
||||
inset -2px 0 0,
|
||||
inset 2px 0 0;
|
||||
border-bottom-left-radius: 1px;
|
||||
border-bottom-right-radius: 1px;
|
||||
margin-top: 4px
|
||||
}
|
||||
.gg-trash::after,
|
||||
.gg-trash::before {
|
||||
content: "";
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
position: absolute
|
||||
}
|
||||
.gg-trash::after {
|
||||
background: currentColor;
|
||||
border-radius: 3px;
|
||||
width: 16px;
|
||||
height: 2px;
|
||||
top: -4px;
|
||||
left: -5px
|
||||
}
|
||||
.gg-trash::before {
|
||||
width: 10px;
|
||||
height: 4px;
|
||||
border: 2px solid;
|
||||
border-bottom: transparent;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
top: -7px;
|
||||
left: -2px
|
||||
.article {
|
||||
width: 700px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 100px;
|
||||
}
|
||||
|
@ -1,304 +1,54 @@
|
||||
import React, { useState } from "react";
|
||||
import React 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);
|
||||
};
|
||||
import {
|
||||
gotRpcAddrState,
|
||||
hasResultState,
|
||||
isConnectedState,
|
||||
isDeployedState,
|
||||
} from "./appState";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { ConnectedInfo } from "./Components/ConnectedInfo";
|
||||
import { ConnectionForm } from "./Components/ConnectionForm";
|
||||
import { IpfsForm } from "./Components/IpfsForm";
|
||||
import { IpfsDeploymentInfo } from "./Components/IpfsDeploymentInfo";
|
||||
import { SizeCalcForm } from "./Components/SizeCalcForm";
|
||||
import { SizeCalcResult } from "./Components/SizeCalcResult";
|
||||
|
||||
function App() {
|
||||
const [client, setClient] = useState<FluenceClient | null>(null);
|
||||
const [serviceId, setServiceId] = useState<string | null>(null);
|
||||
const isConnected = useRecoilValue(isConnectedState);
|
||||
const gotRpcAddr = useRecoilValue(gotRpcAddrState);
|
||||
const isDeployed = useRecoilValue(isDeployedState);
|
||||
const hasResult = useRecoilValue(hasResultState);
|
||||
|
||||
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);
|
||||
console.log(
|
||||
"isConnected gotRpcAddr deployed\n",
|
||||
isConnected,
|
||||
gotRpcAddr,
|
||||
isDeployed
|
||||
);
|
||||
|
||||
const isConnected = client !== null;
|
||||
const gotRpcAddr = rpcAddr !== null;
|
||||
const deployed = serviceId !== null;
|
||||
return (
|
||||
<div className="App">
|
||||
<header>
|
||||
<img src={logo} className="logo" alt="logo" />
|
||||
</header>
|
||||
|
||||
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">
|
||||
<div className="content">
|
||||
{!isConnected && <ConnectionForm />}
|
||||
{isConnected && <ConnectedInfo />}
|
||||
{isConnected && gotRpcAddr && !isDeployed && <IpfsForm />}
|
||||
{isDeployed && (
|
||||
<>
|
||||
<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>
|
||||
<IpfsDeploymentInfo />
|
||||
<SizeCalcForm />
|
||||
</>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
}
|
||||
)}
|
||||
{isDeployed && hasResult && <SizeCalcResult />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { clientState } from "../appState";
|
||||
import { TextWithLabel } from "./TextInput";
|
||||
|
||||
export const ConnectedInfo = () => {
|
||||
const client = useRecoilValue(clientState);
|
||||
if (client === null) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Connected</h1>
|
||||
<TextWithLabel text={"Peer id:"} value={client.selfPeerId} />
|
||||
<TextWithLabel text={"Relay peer id:"} value={client.selfPeerId} />
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,21 @@
|
||||
import { relayNodes, useClientConnect } from "../appLogic";
|
||||
|
||||
export const ConnectionForm = () => {
|
||||
const connect = useClientConnect();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Pick a relay</h1>
|
||||
<ul>
|
||||
{relayNodes.map((x) => (
|
||||
<li key={x.peerId}>
|
||||
<span className="mono">{x.peerId}</span>
|
||||
<button className="btn" onClick={() => connect(x.multiaddr)}>
|
||||
Connect
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { useRemoveService } from "../appLogic";
|
||||
import { serviceIdState, wasmState } from "../appState";
|
||||
import { TextWithLabel } from "./TextInput";
|
||||
|
||||
export const IpfsDeploymentInfo = () => {
|
||||
const wasm = useRecoilValue(wasmState);
|
||||
const serviceId = useRecoilValue(serviceIdState);
|
||||
const removeService = useRemoveService();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>
|
||||
Service deployed{" "}
|
||||
<button className="btn-inline" onClick={removeService}>
|
||||
remove
|
||||
</button>
|
||||
</h2>
|
||||
<TextWithLabel text={"process_files.wasm CID:"} value={wasm} />
|
||||
<TextWithLabel text={"Service ID:"} value={serviceId} />
|
||||
</>
|
||||
);
|
||||
};
|
40
intro/4-ipfs-code-execution/web/src/Components/IpfsForm.tsx
Normal file
40
intro/4-ipfs-code-execution/web/src/Components/IpfsForm.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import { useRecoilState } from "recoil";
|
||||
import { useDeployService } from "../appLogic";
|
||||
import { rpcAddrState, wasmState } from "../appState";
|
||||
import { TextInput } from "./TextInput";
|
||||
|
||||
export const IpfsForm = () => {
|
||||
const [rpcAddr, setRpcAddr] = useRecoilState(rpcAddrState);
|
||||
const [wasm, setWasm] = useRecoilState(wasmState);
|
||||
const deployService = useDeployService();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>Deploy service from IPFS</h2>
|
||||
<div className="article">
|
||||
<p>Now we can deploy service from IPFS into Fluence network</p>
|
||||
<p>
|
||||
To do so, please specify IPFS RPC address of process_files.wasm from,
|
||||
and the CID of WebAssembly module to use (process_files.wasm)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<TextInput
|
||||
text={"IPFS RPC address"}
|
||||
value={rpcAddr}
|
||||
setValue={setRpcAddr}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
text={"process_files.wasm CID"}
|
||||
value={wasm}
|
||||
setValue={setWasm}
|
||||
/>
|
||||
<div className="row">
|
||||
<button className="btn btn-right" onClick={deployService}>
|
||||
deploy service
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
import { useRecoilState, useRecoilValue } from "recoil";
|
||||
import { useGetFileSize } from "../appLogic";
|
||||
import { fileCIDState, rpcAddrState } from "../appState";
|
||||
import { TextInput } from "./TextInput";
|
||||
|
||||
export const SizeCalcForm = () => {
|
||||
const [rpcAddr, setRpcAddr] = useRecoilState(rpcAddrState);
|
||||
const [fileCID, setFileCID] = useRecoilState(fileCIDState);
|
||||
const getFileSize = useGetFileSize();
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>Get file size</h2>
|
||||
<div className="article">
|
||||
<p>
|
||||
Upload any file to IPFS node <b>{rpcAddr}</b>
|
||||
</p>
|
||||
<p>
|
||||
And paste CID here and get the size of that file via ProcessFiles
|
||||
service you have just deployed
|
||||
</p>
|
||||
</div>
|
||||
<TextInput
|
||||
text={"IPFS RPC address"}
|
||||
value={rpcAddr}
|
||||
setValue={setRpcAddr}
|
||||
/>
|
||||
<TextInput text={"IPFS CID"} value={fileCID} setValue={setFileCID} />
|
||||
|
||||
<div className="row">
|
||||
<button className="btn btn-right" onClick={getFileSize}>
|
||||
get size
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { fileSizeCIDState, fileSizeState } from "../appState";
|
||||
import { TextWithLabel } from "./TextInput";
|
||||
|
||||
export const SizeCalcResult = () => {
|
||||
const fileSize = useRecoilValue(fileSizeState);
|
||||
const fileSizeCID = useRecoilValue(fileSizeCIDState);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2>Result</h2>
|
||||
<div className="article">
|
||||
<p>
|
||||
File size has been calculated and displayed below. Also the result of
|
||||
the calculation has been uploaded to IPFS and is available under it's
|
||||
CID
|
||||
</p>
|
||||
</div>
|
||||
<TextWithLabel text="File size:" value={fileSize} />
|
||||
<TextWithLabel text="File size IPFS CID:" value={fileSizeCID} />
|
||||
</>
|
||||
);
|
||||
};
|
32
intro/4-ipfs-code-execution/web/src/Components/TextInput.tsx
Normal file
32
intro/4-ipfs-code-execution/web/src/Components/TextInput.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React from "react";
|
||||
|
||||
export const TextInput = (props: {
|
||||
text: string;
|
||||
value: string | null;
|
||||
setValue: (val: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="row">
|
||||
<label className="label bold">{props.text}</label>
|
||||
<input
|
||||
className="input"
|
||||
type="text"
|
||||
onChange={(e) => props.setValue(e.target.value)}
|
||||
value={props.value || ""}
|
||||
required={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const TextWithLabel = (props: {
|
||||
text: string;
|
||||
value: string | null;
|
||||
}) => {
|
||||
return (
|
||||
<div className="row">
|
||||
<label className="label bold">{props.text}</label>
|
||||
<div className="input-ro">{props.value || ""}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
133
intro/4-ipfs-code-execution/web/src/appLogic.ts
Normal file
133
intro/4-ipfs-code-execution/web/src/appLogic.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import { get_external_api_multiaddr } from "@fluencelabs/aqua-ipfs";
|
||||
import { FluenceClient, createClient } from "@fluencelabs/fluence";
|
||||
import { stage } from "@fluencelabs/fluence-network-environment";
|
||||
import { useSetRecoilState, useRecoilValue, useRecoilState } from "recoil";
|
||||
import {
|
||||
deploy_service,
|
||||
put_file_size,
|
||||
remove_service,
|
||||
} from "@fluencelabs/ipfs-execution";
|
||||
import {
|
||||
clientState,
|
||||
rpcAddrState,
|
||||
wasmState,
|
||||
serviceIdState,
|
||||
fileCIDState,
|
||||
fileSizeState,
|
||||
fileSizeCIDState,
|
||||
} from "./appState";
|
||||
import { decapsulateP2P, fromOption } from "./util";
|
||||
|
||||
export const relayNodes = [stage[0], stage[1], stage[2]];
|
||||
|
||||
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;
|
||||
return decapsulateP2P(rpcAddr);
|
||||
};
|
||||
|
||||
export const useClientConnect = () => {
|
||||
const setClient = useSetRecoilState(clientState);
|
||||
const setRpcAddr = useSetRecoilState(rpcAddrState);
|
||||
|
||||
const connect = async (relayPeerId: string) => {
|
||||
try {
|
||||
const client = await createClient(relayPeerId);
|
||||
const addr = await getRpcAddr(client);
|
||||
setRpcAddr(addr!);
|
||||
setClient(client);
|
||||
} catch (err) {
|
||||
console.log("Client initialization failed", err);
|
||||
}
|
||||
};
|
||||
|
||||
return connect;
|
||||
};
|
||||
|
||||
export const useDeployService = () => {
|
||||
const wasm = useRecoilValue(wasmState);
|
||||
const rpcAddr = useRecoilValue(rpcAddrState);
|
||||
const client = useRecoilValue(clientState);
|
||||
const setServiceId = useSetRecoilState(serviceIdState);
|
||||
|
||||
return async () => {
|
||||
console.log("wasm %s rpcAddr %s", wasm, rpcAddr);
|
||||
if (client === null || wasm === null || rpcAddr === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var service_id = await deploy_service(
|
||||
client,
|
||||
client.relayPeerId!,
|
||||
wasm,
|
||||
rpcAddr,
|
||||
(msg, value) => console.log(msg, value),
|
||||
{ ttl: 10000 }
|
||||
);
|
||||
service_id = fromOption(service_id);
|
||||
setServiceId(service_id);
|
||||
};
|
||||
};
|
||||
|
||||
export const useGetFileSize = () => {
|
||||
const rpcAddr = useRecoilValue(rpcAddrState);
|
||||
const client = useRecoilValue(clientState);
|
||||
const serviceId = useRecoilValue(serviceIdState);
|
||||
const fileCID = useRecoilValue(fileCIDState);
|
||||
const setFileSize = useSetRecoilState(fileSizeState);
|
||||
const setFileSizeCID = useSetRecoilState(fileSizeCIDState);
|
||||
|
||||
return async () => {
|
||||
if (client === null || serviceId === null || rpcAddr === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var putResult = await put_file_size(
|
||||
client,
|
||||
client.relayPeerId!,
|
||||
fileCID!,
|
||||
rpcAddr,
|
||||
serviceId,
|
||||
(size) => setFileSize(size.toString()),
|
||||
(label, error) => setFileSize("Error: " + label + ": " + error),
|
||||
{ ttl: 10000 }
|
||||
);
|
||||
putResult = fromOption(putResult);
|
||||
if (putResult === null) {
|
||||
return;
|
||||
}
|
||||
if (putResult.success) {
|
||||
setFileSizeCID(putResult.hash);
|
||||
} else {
|
||||
setFileSizeCID("Error: " + putResult.error);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const useRemoveService = () => {
|
||||
const client = useRecoilValue(clientState);
|
||||
const [serviceId, setServiceId] = useRecoilState(serviceIdState);
|
||||
const setFileCID = useSetRecoilState(fileCIDState);
|
||||
const setFileSize = useSetRecoilState(fileSizeState);
|
||||
const setFileSizeCID = useSetRecoilState(fileSizeCIDState);
|
||||
|
||||
return async () => {
|
||||
if (client === null || serviceId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await remove_service(client, client.relayPeerId!, serviceId, {
|
||||
ttl: 10000,
|
||||
});
|
||||
setServiceId(null);
|
||||
setFileCID(null);
|
||||
setFileSize(null);
|
||||
setFileSizeCID(null);
|
||||
};
|
||||
};
|
74
intro/4-ipfs-code-execution/web/src/appState.ts
Normal file
74
intro/4-ipfs-code-execution/web/src/appState.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { FluenceClient } from "@fluencelabs/fluence";
|
||||
import { atom, selector } from "recoil";
|
||||
|
||||
export const clientState = atom<FluenceClient | null>({
|
||||
key: "clientState",
|
||||
default: null,
|
||||
dangerouslyAllowMutability: true,
|
||||
});
|
||||
|
||||
export const serviceIdState = atom<string | null>({
|
||||
key: "serviceIdState",
|
||||
default: null,
|
||||
});
|
||||
|
||||
export const wasmState = atom<string>({
|
||||
key: "serviceState",
|
||||
default: "Qmf8fH2cDZXGKS9uDGBcHxv5uQ51ChrigdZKe3QxS2C1AF",
|
||||
});
|
||||
|
||||
export const rpcAddrState = atom<string | null>({
|
||||
key: "rpcAddrState",
|
||||
default: null,
|
||||
});
|
||||
|
||||
export const fileCIDState = atom<string | null>({
|
||||
key: "fileCIDState",
|
||||
default: "Qmf8fH2cDZXGKS9uDGBcHxv5uQ51ChrigdZKe3QxS2C1AF",
|
||||
});
|
||||
|
||||
export const fileSizeState = atom<string | null>({
|
||||
key: "fileSizeState",
|
||||
default: null,
|
||||
});
|
||||
|
||||
export const fileSizeCIDState = atom<string | null>({
|
||||
key: "fileSizeCIDState",
|
||||
default: null,
|
||||
});
|
||||
|
||||
export const isConnectedState = selector({
|
||||
key: "isConnectedState",
|
||||
get: ({ get }) => {
|
||||
const client = get(clientState);
|
||||
|
||||
return client !== null && client.isConnected;
|
||||
},
|
||||
dangerouslyAllowMutability: true,
|
||||
});
|
||||
|
||||
export const gotRpcAddrState = selector({
|
||||
key: "getRpcAddrState",
|
||||
get: ({ get }) => {
|
||||
const rpcAddr = get(rpcAddrState);
|
||||
|
||||
return rpcAddr !== null;
|
||||
},
|
||||
});
|
||||
|
||||
export const isDeployedState = selector({
|
||||
key: "isDeployedState",
|
||||
get: ({ get }) => {
|
||||
const serviceId = get(serviceIdState);
|
||||
|
||||
return serviceId !== null;
|
||||
},
|
||||
});
|
||||
|
||||
export const hasResultState = selector({
|
||||
key: "hasResultState",
|
||||
get: ({ get }) => {
|
||||
const fileSize = get(fileSizeState);
|
||||
return fileSize !== null;
|
||||
},
|
||||
});
|
@ -1,12 +1,14 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
import { RecoilRoot } from "recoil";
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<RecoilRoot>
|
||||
<App />
|
||||
</RecoilRoot>
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
|
22
intro/4-ipfs-code-execution/web/src/util.ts
Normal file
22
intro/4-ipfs-code-execution/web/src/util.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Multiaddr, protocols } from "multiaddr";
|
||||
|
||||
export const decapsulateP2P = (rpcAddr: string) => {
|
||||
return new Multiaddr(rpcAddr)
|
||||
.decapsulateCode(protocols.names.p2p.code)
|
||||
.toString();
|
||||
};
|
||||
|
||||
export const fromOption = <T>(opt: T | T[] | null): T | null => {
|
||||
if (Array.isArray(opt)) {
|
||||
if (opt.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
opt = opt[0];
|
||||
}
|
||||
if (opt === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return opt;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user