Skip to content

Commit

Permalink
Merge pull request #110 from GenesysGo/tracy/edit-file-updates
Browse files Browse the repository at this point in the history
edit-file refactor
  • Loading branch information
tracy-codes authored Jul 12, 2024
2 parents 6ad8762 + 1f7c504 commit f82c3cd
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 51 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shadow-drive/sdk",
"version": "5.1.1",
"version": "6.0.0",
"description": "Interfaces for GenesysGo ShadowDrive",
"main": "./dist/index.js",
"module": "./dist/index.js",
Expand Down
77 changes: 31 additions & 46 deletions src/methods/edit-file.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,27 @@
import { web3 } from "@coral-xyz/anchor";
import { isBrowser, SHDW_DRIVE_ENDPOINT } from "../utils/common";
import crypto from "crypto";
import { ShadowFile, ShadowEditResponse } from "../types";
import fetch from "cross-fetch";
import { ShadowFile, ShadowUploadResponse } from "../types";
import NodeFormData from "form-data";
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
import nacl from "tweetnacl";
import { UserInfo } from "../types/accounts";
/**
*
* @param {web3.PublicKey} key - Publickey of Storage Account
* @param {string} url - URL of existing file
* @param {web3.PublicKey} key - Publickey of Storage Account.
* @param {File | ShadowFile} data - File or ShadowFile object, file extensions should be included in the name property of ShadowFiles.
* @returns {ShadowEditResponse} - File location
* @returns {ShadowUploadResponse} File location and transaction signature.
*/

export default async function editFile(
key: web3.PublicKey,
url: string,
key: web3.PublicKey,
data: File | ShadowFile
): Promise<ShadowEditResponse> {
): Promise<ShadowUploadResponse> {
let fileErrors = [];
let fileBuffer: Buffer | ArrayBuffer;
let fileBuffer: Buffer;
let form;
let file;

if (!isBrowser) {
console.log(`not browser`);
data = data as ShadowFile;
form = new NodeFormData();
file = data.file;
Expand All @@ -41,70 +36,60 @@ export default async function editFile(

if (fileBuffer.byteLength > 1_073_741_824 * 1) {
fileErrors.push({
file: file,
file: data.name,
erorr: "Exceeds the 1GB limit.",
});
}
/**
*
* Users must remember to include the file extension when uploading from Node.
*
*/
// if (!isBrowser && data.name.lastIndexOf(".") == -1) {
// fileErrors.push({
// file: data.name,
// error: "File extension must be included.",
// });
// }
if (fileErrors.length) {
return Promise.reject(fileErrors);
}
const userInfoAccount = await UserInfo.fetch(this.connection, this.userInfo);
if (userInfoAccount === null) {
if (!this.userInfo) {
return Promise.reject(
new Error(
"You have not created a storage account on Shadow Drive yet. Please see the 'create-storage-account' command to get started."
)
"You have not created a storage account on Shadow Drive yet. Please see the 'create-storage-account' command to get started."
);
}
let existingFileData, fileDataResponse;
try {
existingFileData = await fetch(`${SHDW_DRIVE_ENDPOINT}/get-object-data`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
location: url,
}),
});
fileDataResponse = await existingFileData.json();
} catch (e) {
return Promise.reject(new Error(e.message));
}
const fileOwnerOnChain = new web3.PublicKey(
fileDataResponse.file_data["owner-account-pubkey"]
);
if (!fileOwnerOnChain.equals(this.wallet.publicKey)) {
return Promise.reject(new Error("Permission denied: Not file owner"));
}
const fileHashSum = crypto.createHash("sha256");
const fileNameHashSum = crypto.createHash("sha256");
fileHashSum.update(
Buffer.isBuffer(fileBuffer) ? fileBuffer : Buffer.from(fileBuffer)
);
const fileHash = fileHashSum.digest("hex");
fileNameHashSum.update(data.name);

const fileNameHash = fileNameHashSum.digest("hex");
try {
const msg = Buffer.from(
`Shadow Drive Signed Message:\n StorageAccount: ${key}\nFile to edit: ${data.name}\nNew file hash: ${fileHash}`
const msg = new TextEncoder().encode(
`Shadow Drive Signed Message:\nStorage Account: ${key}\nUpload files with hash: ${fileNameHash}`
);
let msgSig;
let msgSig: Uint8Array;
if (!this.wallet.signMessage) {
msgSig = nacl.sign.detached(msg, this.wallet.payer.secretKey);
} else {
msgSig = await this.wallet.signMessage(msg);
}
const encodedMsg = bs58.encode(msgSig);
form.append("fileNames", data.name);
form.append("message", encodedMsg);
form.append("signer", this.wallet.publicKey.toString());
form.append("storage_account", key.toString());
form.append("url", url);
form.append("signer", this.wallet.publicKey.toString());
form.append("overwrite", "true");
} catch (e) {
return Promise.reject(new Error(e.message));
}
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 7200000);
const uploadResponse = await fetch(`${SHDW_DRIVE_ENDPOINT}/edit`, {
const uploadResponse = await fetch(`${SHDW_DRIVE_ENDPOINT}/upload`, {
method: "POST",
//@ts-ignore
body: form,
Expand All @@ -116,7 +101,7 @@ export default async function editFile(
Server response status message: ${(await uploadResponse.json()).error}`)
);
}
const responseJson: ShadowEditResponse = await uploadResponse.json();
const responseJson = await uploadResponse.json();
return Promise.resolve(responseJson);
} catch (e) {
return Promise.reject(new Error(e.message));
Expand Down
7 changes: 6 additions & 1 deletion src/methods/upload-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import nacl from "tweetnacl";
*
* @param {web3.PublicKey} key - Publickey of Storage Account.
* @param {File | ShadowFile} data - File or ShadowFile object, file extensions should be included in the name property of ShadowFiles.
* @param {Boolean} overwrite - If true, overwrites if existing. Default is false.
* @returns {ShadowUploadResponse} File location and transaction signature.
*/
export default async function uploadFile(
key: web3.PublicKey,
data: File | ShadowFile
data: File | ShadowFile,
overwrite: Boolean = false
): Promise<ShadowUploadResponse> {
let fileErrors = [];
let fileBuffer: Buffer;
Expand Down Expand Up @@ -82,6 +84,9 @@ export default async function uploadFile(
form.append("message", encodedMsg);
form.append("storage_account", key.toString());
form.append("signer", this.wallet.publicKey.toString());
if(overwrite) {
form.append("overwrite", "true");
}
} catch (e) {
return Promise.reject(new Error(e.message));
}
Expand Down
7 changes: 6 additions & 1 deletion src/methods/upload-multiple-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface FileData {
* @param {web3.PublicKey} key - Storage account PublicKey to upload the files to.
* @param {FileList | ShadowFile[]} data[] - Array of Files or ShadowFile objects to be uploaded
* @param {Number} concurrent - Number of files to concurrently upload. Default: 3
* @param {Boolean} overwrite - If true, overwrites if existing. Default is false.
* @param {Function} callback - Callback function for every batch of files uploaded. A number will be passed into the callback like `callback(num)` indicating the number of files that were confirmed in that specific batch.
* @returns {ShadowBatchUploadResponse[]} - File names, locations and transaction signatures for uploaded files.
*/
Expand All @@ -30,7 +31,8 @@ export default async function uploadMultipleFiles(
key: web3.PublicKey,
data: FileList | ShadowFile[],
concurrent = 3,
callback?: Function
overwrite: Boolean = false,
callback?: Function,
): Promise<ShadowBatchUploadResponse[]> {
let fileData: Array<FileData> = [];
const fileErrors: Array<object> = [];
Expand Down Expand Up @@ -218,6 +220,9 @@ export default async function uploadMultipleFiles(
fd.append("storage_account", key.toString());
fd.append("signer", this.wallet.publicKey.toString());
fd.append("fileNames", allFileNames.toString());
if (overwrite) {
fd.append("overwrite", "true");
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 7200000);
const response = await fetch(`${SHDW_DRIVE_ENDPOINT}/upload`, {
Expand Down

0 comments on commit f82c3cd

Please sign in to comment.