From 0db068ef6f286a315c68bf7b4baf379f93691189 Mon Sep 17 00:00:00 2001 From: xiaoyuanxun <53613219+xiaoyuanxun@users.noreply.github.com> Date: Sun, 26 Nov 2023 22:20:58 +0800 Subject: [PATCH] test update --- package-lock.json | 318 ++++++++++++++++++ package.json | 3 +- .../commentFetch/commentFetch.did | 8 + .../commentFetch/commentFetch.did.d.ts | 2 + .../commentFetch/commentFetch.did.js | 10 + src/declarations/feed/feed.did | 1 + src/declarations/feed/feed.did.d.ts | 1 + src/declarations/feed/feed.did.js | 1 + src/declarations/likeFetch/likeFetch.did | 8 + src/declarations/likeFetch/likeFetch.did.d.ts | 2 + src/declarations/likeFetch/likeFetch.did.js | 10 + src/declarations/postFetch/postFetch.did | 8 + src/declarations/postFetch/postFetch.did.d.ts | 2 + src/declarations/postFetch/postFetch.did.js | 10 + src/declarations/rootFetch/rootFetch.did | 2 +- src/declarations/rootFetch/rootFetch.did.d.ts | 2 +- src/declarations/rootFetch/rootFetch.did.js | 6 +- src/declarations/user/user.did | 4 +- src/declarations/user/user.did.d.ts | 4 +- src/declarations/user/user.did.js | 4 +- src/feed/feed.mo | 14 +- src/feed/rootFeed.mo | 5 +- src/fetch/commentFetch.mo | 9 + src/fetch/likeFetch.mo | 10 +- src/fetch/postFetch.mo | 25 +- src/fetch/rootFetch.mo | 37 +- src/fetch/types.mo | 6 + src/types.mo | 4 + src/user/digraph.mo | 4 + src/user/main.mo | 29 +- src/user/types.mo | 5 + start.sh | 37 +- test/js/feed.js | 57 +++- test/js/identity.js | 4 +- test/js/index.js | 102 +++++- test/js/postFetch.js | 15 + test/js/rootFeed.js | 9 - test/js/rootFetch.js | 39 +++ test/js/user.js | 26 ++ 39 files changed, 770 insertions(+), 73 deletions(-) create mode 100644 test/js/postFetch.js create mode 100644 test/js/rootFetch.js diff --git a/package-lock.json b/package-lock.json index a139002..aa76659 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@dfinity/identity": "^0.20.1", "@dfinity/identity-secp256k1": "^0.20.1", "@dfinity/principal": "^0.20.1", + "assert": "^2.1.0", "dotenv": "^16.3.1" } }, @@ -153,6 +154,29 @@ "node": ">=12.0.0" } }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/base-x": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", @@ -291,6 +315,19 @@ "ieee754": "^1.2.1" } }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -317,6 +354,35 @@ "sha.js": "^2.4.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delimit-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", @@ -347,6 +413,94 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -369,6 +523,17 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hdkey": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-2.1.0.tgz", @@ -459,6 +624,75 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/iso-url": { "version": "0.4.7", "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", @@ -510,6 +744,46 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/pvtsutils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", @@ -583,6 +857,20 @@ "node": ">=14.0.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -614,6 +902,18 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "peer": true }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -631,6 +931,24 @@ "pvtsutils": "^1.3.2", "tslib": "^2.4.0" } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } } } } diff --git a/package.json b/package.json index 4d917e4..b068738 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "author": "NeutronStarDAO", - "type" : "module", + "type": "module", "license": "ISC", "dependencies": { "@dfinity/agent": "^0.20.1", @@ -17,6 +17,7 @@ "@dfinity/identity": "^0.20.1", "@dfinity/identity-secp256k1": "^0.20.1", "@dfinity/principal": "^0.20.1", + "assert": "^2.1.0", "dotenv": "^16.3.1" } } diff --git a/src/declarations/commentFetch/commentFetch.did b/src/declarations/commentFetch/commentFetch.did index b8ebf39..35cc28b 100644 --- a/src/declarations/commentFetch/commentFetch.did +++ b/src/declarations/commentFetch/commentFetch.did @@ -29,6 +29,14 @@ type CommentFetch = principal; principal; }) -> (bool); + getNotifyMapEntries: () -> (vec record { + principal; + vec text; + }) query; + getUserToFeedEntries: () -> (vec record { + principal; + principal; + }) query; initUserToFeed: (vec record { principal; principal; diff --git a/src/declarations/commentFetch/commentFetch.did.d.ts b/src/declarations/commentFetch/commentFetch.did.d.ts index 9cb1157..cf54537 100644 --- a/src/declarations/commentFetch/commentFetch.did.d.ts +++ b/src/declarations/commentFetch/commentFetch.did.d.ts @@ -8,6 +8,8 @@ export interface Comment { } export interface CommentFetch { 'addUserToFeedEntry' : ActorMethod<[[Principal, Principal]], boolean>, + 'getNotifyMapEntries' : ActorMethod<[], Array<[Principal, Array]>>, + 'getUserToFeedEntries' : ActorMethod<[], Array<[Principal, Principal]>>, 'initUserToFeed' : ActorMethod<[Array<[Principal, Principal]>], boolean>, 'receiveNotify' : ActorMethod<[PostImmutable], undefined>, 'receiveRepostUserNotify' : ActorMethod< diff --git a/src/declarations/commentFetch/commentFetch.did.js b/src/declarations/commentFetch/commentFetch.did.js index 4579e8f..9a9b5d2 100644 --- a/src/declarations/commentFetch/commentFetch.did.js +++ b/src/declarations/commentFetch/commentFetch.did.js @@ -26,6 +26,16 @@ export const idlFactory = ({ IDL }) => { [IDL.Bool], [], ), + 'getNotifyMapEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Vec(IDL.Text)))], + ['query'], + ), + 'getUserToFeedEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], + ['query'], + ), 'initUserToFeed' : IDL.Func( [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], [IDL.Bool], diff --git a/src/declarations/feed/feed.did b/src/declarations/feed/feed.did index f9118b4..7f974c5 100644 --- a/src/declarations/feed/feed.did +++ b/src/declarations/feed/feed.did @@ -37,6 +37,7 @@ type Feed = getCommentFetchCanister: () -> (principal) query; getFeed: (text) -> (opt PostImmutable) query; getFeedNumber: () -> (nat) query; + getFollowers: () -> (vec principal) query; getLatestFeed: (nat) -> (vec PostImmutable) query; getLikeFetchCanister: () -> (principal) query; getOwner: () -> (principal) query; diff --git a/src/declarations/feed/feed.did.d.ts b/src/declarations/feed/feed.did.d.ts index 08b8823..c3b970d 100644 --- a/src/declarations/feed/feed.did.d.ts +++ b/src/declarations/feed/feed.did.d.ts @@ -19,6 +19,7 @@ export interface Feed { 'getCommentFetchCanister' : ActorMethod<[], Principal>, 'getFeed' : ActorMethod<[string], [] | [PostImmutable]>, 'getFeedNumber' : ActorMethod<[], bigint>, + 'getFollowers' : ActorMethod<[], Array>, 'getLatestFeed' : ActorMethod<[bigint], Array>, 'getLikeFetchCanister' : ActorMethod<[], Principal>, 'getOwner' : ActorMethod<[], Principal>, diff --git a/src/declarations/feed/feed.did.js b/src/declarations/feed/feed.did.js index e5cb108..8f64f4a 100644 --- a/src/declarations/feed/feed.did.js +++ b/src/declarations/feed/feed.did.js @@ -33,6 +33,7 @@ export const idlFactory = ({ IDL }) => { 'getCommentFetchCanister' : IDL.Func([], [IDL.Principal], ['query']), 'getFeed' : IDL.Func([IDL.Text], [IDL.Opt(PostImmutable)], ['query']), 'getFeedNumber' : IDL.Func([], [IDL.Nat], ['query']), + 'getFollowers' : IDL.Func([], [IDL.Vec(IDL.Principal)], ['query']), 'getLatestFeed' : IDL.Func([IDL.Nat], [IDL.Vec(PostImmutable)], ['query']), 'getLikeFetchCanister' : IDL.Func([], [IDL.Principal], ['query']), 'getOwner' : IDL.Func([], [IDL.Principal], ['query']), diff --git a/src/declarations/likeFetch/likeFetch.did b/src/declarations/likeFetch/likeFetch.did index c593a1f..97a06a2 100644 --- a/src/declarations/likeFetch/likeFetch.did +++ b/src/declarations/likeFetch/likeFetch.did @@ -24,6 +24,14 @@ type LikeFetch = principal; principal; }) -> (bool); + getNotifyMapEntries: () -> (vec record { + principal; + vec text; + }) query; + getUserToFeedEntries: () -> (vec record { + principal; + principal; + }) query; initUserToFeed: (vec record { principal; principal; diff --git a/src/declarations/likeFetch/likeFetch.did.d.ts b/src/declarations/likeFetch/likeFetch.did.d.ts index a9a6663..5f89654 100644 --- a/src/declarations/likeFetch/likeFetch.did.d.ts +++ b/src/declarations/likeFetch/likeFetch.did.d.ts @@ -9,6 +9,8 @@ export interface Comment { export interface Like { 'createdAt' : Time, 'user' : UserId } export interface LikeFetch { 'addUserToFeedEntry' : ActorMethod<[[Principal, Principal]], boolean>, + 'getNotifyMapEntries' : ActorMethod<[], Array<[Principal, Array]>>, + 'getUserToFeedEntries' : ActorMethod<[], Array<[Principal, Principal]>>, 'initUserToFeed' : ActorMethod<[Array<[Principal, Principal]>], boolean>, 'receiveNotify' : ActorMethod<[PostImmutable], undefined>, 'receiveRepostUserNotify' : ActorMethod< diff --git a/src/declarations/likeFetch/likeFetch.did.js b/src/declarations/likeFetch/likeFetch.did.js index 6719628..54507d1 100644 --- a/src/declarations/likeFetch/likeFetch.did.js +++ b/src/declarations/likeFetch/likeFetch.did.js @@ -26,6 +26,16 @@ export const idlFactory = ({ IDL }) => { [IDL.Bool], [], ), + 'getNotifyMapEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Vec(IDL.Text)))], + ['query'], + ), + 'getUserToFeedEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], + ['query'], + ), 'initUserToFeed' : IDL.Func( [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], [IDL.Bool], diff --git a/src/declarations/postFetch/postFetch.did b/src/declarations/postFetch/postFetch.did index 9d04151..f590be8 100644 --- a/src/declarations/postFetch/postFetch.did +++ b/src/declarations/postFetch/postFetch.did @@ -4,6 +4,14 @@ type PostFetch = principal; principal; }) -> (bool); + getNotifyMapEntries: () -> (vec record { + principal; + vec text; + }) query; + getUserToFeedEntries: () -> (vec record { + principal; + principal; + }) query; initUserToFeed: (vec record { principal; principal; diff --git a/src/declarations/postFetch/postFetch.did.d.ts b/src/declarations/postFetch/postFetch.did.d.ts index 8192700..dcc68ba 100644 --- a/src/declarations/postFetch/postFetch.did.d.ts +++ b/src/declarations/postFetch/postFetch.did.d.ts @@ -3,6 +3,8 @@ import type { ActorMethod } from '@dfinity/agent'; export interface PostFetch { 'addUserToFeedEntry' : ActorMethod<[[Principal, Principal]], boolean>, + 'getNotifyMapEntries' : ActorMethod<[], Array<[Principal, Array]>>, + 'getUserToFeedEntries' : ActorMethod<[], Array<[Principal, Principal]>>, 'initUserToFeed' : ActorMethod<[Array<[Principal, Principal]>], boolean>, 'receiveNotify' : ActorMethod<[Array, string], undefined>, 'whoami' : ActorMethod<[], Principal>, diff --git a/src/declarations/postFetch/postFetch.did.js b/src/declarations/postFetch/postFetch.did.js index 3ddb8fa..514a8db 100644 --- a/src/declarations/postFetch/postFetch.did.js +++ b/src/declarations/postFetch/postFetch.did.js @@ -5,6 +5,16 @@ export const idlFactory = ({ IDL }) => { [IDL.Bool], [], ), + 'getNotifyMapEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Vec(IDL.Text)))], + ['query'], + ), + 'getUserToFeedEntries' : IDL.Func( + [], + [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], + ['query'], + ), 'initUserToFeed' : IDL.Func( [IDL.Vec(IDL.Tuple(IDL.Principal, IDL.Principal))], [IDL.Bool], diff --git a/src/declarations/rootFetch/rootFetch.did b/src/declarations/rootFetch/rootFetch.did index 04baf61..b889848 100644 --- a/src/declarations/rootFetch/rootFetch.did +++ b/src/declarations/rootFetch/rootFetch.did @@ -6,6 +6,6 @@ type RootFetch = getAllCommentFetchCanister: () -> (vec principal) query; getAllLikeFetchCanister: () -> (vec principal) query; getAllPostFetchCanister: () -> (vec principal) query; - init: (principal) -> (); + init: (principal, principal, principal, principal) -> (); }; service : (principal) -> RootFetch diff --git a/src/declarations/rootFetch/rootFetch.did.d.ts b/src/declarations/rootFetch/rootFetch.did.d.ts index 07784da..ab9f985 100644 --- a/src/declarations/rootFetch/rootFetch.did.d.ts +++ b/src/declarations/rootFetch/rootFetch.did.d.ts @@ -8,6 +8,6 @@ export interface RootFetch { 'getAllCommentFetchCanister' : ActorMethod<[], Array>, 'getAllLikeFetchCanister' : ActorMethod<[], Array>, 'getAllPostFetchCanister' : ActorMethod<[], Array>, - 'init' : ActorMethod<[Principal], undefined>, + 'init' : ActorMethod<[Principal, Principal, Principal, Principal], undefined>, } export interface _SERVICE extends RootFetch {} diff --git a/src/declarations/rootFetch/rootFetch.did.js b/src/declarations/rootFetch/rootFetch.did.js index 4e91efa..f351f1c 100644 --- a/src/declarations/rootFetch/rootFetch.did.js +++ b/src/declarations/rootFetch/rootFetch.did.js @@ -18,7 +18,11 @@ export const idlFactory = ({ IDL }) => { [IDL.Vec(IDL.Principal)], ['query'], ), - 'init' : IDL.Func([IDL.Principal], [], []), + 'init' : IDL.Func( + [IDL.Principal, IDL.Principal, IDL.Principal, IDL.Principal], + [], + [], + ), }); return RootFetch; }; diff --git a/src/declarations/user/user.did b/src/declarations/user/user.did index 8ae0c9d..f392aa7 100644 --- a/src/declarations/user/user.did +++ b/src/declarations/user/user.did @@ -4,10 +4,12 @@ type UserId = principal; type User = service { createProfile: (NewProfile) -> (); - follow: (Vertex, Vertex) -> (); + follow: (Vertex) -> (); getFollowersList: (Vertex) -> (vec Vertex) query; getFollowingList: (Vertex) -> (vec Vertex) query; getProfile: (UserId__1) -> (opt Profile) query; + getRootFeedCanister: () -> (principal) query; + init: (principal) -> () oneway; searchProfile: (text) -> (vec Profile) query; updateProfile: (NewProfile) -> (); }; diff --git a/src/declarations/user/user.did.d.ts b/src/declarations/user/user.did.d.ts index a0693a5..8f908bd 100644 --- a/src/declarations/user/user.did.d.ts +++ b/src/declarations/user/user.did.d.ts @@ -20,10 +20,12 @@ export interface Profile { } export interface User { 'createProfile' : ActorMethod<[NewProfile], undefined>, - 'follow' : ActorMethod<[Vertex, Vertex], undefined>, + 'follow' : ActorMethod<[Vertex], undefined>, 'getFollowersList' : ActorMethod<[Vertex], Array>, 'getFollowingList' : ActorMethod<[Vertex], Array>, 'getProfile' : ActorMethod<[UserId__1], [] | [Profile]>, + 'getRootFeedCanister' : ActorMethod<[], Principal>, + 'init' : ActorMethod<[Principal], undefined>, 'searchProfile' : ActorMethod<[string], Array>, 'updateProfile' : ActorMethod<[NewProfile], undefined>, } diff --git a/src/declarations/user/user.did.js b/src/declarations/user/user.did.js index 3f0613e..f851990 100644 --- a/src/declarations/user/user.did.js +++ b/src/declarations/user/user.did.js @@ -21,10 +21,12 @@ export const idlFactory = ({ IDL }) => { }); const User = IDL.Service({ 'createProfile' : IDL.Func([NewProfile], [], []), - 'follow' : IDL.Func([Vertex, Vertex], [], []), + 'follow' : IDL.Func([Vertex], [], []), 'getFollowersList' : IDL.Func([Vertex], [IDL.Vec(Vertex)], ['query']), 'getFollowingList' : IDL.Func([Vertex], [IDL.Vec(Vertex)], ['query']), 'getProfile' : IDL.Func([UserId__1], [IDL.Opt(Profile)], ['query']), + 'getRootFeedCanister' : IDL.Func([], [IDL.Principal], ['query']), + 'init' : IDL.Func([IDL.Principal], [], ['oneway']), 'searchProfile' : IDL.Func([IDL.Text], [IDL.Vec(Profile)], ['query']), 'updateProfile' : IDL.Func([NewProfile], [], []), }); diff --git a/src/feed/feed.mo b/src/feed/feed.mo index f1c6cd8..2e4495d 100644 --- a/src/feed/feed.mo +++ b/src/feed/feed.mo @@ -76,6 +76,10 @@ actor class Feed( followers := newFollowers; }; + public query func getFollowers(): async [Principal] { + followers + }; + // Bucket type RootPostActor = Types.RootPostActor; @@ -123,10 +127,14 @@ actor class Feed( // 将帖子内容发送给公共区的 Bucket let bucketActor: BucketActor = actor(Principal.toText(_bucket)); - ignore await bucketActor.storeFeed(post); - + ignore await bucketActor.storeFeed(post); + // 通知 PostFetch let postFetchActor: PostFetchActor = actor(Principal.toText(postFetchCanister)); + Debug.print("postFetchCanister : " # Principal.toText(postFetchCanister)); + for(_follower in followers.vals()) { + Debug.print("Canister Feed, Func createPost, follower : " # Principal.toText(_follower)); + }; ignore postFetchActor.receiveNotify(followers, post.postId); post.postId @@ -174,8 +182,6 @@ actor class Feed( return true; }; }; - - // await sendFeed(); }; // Feed diff --git a/src/feed/rootFeed.mo b/src/feed/rootFeed.mo index fb62349..f5a443e 100644 --- a/src/feed/rootFeed.mo +++ b/src/feed/rootFeed.mo @@ -46,10 +46,9 @@ actor class RootFeed( compute_allocation = null; } }); - + // 更新 fetch 中的信息 - - + ignore updateFetchUserToFeed((caller, feedCanisterId)); ?feedCanisterId }; diff --git a/src/fetch/commentFetch.mo b/src/fetch/commentFetch.mo index c00da92..7d98902 100644 --- a/src/fetch/commentFetch.mo +++ b/src/fetch/commentFetch.mo @@ -3,6 +3,7 @@ import TrieMap "mo:base/TrieMap"; import Types "./types"; import Array "mo:base/Array"; import Timer "mo:base/Timer"; +import Iter "mo:base/Iter"; actor class CommentFetch( userCanister: Principal @@ -39,6 +40,10 @@ actor class CommentFetch( }; }; + public query func getNotifyMapEntries(): async [(Principal, [Text])] { + Iter.toArray(notifyMap.entries()) + }; + // userToFeed var userToFeed = TrieMap.TrieMap(Principal.equal, Principal.hash); @@ -62,6 +67,10 @@ actor class CommentFetch( } }; + public query func getUserToFeedEntries(): async [(Principal, Principal)] { + Iter.toArray(userToFeed.entries()) + }; + public query({caller}) func whoami(): async Principal { caller }; // Timer diff --git a/src/fetch/likeFetch.mo b/src/fetch/likeFetch.mo index 63da193..7448665 100644 --- a/src/fetch/likeFetch.mo +++ b/src/fetch/likeFetch.mo @@ -3,6 +3,7 @@ import TrieMap "mo:base/TrieMap"; import Types "./types"; import Array "mo:base/Array"; import Timer "mo:base/Timer"; +import Iter "mo:base/Iter"; actor class LikeFetch( userCanister: Principal @@ -25,6 +26,10 @@ actor class LikeFetch( _storeNotify(to, postId); }; + public query func getNotifyMapEntries(): async [(Principal, [Text])] { + Iter.toArray(notifyMap.entries()) + }; + private func _storeNotify(followerArray: [Principal], postId: Text) { for(_follower in followerArray.vals()) { switch(notifyMap.get(_follower)) { @@ -38,7 +43,6 @@ actor class LikeFetch( }; }; }; - // userToFeed var userToFeed = TrieMap.TrieMap(Principal.equal, Principal.hash); @@ -62,6 +66,10 @@ actor class LikeFetch( } }; + public query func getUserToFeedEntries(): async [(Principal, Principal)] { + Iter.toArray(userToFeed.entries()) + }; + public query({caller}) func whoami(): async Principal { caller }; // Timer diff --git a/src/fetch/postFetch.mo b/src/fetch/postFetch.mo index 0173a16..0962cc7 100644 --- a/src/fetch/postFetch.mo +++ b/src/fetch/postFetch.mo @@ -4,6 +4,7 @@ import Principal "mo:base/Principal"; import Array "mo:base/Array"; import Timer "mo:base/Timer"; import Debug "mo:base/Debug"; +import Iter "mo:base/Iter"; actor class PostFetch() = this { @@ -12,19 +13,29 @@ actor class PostFetch() = this { // 接收发帖人的通知:帖子 ID 、发帖人、转发人、followers 、Cycles 。 public shared({caller}) func receiveNotify(to: [Principal], postId: Text): async () { + for(_user in to.vals()) { + Debug.print( + "Canister PostFetch, Func receiveNotify, " + # "to : " # Principal.toText(_user) # " ," + # "postId : " # postId + ); + }; for(_follower in to.vals()) { switch(notifyMap.get(_follower)) { case(null) { notifyMap.put(_follower, [postId]); }; case(?_postIdArray) { - let _newPostIdArray = Array.append(_postIdArray, [postId]); - notifyMap.put(_follower, _newPostIdArray); + notifyMap.put(_follower, Array.append(_postIdArray, [postId])); }; }; }; }; + public query func getNotifyMapEntries(): async [(Principal, [Text])] { + Iter.toArray(notifyMap.entries()) + }; + // userToFeed var userToFeed = TrieMap.TrieMap(Principal.equal, Principal.hash); @@ -48,6 +59,10 @@ actor class PostFetch() = this { } }; + public query func getUserToFeedEntries(): async [(Principal, Principal)] { + Iter.toArray(userToFeed.entries()) + }; + public query({caller}) func whoami(): async Principal { caller }; // Timer @@ -57,12 +72,16 @@ actor class PostFetch() = this { // 根据算法用 ignore call 分批次通知 followers 的 Feed 。 // 用 Timers 来处理 func notify(): async () { - for((_user, _postIdArray) in notifyMap.entries()) { + Debug.print("postFetch notify !"); + let _notifyMap = notifyMap; + for((_user, _postIdArray) in _notifyMap.entries()) { switch(userToFeed.get(_user)) { case(null) { }; case(?_feedId) { + Debug.print("Notify feed canister " # Principal.toText(_feedId)); let feedActor: FeedActor = actor(Principal.toText(_feedId)); ignore feedActor.batchReceiveFeed(_postIdArray); + notifyMap.delete(_user); }; }; }; diff --git a/src/fetch/rootFetch.mo b/src/fetch/rootFetch.mo index 76375f6..1a525c6 100644 --- a/src/fetch/rootFetch.mo +++ b/src/fetch/rootFetch.mo @@ -7,13 +7,18 @@ import CommentFetch "./commentFetch"; import LikeFetch "./likeFetch"; import Iter "mo:base/Iter"; import Types "./types"; +import Cycles "mo:base/ExperimentalCycles"; actor class RootFetch( - userCanister: Principal + userCanister: Principal, ) = this { - + type RootFeedActor = Types.RootFeedActor; + type PostFetchActor = Types.PostFetchActor; + type CommentFetchActor = Types.CommentFetchActor; + type LikeFetchActor = Types.LikeFetchActor; + stable let T_CYCLES = 1_000_000_000_000; stable var rootFeedCanister = Principal.fromText("2vxsx-fae"); stable var postFetchCanisterIndex: Nat = 0; stable var commentFetchCanisterIndex: Nat = 0; @@ -23,11 +28,35 @@ actor class RootFetch( let commentFetchMap = TrieMap.TrieMap(Nat.equal, Hash.hash); let likeFetchMap = TrieMap.TrieMap(Nat.equal, Hash.hash); - public shared({caller}) func init(_rootFeedCanister: Principal): async () { + public shared({caller}) func init( + _rootFeedCanister: Principal, + _initPostFetchCanister: Principal, + _initCommentFetchCanister: Principal, + _initLikeFetchCanister: Principal + ): async () { rootFeedCanister := _rootFeedCanister; + + postFetchMap.put(postFetchCanisterIndex, _initPostFetchCanister); + commentFetchMap.put(commentFetchCanisterIndex, _initCommentFetchCanister); + likeFetchMap.put(likeFetchCanisterIndex, _initLikeFetchCanister); + + postFetchCanisterIndex += 1; + commentFetchCanisterIndex += 1; + likeFetchCanisterIndex += 1; + + let rootFeedActor: RootFeedActor = actor(Principal.toText(_rootFeedCanister)); + let _postFetchActor: PostFetchActor = actor(Principal.toText(_initPostFetchCanister)); + let _commentFetchActor: CommentFetchActor = actor(Principal.toText(_initCommentFetchCanister)); + let _likeFetchActor: LikeFetchActor = actor(Principal.toText(_initLikeFetchCanister)); + let _allUserFeedCanister = await rootFeedActor.getAllUserFeedCanister(); + + assert(await _postFetchActor.initUserToFeed(_allUserFeedCanister)); + assert(await _commentFetchActor.initUserToFeed(_allUserFeedCanister)); + assert(await _likeFetchActor.initUserToFeed(_allUserFeedCanister)); }; public shared({caller}) func createPostFetchCanister(): async Principal { + Cycles.add(4 * T_CYCLES); let _canister = await PostFetch.PostFetch(); let _canisterId = Principal.fromActor(_canister); postFetchMap.put(postFetchCanisterIndex, _canisterId); @@ -42,6 +71,7 @@ actor class RootFetch( }; public shared({caller}) func createCommentFetchCanister(): async Principal { + Cycles.add(4 * T_CYCLES); let _canister = await CommentFetch.CommentFetch( userCanister ); @@ -58,6 +88,7 @@ actor class RootFetch( }; public shared({caller}) func createLikeFetchCanister(): async Principal { + Cycles.add(4 * T_CYCLES); let _canister = await LikeFetch.LikeFetch( userCanister ); diff --git a/src/fetch/types.mo b/src/fetch/types.mo index 4cb946f..0a64e12 100644 --- a/src/fetch/types.mo +++ b/src/fetch/types.mo @@ -9,5 +9,11 @@ module { public type RootFeedActor = Types.RootFeedActor; public type FeedActor = Types.FeedActor; + + public type PostFetchActor = Types.PostFetchActor; + + public type CommentFetchActor = Types.CommentFetchActor; + + public type LikeFetchActor = Types.LikeFetchActor; } \ No newline at end of file diff --git a/src/types.mo b/src/types.mo index f64d845..fdc6da1 100644 --- a/src/types.mo +++ b/src/types.mo @@ -68,6 +68,7 @@ module { deleteComment : shared (Principal, Nat, Nat) -> async (); createLike : shared (Principal, Nat) -> async (); deleteLike : shared (Principal, Nat) -> async (); + updateFollowers : shared ([Principal]) -> async (); }; // Post @@ -110,18 +111,21 @@ module { public type PostFetchActor = actor { receiveNotify : shared ([Principal], Text) -> async (); addUserToFeedEntry : shared ((Principal, Principal)) -> async Bool; + initUserToFeed : shared ([(Principal, Principal)]) -> async Bool; }; public type CommentFetchActor = actor { receiveNotify : shared (PostImmutable) -> async (); receiveRepostUserNotify : shared ([Principal], Text) -> async (); addUserToFeedEntry : shared ((Principal, Principal)) -> async Bool; + initUserToFeed : shared ([(Principal, Principal)]) -> async Bool; }; public type LikeFetchActor = actor { receiveNotify : shared (PostImmutable) -> async (); receiveRepostUserNotify : shared ([Principal], Text) -> async (); addUserToFeedEntry : shared ((Principal, Principal)) -> async Bool; + initUserToFeed : shared ([(Principal, Principal)]) -> async Bool; }; // User diff --git a/src/user/digraph.mo b/src/user/digraph.mo index 7b1262b..016a679 100644 --- a/src/user/digraph.mo +++ b/src/user/digraph.mo @@ -17,6 +17,10 @@ module { // 添加 from 到 to 的单向边 public func addEdge(fromVertex: Vertex, toVertex: Vertex) { + // 检查是否已经存在 + assert(Array.find<(Vertex, Vertex)>(edgeList, func((x, y): (Vertex, Vertex)): Bool { + x == fromVertex and y == toVertex + }) == null); edgeList := Array.append<(Vertex, Vertex)>(edgeList, [(fromVertex, toVertex)]); }; diff --git a/src/user/main.mo b/src/user/main.mo index dcc37f5..db6dc9f 100644 --- a/src/user/main.mo +++ b/src/user/main.mo @@ -1,18 +1,41 @@ import Digraph "./digraph"; import Types "./types"; import Database "./database"; +import Principal "mo:base/Principal"; +import Array "mo:base/Array"; actor class User() = this { + stable var rootFeedCanister = Principal.fromText("2vxsx-fae"); + + public shared({caller}) func init(_rootFeedCanister: Principal) { + rootFeedCanister := _rootFeedCanister; + }; + + public query func getRootFeedCanister(): async Principal { + rootFeedCanister + }; + // Follow Info type Vertex = Types.Vertex; + type RootFeedActor = Types.RootFeedActor; + type FeedActor = Types.FeedActor; var graph: Digraph.Digraph = Digraph.Digraph(); - // User A Follow User B - public shared({caller}) func follow(userA: Vertex, userB: Vertex): async () { - graph.addEdge(userA, userB); + // User caller Follow user + public shared({caller}) func follow(user: Vertex): async () { + assert(not Principal.isAnonymous(rootFeedCanister)); + let rootFeedActor: RootFeedActor = actor(Principal.toText(rootFeedCanister)); + for((_, _feedCanister) in (await rootFeedActor.getAllUserFeedCanister()).vals()) { + let feedActor: FeedActor = actor(Principal.toText(_feedCanister)); + ignore feedActor.updateFollowers(Array.append( + graph.getReverseAdjacent(user), + [caller] + )); + }; + graph.addEdge(caller, user); }; public query({caller}) func getFollowingList(user: Vertex): async [Vertex] { diff --git a/src/user/types.mo b/src/user/types.mo index 430ed43..2639167 100644 --- a/src/user/types.mo +++ b/src/user/types.mo @@ -28,4 +28,9 @@ module { }; public type UserActor = Types.UserActor; + + public type RootFeedActor = Types.RootFeedActor; + + public type FeedActor = Types.FeedActor; + }; diff --git a/start.sh b/start.sh index da80361..b5c4788 100755 --- a/start.sh +++ b/start.sh @@ -11,8 +11,8 @@ dfx start --background --clean echo "生成描述接口" dfx generate -echo "切换到 Default 用户" -dfx identity use default +echo "切换到 Proton 用户" +dfx identity use proton # 部署 user canister echo "部署user canister" @@ -53,21 +53,38 @@ dfx deploy rootFeed --argument "( principal \"$likeFetch_canister_id\")" rootFeed_canister_id=$(dfx canister id rootFeed) - - echo "增发 cycles" wallet=$(dfx identity get-wallet) -dfx ledger fabricate-cycles --t 500 --canister $wallet +dfx ledger fabricate-cycles --t 1000 --canister $wallet dfx wallet balance # 给 rootFeed canister 充值cycles -echo "给 rootFeed canister 充值 20T cycles" -dfx wallet send $rootFeed_canister_id 20000000000000 +echo "给 rootFeed canister 充值 100T cycles" +dfx wallet send $rootFeed_canister_id 100000000000000 echo "查询 rootFeed canister 状态" dfx canister status $rootFeed_canister_id # 给 rootPost canister 充值cycles -echo "给 rootPost canister 充值 40T cycles" -dfx wallet send $rootPost_canister_id 40000000000000 +echo "给 rootPost canister 充值 100T cycles" +dfx wallet send $rootPost_canister_id 100000000000000 echo "查询 rootPost canister 状态" -dfx canister status $rootPost_canister_id \ No newline at end of file +dfx canister status $rootPost_canister_id + +# 给 rootFetch canister 充值cycles +echo "给 rootFetch canister 充值 100T cycles" +dfx wallet send $rootFetch_canister_id 100000000000000 +echo "查询 rootPost canister 状态" +dfx canister status $rootFetch_canister_id + +echo "初始化 rootPost" +dfx canister call rootPost init + +echo "init rootFetch canister" +dfx canister call rootFetch init "( + principal \"$rootFeed_canister_id\", + principal \"$postFetch_canister_id\", + principal \"$commentFetch_canister_id\", + principal \"$likeFetch_canister_id\")" + +echo "init user canister" +dfx canister call user init "(principal \"$rootFeed_canister_id\")" diff --git a/test/js/feed.js b/test/js/feed.js index f93ccea..f798df5 100644 --- a/test/js/feed.js +++ b/test/js/feed.js @@ -2,26 +2,47 @@ import { HttpAgent } from "@dfinity/agent"; import { createRequire } from "node:module"; import { createActor } from '../../src/declarations/feed/index.js'; import { _getHttpAgent } from './utils.js'; +import assert from "assert"; export class Feed { - constructor(canisterId, identity) { - this.canisterId = canisterId; - this.identity = identity; - this.actor = createActor(canisterId, { - agent: _getHttpAgent(identity), - }); - } - async createPost() { - // 发帖前更新当前可用的bucket - console.log("checkAvailableBucket : ", (await this.actor.checkAvailableBucket())); - - const result = await this.actor.createPost( - "this is title", - "this is content" - ); - // console.log('createPost result', result); - return result - } + constructor(canisterId, identity) { + this.canisterId = canisterId; + this.identity = identity; + this.actor = createActor(canisterId, { + agent: _getHttpAgent(identity), + }); + } + async createPost() { + // 发帖前更新当前可用的bucket + assert(await this.actor.checkAvailableBucket(), true); + + const result = await this.actor.createPost( + "this is title", + "this is content" + ); + // console.log('createPost result', result); + return result + } + + async createComment(postId, content) { + const result = await this.actor.createComment(postId, content); + return result; + } + + async createRepost(postId) { + const result = await this.actor.createRepost(postId); + return result; + } + + async createLike(postId) { + const result = await this.actor.createLike(postId); + return result; + } + + async getFeedNumber() { + const result = await this.actor.getFeedNumber(); + return result; + } } diff --git a/test/js/identity.js b/test/js/identity.js index 0b4b264..0e862a4 100644 --- a/test/js/identity.js +++ b/test/js/identity.js @@ -9,7 +9,9 @@ const identity = Secp256k1KeyIdentity.fromSeedPhrase(seed); // console.log(`identity principal : ${identity.getPrincipal()}`) -export const identityA = identity; +export const identityTest = identity; + +export const identityA = Secp256k1KeyIdentity.generate(); export const identityB = Secp256k1KeyIdentity.generate(); diff --git a/test/js/index.js b/test/js/index.js index b25509d..4d7f764 100644 --- a/test/js/index.js +++ b/test/js/index.js @@ -1,9 +1,9 @@ // src/index.js - import { User } from './user.js'; import { RootFeed } from './rootFeed.js'; import { Feed } from './feed.js'; import { + identityTest, identityA, identityB, identityC, @@ -13,14 +13,12 @@ import { } from './identity.js'; import { RootPost } from './rootPost.js' import { Bucket } from './bucket.js'; +import { RootFetch } from './rootFetch.js'; +import assert from 'assert'; +import { Principal } from "@dfinity/principal"; async function init() { - const rootPost = new RootPost(identityA); - console.log("初始化 rootPost\n"); - await rootPost.initRootPost(); - console.log("查询当前bucket\n"); - console.log((await rootPost.getAllBuckets())) } async function testUserCanister() { @@ -33,11 +31,10 @@ async function testUserCanister() { async function testFeed() { console.log("Test Feed Canister\n"); - // const _identity = newIdentity(); - const _identity = identityE; + const _identity = newIdentity(); console.log("test identity : ", _identity.getPrincipal().toString(), "\n"); - // 先创建一个 feed canister + console.log("先创建一个 feed canister\n"); const rootFeed = new RootFeed(_identity); const feedCanister = await rootFeed.createFeedCanister(); console.log("created feed canister : ", feedCanister.toString(), "\n"); @@ -51,9 +48,92 @@ async function testFeed() { var partsArray = postId.split("#"); const bucketCanisterId = partsArray[0] const bucket = new Bucket(bucketCanisterId, _identity); - console.log("bucket getPost result : ", (await bucket.getPost(postId)), "\n"); + const post_1 = await bucket.getPost(postId); + console.log("bucket getPost result : ", post_1, "\n"); + + console.log("test create comment"); + const commentResult = await feed.createComment(postId, "this is a comment"); + assert(commentResult, true); + console.log("commentResult : ", commentResult, "\n"); + console.log("检查 bucket 中的 comment 是否更改 \n"); + const post_2 = await bucket.getPost(postId); + console.log("bucket 评论后的 post : ", post_2, "\n"); + assert(post_2[0].comment[0].content, "this is a comment"); + assert(post_2[0].comment[0].user, _identity.getPrincipal()); + console.log("bucket comment : ", post_2[0].comment, "\n"); + + console.log("test create like \n"); + const likeResult = await feed.createLike(postId); + assert(likeResult, true); + console.log("likeResult : ", likeResult, "\n"); + console.log("检查 bucket 中的 like 是否更改 \n"); + const post_3 = await bucket.getPost(postId); + console.log("bucket 点赞后的 post : ", post_3, "\n"); + assert(post_3[0].like[0].user, _identity.getPrincipal()); + console.log("bucket like : ", post_3[0].like, "\n"); + + console.log("测试转发 \n"); + const identity_repost = newIdentity(); + console.log("转发者的身份 : ", identity_repost.getPrincipal().toString(), "\n"); + const feed_repost = new Feed(feedCanister, identity_repost); + const repost_result = await feed_repost.createRepost(postId); + assert(repost_result, true); + console.log("repost_result : ", repost_result, "\n"); + console.log("检查 bucket 中的post是否更新 \n"); + const post_4 = await bucket.getPost(postId); + console.log(" repost 后的 post : ", post_4, "\n"); + assert(post_4[0].repost[0].user, identity_repost.getPrincipal(), "repost assert"); + console.log(" repost : ", post_4[0].repost, "\n"); + +} + +async function testPostFetch() { + + console.log("User A 初始化 Profile \n"); + let userActor = new User(identityA); + await userActor.createProfile(); + + console.log("User A 创建一个 feed canister\n"); + const rootFeed = new RootFeed(identityA); + const feedCanister = await rootFeed.createFeedCanister(); + const userB_FeedCanister = await new RootFeed(identityB).createFeedCanister(); + const userC_FeedCanister = await new RootFeed(identityC).createFeedCanister(); + const userD_FeedCanister = await new RootFeed(identityD).createFeedCanister(); + const userE_FeedCanister = await new RootFeed(identityE).createFeedCanister(); + console.log("User A feed canister : ", feedCanister.toString(), "\n"); + console.log("User B feed canister : ", userB_FeedCanister.toString(), "\n"); + console.log("User C feed canister : ", userC_FeedCanister.toString(), "\n"); + console.log("User D feed canister : ", userD_FeedCanister.toString(), "\n"); + console.log("User E feed canister : ", userE_FeedCanister.toString(), "\n"); + + console.log("User B, C, D, E 去关注 User A \n"); + await new User(identityB).follow(identityA.getPrincipal()); + await new User(identityC).follow(identityA.getPrincipal()); + await new User(identityD).follow(identityA.getPrincipal()); + await new User(identityE).follow(identityA.getPrincipal()); + + // console.log((await userActor.getFollowersList(identityA.getPrincipal()))); + console.log("User A 的粉丝 : ", (await userActor.getFollowersList(identityA.getPrincipal())).map((value) => { + return value.toString(); + })); + + console.log("User A 先创建一个帖子 \n"); + const feed = new Feed(feedCanister, identityA); + const postId = await feed.createPost(feedCanister, identityA); + console.log("user A create post result ", postId, "\n"); + + // 暂停三秒 + await new Promise(resolve => setTimeout(resolve, 3000)); + + console.log("检查 User B, C, D, E 的 feedNumber \n"); + assert(await new Feed(userB_FeedCanister, identityB).getFeedNumber(), BigInt(1)); + assert(await new Feed(userC_FeedCanister, identityC).getFeedNumber(), BigInt(1)); + assert(await new Feed(userD_FeedCanister, identityD).getFeedNumber(), BigInt(1)); + assert(await new Feed(userE_FeedCanister, identityE).getFeedNumber(), BigInt(1)); + } await init(); await testUserCanister(); -await testFeed(); +await testFeed(); +await testPostFetch(); diff --git a/test/js/postFetch.js b/test/js/postFetch.js new file mode 100644 index 0000000..f814bb5 --- /dev/null +++ b/test/js/postFetch.js @@ -0,0 +1,15 @@ +import { createRequire } from "node:module"; +import { createActor } from "../../src/declarations/postFetch/index.js"; +import { _getHttpAgent } from './utils.js'; + +export class PostFetch { + + constructor(canisterId, identity) { + this.canisterId = canisterId; + this.identity = identity; + this.actor = createActor(canisterId, { + agent: _getHttpAgent(identity), + }); + } + +} \ No newline at end of file diff --git a/test/js/rootFeed.js b/test/js/rootFeed.js index d2e637e..4934755 100644 --- a/test/js/rootFeed.js +++ b/test/js/rootFeed.js @@ -28,12 +28,3 @@ export class RootFeed { } } } - -// export async function testCreateFeedCanister() { -// console.log("Test CreateFeedCanister, identityA"); -// const result = await createFeedCanister(); -// if(result.length > 0) { -// console.log("created feed canister : ", result[0].toString()); -// console.log("Test CreateFeedCanister Ok !"); -// } -// } diff --git a/test/js/rootFetch.js b/test/js/rootFetch.js new file mode 100644 index 0000000..301e034 --- /dev/null +++ b/test/js/rootFetch.js @@ -0,0 +1,39 @@ +import { createRequire } from "node:module"; +import { createActor } from "../../src/declarations/rootFetch/index.js"; +import { _getHttpAgent } from './utils.js'; + +const require = createRequire(import.meta.url); +const localCanisterIds = require("../../.dfx/local/canister_ids.json"); +const rootFetchCanisterId = localCanisterIds.rootFetch.local; + +export class RootFetch { + + constructor(identity) { + this.canisterId = rootFetchCanisterId; + this.identity = identity; + this.actor = createActor(rootFetchCanisterId, { + agent: _getHttpAgent(identity), + }); + } + + async init(rootFeedCanister) { + const result = await this.actor.init(rootFeedCanister); + return result; + } + + async createPostFetchCanister() { + const result = await this.actor.createPostFetchCanister(); + return result; + } + + async createCommentFetchCanister() { + const result = await this.actor.createCommentFetchCanister(); + return result; + } + + async createLikeFetchCanister() { + const result = await this.actor.createLikeFetchCanister(); + return result; + } + +} \ No newline at end of file diff --git a/test/js/user.js b/test/js/user.js index 6a2e53c..77813dc 100644 --- a/test/js/user.js +++ b/test/js/user.js @@ -29,9 +29,35 @@ export class User { console.log("createProfile Result", result, "\n"); } + async updateProfile() { + const result = await this.actor.updateProfile({ + name: "update: John", + biography : "update: I am a developer", + education : "update: MIT", + company : "update: Dfinity Foundation", + imgUrl : "https://images.unsplash.com/photo-1593642532842-98d0fd5ebc1a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80", + feedCanister : [] //, + }); + console.log("updateProfile Result", result, "\n"); + } + async getProfile() { const result = await this.actor.getProfile(this.identity.getPrincipal()); console.log("getProfile result : ", result, "\n"); } + async follow(user) { + const result = await this.actor.follow(user); + return result; + } + + async getFollowersList(user) { + const result = await this.actor.getFollowersList(user); + return result; + } + + async init(_rootFeedCanister) { + const result = await this.actor.init(_rootFeedCanister); + return result; + } } \ No newline at end of file