Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lighthouse <img src="https://img.shields.io/badge/v0.4.0-green"/>
# Lighthouse <img src="https://img.shields.io/badge/v0.4.1-green"/>

Lighthouse is a permanent decentralized file storage protocol that allows the ability to pay once and store forever. While traditionally, users need to repeatedly keep track and pay for their storage after every fixed amount of time, Lighthouse manages this for them and makes sure that user files are stored forever. The aim is to move users from a rent-based cost model where they are renting their own files on cloud storage to a permanent ownership model. It is built on top of IPFS, Filecoin, and Polygon. It uses the existing miner network and storage capacity of the filecoin network.

Expand Down
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": "@lighthouse-web3/sdk",
"version": "0.4.0",
"version": "0.4.1",
"description": "NPM package and CLI tool to interact with lighthouse protocol",
"main": "./dist/Lighthouse/index.js",
"types": "./dist/Lighthouse/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Command.prototype.helpInformation = function (context: any) {
}

widgets.addHelpText('before', 'Welcome to lighthouse-web3')
widgets.version('0.4.0')
widgets.version('0.4.1')

widgets
.command('wallet')
Expand Down
10 changes: 8 additions & 2 deletions src/Lighthouse/encryption/applyAccessCondition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,14 @@ export default async (
chainType
)

if (error) {
throw error
if (!isSuccess || error) {
const errorMessage =
typeof error === 'string'
? error
: error instanceof Error
? error.message
: JSON.stringify(error)
throw new Error(errorMessage)
}
return { data: { cid: cid, status: 'Success' } }
}
6 changes: 1 addition & 5 deletions src/Lighthouse/tests/encryption.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const signAuthMessage = async (privateKey: string) => {
describe('encryption', () => {
describe('getAuthMessage', () => {
it('should get auth message when valid public key is provided', async () => {
console.log('testing getAuthMessage')
const response = await lighthouse.getAuthMessage(
'0x1Ec09D4B3Cb565b7CCe2eEAf71CC90c9b46c5c26'
)
Expand All @@ -24,7 +23,6 @@ describe('encryption', () => {

it('should not get auth message when invalid public key is provided', async () => {
try {
console.log('testing getAuthMessage with invalid public key')
const response = await lighthouse.getAuthMessage('invalidPublicKey')
} catch (error) {
expect(error.message).toBe('Invalid public Key')
Expand All @@ -38,7 +36,6 @@ describe('encryption', () => {
const cid = 'QmVkHgHnYVUfvTXsaJisHRgc89zsrgVL6ATh9mSiegRYrX'

it('should fetch encryption key when correct public-private key pair is provided', async () => {
console.log('testing fetchEncryptionKey')
const signed_message = await signAuthMessage(privateKey)
const response = await lighthouse.fetchEncryptionKey(
cid,
Expand All @@ -50,7 +47,6 @@ describe('encryption', () => {

it('should not fetch encryption key when incorrect public-private key pair is provided', async () => {
try {
console.log('testing fetchEncryptionKey with incorrect key pair')
const randomPublicKey = '0x1ccEF158Dcbe6643F1cC577F236af79993F4D066'
const signed_message = await signAuthMessage(privateKey)
const response = await lighthouse.fetchEncryptionKey(
Expand Down Expand Up @@ -122,7 +118,7 @@ describe('encryption', () => {
signed_message
)
} catch (error) {
expect(error.message.message.message).toEqual('access denied')
expect(error.message[0].message.message).toEqual('access denied')
}
}, 10000)
})
Expand Down
2 changes: 1 addition & 1 deletion src/Lighthouse/tests/upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('uploadFiles', () => {
)
await lighthouse.upload(path, 'random apiKey')
} catch (error) {
expect(error.message).toBe('Error: Authentication failed')
expect(error.message).toBe('Error: Request failed with status code 401')
}
}, 60000)
})
2 changes: 1 addition & 1 deletion src/Lighthouse/upload/files/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async function uploadFiles(
// Upload File to IPFS
//@ts-ignore
if (typeof window === 'undefined') {
return await uploadFile(path, apiKey, cidVersion)
return await uploadFile(path, apiKey, cidVersion, uploadProgressCallback)
} else {
return await uploadFileBrowser(
path,
Expand Down
110 changes: 58 additions & 52 deletions src/Lighthouse/upload/files/node.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import basePathConvert from '../../utils/basePathConvert'
import { lighthouseConfig } from '../../../lighthouse.config'
import { fetchWithTimeout } from '../../utils/util'
import { IFileUploadedResponse } from '../../../types'
import { fetchWithDirectStream } from '../../utils/util'
import { IFileUploadedResponse, IUploadProgressCallback } from '../../../types'
export async function walk(dir: string) {
const { readdir, stat } = eval(`require`)('fs-extra')
let results: string[] = []
Expand All @@ -24,79 +24,85 @@ export async function walk(dir: string) {
export default async (
sourcePath: string,
apiKey: string,
cidVersion: number
cidVersion: number,
uploadProgressCallback?: (data: IUploadProgressCallback) => void
): Promise<{ data: IFileUploadedResponse }> => {
const { createReadStream, lstatSync } = eval(`require`)('fs-extra')
const path = eval(`require`)('path')

const token = 'Bearer ' + apiKey
const stats = lstatSync(sourcePath)

try {
const endpoint =
lighthouseConfig.lighthouseNode +
`/api/v0/add?wrap-with-directory=false&cid-version=${cidVersion}`
const boundary =
'----WebKitFormBoundary' + Math.random().toString(16).substr(2)

const headers = {
Authorization: token,
}

if (stats.isFile()) {
const data = new FormData()
const stream = createReadStream(sourcePath)
const buffers: Buffer[] = []
for await (const chunk of stream) {
buffers.push(chunk)
const streamData = {
boundary,
files: [
{
stream,
filename: path.basename(sourcePath),
size: stats.size,
},
],
}
const blob = new Blob(buffers)

data.append('file', blob, path.basename(sourcePath))

const response = await fetchWithTimeout(endpoint, {
method: 'POST',
body: data,
timeout: 7200000,
headers: {
Authorization: token
const response = await fetchWithDirectStream(
endpoint,
{
method: 'POST',
headers,
timeout: 7200000,
onProgress: uploadProgressCallback
? (data: { progress: number }) => uploadProgressCallback(data)
: undefined,
},
})
streamData
)

if (!response.ok) {
const res = (await response.json())
throw new Error(res.error)
}

const responseData = (await response.json())
return { data: responseData }
return response
} else {
// Handle directory upload
const files = await walk(sourcePath)
const data = new FormData()

for (const file of files) {
const stream = createReadStream(file)
const buffers: Buffer[] = []
for await (const chunk of stream) {
buffers.push(chunk)
}
const blob = new Blob(buffers)
const createStreamData = () => ({
boundary,
files: files.map((file) => {
const fileStats = lstatSync(file)
return {
stream: createReadStream(file),
filename: basePathConvert(sourcePath, file),
size: fileStats.size,
}
}),
})

data.append(
'file',
blob,
basePathConvert(sourcePath, file)
)
}
const streamData = createStreamData()

const response = await fetchWithTimeout(endpoint, {
method: 'POST',
body: data,
timeout: 7200000,
headers: {
Authorization: token
const response = await fetchWithDirectStream(
endpoint,
{
method: 'POST',
headers,
timeout: 7200000,
onProgress: uploadProgressCallback
? (data: { progress: number }) => uploadProgressCallback(data)
: undefined,
},
})

if (!response.ok) {
const res = (await response.json())
throw new Error(res.error)
}
streamData
)

const responseData = (await response.json())
return { data: responseData }
return response
}
} catch (error: any) {
throw new Error(error)
Expand Down
102 changes: 45 additions & 57 deletions src/Lighthouse/uploadEncrypted/encryptionBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,72 +19,60 @@ const deriveKey = async (
)

export const encryptFile = async (fileArrayBuffer: any, password: any) => {
try {
const plainTextBytes = new Uint8Array(fileArrayBuffer)
const passwordBytes = new TextEncoder().encode(password)
const plainTextBytes = new Uint8Array(fileArrayBuffer)
const passwordBytes = new TextEncoder().encode(password)

const salt = window.crypto.getRandomValues(new Uint8Array(16))
const iv = window.crypto.getRandomValues(new Uint8Array(12))
const salt = window.crypto.getRandomValues(new Uint8Array(16))
const iv = window.crypto.getRandomValues(new Uint8Array(12))

const passwordKey = await importKeyFromBytes(passwordBytes)
const passwordKey = await importKeyFromBytes(passwordBytes)

const aesKey = await deriveKey(passwordKey, ['encrypt'], {
name: 'PBKDF2',
salt: salt,
iterations: 250000,
hash: 'SHA-256',
})
const cipherBytes = await window.crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
aesKey,
plainTextBytes
)
const aesKey = await deriveKey(passwordKey, ['encrypt'], {
name: 'PBKDF2',
salt: salt,
iterations: 250000,
hash: 'SHA-256',
})
const cipherBytes = await window.crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: iv },
aesKey,
plainTextBytes
)

const cipherBytesArray = new Uint8Array(cipherBytes)
const resultBytes = new Uint8Array(
cipherBytesArray.byteLength + salt.byteLength + iv.byteLength
)
resultBytes.set(salt, 0)
resultBytes.set(iv, salt.byteLength)
resultBytes.set(cipherBytesArray, salt.byteLength + iv.byteLength)
const cipherBytesArray = new Uint8Array(cipherBytes)
const resultBytes = new Uint8Array(
cipherBytesArray.byteLength + salt.byteLength + iv.byteLength
)
resultBytes.set(salt, 0)
resultBytes.set(iv, salt.byteLength)
resultBytes.set(cipherBytesArray, salt.byteLength + iv.byteLength)

return resultBytes
} catch (error) {
console.error('Error encrypting file')
console.error(error)
throw error
}
return resultBytes
}

export const decryptFile = async (cipher: any, password: any) => {
try {
const cipherBytes = new Uint8Array(cipher)
const passwordBytes = new TextEncoder().encode(password)
const cipherBytes = new Uint8Array(cipher)
const passwordBytes = new TextEncoder().encode(password)

const salt = cipherBytes.slice(0, 16)
const iv = cipherBytes.slice(16, 16 + 12)
const data = cipherBytes.slice(16 + 12)
const passwordKey = await importKeyFromBytes(passwordBytes)
const aesKey = await deriveKey(passwordKey, ['decrypt'], {
name: 'PBKDF2',
salt: salt,
iterations: 250000,
hash: 'SHA-256',
})
const salt = cipherBytes.slice(0, 16)
const iv = cipherBytes.slice(16, 16 + 12)
const data = cipherBytes.slice(16 + 12)
const passwordKey = await importKeyFromBytes(passwordBytes)
const aesKey = await deriveKey(passwordKey, ['decrypt'], {
name: 'PBKDF2',
salt: salt,
iterations: 250000,
hash: 'SHA-256',
})

const decryptedContent = await window.crypto.subtle.decrypt(
{
name: 'AES-GCM',
iv: iv,
},
aesKey,
data
)
const decryptedContent = await window.crypto.subtle.decrypt(
{
name: 'AES-GCM',
iv: iv,
},
aesKey,
data
)

return decryptedContent
} catch (error) {
console.error('Error decrypting file')
console.error(error)
return
}
return decryptedContent
}
Loading