Merge pull request from bluesky-social/naive-follows

Simple follows
This commit is contained in:
Daniel Holmgren 2022-02-03 13:17:49 -07:00 committed by GitHub
commit 873700d405
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 21 deletions

@ -11,7 +11,12 @@ export type User = {
did: string
nextPost: number
postsRoot: CID
follows: string[]
follows: Follow[]
}
export type Follow = {
username: string
did: string
}
export type Post = {

@ -10,7 +10,7 @@ import * as hashmap from 'ipld-hashmap'
import { Didable, Keypair } from "ucans"
import { User, Post, BlockstoreI } from "./types"
import { User, Post, BlockstoreI, Follow } from "./types"
import { streamToArray } from './util'
export class UserStore {
@ -20,25 +20,35 @@ export class UserStore {
postMap: hashmap.HashMap<Post>
root: CID
posts: Post[]
follows: Follow[]
keypair: Keypair
constructor(blockstore: BlockstoreI, ipldStore: IpldStore, postMap: hashmap.HashMap<Post>, root: CID, posts: Post[], keypair: Keypair) {
this.blockstore = blockstore
this.ipldStore = ipldStore
this.postMap = postMap
this.root = root
this.posts = posts
this.keypair = keypair
constructor(params: {
blockstore: BlockstoreI,
ipldStore: IpldStore,
postMap: hashmap.HashMap<Post>,
root: CID,
posts: Post[],
follows: Follow[],
keypair: Keypair
}) {
this.blockstore = params.blockstore
this.ipldStore = params.ipldStore
this.postMap = params.postMap
this.root = params.root
this.posts = params.posts
this.follows = params.follows
this.keypair = params.keypair
}
static async create(username: string, blockstore: BlockstoreI, keypair: Keypair & Didable) {
const posts = await hashmap.create(blockstore, { bitWidth: 4, bucketSize: 2, blockHasher, blockCodec }) as hashmap.HashMap<Post>
const postMap = await hashmap.create(blockstore, { bitWidth: 4, bucketSize: 2, blockHasher, blockCodec }) as hashmap.HashMap<Post>
const ipldStore = new IpldStore(blockstore)
const user = {
did: await keypair.did(),
name: username,
nextPost: 0,
postsRoot: posts.cid,
postsRoot: postMap.cid,
follows: []
}
@ -50,7 +60,15 @@ export class UserStore {
const root = await ipldStore.put(signedRoot)
return new UserStore(blockstore, ipldStore, posts, root, [], keypair)
return new UserStore({
blockstore,
ipldStore,
postMap,
root,
posts: [],
follows: [],
keypair
})
}
static async get(root: CID, blockstore: BlockstoreI, keypair: Keypair) {
@ -59,7 +77,16 @@ export class UserStore {
const user = await ipldStore.getUser(rootObj.user)
const postMap = await hashmap.load(blockstore, user.postsRoot, { bitWidth: 4, bucketSize: 2, blockHasher, blockCodec }) as hashmap.HashMap<Post>
const posts = await UserStore.postsListFromMap(postMap)
return new UserStore(blockstore, ipldStore, postMap, root, posts, keypair)
const follows = user.follows
return new UserStore({
blockstore,
ipldStore,
postMap,
root,
posts,
follows,
keypair
})
}
static async fromCarFile(buf: Uint8Array, blockstore: BlockstoreI, keypair: Keypair) {
@ -80,7 +107,16 @@ export class UserStore {
const user = await ipldStore.getUser(rootObj.user)
const postMap = await hashmap.load(blockstore, user.postsRoot, { bitWidth: 4, bucketSize: 2, blockHasher, blockCodec }) as hashmap.HashMap<Post>
const posts = await UserStore.postsListFromMap(postMap)
return new UserStore(blockstore, ipldStore, postMap, root, posts, keypair)
const follows = user.follows
return new UserStore({
blockstore,
ipldStore,
postMap,
root,
posts,
follows,
keypair
})
}
static async postsListFromMap(postMap: hashmap.HashMap<Post>) {
@ -102,13 +138,7 @@ export class UserStore {
user.nextPost++
user.postsRoot = this.postMap.cid
const userCid = await this.ipldStore.put(user)
const signedRoot = {
user: userCid,
sig: await this.keypair.sign(userCid.bytes)
}
this.root = await this.ipldStore.put(signedRoot)
await this.updateUserRoot(user)
this.posts = [post, ...this.posts]
}
@ -118,6 +148,29 @@ export class UserStore {
return posts
}
async followUser(username: string, did: string): Promise<void> {
const user = await this.getUser()
if (user.follows.some(u => u.username === username)) {
throw new Error(`User with username ${username} already exists.`)
} else if (user.follows.some(u => u.did === did)) {
throw new Error(`User with did ${did} already exists.`)
}
user.follows.push({ username, did })
await this.updateUserRoot(user)
this.follows.push({ username, did })
}
async updateUserRoot(user: User) {
const userCid = await this.ipldStore.put(user)
const signedRoot = {
user: userCid,
sig: await this.keypair.sign(userCid.bytes)
}
this.root = await this.ipldStore.put(signedRoot)
}
getCarStream(): AsyncIterable<Uint8Array> {
const writeblockstore = async (car: BlockWriter) => {
const addCid = async (cid: CID) => {