diff --git a/aqua-examples/ceramic-demo/.gitignore b/aqua-examples/ceramic-demo/.gitignore new file mode 100644 index 0000000..bbccc88 --- /dev/null +++ b/aqua-examples/ceramic-demo/.gitignore @@ -0,0 +1,5 @@ +debug/ +target/ +Cargo.lock +**/*.bk +**/*.bak diff --git a/aqua-examples/ceramic-demo/Config.toml b/aqua-examples/ceramic-demo/Config.toml new file mode 100644 index 0000000..029320f --- /dev/null +++ b/aqua-examples/ceramic-demo/Config.toml @@ -0,0 +1,19 @@ +modules_dir = "artifacts" + + +[[module]] +name = "curl_adapter" +mem_pages_count = 100 +logger_enabled = true + +[module.mounted_binaries] +curl = "/usr/bin/curl" + + +[[module]] +name = "ceramic_adapter" +mem_pages_count = 50 +logger_enabled = true + +[module.mounted_binaries] +ceramic = "/Users/bebo/.nvm/versions/node/v14.16.0/bin/ceramic" diff --git a/aqua-examples/ceramic-demo/aqua/ceramic_demo.aqua b/aqua-examples/ceramic-demo/aqua/ceramic_demo.aqua new file mode 100644 index 0000000..85b4888 --- /dev/null +++ b/aqua-examples/ceramic-demo/aqua/ceramic_demo.aqua @@ -0,0 +1,37 @@ +data CeramicResult: + ret_code: i32 + stderr: string + stdout: string + +service CeramicAdapter("service-id"): + ceramic_request(args: []string) -> CeramicResult + create_schema(schema: string) -> CeramicResult + create_stream(payload: string) -> CeramicResult + show(stream_id: string) -> CeramicResult + state(stream_id: string) -> CeramicResult + update(stream_id: string, payload: string) -> CeramicResult + +-- aqua fuction to create stream and return stream id +func create(payload:string, node:string, service_id:string) -> string: + on node: + CeramicAdapter service_id + create_res <- CeramicAdapter.create_stream(payload) + <- create_res.stdout + +-- aqua fuction to create stream and return CeramicResult +func create_obj(payload:string, node:string, service_id:string) -> CeramicResult: + on node: + CeramicAdapter service_id + create_res <- CeramicAdapter.create_stream(payload) + <- create_res + +-- aqua fuction to create stream, show, update and return stream id, show and update as stdout strings +func roundtrip(payload:string, payload_two: string, node:string, service_id:string) -> string, string, string: + on node: + CeramicAdapter service_id + create_res <- CeramicAdapter.create_stream(payload) --< return the sream_id in stdout + show_res <- CeramicAdapter.show(create_res.stdout) --< + update_res <- CeramicAdapter.update(create_res.stdout, payload_two) + <- create_res.stdout, show_res.stdout, update_res.stdout + + diff --git a/aqua-examples/ceramic-demo/ceramic/schema_id.txt b/aqua-examples/ceramic-demo/ceramic/schema_id.txt new file mode 100644 index 0000000..37fad17 --- /dev/null +++ b/aqua-examples/ceramic-demo/ceramic/schema_id.txt @@ -0,0 +1,85 @@ +kjzl6cwe1jw14b4395tqak897qks1f87ljtkkoaop4133wdsire65g0tzol8zaa +eraStreamID(kjzl6cwe1jw14b4395tqak897qks1f87ljtkkoaop4133wdsire65g0tzol8zaa) + + +commit: + +ceramic commits% mbp16~/localdev(:|✔) % ceramic commits kjzl6cwe1jw14b4395tqak897qks1f87ljtkkoaop4133wdsire65g0tzol8zaa +[ + "k3y52l7qbv1fryn1355fez3upj0zre4ae18yab0rzmknq3qa2tesrqpxx9qv3ux34", + "k6zn3rc3v8qin273e8dy6fftce0s2pe6w9yo2o2ebaz3i0r1onkflgr2wvycxpja9ov4dsqgx4zpw0shihnafw3dlq5lv2qs0q1mpoqfrj996ooh3q0utj7" +] + + + + +StreamID(kjzl6cwe1jw14b9zk6i99zoupa7odnn3r9ftwfh7iocgrgvep6jfbhe3ko8a7jf) +{ + "proposal": "https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx" +} + + + +ceramic create tile --content '{"proposal":"https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx"}' --schema k3y52l7qbv1fryn1355fez3upj0zre4ae18yab0rzmknq3qa2tesrqpxx9qv3ux34 +StreamID(kjzl6cwe1jw14b9zk6i99zoupa7odnn3r9ftwfh7iocgrgvep6jfbhe3ko8a7jf) +{ + "proposal": "https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx" +} + + + +ceramic create tile --content '{"proposal":"https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx"}' --schema k3y52l7qbv1fryn1355fez3upj0zre4ae18yab0rzmknq3qa2tesrqpxx9qv3ux34 +StreamID(kjzl6cwe1jw14b9zk6i99zoupa7odnn3r9ftwfh7iocgrgvep6jfbhe3ko8a7jf) +{ + "proposal": "https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx" + + + + + + + +ceramic create tile --content '{"proposal":"https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx"}' --schema k3y52l7qbv1fryn1355fez3upj0zre4ae18yab0rzmknq3qa2tesrqpxx9qv3ux34 +StreamID(kjzl6cwe1jw14946s42j0ew60kmmw5g0tzc28ceat2algr49l7bb8shv30zd2h3) +{ + "proposal": "https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx" +} + + + +ceramic state kjzl6cwe1jw14946s42j0ew60kmmw5g0tzc28ceat2algr49l7bb8shv30zd2h3 +{ + "type": 0, + "content": { + "proposal": "https://ipfs.fleek.co/ipfs/Qmd6o2bFhuN2pkXa3qTW32zAcKHwhvz5pcj5rs1NzPcJcx" + }, + "metadata": { + "schema": "k3y52l7qbv1fryn1355fez3upj0zre4ae18yab0rzmknq3qa2tesrqpxx9qv3ux34", + "unique": "USgiCW4TyR3dax1w", + "controllers": [ + "did:key:z6Mkupzc4V3f7RiQCzjxVqqqRXbkmuAdN38oPqATcyWq2HaN" + ] + }, + "signature": 2, + "anchorStatus": "ANCHORED", + "log": [ + { + "cid": "bagcqceratishgp6t3ffgdxhwxqj6cnglwrc7ukg64jqdtybpawpgzrjsiddq", + "type": 0 + }, + { + "cid": "bafyreidncrcks36g6yctlr743ouygvtdg7657xe4gf2brmmx4etjysrhxi", + "type": 2, + "timestamp": 1629951384 + } + ], + "anchorProof": { + "root": "bafyreidpqmfi2enod635viwxmixzfe2qdoon5hdlkowdot6r5bhwovaamy", + "txHash": "bagjqcgzaplsuv3z3nuqw3n6mai4cjvujczgqjjfetqnh3nczjav2gsaurjmq", + "chainId": "eip155:3", + "blockNumber": 10910933, + "blockTimestamp": 1629951384 + }, + "doctype": "tile" +} +mbp16~/localdev(:|✔) % \ No newline at end of file diff --git a/aqua-examples/ceramic-demo/ceramic/snapshot_schema.json b/aqua-examples/ceramic-demo/ceramic/snapshot_schema.json new file mode 100644 index 0000000..6250e2e --- /dev/null +++ b/aqua-examples/ceramic-demo/ceramic/snapshot_schema.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Snapshot", + "type": "object", + "properties": { + "proposal": { "type": "string" }, + "proposal_verifications": { + "type": "array", + "items": { "type": "string" } + }, + "vote": { "type": "string" }, + "vote_verifications": { "type": "array", "items": { "type": "string" } } + }, + "required": ["proposal"] +} diff --git a/aqua-examples/ceramic-demo/compiled-aqua/builtin.ts b/aqua-examples/ceramic-demo/compiled-aqua/builtin.ts new file mode 100644 index 0000000..4a33ab1 --- /dev/null +++ b/aqua-examples/ceramic-demo/compiled-aqua/builtin.ts @@ -0,0 +1,921 @@ +/** + * + * This file is auto-generated. Do not edit manually: changes may be erased. + * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. + * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues + * Aqua version: 0.3.0-226 + * + */ +import { Fluence, FluencePeer } from '@fluencelabs/fluence'; +import { + ResultCodes, + RequestFlow, + RequestFlowBuilder, + CallParams, +} from '@fluencelabs/fluence/dist/internal/compilerSupport/v1'; + + +// Services + + export interface SrvDef { + add_alias: (alias: string, service_id: string, callParams: CallParams<'alias' | 'service_id'>) => void; +create: (blueprint_id: string, callParams: CallParams<'blueprint_id'>) => string; +get_interface: (service_id: string, callParams: CallParams<'service_id'>) => {function_signatures:{arguments:string[][];name:string;output_types:string[]}[];record_types:{fields:string[][];id:number;name:string}[]}; +list: (callParams: CallParams) => {blueprint_id:string;id:string;owner_id:string}[]; +remove: (service_id: string, callParams: CallParams<'service_id'>) => void; +resolve_alias: (alias: string, callParams: CallParams<'alias'>) => string; + } + + export function registerSrv(service: SrvDef): void; +export function registerSrv(serviceId: string, service: SrvDef): void; +export function registerSrv(peer: FluencePeer, service: SrvDef): void; +export function registerSrv(peer: FluencePeer, serviceId: string, service: SrvDef): void; + export function registerSrv(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "srv" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'add_alias') { + + const callParams = { + ...req.particleContext, + tetraplets: { + alias: req.tetraplets[0],service_id: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + service.add_alias(req.args[0], req.args[1], callParams); resp.result = {} + + } + + + + if (req.fnName === 'create') { + + const callParams = { + ...req.particleContext, + tetraplets: { + blueprint_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.create(req.args[0], callParams) + + } + + + + if (req.fnName === 'get_interface') { + + const callParams = { + ...req.particleContext, + tetraplets: { + service_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.get_interface(req.args[0], callParams) + + } + + + + if (req.fnName === 'list') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.list(callParams) + + } + + + + if (req.fnName === 'remove') { + + const callParams = { + ...req.particleContext, + tetraplets: { + service_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + service.remove(req.args[0], callParams); resp.result = {} + + } + + + + if (req.fnName === 'resolve_alias') { + + const callParams = { + ...req.particleContext, + tetraplets: { + alias: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.resolve_alias(req.args[0], callParams) + + } + + + next(); + }); + } + + + + export interface PeerDef { + connect: (id: string, multiaddrs: string[] | null, callParams: CallParams<'id' | 'multiaddrs'>) => boolean; +get_contact: (peer: string, callParams: CallParams<'peer'>) => {addresses:string[];peer_id:string}; +identify: (callParams: CallParams) => {external_addresses:string[]}; +is_connected: (peer: string, callParams: CallParams<'peer'>) => boolean; +timestamp_ms: (callParams: CallParams) => number; +timestamp_sec: (callParams: CallParams) => number; + } + + export function registerPeer(service: PeerDef): void; +export function registerPeer(serviceId: string, service: PeerDef): void; +export function registerPeer(peer: FluencePeer, service: PeerDef): void; +export function registerPeer(peer: FluencePeer, serviceId: string, service: PeerDef): void; + export function registerPeer(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "peer" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'connect') { + + const callParams = { + ...req.particleContext, + tetraplets: { + id: req.tetraplets[0],multiaddrs: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.connect(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], callParams) + + } + + + + if (req.fnName === 'get_contact') { + + const callParams = { + ...req.particleContext, + tetraplets: { + peer: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.get_contact(req.args[0], callParams) + + } + + + + if (req.fnName === 'identify') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.identify(callParams) + + } + + + + if (req.fnName === 'is_connected') { + + const callParams = { + ...req.particleContext, + tetraplets: { + peer: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.is_connected(req.args[0], callParams) + + } + + + + if (req.fnName === 'timestamp_ms') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.timestamp_ms(callParams) + + } + + + + if (req.fnName === 'timestamp_sec') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.timestamp_sec(callParams) + + } + + + next(); + }); + } + + + + export interface OpDef { + array: (a: string, b: string | null, c: string | null, d: string | null, callParams: CallParams<'a' | 'b' | 'c' | 'd'>) => string[]; +array_length: (array: string[], callParams: CallParams<'array'>) => number; +bytes_from_b58: (b: string, callParams: CallParams<'b'>) => number[]; +bytes_to_b58: (bs: number[], callParams: CallParams<'bs'>) => string; +concat: (a: string[], b: string[] | null, c: string[] | null, d: string[] | null, callParams: CallParams<'a' | 'b' | 'c' | 'd'>) => string[]; +concat_strings: (a: string, b: string, callParams: CallParams<'a' | 'b'>) => string; +identity: (s: string | null, callParams: CallParams<'s'>) => string | null; +noop: (callParams: CallParams) => void; +sha256_string: (s: string, callParams: CallParams<'s'>) => string; +string_from_b58: (b: string, callParams: CallParams<'b'>) => string; +string_to_b58: (s: string, callParams: CallParams<'s'>) => string; + } + + export function registerOp(service: OpDef): void; +export function registerOp(serviceId: string, service: OpDef): void; +export function registerOp(peer: FluencePeer, service: OpDef): void; +export function registerOp(peer: FluencePeer, serviceId: string, service: OpDef): void; + export function registerOp(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "op" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'array') { + + const callParams = { + ...req.particleContext, + tetraplets: { + a: req.tetraplets[0],b: req.tetraplets[1],c: req.tetraplets[2],d: req.tetraplets[3] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.array(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], req.args[2].length === 0 ? null : req.args[2][0], req.args[3].length === 0 ? null : req.args[3][0], callParams) + + } + + + + if (req.fnName === 'array_length') { + + const callParams = { + ...req.particleContext, + tetraplets: { + array: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.array_length(req.args[0], callParams) + + } + + + + if (req.fnName === 'bytes_from_b58') { + + const callParams = { + ...req.particleContext, + tetraplets: { + b: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.bytes_from_b58(req.args[0], callParams) + + } + + + + if (req.fnName === 'bytes_to_b58') { + + const callParams = { + ...req.particleContext, + tetraplets: { + bs: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.bytes_to_b58(req.args[0], callParams) + + } + + + + if (req.fnName === 'concat') { + + const callParams = { + ...req.particleContext, + tetraplets: { + a: req.tetraplets[0],b: req.tetraplets[1],c: req.tetraplets[2],d: req.tetraplets[3] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.concat(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], req.args[2].length === 0 ? null : req.args[2][0], req.args[3].length === 0 ? null : req.args[3][0], callParams) + + } + + + + if (req.fnName === 'concat_strings') { + + const callParams = { + ...req.particleContext, + tetraplets: { + a: req.tetraplets[0],b: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.concat_strings(req.args[0], req.args[1], callParams) + + } + + + + if (req.fnName === 'identity') { + + const callParams = { + ...req.particleContext, + tetraplets: { + s: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + + var respResult = service.identity(req.args[0].length === 0 ? null : req.args[0][0], callParams); + resp.result = respResult === null ? [] : [respResult] + + + } + + + + if (req.fnName === 'noop') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + service.noop(callParams); resp.result = {} + + } + + + + if (req.fnName === 'sha256_string') { + + const callParams = { + ...req.particleContext, + tetraplets: { + s: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.sha256_string(req.args[0], callParams) + + } + + + + if (req.fnName === 'string_from_b58') { + + const callParams = { + ...req.particleContext, + tetraplets: { + b: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.string_from_b58(req.args[0], callParams) + + } + + + + if (req.fnName === 'string_to_b58') { + + const callParams = { + ...req.particleContext, + tetraplets: { + s: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.string_to_b58(req.args[0], callParams) + + } + + + next(); + }); + } + + + + export interface KademliaDef { + merge: (target: string, left: string[], right: string[], count: number | null, callParams: CallParams<'target' | 'left' | 'right' | 'count'>) => string[]; +neighborhood: (key: string, already_hashed: boolean | null, count: number | null, callParams: CallParams<'key' | 'already_hashed' | 'count'>) => string[]; + } + + export function registerKademlia(service: KademliaDef): void; +export function registerKademlia(serviceId: string, service: KademliaDef): void; +export function registerKademlia(peer: FluencePeer, service: KademliaDef): void; +export function registerKademlia(peer: FluencePeer, serviceId: string, service: KademliaDef): void; + export function registerKademlia(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "kad" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'merge') { + + const callParams = { + ...req.particleContext, + tetraplets: { + target: req.tetraplets[0],left: req.tetraplets[1],right: req.tetraplets[2],count: req.tetraplets[3] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.merge(req.args[0], req.args[1], req.args[2], req.args[3].length === 0 ? null : req.args[3][0], callParams) + + } + + + + if (req.fnName === 'neighborhood') { + + const callParams = { + ...req.particleContext, + tetraplets: { + key: req.tetraplets[0],already_hashed: req.tetraplets[1],count: req.tetraplets[2] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.neighborhood(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], req.args[2].length === 0 ? null : req.args[2][0], callParams) + + } + + + next(); + }); + } + + + + export interface ScriptDef { + add: (air_script: string, interval: string | null, callParams: CallParams<'air_script' | 'interval'>) => string; +list: (callParams: CallParams) => {failures:number;id:string;interval:string;owner:string;src:string}; +remove: (script_id: string, callParams: CallParams<'script_id'>) => boolean; + } + + export function registerScript(service: ScriptDef): void; +export function registerScript(serviceId: string, service: ScriptDef): void; +export function registerScript(peer: FluencePeer, service: ScriptDef): void; +export function registerScript(peer: FluencePeer, serviceId: string, service: ScriptDef): void; + export function registerScript(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "script" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'add') { + + const callParams = { + ...req.particleContext, + tetraplets: { + air_script: req.tetraplets[0],interval: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.add(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], callParams) + + } + + + + if (req.fnName === 'list') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.list(callParams) + + } + + + + if (req.fnName === 'remove') { + + const callParams = { + ...req.particleContext, + tetraplets: { + script_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.remove(req.args[0], callParams) + + } + + + next(); + }); + } + + + + export interface DistDef { + add_blueprint: (blueprint: {dependencies:string[];name:string}, callParams: CallParams<'blueprint'>) => string; +add_module: (wasm_b56_content: number[], conf: {name:string}, callParams: CallParams<'wasm_b56_content' | 'conf'>) => string; +add_module_from_vault: (path: string, config: {name:string}, callParams: CallParams<'path' | 'config'>) => string; +default_module_config: (module_name: string, callParams: CallParams<'module_name'>) => {name:string}; +get_interface: (module_id: string, callParams: CallParams<'module_id'>) => {function_signatures:{arguments:string[][];name:string;output_types:string[]}[];record_types:{fields:string[][];id:number;name:string}[]}; +list_blueprints: (callParams: CallParams) => {dependencies:string[];id:string;name:string}[]; +list_modules: (callParams: CallParams) => {config:{name:string};hash:string;name:string}[]; +make_blueprint: (name: string, dependencies: string[], callParams: CallParams<'name' | 'dependencies'>) => {dependencies:string[];name:string}; +make_module_config: (name: string, mem_pages_count: number | null, logger_enabled: boolean | null, preopened_files: string[] | null, envs: string[][] | null, mapped_dirs: string[][] | null, mounted_binaries: string[][] | null, logging_mask: number | null, callParams: CallParams<'name' | 'mem_pages_count' | 'logger_enabled' | 'preopened_files' | 'envs' | 'mapped_dirs' | 'mounted_binaries' | 'logging_mask'>) => {name:string}; + } + + export function registerDist(service: DistDef): void; +export function registerDist(serviceId: string, service: DistDef): void; +export function registerDist(peer: FluencePeer, service: DistDef): void; +export function registerDist(peer: FluencePeer, serviceId: string, service: DistDef): void; + export function registerDist(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "dist" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'add_blueprint') { + + const callParams = { + ...req.particleContext, + tetraplets: { + blueprint: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.add_blueprint(req.args[0], callParams) + + } + + + + if (req.fnName === 'add_module') { + + const callParams = { + ...req.particleContext, + tetraplets: { + wasm_b56_content: req.tetraplets[0],conf: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.add_module(req.args[0], req.args[1], callParams) + + } + + + + if (req.fnName === 'add_module_from_vault') { + + const callParams = { + ...req.particleContext, + tetraplets: { + path: req.tetraplets[0],config: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.add_module_from_vault(req.args[0], req.args[1], callParams) + + } + + + + if (req.fnName === 'default_module_config') { + + const callParams = { + ...req.particleContext, + tetraplets: { + module_name: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.default_module_config(req.args[0], callParams) + + } + + + + if (req.fnName === 'get_interface') { + + const callParams = { + ...req.particleContext, + tetraplets: { + module_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.get_interface(req.args[0], callParams) + + } + + + + if (req.fnName === 'list_blueprints') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.list_blueprints(callParams) + + } + + + + if (req.fnName === 'list_modules') { + + const callParams = { + ...req.particleContext, + tetraplets: { + + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.list_modules(callParams) + + } + + + + if (req.fnName === 'make_blueprint') { + + const callParams = { + ...req.particleContext, + tetraplets: { + name: req.tetraplets[0],dependencies: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.make_blueprint(req.args[0], req.args[1], callParams) + + } + + + + if (req.fnName === 'make_module_config') { + + const callParams = { + ...req.particleContext, + tetraplets: { + name: req.tetraplets[0],mem_pages_count: req.tetraplets[1],logger_enabled: req.tetraplets[2],preopened_files: req.tetraplets[3],envs: req.tetraplets[4],mapped_dirs: req.tetraplets[5],mounted_binaries: req.tetraplets[6],logging_mask: req.tetraplets[7] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.make_module_config(req.args[0], req.args[1].length === 0 ? null : req.args[1][0], req.args[2].length === 0 ? null : req.args[2][0], req.args[3].length === 0 ? null : req.args[3][0], req.args[4].length === 0 ? null : req.args[4][0], req.args[5].length === 0 ? null : req.args[5][0], req.args[6].length === 0 ? null : req.args[6][0], req.args[7].length === 0 ? null : req.args[7][0], callParams) + + } + + + next(); + }); + } + + +// Functions + diff --git a/aqua-examples/ceramic-demo/compiled-aqua/ceramic_demo.ts b/aqua-examples/ceramic-demo/compiled-aqua/ceramic_demo.ts new file mode 100644 index 0000000..382e1d6 --- /dev/null +++ b/aqua-examples/ceramic-demo/compiled-aqua/ceramic_demo.ts @@ -0,0 +1,279 @@ +/** + * + * This file is auto-generated. Do not edit manually: changes may be erased. + * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. + * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues + * Aqua version: 0.3.0-226 + * + */ +import { Fluence, FluencePeer } from '@fluencelabs/fluence'; +import { + ResultCodes, + RequestFlow, + RequestFlowBuilder, + CallParams, +} from '@fluencelabs/fluence/dist/internal/compilerSupport/v1'; + + +// Services + + export interface CeramicAdapterDef { + ceramic_request: (args: string[], callParams: CallParams<'args'>) => {ret_code:number;stderr:string;stdout:string}; +create_schema: (schema: string, callParams: CallParams<'schema'>) => {ret_code:number;stderr:string;stdout:string}; +create_stream: (payload: string, callParams: CallParams<'payload'>) => {ret_code:number;stderr:string;stdout:string}; +show: (stream_id: string, callParams: CallParams<'stream_id'>) => {ret_code:number;stderr:string;stdout:string}; +state: (stream_id: string, callParams: CallParams<'stream_id'>) => {ret_code:number;stderr:string;stdout:string}; +update: (stream_id: string, payload: string, callParams: CallParams<'stream_id' | 'payload'>) => {ret_code:number;stderr:string;stdout:string}; + } + + export function registerCeramicAdapter(service: CeramicAdapterDef): void; +export function registerCeramicAdapter(serviceId: string, service: CeramicAdapterDef): void; +export function registerCeramicAdapter(peer: FluencePeer, service: CeramicAdapterDef): void; +export function registerCeramicAdapter(peer: FluencePeer, serviceId: string, service: CeramicAdapterDef): void; + export function registerCeramicAdapter(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "service-id" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'ceramic_request') { + + const callParams = { + ...req.particleContext, + tetraplets: { + args: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.ceramic_request(req.args[0], callParams) + + } + + + + if (req.fnName === 'create_schema') { + + const callParams = { + ...req.particleContext, + tetraplets: { + schema: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.create_schema(req.args[0], callParams) + + } + + + + if (req.fnName === 'create_stream') { + + const callParams = { + ...req.particleContext, + tetraplets: { + payload: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.create_stream(req.args[0], callParams) + + } + + + + if (req.fnName === 'show') { + + const callParams = { + ...req.particleContext, + tetraplets: { + stream_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.show(req.args[0], callParams) + + } + + + + if (req.fnName === 'state') { + + const callParams = { + ...req.particleContext, + tetraplets: { + stream_id: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.state(req.args[0], callParams) + + } + + + + if (req.fnName === 'update') { + + const callParams = { + ...req.particleContext, + tetraplets: { + stream_id: req.tetraplets[0],payload: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.update(req.args[0], req.args[1], callParams) + + } + + + next(); + }); + } + + +// Functions + + export function roundtrip(payload: string, payload_two: string, node: string, service_id: string, config?: {ttl?: number}) : Promise<[string, string]>; + export function roundtrip(peer: FluencePeer, payload: string, payload_two: string, node: string, service_id: string, config?: {ttl?: number}) : Promise<[string, string]>; + export function roundtrip(...args: any) { + let peer: FluencePeer; + let payload: any; +let payload_two: any; +let node: any; +let service_id: any; + let config: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + payload = args[1]; +payload_two = args[2]; +node = args[3]; +service_id = args[4]; +config = args[5]; + } else { + peer = Fluence.getPeer(); + payload = args[0]; +payload_two = args[1]; +node = args[2]; +service_id = args[3]; +config = args[4]; + } + + let request: RequestFlow; + const promise = new Promise<[string, string]>((resolve, reject) => { + const r = new RequestFlowBuilder() + .disableInjections() + .withRawScript( + ` + (xor + (seq + (seq + (seq + (seq + (seq + (seq + (seq + (seq + (call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-) + (call %init_peer_id% ("getDataSrv" "payload") [] payload) + ) + (call %init_peer_id% ("getDataSrv" "payload_two") [] payload_two) + ) + (call %init_peer_id% ("getDataSrv" "node") [] node) + ) + (call %init_peer_id% ("getDataSrv" "service_id") [] service_id) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (seq + (seq + (seq + (call -relay- ("op" "noop") []) + (call node (service_id "create_stream") [payload] create_res) + ) + (call node (service_id "show") [create_res.$.stdout!] show_res) + ) + (call node (service_id "update") [create_res.$.stdout! payload_two] update_res) + ) + (seq + (call -relay- ("op" "noop") []) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1]) + ) + ) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (call %init_peer_id% ("callbackSrv" "response") [create_res.$.stdout! update_res.$.stdout!]) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2]) + ) + ) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3]) +) + + `, + ) + .configHandler((h) => { + h.on('getDataSrv', '-relay-', () => { + return peer.getStatus().relayPeerId; + }); + h.on('getDataSrv', 'payload', () => {return payload;}); +h.on('getDataSrv', 'payload_two', () => {return payload_two;}); +h.on('getDataSrv', 'node', () => {return node;}); +h.on('getDataSrv', 'service_id', () => {return service_id;}); + h.onEvent('callbackSrv', 'response', (args) => { + let opt: any = args; + + return resolve(opt); +}); + + h.onEvent('errorHandlingSrv', 'error', (args) => { + const [err] = args; + reject(err); + }); + }) + .handleScriptError(reject) + .handleTimeout(() => { + reject('Request timed out for roundtrip'); + }) + if(config && config.ttl) { + r.withTTL(config.ttl) + } + request = r.build(); + }); + peer.internals.initiateFlow(request!); + return promise; +} + diff --git a/aqua-examples/ceramic-demo/compiled-aqua/timestamp.ts b/aqua-examples/ceramic-demo/compiled-aqua/timestamp.ts new file mode 100644 index 0000000..a4c31a4 --- /dev/null +++ b/aqua-examples/ceramic-demo/compiled-aqua/timestamp.ts @@ -0,0 +1,204 @@ +/** + * + * This file is auto-generated. Do not edit manually: changes may be erased. + * Generated by Aqua compiler: https://github.com/fluencelabs/aqua/. + * If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues + * Aqua version: 0.3.0-226 + * + */ +import { Fluence, FluencePeer } from '@fluencelabs/fluence'; +import { + ResultCodes, + RequestFlow, + RequestFlowBuilder, + CallParams, +} from '@fluencelabs/fluence/dist/internal/compilerSupport/v1'; + + +// Services + + export interface Op2Def { + array: (a: string, b: number, callParams: CallParams<'a' | 'b'>) => string; +identity: (s: number, callParams: CallParams<'s'>) => void; + } + + export function registerOp2(service: Op2Def): void; +export function registerOp2(serviceId: string, service: Op2Def): void; +export function registerOp2(peer: FluencePeer, service: Op2Def): void; +export function registerOp2(peer: FluencePeer, serviceId: string, service: Op2Def): void; + export function registerOp2(...args: any) { + let peer: FluencePeer; + let serviceId: any; + let service: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + } else { + peer = Fluence.getPeer(); + } + + if (typeof args[0] === 'string') { + serviceId = args[0]; + } else if (typeof args[1] === 'string') { + serviceId = args[1]; + } + else { + serviceId = "op" +} + + // Figuring out which overload is the service. + // If the first argument is not Fluence Peer and it is an object, then it can only be the service def + // If the first argument is peer, we are checking further. The second argument might either be + // an object, that it must be the service object + // or a string, which is the service id. In that case the service is the third argument + if (!(FluencePeer.isInstance(args[0])) && typeof args[0] === 'object') { + service = args[0]; + } else if (typeof args[1] === 'object') { + service = args[1]; + } else { + service = args[2]; + } + + peer.internals.callServiceHandler.use((req, resp, next) => { + if (req.serviceId !== serviceId) { + next(); + return; + } + + + if (req.fnName === 'array') { + + const callParams = { + ...req.particleContext, + tetraplets: { + a: req.tetraplets[0],b: req.tetraplets[1] + }, + }; + resp.retCode = ResultCodes.success; + resp.result = service.array(req.args[0], req.args[1], callParams) + + } + + + + if (req.fnName === 'identity') { + + const callParams = { + ...req.particleContext, + tetraplets: { + s: req.tetraplets[0] + }, + }; + resp.retCode = ResultCodes.success; + service.identity(req.args[0], callParams); resp.result = {} + + } + + + next(); + }); + } + + +// Functions + + export function ts_getter(node: string, config?: {ttl?: number}) : Promise; + export function ts_getter(peer: FluencePeer, node: string, config?: {ttl?: number}) : Promise; + export function ts_getter(...args: any) { + let peer: FluencePeer; + let node: any; + let config: any; + if (FluencePeer.isInstance(args[0])) { + peer = args[0]; + node = args[1]; +config = args[2]; + } else { + peer = Fluence.getPeer(); + node = args[0]; +config = args[1]; + } + + let request: RequestFlow; + const promise = new Promise((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" "node") [] node) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (seq + (seq + (seq + (call node ("op" "string_to_b58") [node] k) + (call node ("kad" "neighborhood") [k [] []] nodes) + ) + (fold nodes n + (par + (seq + (xor + (call n ("peer" "timestamp_ms") [] $res) + (null) + ) + (call node ("op" "noop") []) + ) + (next n) + ) + ) + ) + (call node ("op" "identity") [$res.$.[1]!]) + ) + (seq + (call -relay- ("op" "noop") []) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1]) + ) + ) + ) + (call -relay- ("op" "noop") []) + ) + (xor + (call %init_peer_id% ("callbackSrv" "response") [$res]) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2]) + ) + ) + (call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 3]) +) + + `, + ) + .configHandler((h) => { + h.on('getDataSrv', '-relay-', () => { + return peer.getStatus().relayPeerId; + }); + h.on('getDataSrv', 'node', () => {return node;}); + h.onEvent('callbackSrv', 'response', (args) => { + const [res] = args; + resolve(res); +}); + + h.onEvent('errorHandlingSrv', 'error', (args) => { + const [err] = args; + reject(err); + }); + }) + .handleScriptError(reject) + .handleTimeout(() => { + reject('Request timed out for ts_getter'); + }) + if(config && config.ttl) { + r.withTTL(config.ttl) + } + request = r.build(); + }); + peer.internals.initiateFlow(request!); + return promise; +} + diff --git a/aqua-examples/ceramic-demo/configs/Config.toml b/aqua-examples/ceramic-demo/configs/Config.toml new file mode 100644 index 0000000..7b41e33 --- /dev/null +++ b/aqua-examples/ceramic-demo/configs/Config.toml @@ -0,0 +1,18 @@ +modules_dir = "artifacts/" + +[[module]] +name = "ceramic_adapter" +mem_pages_count = 100 +logger_enabled = false + +[module.mounted_binaries] +ceramic = "~/.nvm/versions/node/v14.16.0/bin/ceramic" + + +[[module]] +name = "curl_adpater" +mem_pages_count = 100 +logger_enabled = false + +[module.mounted_binaries] +curl = "/usr/bin/curl" diff --git a/aqua-examples/ceramic-demo/configs/ceramic_adapter_cfg.json b/aqua-examples/ceramic-demo/configs/ceramic_adapter_cfg.json new file mode 100644 index 0000000..9b3a20e --- /dev/null +++ b/aqua-examples/ceramic-demo/configs/ceramic_adapter_cfg.json @@ -0,0 +1,8 @@ +{ + "name": "ceramic_adapter", + "mountedBinaries": { + "ceramic": "root/.nvm/versions/node/v14.17.0/bin/ceramic" + }, + "mem_page_count": 100, + "logger_enabled": false +} diff --git a/aqua-examples/ceramic-demo/configs/curl_adapter_cfg.json b/aqua-examples/ceramic-demo/configs/curl_adapter_cfg.json new file mode 100644 index 0000000..1b67e30 --- /dev/null +++ b/aqua-examples/ceramic-demo/configs/curl_adapter_cfg.json @@ -0,0 +1,8 @@ +{ + "name": "curl_adapter", + "mountedBinaries": { + "curl": "/usr/bin/curl" + }, + "mem_page_count": 100, + "logger_enabled": false +} diff --git a/aqua-examples/ceramic-demo/scripts/build.sh b/aqua-examples/ceramic-demo/scripts/build.sh new file mode 100755 index 0000000..29a965e --- /dev/null +++ b/aqua-examples/ceramic-demo/scripts/build.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash -o errexit -o nounset -o pipefail + + +mkdir -p artifacts +rm -f artifacts/*.wasm + +cd services/curl-adapter +cargo update --aggressive +marine build --release +cp target/wasm32-wasi/release/curl_adapter.wasm ../../artifacts/ + +cd ../ceramic-adapter +cargo update --aggressive +marine build --release +cp target/wasm32-wasi/release/ceramic_adapter.wasm ../../artifacts/ + diff --git a/aqua-examples/ceramic-demo/services/ceramic-adapter/.gitignore b/aqua-examples/ceramic-demo/services/ceramic-adapter/.gitignore new file mode 100644 index 0000000..bbccc88 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/ceramic-adapter/.gitignore @@ -0,0 +1,5 @@ +debug/ +target/ +Cargo.lock +**/*.bk +**/*.bak diff --git a/aqua-examples/ceramic-demo/services/ceramic-adapter/Cargo.toml b/aqua-examples/ceramic-demo/services/ceramic-adapter/Cargo.toml new file mode 100644 index 0000000..31f782a --- /dev/null +++ b/aqua-examples/ceramic-demo/services/ceramic-adapter/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "ceramic" +version = "0.1.0" +authors = ["boneyard93501 <4523011+boneyard93501@users.noreply.github.com>"] +edition = "2018" +description = "ceramic-adapter" +license = "Apache-2.0" + +[[bin]] +name = "ceramic_adapter" +path = "src/main.rs" + +[dependencies] +marine-rs-sdk = { version = "0.6.11", features = ["logger"] } +log = "0.4.14" + +[dev-dependencies] +marine-rs-sdk-test = "0.1.11" + +[dev] +[profile.release] +opt-level = "s" diff --git a/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_cli.rs b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_cli.rs new file mode 100644 index 0000000..9f07d5c --- /dev/null +++ b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_cli.rs @@ -0,0 +1,101 @@ +use marine_rs_sdk::{marine, MountedBinaryResult}; + +#[marine] +pub struct CeramicResult { + pub ret_code: i32, + pub stderr: String, + pub stdout: String, +} + +impl CeramicResult { + fn new(mb: MountedBinaryResult) -> Self { + CeramicResult { + ret_code: mb.ret_code, + stderr: String::from_utf8(mb.stderr).unwrap(), + stdout: String::from_utf8(mb.stdout).unwrap(), + } + } + + fn create(ret_code: i32, stdout: String, stderr: String) -> Self { + CeramicResult { + ret_code, + stderr, + stdout, + } + } +} + +#[marine] +pub fn ceramic_request(args: Vec) -> CeramicResult { + let response = ceramic(args); + CeramicResult::new(response) +} + +#[marine] +pub fn create_stream(payload: String) -> CeramicResult { + let args = vec![ + "create".to_string(), + "tile".to_string(), + "--content".to_string(), + payload, + ]; + let response: MountedBinaryResult = ceramic(args); + if response.stderr.len() > 0 { + return CeramicResult::new(response); + } + let stdout_str: String = String::from_utf8(response.stdout).unwrap(); + + if stdout_str.contains("StreamID") { + let res: Vec<&str> = stdout_str.split("\n").collect(); + let stream_id = res[0].replace("StreamID(", "").replace(")", ""); + return CeramicResult::create(response.ret_code, stream_id.to_string(), "".to_string()); + } else { + return CeramicResult::create( + response.ret_code, + "Missing StreamId".to_string(), + "".to_string(), + ); + } +} + +#[marine] +pub fn show(stream_id: String) -> CeramicResult { + let response = ceramic(vec!["show".to_string(), stream_id]); + CeramicResult::new(response) +} + +#[marine] +pub fn state(stream_id: String) -> CeramicResult { + let response = ceramic(vec!["state".to_string(), stream_id]); + CeramicResult::new(response) +} + +#[marine] +pub fn update(stream_id: String, payload: String) -> CeramicResult { + let response = ceramic(vec![ + "update".to_string(), + stream_id, + "--content".to_string(), + payload, + ]); + CeramicResult::new(response) +} + +#[marine] +pub fn create_schema(schema: String) -> CeramicResult { + let args = vec![ + "create".to_string(), + "tile".to_string(), + "--content".to_string(), + schema, + ]; + let response = ceramic(args); + CeramicResult::new(response) +} + +// mounted_binaries are available to import like this: +#[marine] +#[link(wasm_import_module = "host")] +extern "C" { + pub fn ceramic(cmd: Vec) -> MountedBinaryResult; +} diff --git a/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_http.rs b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_http.rs new file mode 100644 index 0000000..8a034e0 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/ceramic_http.rs @@ -0,0 +1,34 @@ +use marine_rs_sdk::{marine, MountedBinaryResult}; + +// source: https://developers.ceramic.network/build/http/api/ +static API: &str = "api"; +static VERSION: &str = "v0"; +static STREAM: &str = "streams"; + +fn url_maker(host: String, port: u32, arg: String, stream_id: String) -> String { + format!( + "http://{}:{}/{}/{}/{}/{}", + host, + port, + API, + VERSION, + arg.to_uppercase(), + stream_id, + ) +} + +#[marine] +pub fn http_streams(url: String, port: u32, stream_id: String) -> String { + // curl http://localhost:7007/api/v0/streams/kjzl6cwe1jw147r7878h32yazawcll6bxe5v92348cxitif6cota91qp68grbhm + let url = url_maker(url, port, STREAM.to_string(), stream_id); + let cmd = vec![url, "GET".to_string()]; + println!("cmd: {:?}", cmd); + let response: MountedBinaryResult = curl_request(cmd); + String::from_utf8(response.stdout).unwrap() +} + +#[marine] +#[link(wasm_import_module = "curl_adapter")] +extern "C" { + pub fn curl_request(cmd: Vec) -> MountedBinaryResult; +} diff --git a/aqua-examples/ceramic-demo/services/ceramic-adapter/src/main.rs b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/main.rs new file mode 100644 index 0000000..13fc255 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/ceramic-adapter/src/main.rs @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use marine_rs_sdk::{module_manifest, WasmLoggerBuilder}; + +module_manifest!(); + +pub mod ceramic_cli; +pub mod ceramic_http; + +pub fn main() { + // WasmLoggerBuilder::new().build().ok(); +} diff --git a/aqua-examples/ceramic-demo/services/curl-adapter/Cargo.toml b/aqua-examples/ceramic-demo/services/curl-adapter/Cargo.toml new file mode 100644 index 0000000..fc4e0bb --- /dev/null +++ b/aqua-examples/ceramic-demo/services/curl-adapter/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "curl-adapter" +version = "0.1.0" +authors = ["Fluence Labs"] +edition = "2018" +publish = false + +[[bin]] +path = "src/main.rs" +name = "curl_adapter" + +[dependencies] +marine-rs-sdk = { version = "0.6.11", features = ["logger"] } +log = "0.4.14" + +[dev-dependencies] +marine-rs-sdk-test = "0.3.0" + +[dev] +[profile.release] +opt-level = "s" diff --git a/aqua-examples/ceramic-demo/services/curl-adapter/src/main.rs b/aqua-examples/ceramic-demo/services/curl-adapter/src/main.rs new file mode 100644 index 0000000..16b1451 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/curl-adapter/src/main.rs @@ -0,0 +1,39 @@ +/* + * Copyright 2021 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#![allow(improper_ctypes)] + +use marine_rs_sdk::marine; +use marine_rs_sdk::module_manifest; +use marine_rs_sdk::MountedBinaryResult; +use marine_rs_sdk::WasmLoggerBuilder; + +module_manifest!(); + +pub fn main() { + // WasmLoggerBuilder::new().build().ok(); +} + +#[marine] +pub fn curl_request(cmd: Vec) -> MountedBinaryResult { + curl(cmd) +} + +#[marine] +#[link(wasm_import_module = "host")] +extern "C" { + fn curl(cmd: Vec) -> MountedBinaryResult; +} diff --git a/aqua-examples/ceramic-demo/services/processor/.gitignore b/aqua-examples/ceramic-demo/services/processor/.gitignore new file mode 100644 index 0000000..bbccc88 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/processor/.gitignore @@ -0,0 +1,5 @@ +debug/ +target/ +Cargo.lock +**/*.bk +**/*.bak diff --git a/aqua-examples/ceramic-demo/services/processor/Cargo.toml b/aqua-examples/ceramic-demo/services/processor/Cargo.toml new file mode 100644 index 0000000..788fe91 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/processor/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "processor" +version = "0.1.0" +authors = ["boneyard93501 <4523011+boneyard93501@users.noreply.github.com>"] +edition = "2018" +description = "processor, a Marine wasi module" +license = "Apache-2.0" + +[[bin]] +name = "processor" +path = "src/main.rs" + +[dependencies] +marine-rs-sdk = { version = "0.6.11", features = ["logger"] } +log = "0.4.14" +# eip-712 = { git = "https://github.com/717a56e1/openethereum/", branch = "eip-712-parser", package = "eip-712" } +eip-712 = { path = "/Users/bebo/localdev/openethereum/crates/util/EIP-712" } +rustc-hex = "2.1.0" +serde_json = "1.0.66" +zeroize = "1.4.1" +validator = "0.8" +chrono = "0.4.19" +libsecp256k1 = "0.6.0" +tiny-keccak = "2.0.2" +hex = "0.4.3" + +[dev-dependencies] +marine-rs-sdk-test = "0.1.11" + +[dev] +[profile.release] +opt-level = "s" diff --git a/aqua-examples/ceramic-demo/services/processor/Config.toml b/aqua-examples/ceramic-demo/services/processor/Config.toml new file mode 100644 index 0000000..b22b42c --- /dev/null +++ b/aqua-examples/ceramic-demo/services/processor/Config.toml @@ -0,0 +1,6 @@ +modules_dir = "artifacts/" + +[[module]] + name = "processor" + mem_pages_count = 1 + logger_enabled = true diff --git a/aqua-examples/ceramic-demo/services/processor/scripts/build.sh b/aqua-examples/ceramic-demo/services/processor/scripts/build.sh new file mode 100755 index 0000000..705d8cd --- /dev/null +++ b/aqua-examples/ceramic-demo/services/processor/scripts/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash -o errexit -o nounset -o pipefail +cargo update --aggressive + +mkdir -p artifacts +rm -f artifacts/*.wasm +marine build --release +cp target/wasm32-wasi/release/processor.wasm artifacts/ diff --git a/aqua-examples/ceramic-demo/services/processor/src/main.rs b/aqua-examples/ceramic-demo/services/processor/src/main.rs new file mode 100644 index 0000000..5373f81 --- /dev/null +++ b/aqua-examples/ceramic-demo/services/processor/src/main.rs @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Fluence Labs Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use marine_rs_sdk::{marine, module_manifest, WasmLoggerBuilder}; +use serde_json; + +module_manifest!(); + +pub fn main() { + WasmLoggerBuilder::new().build().ok(); +}