Skip to content

Commit

Permalink
upload 関数の修正途中まで
Browse files Browse the repository at this point in the history
  • Loading branch information
Huzitatuguharu committed May 29, 2024
1 parent f4b3331 commit eb83502
Showing 4 changed files with 127 additions and 70 deletions.
11 changes: 3 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -56,18 +56,13 @@ AWSConfig(*1)
| cloudFrontUrl | true | string | cloudFront url connect to s3 which is uploaded content |
| bucketName | true | {content: string, metadata: string} | bucketName of metadata and content, it's ok they are same |

export type IPFSConfig = {
apiKey: string;
apiSecret?: string;
};


IPFSConfig(*1)
IPFSConfig(*2)

| name | required | type | description |
| ------------- | -------- | ----------------------------------- | --------------------------------------------------------- |
| apiKey | true | string | API key region |
| apiSecret | false | string | API Secret key S3-put-object |
| apiKey | true | string | API key |
| apiSecret | false | string | API secret key |
|
### sign to server

162 changes: 103 additions & 59 deletions src/storage/ipfs/upload.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import axios from "axios";
import FormData from "form-data";
import FormData, { Readable } from "form-data";
import fs from "fs";
import * as Stream from "stream";

import { EncryptLogic, FileOrPath } from "../../vwbl/types";
import { IPFSConfig } from "./types";

const pinataEndpoint = "https://api.pinata.cloud/pinning/pinFileToIPFS";

// Pinataの認証テスト関数
// Pinata Authentication Test Functions
export const testPinataAuthentication = async (ipfsConfig: IPFSConfig): Promise<void> => {
const headers: Record<string, string | number | boolean> = {
pinata_api_key: ipfsConfig.apiKey,
@@ -22,85 +22,113 @@ export const testPinataAuthentication = async (ipfsConfig: IPFSConfig): Promise<
};

try {
const response = await axios.get("https://api.pinata.cloud/data/testAuthentication", config);
console.log("Pinata認証成功:", response.data);
const response = await axios.get(pinataEndpoint, config);
console.log("Pinata authentication succeeded:", response.data);
} catch (err: any) {

Check warning on line 27 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unexpected any. Specify a different type
console.error("Pinata認証失敗:", config.headers);
console.error("Pinata認証失敗:", err.message);
console.error("Pinata authentication failed:", config.headers);
console.error("Pinata authentication failed:", err.message);

Check warning on line 29 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .message on an `any` value
throw new Error(`Pinata authentication failed: ${err.message}`);

Check warning on line 30 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .message on an `any` value
}
};

// 暗号化ファイルのアップロード関数
// Check if the environment in which it is running is Node.js
function isNode() {
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
}
// Upload function for encrypted files
export const uploadEncryptedFileToIPFS = async (
encryptedContent: string | ArrayBuffer | Buffer,
encryptedContent: string | Uint8Array | Stream.Readable,
ipfsConfig?: IPFSConfig
): Promise<string> => {
if (!ipfsConfig || !ipfsConfig.apiKey || !ipfsConfig.apiSecret) {
throw new Error("Pinata API key or secret is not specified.");
}
console.error("uploadEncryptedFileToIPFS:", ipfsConfig);
await testPinataAuthentication(ipfsConfig); // 認証テスト

// encryptedContentをBufferに変換
let fileBuffer: Buffer;
if (typeof encryptedContent === "string") {
fileBuffer = Buffer.from(encryptedContent, "utf-8"); // UTF-8エンコーディングを想定
} else if (encryptedContent instanceof ArrayBuffer) {
fileBuffer = Buffer.from(encryptedContent);
} else {
fileBuffer = encryptedContent; // すでにBuffer型ならそのまま使用
}

const formData = new FormData();
formData.append("file", fileBuffer, "encrypted-file");
if (typeof encryptedContent === "string" || encryptedContent instanceof Uint8Array) {
// assuming encryptedContent is base64 string or Uint8Array for simplicity
formData.append("file", Buffer.from(encryptedContent), {
filename: "encrypted-file",
contentType: "application/octet-stream",
});
} else if (encryptedContent instanceof Readable) {
formData.append("file", encryptedContent, "encrypted-file");
}

const config = {
headers: {
...formData.getHeaders(),
pinata_api_key: ipfsConfig.apiKey,
pinata_secret_api_key: ipfsConfig.apiSecret,
...formData.getHeaders(),
},
onUploadProgress: (progressEvent: any) => {
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`uploadEncryptedFileToPinataアップロード進行中: ${progress}%`);
},
onUploadProgress: isNode()
? undefined
: (progressEvent: any) => {

Check warning on line 65 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unexpected any. Specify a different type
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);

Check warning on line 66 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .loaded on an `any` value

Check warning on line 66 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .total on an `any` value
console.log(`uploadEncryptedFileProgress: ${progress}%`);
},
};

console.log("Uploading encrypted data to IPFS...");

try {
const response = await axios.post(pinataEndpoint, formData, config);
return `https://gateway.pinata.cloud/ipfs/${response.data.IpfsHash}`;

Check warning on line 75 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .IpfsHash on an `any` value
} catch (err: any) {

Check warning on line 76 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unexpected any. Specify a different type
console.error("Pinata upload failed:", err.response ? err.response.data : err.message);

Check warning on line 77 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Unsafe member access .response on an `any` value
throw new Error(`Pinata upload failed: ${err.message}`);
}
};

export const uploadThumbnailToIPFS = async (thumbnailImage: FileOrPath, ipfsConfig?: IPFSConfig): Promise<string> => {
// upload function for thumbnailImage
export const uploadThumbnailToIPFS = async (
thumbnailImage: string | File | Blob,
ipfsConfig?: IPFSConfig
): Promise<string> => {
if (!ipfsConfig || !ipfsConfig.apiKey || !ipfsConfig.apiSecret) {
throw new Error("Pinata API key or secret is not specified.");
}

const formData = new FormData();

if (Buffer.isBuffer(thumbnailImage)) {
formData.append("file", thumbnailImage, { filename: "thumbnail.png" });
} else if (typeof thumbnailImage === "string") {
const stream = fs.createReadStream(thumbnailImage);
formData.append("file", stream, { filename: "thumbnail.png" });
if (isNode()) {
// Node.js
if (typeof thumbnailImage === "string") {
const stream = fs.createReadStream(thumbnailImage);
formData.append("file", stream);
} else {
throw new Error("Invalid type for thumbnailImage in Node.js environment");
}
} else {
throw new Error("Invalid type for thumbnailImage");
// Browser
if (thumbnailImage instanceof File || thumbnailImage instanceof Blob) {
formData.append("file", thumbnailImage);
} else if (typeof thumbnailImage === "string") {
const response = await fetch(thumbnailImage);
const blob = await response.blob();
formData.append("file", new File([blob], "thumbnail", { type: blob.type }));
} else {
throw new Error("Invalid type for thumbnailImage in browser environment");
}
}

const headers = {
pinata_api_key: ipfsConfig.apiKey,
pinata_secret_api_key: ipfsConfig.apiSecret,
"Content-Type": "multipart/form-data",
};

if (isNode()) {
Object.assign(headers, formData.getHeaders());
}

const config = {
headers: {
pinata_api_key: ipfsConfig.apiKey,
pinata_secret_api_key: ipfsConfig.apiSecret,
...formData.getHeaders(),
},
onUploadProgress: (progressEvent: any) => {
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`uploadThumbnailToPinataアップロード進行中: ${progress}%`);
},
headers: headers,
onUploadProgress: isNode()
? undefined
: (progressEvent: any) => {
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`uploadThumbnailProgress: ${progress}%`);
},
};

try {
@@ -111,7 +139,7 @@ export const uploadThumbnailToIPFS = async (thumbnailImage: FileOrPath, ipfsConf
}
};

// メタデータのアップロード関数
// upload function for metadata
export const uploadMetadataToIPFS = async (
name: string,
description: string,
@@ -135,22 +163,38 @@ export const uploadMetadataToIPFS = async (
};

const metadataJSON = JSON.stringify(metadata);
const formData = new FormData();
formData.append("file", Buffer.from(metadataJSON), {
filename: "metadata.json",
contentType: "application/json",
});
const formData = isNode() ? new (require("form-data"))() : new FormData();

Check failure on line 166 in src/storage/ipfs/upload.ts

GitHub Actions / ci (20.x)

Require statement not part of import statement

if (isNode()) {
// Node.js
formData.append("file", Buffer.from(metadataJSON), {
filename: "metadata.json",
contentType: "application/json",
});
} else {
// Browser
const blob = new Blob([metadataJSON], { type: "application/json" });
formData.append("file", blob, "metadata.json");
}

const headers = {
pinata_api_key: ipfsConfig.apiKey,
pinata_secret_api_key: ipfsConfig.apiSecret,
"Content-Type": "multipart/form-data",
};

if (isNode()) {
Object.assign(headers, formData.getHeaders());
}

const config = {
headers: {
pinata_api_key: ipfsConfig.apiKey,
pinata_secret_api_key: ipfsConfig.apiSecret,
...formData.getHeaders(),
},
onUploadProgress: (progressEvent: any) => {
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`uploadMetadataToPinataアップロード進行中: ${progress}%`);
},
headers: headers,
onUploadProgress: isNode()
? undefined
: (progressEvent: any) => {
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(`uploadMetadataProgress: ${progress}%`);
},
};

try {
21 changes: 19 additions & 2 deletions src/vwbl/erc721/VWBLMetaTx.ts
Original file line number Diff line number Diff line change
@@ -245,20 +245,37 @@ export class VWBLMetaTx extends VWBLBase {

subscriber?.kickStep(StepStatus.ENCRYPT_DATA);

// プリフィックスがあるかどうかをチェックする関数
const hasPrefix = (base64: any) => {
return base64.startsWith("data:");
};

// Base64エンコードされた文字列にプリフィックスを付加する関数
const toDataURL = (base64: any) => {
if (hasPrefix(base64)) {
return base64;
}
return `data:image/png;base64,${base64}`;
};

// 3. upload data
console.log("upload data");
const isRunningOnBrowser = typeof window !== "undefined";
const encryptedDataUrls = await Promise.all(
plainFileArray.map(async (file) => {
const plainFileBlob = file instanceof File ? file : new File([await fs.promises.readFile(file)], file);
const filePath = file instanceof File ? file.name : file;
const fileName: string = file instanceof File ? file.name : file.split("/").slice(-1)[0];
const encryptedContent =
encryptLogic === "base64"
? encryptString(await toBase64FromBlob(plainFileBlob), key)
: await encryptFile(plainFileBlob, key);
: isRunningOnBrowser
? await encryptFile(plainFileBlob, key)
: encryptStream(fs.createReadStream(filePath), key);
console.log("managedCreateTokenForIPFS>>>>>>", encryptedContent);
return await uploadEncryptedFileCallback(encryptedContent, ipfsConfig);
})
);

const thumbnailImageUrl = await uploadThumbnailCallback(thumbnailImage, ipfsConfig);
subscriber?.kickStep(StepStatus.UPLOAD_CONTENT);

3 changes: 2 additions & 1 deletion src/vwbl/types/File.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,8 @@ type UploadMetadata = (

// type UploadEncryptedFileToIPFS = (encryptedContent: string | ArrayBuffer, ipfsConfig?: IPFSConfig) => Promise<string>;
type UploadEncryptedFileToIPFS = (
encryptedContent: string | Uint8Array | Buffer,
// encryptedContent: string | Uint8Array | Buffer,
encryptedContent: string | Uint8Array | Stream.Readable,
ipfsConfig?: IPFSConfig
) => Promise<string>;

0 comments on commit eb83502

Please sign in to comment.