@campnetwork/origin 1.4.0-alpha.4 → 1.4.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs +213 -142
- package/dist/core.d.ts +108 -2
- package/dist/core.esm.d.ts +108 -2
- package/dist/core.esm.js +229 -158
- package/dist/react/index.esm.d.ts +108 -2
- package/dist/react/index.esm.js +405 -29
- package/package.json +1 -1
package/dist/react/index.esm.js
CHANGED
|
@@ -6599,6 +6599,7 @@ var constants = {
|
|
|
6599
6599
|
SUPPORTED_VIDEO_FORMATS: ["video/mp4", "video/webm"],
|
|
6600
6600
|
SUPPORTED_AUDIO_FORMATS: ["audio/mpeg", "audio/wav", "audio/ogg"],
|
|
6601
6601
|
SUPPORTED_TEXT_FORMATS: ["text/plain"],
|
|
6602
|
+
MAX_FILE_SIZE: 20 * 1024 * 1024, // 20 MB
|
|
6602
6603
|
AVAILABLE_SOCIALS: ["twitter", "spotify"], // tiktok disabled
|
|
6603
6604
|
MAX_LICENSE_DURATION: 2628000, // 30 days in seconds
|
|
6604
6605
|
MIN_LICENSE_DURATION: 86400, // 1 day in seconds
|
|
@@ -8412,7 +8413,7 @@ function bulkBuyAccessSmart(tokenIds, options) {
|
|
|
8412
8413
|
* creatorContentHash: "0x...",
|
|
8413
8414
|
* uri: "ipfs://...",
|
|
8414
8415
|
* licenseTerms: { price: 1000n, duration: 86400, royaltyBps: 500, paymentToken: zeroAddress, licenseType: 0 },
|
|
8415
|
-
* deadline: BigInt(Date.now() +
|
|
8416
|
+
* deadline: BigInt(Math.floor(Date.now() / 1000) + 600),
|
|
8416
8417
|
* parents: [],
|
|
8417
8418
|
* isIP: true,
|
|
8418
8419
|
* appId: "myApp",
|
|
@@ -8443,6 +8444,311 @@ function bulkMintTolerant(mints) {
|
|
|
8443
8444
|
return this.callContractMethod(this.environment.BATCH_OPERATIONS_CONTRACT_ADDRESS, this.environment.BATCH_OPERATIONS_ABI, "bulkMintTolerant", [mints], { waitForReceipt: true });
|
|
8444
8445
|
}
|
|
8445
8446
|
|
|
8447
|
+
function validateIpfsCredentials(credentials) {
|
|
8448
|
+
switch (credentials.provider) {
|
|
8449
|
+
case "pinata":
|
|
8450
|
+
if (!credentials.jwt && !(credentials.apiKey && credentials.apiSecret)) {
|
|
8451
|
+
throw new ValidationError("Pinata requires either 'jwt' or both 'apiKey' and 'apiSecret'");
|
|
8452
|
+
}
|
|
8453
|
+
break;
|
|
8454
|
+
case "infura":
|
|
8455
|
+
if (!credentials.projectId || !credentials.projectSecret) {
|
|
8456
|
+
throw new ValidationError("Infura requires both 'projectId' and 'projectSecret'");
|
|
8457
|
+
}
|
|
8458
|
+
break;
|
|
8459
|
+
case "web3storage":
|
|
8460
|
+
if (!credentials.token) {
|
|
8461
|
+
throw new ValidationError("web3.storage requires 'token'");
|
|
8462
|
+
}
|
|
8463
|
+
break;
|
|
8464
|
+
default:
|
|
8465
|
+
throw new ValidationError(`Unsupported IPFS provider: ${credentials.provider}`);
|
|
8466
|
+
}
|
|
8467
|
+
}
|
|
8468
|
+
/**
|
|
8469
|
+
* Save IPFS credentials for large file uploads.
|
|
8470
|
+
* Users can configure their own IPFS pinning service (Pinata, Infura, or web3.storage).
|
|
8471
|
+
* @param credentials The IPFS credentials to save.
|
|
8472
|
+
* @throws {APIError} If saving credentials fails.
|
|
8473
|
+
* @example
|
|
8474
|
+
* ```typescript
|
|
8475
|
+
* // Save Pinata credentials
|
|
8476
|
+
* await origin.saveIpfsCredentials({
|
|
8477
|
+
* provider: 'pinata',
|
|
8478
|
+
* jwt: 'your-pinata-jwt-token'
|
|
8479
|
+
* });
|
|
8480
|
+
*
|
|
8481
|
+
* // Save Infura credentials
|
|
8482
|
+
* await origin.saveIpfsCredentials({
|
|
8483
|
+
* provider: 'infura',
|
|
8484
|
+
* projectId: 'your-project-id',
|
|
8485
|
+
* projectSecret: 'your-project-secret'
|
|
8486
|
+
* });
|
|
8487
|
+
* ```
|
|
8488
|
+
*/
|
|
8489
|
+
function saveIpfsCredentials(credentials) {
|
|
8490
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8491
|
+
if (!this.jwt) {
|
|
8492
|
+
throw new APIError("JWT token required for IPFS credentials management");
|
|
8493
|
+
}
|
|
8494
|
+
// Validate credentials before sending
|
|
8495
|
+
validateIpfsCredentials(credentials);
|
|
8496
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/credentials`, {
|
|
8497
|
+
method: "POST",
|
|
8498
|
+
headers: {
|
|
8499
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8500
|
+
"Content-Type": "application/json",
|
|
8501
|
+
},
|
|
8502
|
+
body: JSON.stringify(credentials),
|
|
8503
|
+
});
|
|
8504
|
+
if (!response.ok) {
|
|
8505
|
+
const errorData = yield response.json().catch(() => ({}));
|
|
8506
|
+
throw new APIError(errorData.message ||
|
|
8507
|
+
`Failed to save IPFS credentials (HTTP ${response.status})`, response.status);
|
|
8508
|
+
}
|
|
8509
|
+
});
|
|
8510
|
+
}
|
|
8511
|
+
/**
|
|
8512
|
+
* Verify that saved IPFS credentials are valid.
|
|
8513
|
+
* @returns Object with valid boolean and optional error message.
|
|
8514
|
+
* @throws {APIError} If verification request fails.
|
|
8515
|
+
*/
|
|
8516
|
+
function verifyIpfsCredentials() {
|
|
8517
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8518
|
+
if (!this.jwt) {
|
|
8519
|
+
throw new APIError("JWT token required for IPFS credentials management");
|
|
8520
|
+
}
|
|
8521
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/credentials/verify`, {
|
|
8522
|
+
method: "POST",
|
|
8523
|
+
headers: {
|
|
8524
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8525
|
+
"Content-Type": "application/json",
|
|
8526
|
+
},
|
|
8527
|
+
});
|
|
8528
|
+
if (!response.ok) {
|
|
8529
|
+
if (response.status === 404) {
|
|
8530
|
+
return { valid: false, error: "No IPFS credentials configured" };
|
|
8531
|
+
}
|
|
8532
|
+
const errorData = yield response.json().catch(() => ({}));
|
|
8533
|
+
throw new APIError(errorData.message ||
|
|
8534
|
+
`Failed to verify IPFS credentials (HTTP ${response.status})`, response.status);
|
|
8535
|
+
}
|
|
8536
|
+
return response.json();
|
|
8537
|
+
});
|
|
8538
|
+
}
|
|
8539
|
+
/**
|
|
8540
|
+
* Delete saved IPFS credentials.
|
|
8541
|
+
* @throws {APIError} If deletion fails.
|
|
8542
|
+
*/
|
|
8543
|
+
function deleteIpfsCredentials() {
|
|
8544
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8545
|
+
if (!this.jwt) {
|
|
8546
|
+
throw new APIError("JWT token required for IPFS credentials management");
|
|
8547
|
+
}
|
|
8548
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/credentials`, {
|
|
8549
|
+
method: "DELETE",
|
|
8550
|
+
headers: {
|
|
8551
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8552
|
+
},
|
|
8553
|
+
});
|
|
8554
|
+
if (!response.ok) {
|
|
8555
|
+
const errorData = yield response.json().catch(() => ({}));
|
|
8556
|
+
throw new APIError(errorData.message ||
|
|
8557
|
+
`Failed to delete IPFS credentials (HTTP ${response.status})`, response.status);
|
|
8558
|
+
}
|
|
8559
|
+
});
|
|
8560
|
+
}
|
|
8561
|
+
/**
|
|
8562
|
+
* Check if user has IPFS credentials configured.
|
|
8563
|
+
* @returns True if credentials are configured, false otherwise.
|
|
8564
|
+
*/
|
|
8565
|
+
function hasIpfsCredentials() {
|
|
8566
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8567
|
+
var _a;
|
|
8568
|
+
if (!this.jwt) {
|
|
8569
|
+
return false;
|
|
8570
|
+
}
|
|
8571
|
+
try {
|
|
8572
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/credentials`, {
|
|
8573
|
+
method: "GET",
|
|
8574
|
+
headers: {
|
|
8575
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8576
|
+
},
|
|
8577
|
+
});
|
|
8578
|
+
if (!response.ok) {
|
|
8579
|
+
return false;
|
|
8580
|
+
}
|
|
8581
|
+
const data = yield response.json();
|
|
8582
|
+
return ((_a = data.data) === null || _a === void 0 ? void 0 : _a.hasCredentials) || false;
|
|
8583
|
+
}
|
|
8584
|
+
catch (_b) {
|
|
8585
|
+
return false;
|
|
8586
|
+
}
|
|
8587
|
+
});
|
|
8588
|
+
}
|
|
8589
|
+
/**
|
|
8590
|
+
* Get IPFS upload config for client-side uploads.
|
|
8591
|
+
* @returns IPFS config or null if not configured.
|
|
8592
|
+
*/
|
|
8593
|
+
function getIpfsUploadConfig() {
|
|
8594
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8595
|
+
if (!this.jwt) {
|
|
8596
|
+
return null;
|
|
8597
|
+
}
|
|
8598
|
+
try {
|
|
8599
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/upload-config`, {
|
|
8600
|
+
method: "GET",
|
|
8601
|
+
headers: {
|
|
8602
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8603
|
+
},
|
|
8604
|
+
});
|
|
8605
|
+
if (!response.ok) {
|
|
8606
|
+
return null;
|
|
8607
|
+
}
|
|
8608
|
+
const result = yield response.json();
|
|
8609
|
+
return result.data || null;
|
|
8610
|
+
}
|
|
8611
|
+
catch (_a) {
|
|
8612
|
+
return null;
|
|
8613
|
+
}
|
|
8614
|
+
});
|
|
8615
|
+
}
|
|
8616
|
+
/**
|
|
8617
|
+
* Upload a file to user's IPFS pinning service.
|
|
8618
|
+
* @param file The file to upload.
|
|
8619
|
+
* @param config The IPFS upload config.
|
|
8620
|
+
* @param progressCallback Optional progress callback with intermediate upload progress.
|
|
8621
|
+
* @returns The IPFS CID of the uploaded file.
|
|
8622
|
+
*/
|
|
8623
|
+
function uploadToUserIPFS(file, config, progressCallback) {
|
|
8624
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8625
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
8626
|
+
// Validate file input
|
|
8627
|
+
if (!file || !(file instanceof File)) {
|
|
8628
|
+
throw new ValidationError("Invalid file: must be a File object");
|
|
8629
|
+
}
|
|
8630
|
+
if (file.size === 0) {
|
|
8631
|
+
throw new ValidationError("Cannot upload empty file");
|
|
8632
|
+
}
|
|
8633
|
+
progressCallback === null || progressCallback === void 0 ? void 0 : progressCallback(0);
|
|
8634
|
+
const onUploadProgress = progressCallback
|
|
8635
|
+
? (progressEvent) => {
|
|
8636
|
+
if (progressEvent.total) {
|
|
8637
|
+
const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100);
|
|
8638
|
+
progressCallback(percent);
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
: undefined;
|
|
8642
|
+
let cid;
|
|
8643
|
+
switch (config.provider) {
|
|
8644
|
+
case "pinata": {
|
|
8645
|
+
const formData = new FormData();
|
|
8646
|
+
formData.append("file", file);
|
|
8647
|
+
const headers = {};
|
|
8648
|
+
if ((_a = config.pinata) === null || _a === void 0 ? void 0 : _a.jwt) {
|
|
8649
|
+
headers["Authorization"] = `Bearer ${config.pinata.jwt}`;
|
|
8650
|
+
}
|
|
8651
|
+
else if (((_b = config.pinata) === null || _b === void 0 ? void 0 : _b.apiKey) && ((_c = config.pinata) === null || _c === void 0 ? void 0 : _c.apiSecret)) {
|
|
8652
|
+
headers["pinata_api_key"] = config.pinata.apiKey;
|
|
8653
|
+
headers["pinata_secret_api_key"] = config.pinata.apiSecret;
|
|
8654
|
+
}
|
|
8655
|
+
try {
|
|
8656
|
+
const response = yield axios.post("https://api.pinata.cloud/pinning/pinFileToIPFS", formData, { headers, onUploadProgress, timeout: 600000 });
|
|
8657
|
+
cid = response.data.IpfsHash;
|
|
8658
|
+
}
|
|
8659
|
+
catch (error) {
|
|
8660
|
+
const status = (_d = error.response) === null || _d === void 0 ? void 0 : _d.status;
|
|
8661
|
+
const message = ((_g = (_f = (_e = error.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.error) === null || _g === void 0 ? void 0 : _g.details) ||
|
|
8662
|
+
((_j = (_h = error.response) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.message) ||
|
|
8663
|
+
error.message;
|
|
8664
|
+
throw new APIError(`Pinata IPFS upload failed: ${message}`, status);
|
|
8665
|
+
}
|
|
8666
|
+
break;
|
|
8667
|
+
}
|
|
8668
|
+
case "infura": {
|
|
8669
|
+
if (!config.infura) {
|
|
8670
|
+
throw new Error("Infura config missing");
|
|
8671
|
+
}
|
|
8672
|
+
const formData = new FormData();
|
|
8673
|
+
formData.append("file", file);
|
|
8674
|
+
const auth = btoa(`${config.infura.projectId}:${config.infura.projectSecret}`);
|
|
8675
|
+
try {
|
|
8676
|
+
const response = yield axios.post(`${config.infura.endpoint}/api/v0/add`, formData, {
|
|
8677
|
+
headers: { Authorization: `Basic ${auth}` },
|
|
8678
|
+
onUploadProgress,
|
|
8679
|
+
timeout: 600000,
|
|
8680
|
+
});
|
|
8681
|
+
cid = response.data.Hash;
|
|
8682
|
+
}
|
|
8683
|
+
catch (error) {
|
|
8684
|
+
const status = (_k = error.response) === null || _k === void 0 ? void 0 : _k.status;
|
|
8685
|
+
const message = ((_m = (_l = error.response) === null || _l === void 0 ? void 0 : _l.data) === null || _m === void 0 ? void 0 : _m.Message) || error.message;
|
|
8686
|
+
throw new APIError(`Infura IPFS upload failed: ${message}`, status);
|
|
8687
|
+
}
|
|
8688
|
+
break;
|
|
8689
|
+
}
|
|
8690
|
+
case "web3storage": {
|
|
8691
|
+
if (!((_o = config.web3storage) === null || _o === void 0 ? void 0 : _o.token)) {
|
|
8692
|
+
throw new Error("web3.storage config missing");
|
|
8693
|
+
}
|
|
8694
|
+
try {
|
|
8695
|
+
const response = yield axios.post("https://api.web3.storage/upload", file, {
|
|
8696
|
+
headers: {
|
|
8697
|
+
Authorization: `Bearer ${config.web3storage.token}`,
|
|
8698
|
+
"X-Name": file.name,
|
|
8699
|
+
},
|
|
8700
|
+
onUploadProgress,
|
|
8701
|
+
timeout: 600000,
|
|
8702
|
+
});
|
|
8703
|
+
cid = response.data.cid;
|
|
8704
|
+
}
|
|
8705
|
+
catch (error) {
|
|
8706
|
+
const status = (_p = error.response) === null || _p === void 0 ? void 0 : _p.status;
|
|
8707
|
+
const message = ((_r = (_q = error.response) === null || _q === void 0 ? void 0 : _q.data) === null || _r === void 0 ? void 0 : _r.message) || error.message;
|
|
8708
|
+
throw new APIError(`web3.storage IPFS upload failed: ${message}`, status);
|
|
8709
|
+
}
|
|
8710
|
+
break;
|
|
8711
|
+
}
|
|
8712
|
+
default:
|
|
8713
|
+
throw new ValidationError(`Unsupported IPFS provider: ${config.provider}. Supported providers: pinata, infura, web3storage`);
|
|
8714
|
+
}
|
|
8715
|
+
if (!cid || typeof cid !== "string") {
|
|
8716
|
+
throw new APIError(`IPFS upload to ${config.provider} succeeded but returned no CID`);
|
|
8717
|
+
}
|
|
8718
|
+
progressCallback === null || progressCallback === void 0 ? void 0 : progressCallback(100);
|
|
8719
|
+
return cid;
|
|
8720
|
+
});
|
|
8721
|
+
}
|
|
8722
|
+
/**
|
|
8723
|
+
* Register an IPFS file with the backend after client-side upload.
|
|
8724
|
+
* @param cid The IPFS CID of the uploaded file.
|
|
8725
|
+
* @param fileName The original file name.
|
|
8726
|
+
* @param fileType The file MIME type.
|
|
8727
|
+
* @returns The registered file key.
|
|
8728
|
+
*/
|
|
8729
|
+
function registerIpfsFile(cid, fileName, fileType) {
|
|
8730
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8731
|
+
if (!this.jwt) {
|
|
8732
|
+
throw new APIError("JWT token required for IPFS file registration");
|
|
8733
|
+
}
|
|
8734
|
+
const response = yield fetch(`${this.environment.AUTH_HUB_BASE_API}/ipfs/register-file`, {
|
|
8735
|
+
method: "POST",
|
|
8736
|
+
headers: {
|
|
8737
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
8738
|
+
"Content-Type": "application/json",
|
|
8739
|
+
},
|
|
8740
|
+
body: JSON.stringify({ cid, fileName, fileType }),
|
|
8741
|
+
});
|
|
8742
|
+
if (!response.ok) {
|
|
8743
|
+
const errorData = yield response.json().catch(() => ({}));
|
|
8744
|
+
throw new APIError(errorData.message ||
|
|
8745
|
+
`Failed to register IPFS file (HTTP ${response.status})`, response.status);
|
|
8746
|
+
}
|
|
8747
|
+
const result = yield response.json();
|
|
8748
|
+
return { fileKey: result.data.fileKey };
|
|
8749
|
+
});
|
|
8750
|
+
}
|
|
8751
|
+
|
|
8446
8752
|
var _Origin_instances, _Origin_generateURL, _Origin_setOriginStatus, _Origin_uploadToIPFS, _Origin_uploadFile, _Origin_waitForTxReceipt, _Origin_ensureChainId, _Origin_getCurrentAccount, _Origin_getProtocolFeeBps, _Origin_getAppFeeBpsForToken, _Origin_resolveWalletAddress;
|
|
8447
8753
|
/**
|
|
8448
8754
|
* The Origin class
|
|
@@ -8516,6 +8822,14 @@ class Origin {
|
|
|
8516
8822
|
this.getRoyaltyTokenBalance = getRoyaltyTokenBalance.bind(this);
|
|
8517
8823
|
// AppRegistry module methods
|
|
8518
8824
|
this.getAppInfo = getAppInfo.bind(this);
|
|
8825
|
+
// IPFS credentials methods
|
|
8826
|
+
this.saveIpfsCredentials = saveIpfsCredentials.bind(this);
|
|
8827
|
+
this.verifyIpfsCredentials = verifyIpfsCredentials.bind(this);
|
|
8828
|
+
this.deleteIpfsCredentials = deleteIpfsCredentials.bind(this);
|
|
8829
|
+
this.hasIpfsCredentials = hasIpfsCredentials.bind(this);
|
|
8830
|
+
this.getIpfsUploadConfig = getIpfsUploadConfig.bind(this);
|
|
8831
|
+
this.uploadToUserIPFS = uploadToUserIPFS.bind(this);
|
|
8832
|
+
this.registerIpfsFile = registerIpfsFile.bind(this);
|
|
8519
8833
|
}
|
|
8520
8834
|
getJwt() {
|
|
8521
8835
|
return this.jwt;
|
|
@@ -8569,7 +8883,7 @@ class Origin {
|
|
|
8569
8883
|
* @param metadata The metadata associated with the file.
|
|
8570
8884
|
* @param license The license terms for the IpNFT.
|
|
8571
8885
|
* @param parents Optional parent token IDs for lineage tracking.
|
|
8572
|
-
* @param options Optional parameters including progress callback, preview image,
|
|
8886
|
+
* @param options Optional parameters including progress callback, preview image, use asset as preview flag, and forceIpfs.
|
|
8573
8887
|
* @returns The token ID of the minted IpNFT as a string, or null if minting failed.
|
|
8574
8888
|
*/
|
|
8575
8889
|
mintFile(file, metadata, license, parents, options) {
|
|
@@ -8581,17 +8895,37 @@ class Origin {
|
|
|
8581
8895
|
catch (error) {
|
|
8582
8896
|
throw new WalletError(`Cannot mint file "${file.name}": wallet not connected. Please connect a wallet first.`);
|
|
8583
8897
|
}
|
|
8898
|
+
// Check if we should use IPFS for this file
|
|
8899
|
+
const shouldUseIpfs = (options === null || options === void 0 ? void 0 : options.forceIpfs) || file.size > constants.MAX_FILE_SIZE;
|
|
8584
8900
|
let info;
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8901
|
+
if (shouldUseIpfs) {
|
|
8902
|
+
// Large file - use user's IPFS pinning service
|
|
8903
|
+
const ipfsConfig = yield this.getIpfsUploadConfig();
|
|
8904
|
+
if (!ipfsConfig) {
|
|
8905
|
+
throw new APIError(`File "${file.name}" exceeds 20MB limit. Please configure your IPFS pinning service in Settings to upload large files.`);
|
|
8906
|
+
}
|
|
8907
|
+
try {
|
|
8908
|
+
const cid = yield this.uploadToUserIPFS(file, ipfsConfig, options === null || options === void 0 ? void 0 : options.progressCallback);
|
|
8909
|
+
const { fileKey } = yield this.registerIpfsFile(cid, file.name, file.type);
|
|
8910
|
+
info = { key: fileKey, uploadId: "" };
|
|
8911
|
+
}
|
|
8912
|
+
catch (error) {
|
|
8913
|
+
throw new APIError(`Failed to upload file "${file.name}" to IPFS: ${getErrorMessage(error)}`);
|
|
8589
8914
|
}
|
|
8590
8915
|
}
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8916
|
+
else {
|
|
8917
|
+
// Normal file - use S3
|
|
8918
|
+
try {
|
|
8919
|
+
info = yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_uploadFile).call(this, file, options);
|
|
8920
|
+
if (!info || !info.key) {
|
|
8921
|
+
throw new APIError(`Failed to upload file "${file.name}": no upload info returned from server`);
|
|
8922
|
+
}
|
|
8923
|
+
}
|
|
8924
|
+
catch (error) {
|
|
8925
|
+
if (error instanceof APIError || error instanceof WalletError)
|
|
8926
|
+
throw error;
|
|
8927
|
+
throw new APIError(`Failed to upload file "${file.name}": ${getErrorMessage(error)}`);
|
|
8928
|
+
}
|
|
8595
8929
|
}
|
|
8596
8930
|
if (file.type) {
|
|
8597
8931
|
metadata.mimetype = file.type;
|
|
@@ -8607,7 +8941,7 @@ class Origin {
|
|
|
8607
8941
|
if (previewImageIpfsHash) {
|
|
8608
8942
|
metadata.image = `ipfs://${previewImageIpfsHash}`;
|
|
8609
8943
|
}
|
|
8610
|
-
const deadline = BigInt(Date.now() +
|
|
8944
|
+
const deadline = BigInt(Math.floor(Date.now() / 1000) + 600); // 10 minutes from now
|
|
8611
8945
|
if (this.baseParentId) {
|
|
8612
8946
|
if (!parents) {
|
|
8613
8947
|
parents = [];
|
|
@@ -8621,7 +8955,10 @@ class Origin {
|
|
|
8621
8955
|
parents, this.appId);
|
|
8622
8956
|
}
|
|
8623
8957
|
catch (error) {
|
|
8624
|
-
|
|
8958
|
+
// Only update S3 status if we have an uploadId (non-IPFS flow)
|
|
8959
|
+
if (info.uploadId) {
|
|
8960
|
+
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
8961
|
+
}
|
|
8625
8962
|
throw new Error(`Failed to register IpNFT: ${error instanceof Error ? error.message : String(error)}`);
|
|
8626
8963
|
}
|
|
8627
8964
|
const { tokenId, signerAddress, creatorContentHash, signature, uri } = registration;
|
|
@@ -8635,12 +8972,18 @@ class Origin {
|
|
|
8635
8972
|
try {
|
|
8636
8973
|
const mintResult = yield this.mintWithSignature(account, tokenId, parents || [], true, creatorContentHash, uri, license, deadline, signature, this.appId);
|
|
8637
8974
|
if (["0x1", "success"].indexOf(mintResult.receipt.status) === -1) {
|
|
8638
|
-
|
|
8975
|
+
// Only update S3 status if we have an uploadId (non-IPFS flow)
|
|
8976
|
+
if (info.uploadId) {
|
|
8977
|
+
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
8978
|
+
}
|
|
8639
8979
|
throw new Error(`Minting failed with status: ${mintResult.receipt.status}`);
|
|
8640
8980
|
}
|
|
8641
8981
|
}
|
|
8642
8982
|
catch (error) {
|
|
8643
|
-
|
|
8983
|
+
// Only update S3 status if we have an uploadId (non-IPFS flow)
|
|
8984
|
+
if (info.uploadId) {
|
|
8985
|
+
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
8986
|
+
}
|
|
8644
8987
|
throw new Error(`Minting transaction failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
8645
8988
|
}
|
|
8646
8989
|
return tokenId.toString();
|
|
@@ -8687,10 +9030,15 @@ class Origin {
|
|
|
8687
9030
|
const { file, metadata, license } = entry;
|
|
8688
9031
|
let { parents } = entry;
|
|
8689
9032
|
// Upload file
|
|
9033
|
+
const shouldUseIpfs = (options === null || options === void 0 ? void 0 : options.forceIpfs) || file.size > constants.MAX_FILE_SIZE;
|
|
8690
9034
|
let info;
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
9035
|
+
if (shouldUseIpfs) {
|
|
9036
|
+
const ipfsConfig = yield this.getIpfsUploadConfig();
|
|
9037
|
+
if (!ipfsConfig) {
|
|
9038
|
+
throw new APIError(`File "${file.name}" exceeds 20MB limit. Please configure your IPFS pinning service in Settings to upload large files.`);
|
|
9039
|
+
}
|
|
9040
|
+
try {
|
|
9041
|
+
const cid = yield this.uploadToUserIPFS(file, ipfsConfig, (percent) => {
|
|
8694
9042
|
var _a;
|
|
8695
9043
|
(_a = options === null || options === void 0 ? void 0 : options.progressCallback) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
8696
9044
|
fileIndex: i,
|
|
@@ -8698,16 +9046,38 @@ class Origin {
|
|
|
8698
9046
|
stage: "uploading",
|
|
8699
9047
|
percent,
|
|
8700
9048
|
});
|
|
8701
|
-
}
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
9049
|
+
});
|
|
9050
|
+
const { fileKey } = yield this.registerIpfsFile(cid, file.name, file.type);
|
|
9051
|
+
info = { key: fileKey, uploadId: "" };
|
|
9052
|
+
}
|
|
9053
|
+
catch (error) {
|
|
9054
|
+
if (error instanceof APIError)
|
|
9055
|
+
throw error;
|
|
9056
|
+
throw new APIError(`Failed to upload file "${file.name}" to IPFS: ${getErrorMessage(error)}`);
|
|
8705
9057
|
}
|
|
8706
9058
|
}
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
9059
|
+
else {
|
|
9060
|
+
try {
|
|
9061
|
+
info = yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_uploadFile).call(this, file, {
|
|
9062
|
+
progressCallback: (percent) => {
|
|
9063
|
+
var _a;
|
|
9064
|
+
(_a = options === null || options === void 0 ? void 0 : options.progressCallback) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
9065
|
+
fileIndex: i,
|
|
9066
|
+
fileCount: entries.length,
|
|
9067
|
+
stage: "uploading",
|
|
9068
|
+
percent,
|
|
9069
|
+
});
|
|
9070
|
+
},
|
|
9071
|
+
});
|
|
9072
|
+
if (!info || !info.key) {
|
|
9073
|
+
throw new APIError(`Failed to upload file "${file.name}": no upload info returned from server`);
|
|
9074
|
+
}
|
|
9075
|
+
}
|
|
9076
|
+
catch (error) {
|
|
9077
|
+
if (error instanceof APIError || error instanceof WalletError)
|
|
9078
|
+
throw error;
|
|
9079
|
+
throw new APIError(`Failed to upload file "${file.name}": ${getErrorMessage(error)}`);
|
|
9080
|
+
}
|
|
8711
9081
|
}
|
|
8712
9082
|
uploadInfos.push(info);
|
|
8713
9083
|
// Set mimetype
|
|
@@ -8725,7 +9095,7 @@ class Origin {
|
|
|
8725
9095
|
if (previewImageIpfsHash) {
|
|
8726
9096
|
metadata.image = `ipfs://${previewImageIpfsHash}`;
|
|
8727
9097
|
}
|
|
8728
|
-
const deadline = BigInt(Date.now() +
|
|
9098
|
+
const deadline = BigInt(Math.floor(Date.now() / 1000) + 600); // 10 minutes from now
|
|
8729
9099
|
// Prepare parents
|
|
8730
9100
|
if (this.baseParentId) {
|
|
8731
9101
|
if (!parents) {
|
|
@@ -8747,12 +9117,16 @@ class Origin {
|
|
|
8747
9117
|
parents, this.appId);
|
|
8748
9118
|
}
|
|
8749
9119
|
catch (error) {
|
|
8750
|
-
|
|
9120
|
+
if (info.uploadId) {
|
|
9121
|
+
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
9122
|
+
}
|
|
8751
9123
|
throw new Error(`Failed to register IpNFT for file "${file.name}": ${error instanceof Error ? error.message : String(error)}`);
|
|
8752
9124
|
}
|
|
8753
9125
|
const { tokenId, creatorContentHash, signature, uri } = registration;
|
|
8754
9126
|
if (!tokenId || !creatorContentHash || signature === undefined || !uri) {
|
|
8755
|
-
|
|
9127
|
+
if (info.uploadId) {
|
|
9128
|
+
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
9129
|
+
}
|
|
8756
9130
|
throw new Error(`Failed to register IpNFT for file "${file.name}": Missing required fields in registration response.`);
|
|
8757
9131
|
}
|
|
8758
9132
|
tokenIds.push(tokenId.toString());
|
|
@@ -8781,8 +9155,10 @@ class Origin {
|
|
|
8781
9155
|
return { tokenIds, result };
|
|
8782
9156
|
}
|
|
8783
9157
|
catch (error) {
|
|
8784
|
-
// Mark all uploads as failed
|
|
9158
|
+
// Mark all S3 uploads as failed (skip IPFS entries with no uploadId)
|
|
8785
9159
|
for (const info of uploadInfos) {
|
|
9160
|
+
if (!info.uploadId)
|
|
9161
|
+
continue;
|
|
8786
9162
|
try {
|
|
8787
9163
|
yield __classPrivateFieldGet(this, _Origin_instances, "m", _Origin_setOriginStatus).call(this, info.key, info.uploadId, []);
|
|
8788
9164
|
}
|