Skip to content
This repository has been archived by the owner on Jun 15, 2023. It is now read-only.

Commit

Permalink
feat(notes): support for getting mutiple crossbell notes
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed May 26, 2022
1 parent d4058b8 commit 3269632
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 59 deletions.
7 changes: 6 additions & 1 deletion docs/guide/notes/Crossbell-Note.md
Expand Up @@ -17,15 +17,20 @@ You can initialize with `ipfsGateway` to potentially get a faster response or hi
```ts
const notes: Notes = await unidata.notes.get(options: {
source: 'Crossbell Note';
identity: string;
identity?: string;
platform?: string;
limit?: number;
cursor?: string;
filter?: {
url?: string;
}
});
```

- `identity` is optional, returns data based on filter only when not provided.
- Use Ethereum address as the `identity` and `'Ethereum'` as the `platform` to get notes from all profiles belonging to this address.
- Use Crossbell handle as the `identity` and `'Crossbell'` as the `platform` to get notes from a specific profile.
- Use `filter.url` to get notes linking to the url.

### Set

Expand Down
4 changes: 3 additions & 1 deletion docs/guide/notes/README.md
Expand Up @@ -13,17 +13,19 @@ You can initialize with `ipfsGateway` to potentially get a faster response or hi
```ts
const notes: Notes = await unidata.notes.get(options: {
source: string;
identity: string;
identity?: string;
platform?: string;
limit?: number;
cursor?: any;
filters?: any;
});
```

- `identity`: Ethereum address, Solana address, Flow address, etc.
- `platform`: Platfrom of the identity. Ethereum, Solana, Flow, Crossbell, etc. Default to `Ethereum`.
- `limit`: The number of assets to return. Since providers use different pagination schemes, there is no guarantee that the quantities are always accurate.
- `cursor`: The pagination cursor returned from the previous page's results. Since providers use different pagination schemes, the type is uncertain.
- `filters`: Varies depending on the source.

### Set

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -40,7 +40,7 @@
"dependencies": {
"@urql/core": "2.5.0",
"axios": "0.27.2",
"crossbell.js": "0.5.12",
"crossbell.js": "0.5.13",
"ethers": "5.6.8",
"graphql": "16.5.0",
"lodash": "4.17.21",
Expand Down
13 changes: 2 additions & 11 deletions src/assets/index.ts
@@ -1,7 +1,6 @@
import Main from '../index';
import Base from './base';
import { mergeWith, keyBy, values, uniqWith, isEqual } from 'lodash';
import mime from 'mime';
import EthereumNFTMoralis from './ethereum-nft-moralis';
import EthereumNFTOpenSea from './ethereum-nft-opensea';
import EthereumNFTPOAP from './ethereum-nft-poap';
Expand Down Expand Up @@ -95,14 +94,6 @@ class Assets {
}
}

private generateMimeType(address: string) {
address = this.main.utils.replaceIPFS(address);
const mimeType = mime.getType(address);
if (mimeType) {
return mimeType;
}
}

async get(options: AssetsOptions) {
options = Object.assign(
{
Expand Down Expand Up @@ -168,7 +159,7 @@ class Assets {
item.address = this.main.utils.replaceIPFS(item.address);
}
if (item.address && !item.mime_type) {
item.mime_type = this.generateMimeType(item.address);
item.mime_type = this.main.utils.getMimeType(item.address);
}
});
}
Expand All @@ -178,7 +169,7 @@ class Assets {
item.address = this.main.utils.replaceIPFS(item.address);
}
if (item.address && !item.mime_type) {
item.mime_type = this.generateMimeType(item.address);
item.mime_type = this.main.utils.getMimeType(item.address);
}
});
}
Expand Down
136 changes: 97 additions & 39 deletions src/notes/crossbell-note.ts
Expand Up @@ -3,71 +3,126 @@ import Base from './base';
import { NotesOptions, NoteSetOptions, NoteInput } from './index';
import { Indexer, Contract, Network } from 'crossbell.js';
import { Web3Storage } from 'web3.storage';
import { BigNumber } from 'ethers';

class CrossbellNote extends Base {
indexer: Indexer;
contract: Contract;
contractSet: Contract;

constructor(main: Main) {
super(main);

Network.setIpfsGateway(this.main.options.ipfsGateway!);
}

async init() {
await Network.switchToCrossbellMainnet(this.main.options.ethereumProvider);
this.contract = new Contract(this.main.options.ethereumProvider);
await this.contract.connect();
}

async get(options: NotesOptions) {
if (!this.contract) {
this.contract = new Contract();
await this.contract.connect();
await this.init();
}

options = Object.assign(
{
platform: 'Ethereum',
},
options,
);

let profileId = await this.main.utils.getCrossbellProfileId({
identity: options.identity,
platform: options.platform!,
});
if (profileId === '0') {
return {
total: 0,
list: [],
};
// @ts-ignore
const initialContract = this.contract.contract;

let events: any;
if (options.identity) {
let profileId = await this.main.utils.getCrossbellProfileId({
identity: options.identity,
platform: options.platform!,
});
if (profileId === '0') {
return {
total: 0,
list: [],
};
}
const filter = initialContract.filters.PostNote(BigNumber.from(profileId));
events = await initialContract.queryFilter(filter);
} else if (options.filter?.url) {
const filter = initialContract.filters.PostNote(
null,
null,
this.contract.getLinkKeyForAnyUri(options.filter?.url),
);
events = await initialContract.queryFilter(filter);
}

const result = (await this.contract.getNote(profileId, '1')).data;
const list = await Promise.all(
events.reverse().map(async (event: any) => {
const profileId = event.args.profileId.toString();
const nodeId = event.args.noteId.toString();
const note = (await this.contract.getNote(profileId, nodeId, 'AnyUri')).data;

const now = new Date().toISOString();
// @ts-ignore
const date = new Date((await initialContract.provider.getBlock(event.blockNumber)).timestamp * 1000);

const item: Note = Object.assign({}, <any>result.metadata, {
id: result.noteId,
const item: Note = Object.assign({}, note.metadata as Partial<Note>, {
id: `${profileId}-${nodeId}`,

date_created: now,
date_updated: now,
date_created: date,
date_updated: date,

authors: [options.identity],
related_urls: [
...(note.linkItem?.uri && [note.linkItem?.uri]),
`https://scan.crossbell.io/tx/${event.transactionHash}`,
],

source: 'Crossbell Note',
metadata: {
network: 'Crossbell',
proof: result.noteId,
},
});
authors: [options.identity],

// Crossbell specification compatibility
if (item.summary) {
item.summary = {
content: (<any>item).summary,
mime_type: 'text/markdown',
};
}
source: 'Crossbell Note',
metadata: {
network: 'Crossbell',
proof: event.transactionHash,

block_number: event.blockNumber,
},
});

// Crossbell specification compatibility
if (item.summary) {
item.summary = {
content: (<any>item).summary,
mime_type: 'text/markdown',
};
}
if ((<any>item).content) {
item.summary = {
content: (<any>item).content,
mime_type: 'text/markdown',
};
delete (<any>item).content;
}

if (item.attachments) {
item.attachments.forEach((attachment) => {
if (attachment.address) {
attachment.address = this.main.utils.replaceIPFS(attachment.address);
}
if (attachment.address && !attachment.mime_type) {
attachment.mime_type = this.main.utils.getMimeType(attachment.address);
}
});
}

return item;
}),
);

return {
total: 1,
list: [item],
total: list.length,
list: list,
};
}

Expand All @@ -80,9 +135,8 @@ class CrossbellNote extends Base {
options,
);

if (!this.contractSet) {
this.contractSet = new Contract(this.main.options.ethereumProvider);
await this.contractSet.connect();
if (!this.contract) {
await this.init();
}

let profileId = await this.main.utils.getCrossbellProfileId({
Expand All @@ -103,6 +157,10 @@ class CrossbellNote extends Base {
});

// Crossbell specification compatibility
if (input.body) {
(<any>input).content = input.body.content;
delete input.body;
}
if (input.summary) {
(<any>input).summary = input.summary.content;
}
Expand All @@ -117,7 +175,7 @@ class CrossbellNote extends Base {
wrapWithDirectory: false,
});

const data = await this.contractSet.postNote(profileId, `ipfs://${cid}`);
const data = await this.contract.postNote(profileId, `ipfs://${cid}`);

return {
code: 0,
Expand All @@ -132,7 +190,7 @@ class CrossbellNote extends Base {
message: 'Missing id',
};
} else {
await this.contractSet.deleteNote(profileId, input.id);
await this.contract.deleteNote(profileId, input.id);

return {
code: 0,
Expand Down
3 changes: 2 additions & 1 deletion src/notes/index.ts
Expand Up @@ -7,10 +7,11 @@ import CrossbellNote from './crossbell-note';

export type NotesOptions = {
source: string;
identity: string;
identity?: string;
platform?: string;
limit?: number;
cursor?: any;
filter?: any;
};

export type NoteSetOptions = {
Expand Down
9 changes: 9 additions & 0 deletions src/utils.ts
@@ -1,5 +1,6 @@
import Main from './index';
import { Indexer, Contract, Network } from 'crossbell.js';
import mime from 'mime';

class Utils {
main: Main;
Expand Down Expand Up @@ -79,6 +80,14 @@ class Utils {
delete father.obj[father.key];
}
}

getMimeType(address: string) {
address = this.main.utils.replaceIPFS(address);
const mimeType = mime.getType(address);
if (mimeType) {
return mimeType;
}
}
}

export default Utils;
10 changes: 5 additions & 5 deletions yarn.lock
Expand Up @@ -2316,14 +2316,14 @@ __metadata:
languageName: node
linkType: hard

"crossbell.js@npm:0.5.12":
version: 0.5.12
resolution: "crossbell.js@npm:0.5.12"
"crossbell.js@npm:0.5.13":
version: 0.5.13
resolution: "crossbell.js@npm:0.5.13"
dependencies:
ethers: ^5.6.3
ts-mixer: ^6.0.1
undici: ^5.2.0
checksum: db66811a4362c12a7a4d7f04f8bdde6ff7e72ce0b21fa77d4efb517a7a3fb104e61bb85f6d2a7519e165e48251c81141b22ed13436d84b2ca522a2de270d4434
checksum: 706d109eca1542efdb4c3836a9209292fdcedbae15687c7b3411de1f724d921a21bfbe03a271490a274f38ac4e5f57c25012359429e47587f990fecb1e0767d6
languageName: node
linkType: hard

Expand Down Expand Up @@ -6149,7 +6149,7 @@ __metadata:
"@vuepress/plugin-docsearch": 2.0.0-beta.45
"@vuepress/plugin-register-components": 2.0.0-beta.45
axios: 0.27.2
crossbell.js: 0.5.12
crossbell.js: 0.5.13
element-plus: 2.2.2
ethers: 5.6.8
graphql: 16.5.0
Expand Down

0 comments on commit 3269632

Please sign in to comment.