Skip to content
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"./packages/icons/**",
"./packages/mask/swap/webgl/**",
"./packages/web3-contracts/types/**",
"./patches/**",
".github",
".gitignore",
".patch",
Expand Down Expand Up @@ -66,6 +67,7 @@
"cyberconnect",
"cyberlab",
"darkweb",
"dataitem",
"debank",
"deficonnect",
"devnet",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"yarn": ">=999.0.0",
"npm": ">=999.0.0"
},
"version": "2.34.0",
"version": "2.34.1",
"private": true,
"license": "AGPL-3.0-or-later",
"scripts": {
Expand Down
5 changes: 4 additions & 1 deletion packages/mask/.webpack/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ export async function createConfiguration(
console.error("Environment variable WEB3_CONSTANTS_RPC should be JSON.stringify'ed twice")
WEB3_CONSTANTS_RPC = JSON.stringify(WEB3_CONSTANTS_RPC)
}
} catch (err) {}
} catch (err) {
console.error('Environment variable WEB3_CONSTANTS_RPC is not valid JSON')
}
}
const baseConfig = {
name: 'mask',
Expand Down Expand Up @@ -239,6 +241,7 @@ export async function createConfiguration(
SOLANA_DEFAULT_RPC_URL: process.env.SOLANA_DEFAULT_RPC_URL || '',
MASK_ENABLE_EXCHANGE: process.env.MASK_ENABLE_EXCHANGE || '',
GOOGLE_CLIENT_ID: JSON.stringify(process.env.GOOGLE_CLIENT_ID) || '',
LOAD_KEY: process.env.LOAD_KEY || '',
}),
new (rspack?.DefinePlugin || webpack.default.DefinePlugin)({
'process.browser': 'true',
Expand Down
66 changes: 29 additions & 37 deletions packages/plugins/FileService/src/Worker/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import { Attachment } from '@dimensiondev/common-protocols'
import { encodeText } from '@masknet/kit'
import { LANDING_PAGE, Provider } from '../constants.js'
import type { ProviderAgent, LandingPageMetadata, AttachmentOptions } from '../types.js'
import { makeFileKeySigned } from '../helpers.js'
import { LOAD_LEGACY_GATEWAY_URL, LOAD_LEGACY_ID_REGEX, makeFileKeySigned } from '../helpers.js'

const LOAD_GATEWAY_URL = 'https://load0.network/resolve'
const LOAD_UPLOAD_ENDPOINT = 'https://load0.network/upload'
const API_KEY = 'load_acc_ep4bep0uGlmUXMu46BxM0uWXKsqL5M5w' // move to env
const LOAD_GATEWAY_URL = 'https://load-s3-agent.load.network'
const LOAD_UPLOAD_ENDPOINT = 'https://load-s3-agent.load.network/upload'

class LoadAgent implements ProviderAgent {
static providerName = 'Load Network'
Expand Down Expand Up @@ -51,7 +50,9 @@ class LoadAgent implements ProviderAgent {

async uploadLandingPage(metadata: LandingPageMetadata) {
this.init()
const linkPrefix = LOAD_GATEWAY_URL
// decide which gateway URL to use based on ID
const linkPrefix = LOAD_LEGACY_ID_REGEX.test(metadata.txId) ? LOAD_LEGACY_GATEWAY_URL : LOAD_GATEWAY_URL

const encodedMetadata = JSON.stringify({
name: metadata.name,
size: metadata.size,
Expand All @@ -60,6 +61,7 @@ class LoadAgent implements ProviderAgent {
signed: await makeFileKeySigned(metadata.key),
createdAt: new Date().toISOString(),
})

const response = await fetch(LANDING_PAGE)
const text = await response.text()
const replaced = text
Expand All @@ -68,48 +70,38 @@ class LoadAgent implements ProviderAgent {
.replace('__METADATA__', encodedMetadata)

const data = encodeText(replaced)

const landingPageTxId = await this.makePayload(data, 'text/html', `${metadata.name}-landing.html`)

return landingPageTxId
}

async makePayload(data: Uint8Array, type: string, fileName: string = 'file.dat') {
this.init()

try {
const blob = new Blob([data], { type })
const headers = {
'Content-Type': type,
Filename: fileName,
'App-Name': 'Maskbook',
'X-Load-Authorization': API_KEY,
}

const response = await fetch(LOAD_UPLOAD_ENDPOINT, {
method: 'POST',
headers,
body: blob,
signal: this.uploadController?.signal,
})

if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`)
}

const { optimistic_hash } = await response.json()
return optimistic_hash
} catch (error) {
const errorMessage = `Load Network upload failed: ${error instanceof Error ? error.message : String(error)}`
console.error('Load Network detailed error:', errorMessage)
const blob = new Blob([data], { type })
const formData = new FormData()
formData.append('file', blob)
formData.append('content_type', type)
formData.append('app_name', 'Maskbook')

const response = await fetch(LOAD_UPLOAD_ENDPOINT, {
method: 'POST',
headers: {
Authorization: 'Bearer maskMASKhbs3',
},
body: formData,
signal: this.uploadController?.signal,
})

const enhancedError = new Error(errorMessage)
if (error instanceof Error && error.stack) {
enhancedError.stack = error.stack
}
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`)
}

throw enhancedError
const result = await response.json()
if (!result.success || !result.dataitem_id) {
throw new Error('Invalid response from upload service')
}

return result.dataitem_id
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/plugins/FileService/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const META_KEY_2 = 'com.maskbook.fileservice:2'
export const META_KEY_3 = 'com.maskbook.fileservice:3'

export const MAX_FILE_SIZE = 10 * 1000 * 1000
export const MAX_FILE_SIZE_LOAD = 10 * 1024 * 1024
export const MAX_FILE_SIZE_LOAD = 30 * 1024 * 1024

export const LANDING_PAGE = 'https://files.r2d2.to/partner/arweave/landing-page.html'
export const RECOVERY_PAGE = 'https://fileservice.r2d2.to/recover'
Expand Down
13 changes: 11 additions & 2 deletions packages/plugins/FileService/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import schemaV1 from './schema-v1.json' with { type: 'json' }
import schemaV2 from './schema-v2.json' with { type: 'json' }
import schemaV3 from './schema-v3.json' with { type: 'json' }

// Load legacy detection + gateway
export const LOAD_LEGACY_ID_REGEX = /^0x[a-f0-9]{64}$/iu
export const LOAD_LEGACY_GATEWAY_URL = 'https://load0.network/download'

// Note: if the latest version has been changed, please update packages/mask/content-script/components/CompositionDialog/useSubmit.ts
const reader_v1 = createTypedMessageMetadataReader<FileInfoV1>(META_KEY_1, schemaV1)
const reader_v2 = createTypedMessageMetadataReader<FileInfo>(META_KEY_2, schemaV2)
Expand Down Expand Up @@ -45,7 +49,7 @@ const resolveGatewayAPI = createLookupTableResolver<Provider, string>(
{
[Provider.Arweave]: 'https://arweave.net',
[Provider.IPFS]: 'https://mask.infura-ipfs.io/ipfs',
[Provider.Load]: 'https://load0.network/resolve',
[Provider.Load]: 'https://load-s3-agent.load.network',
},
() => 'Unknown provider',
)
Expand All @@ -61,7 +65,12 @@ export function makeFileKey(length = 16) {
}

export function downloadFile(file: FileInfo) {
const gateway = resolveGatewayAPI(file.provider)
let gateway = resolveGatewayAPI(file.provider)

if (file.provider === Provider.Load && LOAD_LEGACY_ID_REGEX.test(String(file.landingTxID ?? ''))) {
gateway = LOAD_LEGACY_GATEWAY_URL
}

let link = urlcat(gateway, '/:txId', { txId: file.landingTxID })
if (isAfter(new Date(2022, 8, 1), new Date(file.createdAt))) {
link = urlcat(RECOVERY_PAGE, {
Expand Down