Skip to content

Commit f0d0f37

Browse files
committed
[Update] Fix baseURI extraction logic and refactor lazy mint form (#4447)
FIXES: DASH-210 <!-- start pr-codex --> ## PR-Codex overview The focus of this PR is to fix the baseURI extraction logic in the `lazy-mint-form.tsx` file. ### Detailed summary - Removed unnecessary `upload` function calls for image and animation URLs - Updated data processing logic in `LazyMintNftForm` - Refactored `getBaseUriFromBatch` function for URI extraction - Added tests for `getBaseUriFromBatch` function > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent f39e1ba commit f0d0f37

File tree

4 files changed

+85
-37
lines changed

4 files changed

+85
-37
lines changed

.changeset/flat-ads-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
fix baseURI extraction logic

apps/dashboard/src/contract-ui/tabs/nfts/components/lazy-mint-form.tsx

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { thirdwebClient } from "@/constants/client";
21
import {
32
Accordion,
43
AccordionButton,
@@ -28,7 +27,6 @@ import type { ThirdwebContract } from "thirdweb";
2827
import { lazyMint as lazyMint721 } from "thirdweb/extensions/erc721";
2928
import { lazyMint as lazyMint1155 } from "thirdweb/extensions/erc1155";
3029
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
31-
import { upload } from "thirdweb/storage";
3230
import {
3331
Button,
3432
FormErrorMessage,
@@ -156,32 +154,13 @@ export const LazyMintNftForm: React.FC<LazyMintNftFormParams> = ({
156154
onError("Please connect your wallet to mint.");
157155
return;
158156
}
159-
let imageUri = "";
160-
if (data.image) {
161-
imageUri = await upload({
162-
client: thirdwebClient,
163-
files: [data.image],
164-
});
165-
}
166-
let animationUri = "";
167-
if (data.animation_url) {
168-
animationUri = await upload({
169-
client: thirdwebClient,
170-
files: [data.animation_url],
171-
});
172-
}
173-
const dataWithCustom = {
174-
...data,
175-
image: imageUri || data.customImage,
176-
animation_url: animationUri || data.customAnimationUrl,
177-
};
178157

179158
trackEvent({
180159
category: "nft",
181160
action: "lazy-mint",
182161
label: "attempt",
183162
});
184-
const nfts = [parseAttributes(dataWithCustom)];
163+
const nfts = [parseAttributes(data)];
185164
const transaction = isErc721
186165
? lazyMint721({ contract, nfts })
187166
: lazyMint1155({ contract, nfts });

packages/thirdweb/src/utils/ipfs.test.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { describe, expect, it } from "vitest";
22
import { createThirdwebClient } from "../client/client.js";
3-
import { findIPFSCidFromUri, resolveScheme } from "./ipfs.js";
3+
import {
4+
findIPFSCidFromUri,
5+
getBaseUriFromBatch,
6+
resolveScheme,
7+
} from "./ipfs.js";
48

59
describe("resolveScheme", () => {
610
it("should resolve ipfs scheme when not passing a gateway override", () => {
@@ -70,3 +74,55 @@ describe("resolveScheme", () => {
7074
expect(findIPFSCidFromUri(uri)).toBe(cid);
7175
});
7276
});
77+
78+
describe("getBaseUriFromBatch", () => {
79+
it("should return the base uri", () => {
80+
const batchOfUris = ["ipfs://Qm.../0", "ipfs://Qm.../1", "ipfs://Qm.../2"];
81+
const baseUri = getBaseUriFromBatch(batchOfUris);
82+
expect(baseUri).toMatchInlineSnapshot(`"ipfs://Qm.../"`);
83+
});
84+
it("should throw if the batch is empty", () => {
85+
expect(() => getBaseUriFromBatch([])).toThrowErrorMatchingInlineSnapshot(
86+
"[Error: Batch of URIs is empty]",
87+
);
88+
});
89+
90+
it("should throw if an element of the array does not have the same base", () => {
91+
const batchOfUris = ["ipfs://Qm.../0", "ipfs://Qm.../1", "ipfs://Qm2.../2"];
92+
expect(() =>
93+
getBaseUriFromBatch(batchOfUris),
94+
).toThrowErrorMatchingInlineSnapshot(
95+
"[Error: All URIs in the batch must have the same base URI]",
96+
);
97+
});
98+
99+
it("should work with a custom domain", () => {
100+
const batchOfUris = [
101+
"https://example.com/0",
102+
"https://example.com/1",
103+
"https://example.com/2",
104+
];
105+
const baseUri = getBaseUriFromBatch(batchOfUris);
106+
expect(baseUri).toMatchInlineSnapshot(`"https://example.com/"`);
107+
});
108+
109+
it("should work with a custom domain and path", () => {
110+
const batchOfUris = [
111+
"https://example.com/path/0",
112+
"https://example.com/path/1",
113+
"https://example.com/path/2",
114+
];
115+
const baseUri = getBaseUriFromBatch(batchOfUris);
116+
expect(baseUri).toMatchInlineSnapshot(`"https://example.com/path/"`);
117+
});
118+
119+
it("should work with a custom domain and path with trailing slash", () => {
120+
const batchOfUris = [
121+
"https://example.com/path/0/",
122+
"https://example.com/path/1/",
123+
"https://example.com/path/2/",
124+
];
125+
const baseUri = getBaseUriFromBatch(batchOfUris);
126+
expect(baseUri).toMatchInlineSnapshot(`"https://example.com/path/"`);
127+
});
128+
});

packages/thirdweb/src/utils/ipfs.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { ThirdwebClient } from "../client/client.js";
2-
32
import type { FileOrBufferOrString } from "../storage/upload/types.js";
43

54
export type ResolveSchemeOptions = {
@@ -109,23 +108,32 @@ export async function uploadOrExtractURIs<
109108
* @internal
110109
*/
111110
export function getBaseUriFromBatch(uris: string[]): string {
112-
const urisWithSlashes = uris.map((uri) => new URL(uri));
113-
const baseUri = urisWithSlashes[0];
114-
for (let i = 0; i < urisWithSlashes.length; i++) {
115-
const uri = urisWithSlashes[i];
116-
if (baseUri?.host !== uri?.host) {
117-
throw new Error(
118-
`Can only create batches with the same base URI for every entry in the batch. Expected '${baseUri}' but got '${uri}'`,
119-
);
111+
const [base, ...rest] = uris.map((uri) => {
112+
// remove query parameters
113+
// biome-ignore lint/style/noParameterAssign: lemme do my stuff
114+
[uri] = uri.split("?") as [string];
115+
// remove fragments
116+
// biome-ignore lint/style/noParameterAssign: lemme do my stuff
117+
[uri] = uri.split("#") as [string];
118+
119+
// if the URI ends with a `/`, remove it
120+
if (uri.endsWith("/")) {
121+
// biome-ignore lint/style/noParameterAssign: lemme do my stuff
122+
uri = uri.slice(0, -1);
120123
}
121-
}
122124

123-
if (!baseUri) {
124-
throw new Error("No base URI found in the batch");
125+
// remove the last part of the URI & add the trailing `/`
126+
return `${uri.split("/").slice(0, -1).join("/")}/`;
127+
});
128+
129+
if (!base) {
130+
throw new Error("Batch of URIs is empty");
125131
}
126132

127-
// Ensure that baseUri ends with trailing slash
128-
return `${baseUri.protocol}//${baseUri.host}/`;
133+
if (rest.some((uri) => uri !== base)) {
134+
throw new Error("All URIs in the batch must have the same base URI");
135+
}
136+
return base;
129137
}
130138

131139
function isUriList<T extends FileOrBufferOrString | Record<string, unknown>>(

0 commit comments

Comments
 (0)