Skip to content

Commit

Permalink
Merge pull request #9 from Akord-com/contract-state
Browse files Browse the repository at this point in the history
feat: add contract state query on akord API
  • Loading branch information
jarrvis authored Sep 29, 2022
2 parents 175dec4 + 915a519 commit 9f05763
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 159 deletions.
1 change: 1 addition & 0 deletions src/__tests__/data/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export const vaults = [
name: 'first vault'
}
];
export const publicVaultId = 'qZAevtQSeEeVr4niKoXC-WwzAupleei69aqynLmijiY';
export const fileId = 'efb8ed89-3221-48e7-b1e5-9b94eef41319';
export const message = 'Quae vel nemo dolorum recusandae temporibus temporibus. Hic id eum quo sint atque voluptates voluptatum. Vero sit aliquid. Nam omnis repudiandae. Corporis quasi ex id incidunt suscipit non. In ea impedit. Consequatur voluptatem et nihil ut debitis similique. Eligendi ut voluptatum fuga eos a ab iure alias molestiae. Sed reiciendis aut sapiente natus inventore iure nesciunt architecto veritatis. Ea omnis similique incidunt voluptas sit pariatur officia nihil cupiditate. Voluptas nobis molestias quia voluptas saepe labore quia consequatur dolorem. Ut quia quis ut iste inventore excepturi. Dolores incidunt eum quia aspernatur et architecto cumque provident architecto. Maiores occaecati suscipit repellat. Quia illum ex doloribus porro. Ipsa doloribus atque et aut molestiae quam magnam enim. Laborum totam adipisci non dolor neque quos saepe. Qui consequuntur sapiente quis non sit explicabo expedita. Odio voluptatibus neque maxime autem harum facilis optio. Eum esse ipsam itaque minima quia repudiandae. Cum eveniet voluptatum consequatur. Dolor mollitia perferendis fuga impedit quia enim consectetur non. Quibusdam nostrum sit at quae sit ducimus blanditiis a deserunt. Qui aperiam id est architecto ut. Ut dolores soluta consequatur at expedita. Et blanditiis nam quam cumque. Similique aut animi voluptas id quam. Id rerum est architecto dolorem quae rerum autem voluptatem. Id cum impedit est cumque quod dolores aut. Qui quo autem vel. Autem sapiente voluptates rerum architecto necessitatibus doloremque consequatur iure quo. Veritatis tenetur voluptatem praesentium. Et sit architecto veritatis modi voluptatem iusto voluptates neque. Soluta explicabo qui provident velit sunt. Quia nisi deleniti perferendis quo et enim explicabo eos. Tempore amet quisquam itaque et corrupti inventore quia illo deserunt. Voluptatum animi et. Earum in vitae nemo officia qui necessitatibus animi totam. Totam amet beatae ex totam quia est labore. Id voluptates voluptatibus. Beatae eos corporis sed ratione ipsa eum vel placeat. Voluptas est quam atque non iure necessitatibus. Ab et numquam excepturi rem vel hic delectus voluptatem. Ut et hic animi minus sint et. Commodi explicabo est quo veniam ratione quisquam iure ducimus sit. Molestias cum voluptas consectetur necessitatibus nobis eveniet veritatis reiciendis illo. Ex est officia eveniet eveniet enim voluptatum iusto labore vitae. Quam eum vero ratione veritatis ex voluptatibus. Vel repellendus voluptatum autem doloremque cupiditate cumque. Delectus aut esse occaecati.'
39 changes: 29 additions & 10 deletions src/__tests__/queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import ApiAuthenticator from "../api/akord/api-authenticator";
import fs from "fs";
import path from "path";
import { email, password } from './data/test-credentials';
import { vaults, fileId, message } from './data/content';
import { vaults, fileId, message, publicVaultId } from './data/content';

let akord1: Akord;
let akord2: Akord;
let clientWithAkordWallet: Akord;
let clientWithArweaveWallet: Akord;
let clientWithoutWallet: Akord;

jest.setTimeout(3000000);

Expand All @@ -31,29 +32,47 @@ describe("Testing querying directly from permaweb", () => {
const jwtToken = await apiAuthenticator.getJWTToken(email, password);
const userAttributes = await apiAuthenticator.getUserAttributes(email, password);
const wallet = await AkordWallet.importFromEncBackupPhrase(password, userAttributes["custom:encBackupPhrase"]);
akord1 = new Akord(wallet, jwtToken, { wallet: <any>"Akord" });
akord2 = new Akord(wallet, undefined, { wallet: <any>"Arweave" });
clientWithAkordWallet = new Akord(wallet, jwtToken, { wallet: <any>"Akord" });
clientWithArweaveWallet = new Akord(wallet, undefined, { wallet: <any>"Arweave" });
clientWithoutWallet = new Akord(undefined, undefined, { wallet: <any>"Akord" });

});

it("Query all vaults from Akord API", async () => {
const result = await akord1.getVaults();
const result = await clientWithAkordWallet.getVaults();
expect(result).toEqual(vaults);
});


it("Should query public vault - contract state from Akord API", async () => {
const result = await clientWithoutWallet.getContractState(publicVaultId);
expect(result.name).not.toBeNull();
expect(result.isPublic).toBeTruthy();
expect(result.folders.length).toBeTruthy();
expect(result.stacks.length).toBeTruthy();
expect(result.notes.length).toBeTruthy();
});

it("Query all vaults from Arweave API", async () => {
const result = await akord2.getVaults();
const result = await clientWithArweaveWallet.getVaults();
expect(result).toEqual(vaults);
});

it("Query memos from Arweave API", async () => {
const result = await akord2.getNodes(vaults[0].id, 'Memo');
const result = await clientWithArweaveWallet.getNodes(vaults[0].id, 'Memo');
expect(result.length).toEqual(1);
expect(result[0].message).toEqual(message);
});

it("Query chunked file from Akord API", async () => {
const decryptedFile = await akord1.getFile(fileId, vaults[0].id, true, 3);
const decryptedFile = await clientWithAkordWallet.getFile(fileId, vaults[0].id, true, 3);
const file = getFileFromPath("./src/__tests__/data/chunked-file.test");
expect(Buffer.from(decryptedFile)).toEqual(file.data);
});

it("Query chunked file from Akord API", async () => {
const decryptedFile = await clientWithAkordWallet.getFile(fileId, vaults[0].id, true, 3);
const file = getFileFromPath("./src/__tests__/data/chunked-file.test");
expect(Buffer.from(decryptedFile)).toEqual(file.data);
});
});
});
150 changes: 81 additions & 69 deletions src/akord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { VaultService } from "./service/vault";
import { StackService } from "./service/stack";
import { NoteService } from "./service/note";
import { ProfileService } from "./service/profile";
import { Contract } from "./model/contract";

export default class Akord {
static readonly reactionEmoji = reactionEmoji;
Expand Down Expand Up @@ -48,20 +49,6 @@ export default class Akord {
this.profile = new ProfileService(wallet, this.api);
}

private async setVaultContext(vaultId: string) {
const vault = await this.api.getObject(vaultId, objectTypes.VAULT);
const service = new Service(this.service.wallet, this.api);
service.setVault(vault);
service.setVaultId(vaultId);
service.setIsPublic(vault.state?.isPublic);
if (!service.isPublic) {
const encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
service.setKeys(encryptionKeys.keys);
(<any>service).setRawDataEncryptionPublicKey(encryptionKeys?.getPublicKey());
}
return service;
}

/**
* @param {{id:string,objectType:string}[]} items
* @returns Promise with corresponding transaction ids
Expand Down Expand Up @@ -144,42 +131,6 @@ export default class Akord {
return response;
}

private async batchAction(
items: { id: string, objectType: string, role?: string }[],
actionType: string,
parentId?: string,
): Promise<{ transactionId: string }[]> {
const groupRef = items && items.length > 1 ? uuidv4() : null;
const vaultId = (await this.api.getObject(items[0].id, items[0].objectType)).dataRoomId;
const vault = await this.api.getObject(vaultId, objectTypes.VAULT);
let encryptionKeys = {} as any;
if (!vault.state?.isPublic) {
encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
}
const transactionIds = [] as { transactionId: string }[];
await Promise.all(items.map(async (item) => {
const service = new ServiceFactory(this.service.wallet, this.api, item.objectType).serviceInstance();
service.setGroupRef(groupRef);
switch (actionType) {
case "REVOKE":
transactionIds.push(await service.revoke(item.id));
break;
case "RESTORE":
transactionIds.push(await service.restore(item.id));
break;
case "MOVE":
transactionIds.push(await service.move(item.id, parentId));
break;
case "DELETE":
transactionIds.push(await service.delete(item.id));
break;
default:
break;
}
}));
return transactionIds;
}

/**
* @param {string} vaultId
* @param {{email:string,role:string}[]} items
Expand Down Expand Up @@ -242,21 +193,15 @@ export default class Akord {
return vaultTable;
}

private async setVaultEncryptionContext(vaultId: string): Promise<any> {
const encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
if (encryptionKeys.encryptionType) {
const keys = encryptionKeys.keys.map(((keyPair) => {
return {
encPrivateKey: keyPair.encPrivateKey,
publicKey: keyPair.publicKey ? keyPair.publicKey : keyPair.encPublicKey
}
}))
this.service.setKeys(keys);
(<any>this.service).setRawDataEncryptionPublicKey(encryptionKeys?.getPublicKey());
this.service.setIsPublic(false);
} else {
this.service.setIsPublic(true);
}
public async getContractState(id: string): Promise<Contract> {
const state = await this.api.getContractState(id);
this.service.setIsPublic(state.isPublic);
const contract = await this.decryptState(state);
contract.folders = await this.decryptState(state.folders);
contract.stacks = await this.decryptState(state.stacks);
contract.notes = await this.decryptState(state.notes);
contract.memos = await this.decryptState(state.memos);
return contract;
}

/**
Expand Down Expand Up @@ -313,7 +258,7 @@ export default class Akord {
* @param {any} state
* @returns Promise with decrypted state
*/
public async decryptState(state: any): Promise<any> {
public async decryptState<T>(state: T): Promise<T> {
const decryptedState = await this.service.processReadObject(state, ["title", "name", "message", "content"]);
if (decryptedState.files && decryptedState.files.length > 0) {
for (const [index, file] of decryptedState.files.entries()) {
Expand Down Expand Up @@ -355,7 +300,7 @@ export default class Akord {
const url = `${id}_${currentChunk}`;
const file = await this.api.downloadFile(url, service.isPublic, progressHook, cancelHook);
const fileData = await service.processReadRaw(file.fileData, file.headers)
fileBinary = this._appendBuffer(fileBinary, fileData);
fileBinary = this.appendBuffer(fileBinary, fileData);
currentChunk++;
}
} catch (e) {
Expand Down Expand Up @@ -390,7 +335,7 @@ export default class Akord {
const url = `${id}_${currentChunk}`;
const file = await this.api.downloadFile(url, true, progressHook, cancelHook);
const fileData = await this.service.processReadRaw(file.fileData, file.headers)
fileBinary = this._appendBuffer(fileBinary, fileData);
fileBinary = this.appendBuffer(fileBinary, fileData);
currentChunk++;
}
} catch (e) {
Expand Down Expand Up @@ -428,7 +373,74 @@ export default class Akord {
return this.getFile(file.resourceUrl, stack.dataRoomId);
}

private _appendBuffer(buffer1: Uint8Array, buffer2: Uint8Array): ArrayBufferLike {
private async batchAction(
items: { id: string, objectType: string, role?: string }[],
actionType: string,
parentId?: string,
): Promise<{ transactionId: string }[]> {
const groupRef = items && items.length > 1 ? uuidv4() : null;
const vaultId = (await this.api.getObject(items[0].id, items[0].objectType)).dataRoomId;
const vault = await this.api.getObject(vaultId, objectTypes.VAULT);
let encryptionKeys = {} as any;
if (!vault.state?.isPublic) {
encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
}
const transactionIds = [] as { transactionId: string }[];
await Promise.all(items.map(async (item) => {
const service = new ServiceFactory(this.service.wallet, this.api, item.objectType).serviceInstance();
service.setGroupRef(groupRef);
switch (actionType) {
case "REVOKE":
transactionIds.push(await service.revoke(item.id));
break;
case "RESTORE":
transactionIds.push(await service.restore(item.id));
break;
case "MOVE":
transactionIds.push(await service.move(item.id, parentId));
break;
case "DELETE":
transactionIds.push(await service.delete(item.id));
break;
default:
break;
}
}));
return transactionIds;
}

private async setVaultContext(vaultId: string) {
const vault = await this.api.getObject(vaultId, objectTypes.VAULT);
const service = new Service(this.service.wallet, this.api);
service.setVault(vault);
service.setVaultId(vaultId);
service.setIsPublic(vault.state?.isPublic);
if (!service.isPublic) {
const encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
service.setKeys(encryptionKeys.keys);
(<any>service).setRawDataEncryptionPublicKey(encryptionKeys?.getPublicKey());
}
return service;
}

private async setVaultEncryptionContext(vaultId: string): Promise<any> {
const encryptionKeys = await this.api.getMembershipKeys(vaultId, this.service.wallet);
if (encryptionKeys.encryptionType) {
const keys = encryptionKeys.keys.map(((keyPair) => {
return {
encPrivateKey: keyPair.encPrivateKey,
publicKey: keyPair.publicKey ? keyPair.publicKey : keyPair.encPublicKey
}
}))
this.service.setKeys(keys);
(<any>this.service).setRawDataEncryptionPublicKey(encryptionKeys?.getPublicKey());
this.service.setIsPublic(false);
} else {
this.service.setIsPublic(true);
}
}

private appendBuffer(buffer1: Uint8Array, buffer2: Uint8Array): ArrayBufferLike {
if (!buffer1 && !buffer2) return;
if (!buffer1) return buffer2;
if (!buffer2) return buffer1;
Expand Down
Loading

0 comments on commit 9f05763

Please sign in to comment.