Created
February 9, 2018 05:43
-
-
Save clarenceb/0cccb48827ce442c775e71c58ecf7657 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "%dna": { | |
| "header": { | |
| "type": "%dna", | |
| "hash": "QmbUdrQoiTzKTzZiJ8BzPeeGye7BPiVUruyQZiBqXNDruk", | |
| "time": "2018-02-08 14:54:25.976547 +1100 AEDT", | |
| "nextHeader": "1", | |
| "next": "%dna: 1", | |
| "entry": "QmSMg4wV1iuvw5V6MwWTD6ppYBeJqBSWyy4M6vm5deqCQ5" | |
| }, | |
| "content": { | |
| "Version": 0, | |
| "UUID": "00000000-0000-0000-0000-000000000000", | |
| "Name": "clutter", | |
| "Properties": { | |
| "description": "distributed micro-blogging (Twitter clone)", | |
| "enableDirectoryAccess": "true", | |
| "language": "en" | |
| }, | |
| "PropertiesSchema": "{\n\t\"title\": \"Properties Schema\",\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"description\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"language\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n\t\t\"enableDirectoryAccess\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t}\n}\n", | |
| "AgentIdentitySchema": "", | |
| "BasedOn": { | |
| "H": null | |
| }, | |
| "RequiresVersion": 18, | |
| "DHTConfig": { | |
| "HashType": "sha2-256", | |
| "NeighborhoodSize": 0 | |
| }, | |
| "Progenitor": { | |
| "Identity": "", | |
| "PubKey": null | |
| }, | |
| "Zomes": [ | |
| { | |
| "Name": "clutter", | |
| "Description": "zome that implements micro-blogging", | |
| "Code": "// ==============================================================================\n// EXPOSED Functions: visible to the UI, can be called via localhost, web browser, or socket\n// ===============================================================================\n\nfunction getProperty(name) { // The definition of the function you intend to expose\n return property(name); // Retrieves a property of the holochain from the DNA (e.g., Name, Language\n}\n\n\nfunction appProperty(name) { // The definition of the function you intend to expose\n if (name == \"App_Agent_Hash\") {return App.Agent.Hash;}\n if (name == \"App_Agent_String\") {return App.Agent.String;}\n if (name == \"App_Key_Hash\") {return App.Key.Hash;}\n if (name == \"App_DNA_Hash\") {return App.DNA.Hash;}\n return \"Error: No App Property with name: \" + name;\n}\n\nfunction follow(userAddress) {\n // Expects a userAddress hash of the person you want to follow\n var me = getMe(); // Looks up my hash address and assign it to 'me'\n\n // Commits a new follow entry to my source chain\n // On the DHT, puts a link on their hash to my hash as a \"follower\"\n // On the DHT, puts a link on my hash to their hash as a \"following\"\n return commit(\"follow\",\n {Links:[\n {Base:userAddress,Link:me,Tag:\"followers\"},\n {Base:me,Link:userAddress,Tag:\"following\"}\n ]});\n\n\n //return User.withHash(getMe()).follow(userAddress);\n}\n\nfunction unfollow(userAddress){\n var me = getMe();\n return commit(\"unfollow\", // On my source chain, commits the unfollow entry\n {Links:[\n {Base:userAddress,Link:me,Tag:\"followers\",LinkAction:HC.LinkAction.Del},\n {Base:me,Link:userAddress,Tag:\"following\",LinkAction:HC.LinkAction.Del}\n ]});\n\n //return User.withHash(userAddress).unfollow(getMe());\n}\n\nfunction post(post) {\n var key = commit(\"post\",post); // Commits the post block to my source chain, assigns resulting hash to 'key'\n var me = getMe(); // Looks up my hash address and assign it to 'me'\n // which DHT nodes will use to request validation info from my source chain\n\n // On the DHT, puts a link on my hash to the new post\n commit(\"post_links\",{Links:[{Base:me,Link:key,Tag:\"post\"}]});\n\n debug(\"meta: \"+JSON.stringify(getLinks(me,\"post\",{Load:true})));\n debug(key);\n return key; // Returns the hash key of the new post to the calling function\n\n\n //return User.withHash(getMe()).createPost(post);\n}\n\nfunction postMod(params) {\n var hash = params.hash;\n var post = params.post;\n // TODO, update the original link too?\n return update(\"post\",post,hash);\n\n // User.withHash(getMe()).updatePost(hash, post)\n}\n\nfunction getPost(params) {\n var post, rawPost = get(params.postHash,{GetMask:HC.GetMask.All});\n if (isErr(rawPost)) {\n return rawPost;\n } else {\n post = {\n post: JSON.parse(rawPost.Entry),\n author: rawPost.Sources[0],\n H: params.postHash\n };\n return post;\n }\n\n // Post.withHash(params.postHash).get();\n}\n\n// TODO add \"last 10\" or \"since timestamp\" when query info is supported\nfunction getPostsBy(userAddresses) {\n // From the DHT, gets all \"post\" metadata entries linked from this userAddress\n var posts = [];\n for (var i=0;i\u003cuserAddresses.length;i++) {\n var author = userAddresses[i];\n var authorPosts = doGetLinkLoad(author,\"post\");\n // add in the author\n for(var j=0;j\u003cauthorPosts.length;j++) {\n var post = authorPosts[j];\n post.author = author;\n posts.push(post);\n }\n }\n return posts;\n}\n\n// get a list of all the people from the DHT a user is following or follows\nfunction getFollow(params) {\n var type = params.type;\n var base = params.from;\n var result = {};\n if ((type == \"followers\") || (type == \"following\")) {\n result[\"result\"] = doGetLink(base,type);\n }\n else {\n result[\"error\"] = \"bad type: \"+type;\n }\n return result;\n}\n\nfunction newHandle(handle){\n var me = getMe();\n var directory = getDirectory();\n var handles = doGetLink(me,\"handle\");\n var n = handles.length - 1;\n if (n \u003e= 0) {\n var oldKey = handles[n];\n var key = update(\"handle\",handle,oldKey);\n\n debug(\"new handle: \"+handle+\" is \"+key);\n debug(\"old handle: was \"+oldKey);\n commit(\"handle_links\",\n {Links:[\n {Base:me,Link:oldKey,Tag:\"handle\",LinkAction:HC.LinkAction.Del},\n {Base:me,Link:key,Tag:\"handle\"}\n ]});\n commit(\"directory_links\",\n {Links:[\n {Base:directory,Link:oldKey,Tag:\"handle\",LinkAction:HC.LinkAction.Del},\n {Base:directory,Link:key,Tag:\"handle\"}\n ]});\n return key;\n }\n return addHandle(handle);\n}\n\n// returns a map of user keys to handles\nfunction getHandles() {\n if (property(\"enableDirectoryAccess\") != \"true\") {\n return undefined;\n }\n var directory = getDirectory();\n var links = getLinks(directory, \"handle\",{Load:true});\n if (isErr(links)) {\n links = [];\n } else {\n links = links;\n }\n var handles = {};\n for (var i=0;i \u003clinks.length;i++) {\n handles[links[i].Source] = links[i].Entry;\n }\n return handles;\n}\n\n// returns the handle of an agent by looking it up on the user's DHT entry, the last handle will be the current one?\nfunction getHandle(userHash) {\n var handles = doGetLinkLoad(userHash,\"handle\");\n var n = handles.length -1;\n var h = handles[n];\n return (n \u003e= 0) ? h.handle : \"\";\n}\n\n// returns the agent associated agent by converting the handle to a hash\n// and getting that hash's source from the DHT\nfunction getAgent(handle) {\n var directory = getDirectory();\n var handleHash = makeHash(\"handle\",handle);\n var sources = get(handleHash,{GetMask:HC.GetMask.Sources});\n if (isErr(sources)) {debug(sources);sources = [];}\n if (sources != undefined) {\n var n = sources.length -1;\n return (n \u003e= 0) ? sources[n] : \"\";\n }\n return \"\";\n}\n\n// ==============================================================================\n// HELPERS: unexposed functions\n// ==============================================================================\n\n// helper function to resolve which has will be used as \"me\"\nfunction getMe() {return App.Key.Hash;}\n\n// helper function to resolve which hash will be used as the base for the directory\n// currently we just use the DNA hash as our entry for linking the directory to\n// TODO commit an anchor entry explicitly for this purpose.\nfunction getDirectory() {return App.DNA.Hash;}\n\n\n// helper function to actually commit a handle and its links on the directory\n// this function gets called at genesis time only because all other times handle gets\n// updated using newHandle\nfunction addHandle(handle) {\n // TODO confirm no collision\n var key = commit(\"handle\",handle); // On my source chain, commits a new handle entry\n var me = getMe();\n var directory = getDirectory();\n\n debug(handle+\" is \"+key);\n\n commit(\"handle_links\", {Links:[{Base:me,Link:key,Tag:\"handle\"}]});\n commit(\"directory_links\", {Links:[{Base:directory,Link:key,Tag:\"handle\"}]});\n\n return key;\n}\n\n// helper function to determine if value returned from holochain function is an error\nfunction isErr(result) {\n return ((typeof result === 'object') \u0026\u0026 result.name == \"HolochainError\");\n}\n\n// helper function to do getLinks call, handle the no-link error case, and copy the returned entry values into a nicer array\nfunction doGetLinkLoad(base, tag) {\n // get the tag from the base in the DHT\n var links = getLinks(base, tag,{Load:true});\n if (isErr(links)) {\n links = [];\n } else {\n links = links;\n }\n var links_filled = [];\n for (var i=0;i \u003clinks.length;i++) {\n var link = {H:links[i].Hash};\n link[tag] = links[i].Entry;\n links_filled.push(link);\n }\n return links_filled;\n}\n\n// helper function to call getLinks, handle the no links entry error, and build a simpler links array.\nfunction doGetLink(base,tag) {\n // get the tag from the base in the DHT\n var links = getLinks(base, tag,{Load:false});\n if (isErr(links)) {\n links = [];\n }\n else {\n links = links;\n }\n debug(\"Links:\"+JSON.stringify(links));\n var links_filled = [];\n for (var i=0;i \u003clinks.length;i++) {\n links_filled.push(links[i].Hash);\n }\n return links_filled;\n}\n\n// ==============================================================================\n// CALLBACKS: Called by back-end system, instead of front-end app or UI\n// ===============================================================================\n\n// GENESIS - Called only when your source chain is generated:'hc gen chain \u003cname\u003e'\n// ===============================================================================\nfunction genesis() { // 'hc gen chain' calls the genesis function in every zome file for the app\n\n // use the agent string (usually email) used with 'hc init' to identify myself and create a new handle\n //addHandle(App.Agent.String);\n //commit(\"anchor\",{type:\"sys\",value:\"directory\"});\n return true;\n}\n\n// ===============================================================================\n// VALIDATION functions for *EVERY* change made to DHT entry -\n// Every DHT node uses their own copy of these functions to validate\n// any and all changes requested before accepting. put / mod / del \u0026 metas\n// ===============================================================================\n\nfunction validateCommit(entry_type,entry,header,pkg,sources) {\n debug(\"validate commit: \"+entry_type);\n return validate(entry_type,entry,header,sources);\n}\n\nfunction validatePut(entry_type,entry,header,pkg,sources) {\n debug(\"validate put: \"+entry_type);\n return validate(entry_type,entry,header,sources);\n}\n\nfunction validate(entry_type,entry,header,sources) {\n if (entry_type==\"post\") {\n var l = entry.message.length;\n if (l\u003e0 \u0026\u0026 l\u003c256) {return true;}\n return false;\n }\n if (entry_type==\"handle\") {\n return true;\n }\n if (entry_type==\"follow\") {\n return true;\n }\n return true;\n}\n\n// Are there types of tags that you need special permission to add links?\n// Examples:\n// - Only Bob should be able to make Bob a \"follower\" of Alice\n// - Only Bob should be able to list Alice in his people he is \"following\"\nfunction validateLink(linkEntryType,baseHash,links,pkg,sources){\n // debug(\"validate link: \"+linkEntryType);\n if (linkEntryType==\"handle_links\") {\n var length = links.length;\n // a valid handle is when:\n\n // there should just be one or two links only\n if (length==2) {\n // if this is a modify it will have two links the first of which\n // will be the del and the second the new link.\n if (links[0].LinkAction != HC.LinkAction.Del) return false;\n if (links[1].LinkAction != HC.LinkAction.Add) return false;\n } else if (length==1) {\n // if this is a new handle, there will just be one Add link\n if (links[0].LinkAction != HC.LinkAction.Add) return false;\n } else {return false;}\n\n for (var i=0;i\u003clength;i++) {\n var link = links[i];\n // the base must be this base\n if (link.Base != baseHash) return false;\n // the base must be the source\n if (link.Base != sources[0]) return false;\n // The tag name should be \"handle\"\n if (link.Tag != \"handle\") return false;\n //TODO check something about the link, i.e. get it and check it's type?\n }\n return true;\n }\n return true;\n}\nfunction validateMod(entry_type,entry,header,replaces,pkg,sources) {\n debug(\"validate mod: \"+entry_type+\" header:\"+JSON.stringify(header)+\" replaces:\"+JSON.stringify(replaces));\n if (entry_type == \"handle\") {\n // check that the source is the same as the creator\n // TODO we could also check that the previous link in the type-chain is the replaces hash.\n var orig_sources = get(replaces,{GetMask:HC.GetMask.Sources});\n if (isErr(orig_sources) || orig_sources == undefined || orig_sources.length !=1 || orig_sources[0] != sources[0]) {return false;}\n\n } else if (entry_type == \"post\") {\n // there must actually be a message\n if (entry.message == \"\") return false;\n var orig = get(replaces,{GetMask:HC.GetMask.Sources+HC.GetMask.Entry});\n\n // check that source is same as creator\n if (orig.Sources.length !=1 || orig.Sources[0] != sources[0]) {return false;}\n\n var orig_message = JSON.parse(orig.Entry).message;\n // message must actually be different\n return orig_message != entry.message;\n }\n return true;\n}\nfunction validateDel(entry_type,hash,pkg,sources) {\n debug(\"validate del: \"+entry_type);\n return true;\n}\n\n// ===============================================================================\n// PACKAGING functions for *EVERY* validation call for DHT entry\n// What data needs to be sent for each above validation function?\n// Default: send and sign the chain entry that matches requested HASH\n// ===============================================================================\n\nfunction validatePutPkg(entry_type) {return null;}\nfunction validateModPkg(entry_type) { return null;}\nfunction validateDelPkg(entry_type) { return null;}\nfunction validateLinkPkg(entry_type) { return null;}\n", | |
| "Entries": [ | |
| { | |
| "Name": "handle", | |
| "DataFormat": "string", | |
| "Sharing": "public", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "post", | |
| "DataFormat": "json", | |
| "Sharing": "public", | |
| "Schema": "{\n \"title\": \"Post Schema\",\n \"type\": \"object\",\n \"properties\": {\n\t\"message\": {\n\t \"type\": \"string\"\n\t},\n\t\"stamp\": {\n\t \"type\": \"integer\"\n\t}\n },\n \"required\": [\"message\",\"stamp\"]\n}\n" | |
| }, | |
| { | |
| "Name": "post_links", | |
| "DataFormat": "links", | |
| "Sharing": "", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "handle_links", | |
| "DataFormat": "links", | |
| "Sharing": "", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "directory_links", | |
| "DataFormat": "links", | |
| "Sharing": "", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "follow", | |
| "DataFormat": "links", | |
| "Sharing": "", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "unfollow", | |
| "DataFormat": "links", | |
| "Sharing": "", | |
| "Schema": "" | |
| }, | |
| { | |
| "Name": "anchor", | |
| "DataFormat": "json", | |
| "Sharing": "public", | |
| "Schema": "{\n \"title\": \"Anchor Schema\",\n \"type\": \"object\",\n \"properties\": {\n\t\"type\": {\n\t \"type\": \"string\"\n\t},\n\t\"value\": {\n\t \"type\": \"string\"\n\t}\n },\n \"required\": [\"type\",\"value\"]\n}\n" | |
| } | |
| ], | |
| "RibosomeType": "js", | |
| "Functions": [ | |
| { | |
| "Name": "getProperty", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "appProperty", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "follow", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "addPost", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "unfollow", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "post", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getPost", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "postMod", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getPostsBy", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "newHandle", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getHandle", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getAgent", | |
| "CallingType": "string", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getFollow", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| }, | |
| { | |
| "Name": "getHandles", | |
| "CallingType": "json", | |
| "Exposure": "public" | |
| } | |
| ], | |
| "BridgeFuncs": null, | |
| "BridgeTo": { | |
| "H": null | |
| } | |
| } | |
| ] | |
| } | |
| }, | |
| "%agent": { | |
| "header": { | |
| "type": "%agent", | |
| "hash": "QmTStgJhG2YWj3EhhKLpSbpgayE8nXstZG2mCx53LTDXzs", | |
| "time": "2018-02-08 14:54:25.977046 +1100 AEDT", | |
| "nextHeader": "QmbUdrQoiTzKTzZiJ8BzPeeGye7BPiVUruyQZiBqXNDruk", | |
| "next": "%agent: 1", | |
| "entry": "QmbGsfXz3D67kdWjj6qkrVNfNwCrimakWDabnVwgzPT6WJ" | |
| }, | |
| "content": { | |
| "Identity": "lucy", | |
| "Revocation": null, | |
| "PublicKey": "CAESIC1t5p0wcEB992lfdZMSEI5R0jJ7dMlVqiN7gBA40oDy" | |
| } | |
| }, | |
| "entries": [ | |
| { | |
| "header": { | |
| "type": "handle", | |
| "hash": "QmVWwEK2TCn2KcfeiUov1Q2zRTKJkRiktKMsg4ivNXLto2", | |
| "time": "2018-02-08 14:55:29.515272 +1100 AEDT", | |
| "nextHeader": "QmTStgJhG2YWj3EhhKLpSbpgayE8nXstZG2mCx53LTDXzs", | |
| "next": "handle: 1", | |
| "entry": "QmW4jaz9N97n7Siu9eHg99Kkcx3siv3tALA3uHnShDFgYk" | |
| }, | |
| "content": "phil" | |
| }, | |
| { | |
| "header": { | |
| "type": "handle_links", | |
| "hash": "Qmag7x4erofR3hVSYKcesazq8oYqRXbvisbRHUn5TX1WB8", | |
| "time": "2018-02-08 14:55:29.527874 +1100 AEDT", | |
| "nextHeader": "QmVWwEK2TCn2KcfeiUov1Q2zRTKJkRiktKMsg4ivNXLto2", | |
| "next": "handle_links: 1", | |
| "entry": "QmQvobj1NS87gH3bypVL5SLubQV4kuT8pRiL4yTxzkLCih" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmW4jaz9N97n7Siu9eHg99Kkcx3siv3tALA3uHnShDFgYk\",\"Tag\":\"handle\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "directory_links", | |
| "hash": "QmW8WPQXpZeajoitSJxXnWEXXNxDdXjYx3rL7kTXXK1trP", | |
| "time": "2018-02-08 14:55:29.536298 +1100 AEDT", | |
| "nextHeader": "Qmag7x4erofR3hVSYKcesazq8oYqRXbvisbRHUn5TX1WB8", | |
| "next": "directory_links: 1", | |
| "entry": "QmcPVsvsh2Y7GdrV8GjMGft4iGGS5SrNNpRJ6WJpENRyzj" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmSMg4wV1iuvw5V6MwWTD6ppYBeJqBSWyy4M6vm5deqCQ5\",\"Link\":\"QmW4jaz9N97n7Siu9eHg99Kkcx3siv3tALA3uHnShDFgYk\",\"Tag\":\"handle\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmRMmXZ2mXBBDoyL3dXisFUUKp7HS4mBkSihu51EWaSp43", | |
| "time": "2018-02-08 14:56:26.068295 +1100 AEDT", | |
| "nextHeader": "QmW8WPQXpZeajoitSJxXnWEXXNxDdXjYx3rL7kTXXK1trP", | |
| "next": "post: 1", | |
| "entry": "QmWox6XvQ1w928NJZu7w5AwwoWnfVDskduB2zSn4nHDymN" | |
| }, | |
| "content": "{\"message\":\"hi people\",\"stamp\":1518062186056}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmendZgUoNekZrvbWSkLgCFQBQ3iM9Uu1m13LUgUoQy4hj", | |
| "time": "2018-02-08 14:56:26.078456 +1100 AEDT", | |
| "nextHeader": "QmRMmXZ2mXBBDoyL3dXisFUUKp7HS4mBkSihu51EWaSp43", | |
| "next": "post_links: 1", | |
| "entry": "QmbGrasgYfrPn6kswg8byYDPbPjSdytgiyrckMCTvb7wQW" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmWox6XvQ1w928NJZu7w5AwwoWnfVDskduB2zSn4nHDymN\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmQhevUqqpp87S9i4yVmxrXW4qd3zyDGDvTAy6EfjAjwPX", | |
| "time": "2018-02-08 14:59:59.228857 +1100 AEDT", | |
| "nextHeader": "QmendZgUoNekZrvbWSkLgCFQBQ3iM9Uu1m13LUgUoQy4hj", | |
| "next": "post: QmRMmXZ2mXBBDoyL3dXisFUUKp7HS4mBkSihu51EWaSp43", | |
| "entry": "QmNWkcnK5ahNAj9tvYAux59PzQbj6v7bGQUCr7iiEaexTt" | |
| }, | |
| "content": "{\"message\":\"yo man\",\"stamp\":1518062399218}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmQLWZxAK37TyiuxonrRkY2mMYTt7PckTUeYC2y7m5A2Xa", | |
| "time": "2018-02-08 14:59:59.239983 +1100 AEDT", | |
| "nextHeader": "QmQhevUqqpp87S9i4yVmxrXW4qd3zyDGDvTAy6EfjAjwPX", | |
| "next": "post_links: QmendZgUoNekZrvbWSkLgCFQBQ3iM9Uu1m13LUgUoQy4hj", | |
| "entry": "QmT5kJrqyvawCYGxfszmAtX8tvxAtn9VhapuwXNr9WWPdx" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmNWkcnK5ahNAj9tvYAux59PzQbj6v7bGQUCr7iiEaexTt\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmTXexcc99GjmvpsdY5d7Q2nLk1C7vSohzkuL4wTsuCpHx", | |
| "time": "2018-02-08 15:37:31.733243 +1100 AEDT", | |
| "nextHeader": "QmQLWZxAK37TyiuxonrRkY2mMYTt7PckTUeYC2y7m5A2Xa", | |
| "next": "post: QmQhevUqqpp87S9i4yVmxrXW4qd3zyDGDvTAy6EfjAjwPX", | |
| "entry": "QmaxsSsEi2PNvbC51Ar9HPMaZkEhDQBQ55GiieTEb63m2f" | |
| }, | |
| "content": "{\"message\":\"wsasd\",\"stamp\":1518064651722}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmdRfs12tUBHUyYUafiVab7JAGi5bnrAf4VZLzYwgoq4kT", | |
| "time": "2018-02-08 15:37:31.744272 +1100 AEDT", | |
| "nextHeader": "QmTXexcc99GjmvpsdY5d7Q2nLk1C7vSohzkuL4wTsuCpHx", | |
| "next": "post_links: QmQLWZxAK37TyiuxonrRkY2mMYTt7PckTUeYC2y7m5A2Xa", | |
| "entry": "QmXAxz1uME51qfJTrKSWYqGegTuStPsW5cgnNM4rRfkCcx" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmaxsSsEi2PNvbC51Ar9HPMaZkEhDQBQ55GiieTEb63m2f\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmQkkrYUTHjxxboBZJJbPJAzo6nMre6axdhbvvFSnU5xAx", | |
| "time": "2018-02-08 15:38:06.431889 +1100 AEDT", | |
| "nextHeader": "QmdRfs12tUBHUyYUafiVab7JAGi5bnrAf4VZLzYwgoq4kT", | |
| "next": "post: QmTXexcc99GjmvpsdY5d7Q2nLk1C7vSohzkuL4wTsuCpHx", | |
| "entry": "QmW858tpKRmrxmdbTKiNGsd6hZ6vX4XaSw5Y6aYkuK3sxe" | |
| }, | |
| "content": "{\"message\":\"asdadd\",\"stamp\":1518064686424}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmTRDb4EWpNtnuuiQD4mE1rM5SphTyrjSqV8suo9TCMNvR", | |
| "time": "2018-02-08 15:38:06.442667 +1100 AEDT", | |
| "nextHeader": "QmQkkrYUTHjxxboBZJJbPJAzo6nMre6axdhbvvFSnU5xAx", | |
| "next": "post_links: QmdRfs12tUBHUyYUafiVab7JAGi5bnrAf4VZLzYwgoq4kT", | |
| "entry": "QmQXSAk7yXk2o6sCKUEeBV2aESQJtxtoq4cM8S54BmLogH" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmW858tpKRmrxmdbTKiNGsd6hZ6vX4XaSw5Y6aYkuK3sxe\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "Qmb9GDCwAiXoyDCSHmCprfUtBcHj7bRMZf5p322R29mhwN", | |
| "time": "2018-02-08 15:38:33.24818 +1100 AEDT", | |
| "nextHeader": "QmTRDb4EWpNtnuuiQD4mE1rM5SphTyrjSqV8suo9TCMNvR", | |
| "next": "post: QmQkkrYUTHjxxboBZJJbPJAzo6nMre6axdhbvvFSnU5xAx", | |
| "entry": "QmRDD9kWBh2rUqe5EEwskE4xphfhbrzV3TdxcQCKvzgXsG" | |
| }, | |
| "content": "{\"message\":\"asdd\",\"stamp\":1518064713235}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmSUmYuqckqMQdpvQjQCf9ReQyYJjxrpzCr8dTDaVnmzdS", | |
| "time": "2018-02-08 15:38:33.256121 +1100 AEDT", | |
| "nextHeader": "Qmb9GDCwAiXoyDCSHmCprfUtBcHj7bRMZf5p322R29mhwN", | |
| "next": "post_links: QmTRDb4EWpNtnuuiQD4mE1rM5SphTyrjSqV8suo9TCMNvR", | |
| "entry": "QmcVVU8aVSnRDYPHbnw17KQJ41WBv7fLjaKzvjf1QdbmYh" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmRDD9kWBh2rUqe5EEwskE4xphfhbrzV3TdxcQCKvzgXsG\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmV3TFhMYfiR9eBRKwWQUegktRsnafjB3HgbVpzyVXDWbA", | |
| "time": "2018-02-08 15:39:04.626188 +1100 AEDT", | |
| "nextHeader": "QmSUmYuqckqMQdpvQjQCf9ReQyYJjxrpzCr8dTDaVnmzdS", | |
| "next": "post: Qmb9GDCwAiXoyDCSHmCprfUtBcHj7bRMZf5p322R29mhwN", | |
| "entry": "QmWSwp4i76tYsQCSMQw2Ls4XwBNzATxVEsBZ6KUdm5tMqS" | |
| }, | |
| "content": "{\"message\":\"asdasd\",\"stamp\":1518064744618}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmYHNPuKVGMfCWv5zDggvwBNeYSfkSfVfLD7sKeoGsN1R2", | |
| "time": "2018-02-08 15:39:04.632202 +1100 AEDT", | |
| "nextHeader": "QmV3TFhMYfiR9eBRKwWQUegktRsnafjB3HgbVpzyVXDWbA", | |
| "next": "post_links: QmSUmYuqckqMQdpvQjQCf9ReQyYJjxrpzCr8dTDaVnmzdS", | |
| "entry": "QmYBH8ANmVqZZyPAeerc6ui8VWUDToJ6tYyycx2ySGNB3M" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmWSwp4i76tYsQCSMQw2Ls4XwBNzATxVEsBZ6KUdm5tMqS\",\"Tag\":\"post\"}]}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post", | |
| "hash": "QmXc33VLmgo3Ty2bDzLyKsiauxAjB1FdA9dkjsdAqHYbZD", | |
| "time": "2018-02-08 15:39:18.191326 +1100 AEDT", | |
| "nextHeader": "QmYHNPuKVGMfCWv5zDggvwBNeYSfkSfVfLD7sKeoGsN1R2", | |
| "next": "post: QmV3TFhMYfiR9eBRKwWQUegktRsnafjB3HgbVpzyVXDWbA", | |
| "entry": "QmcCrrqFNRrcrRkyHnAhCpp1iUXzfY49AjzQVkCFUPQUuN" | |
| }, | |
| "content": "{\"message\":\"asdasd\",\"stamp\":1518064758181}" | |
| }, | |
| { | |
| "header": { | |
| "type": "post_links", | |
| "hash": "QmVLUrexC9xtWEfx5svktCb6zM16vFvU8pJ8vcmCoU1nUe", | |
| "time": "2018-02-08 15:39:18.19923 +1100 AEDT", | |
| "nextHeader": "QmXc33VLmgo3Ty2bDzLyKsiauxAjB1FdA9dkjsdAqHYbZD", | |
| "next": "post_links: QmYHNPuKVGMfCWv5zDggvwBNeYSfkSfVfLD7sKeoGsN1R2", | |
| "entry": "QmYiakjcFzLQuyp6WP8Hn6wqXjMk55KxJ7mC8ak3A3daGX" | |
| }, | |
| "content": "{\"Links\":[{\"Base\":\"QmWQVaqEayZJWnvxLtsKr1iyeTDp3s7m7TTE36HhAUTiTK\",\"Link\":\"QmcCrrqFNRrcrRkyHnAhCpp1iUXzfY49AjzQVkCFUPQUuN\",\"Tag\":\"post\"}]}" | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment