@zoralabs/protocol-sdk 0.7.0 → 0.7.1
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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +6 -0
- package/dist/index.cjs +1169 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1162 -11
- package/dist/index.js.map +1 -1
- package/dist/ipfs/arweave.d.ts +3 -0
- package/dist/ipfs/arweave.d.ts.map +1 -0
- package/dist/ipfs/gateway.d.ts +4 -0
- package/dist/ipfs/gateway.d.ts.map +1 -0
- package/dist/ipfs/index.d.ts +4 -0
- package/dist/ipfs/index.d.ts.map +1 -0
- package/dist/ipfs/ipfs.d.ts +5 -0
- package/dist/ipfs/ipfs.d.ts.map +1 -0
- package/dist/ipfs/mimeTypes.d.ts +25 -0
- package/dist/ipfs/mimeTypes.d.ts.map +1 -0
- package/dist/ipfs/text-metadata.d.ts +5 -0
- package/dist/ipfs/text-metadata.d.ts.map +1 -0
- package/dist/ipfs/token-metadata.d.ts +14 -0
- package/dist/ipfs/token-metadata.d.ts.map +1 -0
- package/dist/ipfs/types.d.ts +49 -0
- package/dist/ipfs/types.d.ts.map +1 -0
- package/dist/premint/premint-client.d.ts +2 -1
- package/dist/premint/premint-client.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +2 -0
- package/src/ipfs/arweave.ts +5 -0
- package/src/ipfs/gateway.ts +48 -0
- package/src/ipfs/index.ts +7 -0
- package/src/ipfs/ipfs.ts +82 -0
- package/src/ipfs/mimeTypes.ts +141 -0
- package/src/ipfs/text-metadata.ts +128 -0
- package/src/ipfs/token-metadata.ts +99 -0
- package/src/ipfs/types.ts +54 -0
- package/src/premint/premint-client.ts +9 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arweave.d.ts","sourceRoot":"","sources":["../../src/ipfs/arweave.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,QAAQ,MAAM,EAAE,CAAC;AAE1C,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEpE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function arweaveGatewayUrl(normalizedArweaveUrl: string | null): string | null;
|
|
2
|
+
export declare function ipfsGatewayUrl(url: string | null): string | null;
|
|
3
|
+
export declare function getFetchableUrl(uri: string | null | undefined): string | null;
|
|
4
|
+
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/ipfs/gateway.ts"],"names":[],"mappings":"AAOA,wBAAgB,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,iBAIpE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,iBAOhD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAyB7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ipfs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAE/D,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type IPFSUrl = `ipfs://${string}`;
|
|
2
|
+
export declare function isCID(str: string | null | undefined): boolean;
|
|
3
|
+
export declare function normalizeIPFSUrl(url: string | null | undefined): IPFSUrl | null;
|
|
4
|
+
export declare function isNormalizeableIPFSUrl(url: string | null | undefined): boolean;
|
|
5
|
+
//# sourceMappingURL=ipfs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipfs.d.ts","sourceRoot":"","sources":["../../src/ipfs/ipfs.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,OAAO,GAAG,UAAU,MAAM,EAAE,CAAC;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAU7D;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7B,OAAO,GAAG,IAAI,CAgChB;AA2BD,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC7B,OAAO,CAET"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const TEXT_PLAIN = "text/plain";
|
|
2
|
+
export declare const isImage: (mimeType: string | null | undefined) => boolean;
|
|
3
|
+
export declare enum MediaType {
|
|
4
|
+
CSV = "CSV",
|
|
5
|
+
NUMBERS = "NUMBERS",
|
|
6
|
+
EXCEL = "EXCEL",
|
|
7
|
+
IMAGE = "IMAGE",
|
|
8
|
+
VIDEO = "VIDEO",
|
|
9
|
+
AUDIO = "AUDIO",
|
|
10
|
+
TIFF = "TIFF",
|
|
11
|
+
TEXT = "TEXT",
|
|
12
|
+
PDF = "PDF",
|
|
13
|
+
MODEL = "MODEL",
|
|
14
|
+
HTML = "HTML",
|
|
15
|
+
ZIP = "ZIP",
|
|
16
|
+
UNKNOWN = "UNKNOWN"
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_THUMBNAIL_CID_HASHES: {
|
|
19
|
+
[key: string]: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const JSON_MIME_TYPE = "application/json";
|
|
22
|
+
/** Return a MediaType for the given mime type. If mime type is unknown you can provide a filename as a fallback, where the type will be guessed based on extension. */
|
|
23
|
+
export declare function mimeTypeToMedia(mimeType?: string | null): MediaType;
|
|
24
|
+
export declare function getMimeType(uri?: string): Promise<string | null | undefined>;
|
|
25
|
+
//# sourceMappingURL=mimeTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mimeTypes.d.ts","sourceRoot":"","sources":["../../src/ipfs/mimeTypes.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,eAAe,CAAC;AAevC,eAAO,MAAM,OAAO,aAAc,MAAM,GAAG,IAAI,GAAG,SAAS,YAG1D,CAAC;AAEF,oBAAY,SAAS;IACnB,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,IAAI,SAAS;IACb,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,KAAK,UAAU;IACf,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,OAAO,YAAY;CACpB;AAED,eAAO,MAAM,4BAA4B,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAYjE,CAAC;AA2BF,eAAO,MAAM,cAAc,qBAAqB,CAAC;AA4CjD,uKAAuK;AACvK,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,aAOvD;AAED,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,sCAM7C"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { TextMetadataFiles } from "./types";
|
|
2
|
+
/** For text nfts, this will generate files that are needed for the metadata json, including the txt.file containing the text, and a thumbnail image containing a preview of the text
|
|
3
|
+
*/
|
|
4
|
+
export declare function generateTextNftMetadataFiles(text: string): Promise<TextMetadataFiles>;
|
|
5
|
+
//# sourceMappingURL=text-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-metadata.d.ts","sourceRoot":"","sources":["../../src/ipfs/text-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAiH5C;GACG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAU5B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { MakeMediaMetadataParams, MakeTextMetadataParams, TokenMetadataJson } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Takes properties for a text based nft and formats it as proper json metadata
|
|
4
|
+
* for the token, which should be uploaded to IPFS.
|
|
5
|
+
* @param parameters - The parameters to format into metadata {@link MakeTextMetadataParams}
|
|
6
|
+
*/
|
|
7
|
+
export declare const makeTextTokenMetadata: (parameters: MakeTextMetadataParams) => TokenMetadataJson;
|
|
8
|
+
/**
|
|
9
|
+
* Takes properties for a media based nft (video, image, etc) and formats it as proper json metadata
|
|
10
|
+
* for the token, which should be uploaded to IPFS.
|
|
11
|
+
* @param parameters - The parameters to format into metadata {@link MakeMediaMetadataParams}
|
|
12
|
+
*/
|
|
13
|
+
export declare const makeMediaTokenMetadata: ({ name, description, attributes, mediaUrl, thumbnailUrl, }: MakeMediaMetadataParams) => Promise<TokenMetadataJson>;
|
|
14
|
+
//# sourceMappingURL=token-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-metadata.d.ts","sourceRoot":"","sources":["../../src/ipfs/token-metadata.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,eACpB,sBAAsB,KACjC,iBAoBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,+DAMhC,uBAAuB,KAAG,QAAQ,iBAAiB,CA4CrD,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type CreateERC1155TokenAttributes = {
|
|
2
|
+
trait_type: string;
|
|
3
|
+
value: string;
|
|
4
|
+
};
|
|
5
|
+
export type ContractMetadataJson = {
|
|
6
|
+
name?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
image?: string;
|
|
9
|
+
};
|
|
10
|
+
export type TokenMetadataJson = {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Primary image file */
|
|
14
|
+
image?: string;
|
|
15
|
+
animation_url?: string | null;
|
|
16
|
+
content?: {
|
|
17
|
+
mime: string;
|
|
18
|
+
uri: string;
|
|
19
|
+
} | null;
|
|
20
|
+
attributes: Array<CreateERC1155TokenAttributes>;
|
|
21
|
+
};
|
|
22
|
+
export type BaseMetadataParams = {
|
|
23
|
+
/** Token name */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Optional description */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** Optional attributes to tag the token with */
|
|
28
|
+
attributes?: CreateERC1155TokenAttributes[];
|
|
29
|
+
};
|
|
30
|
+
export type MakeTextMetadataParams = BaseMetadataParams & {
|
|
31
|
+
/** Ipfs url where media is hosted */
|
|
32
|
+
textFileUrl: string;
|
|
33
|
+
/** If thumbnail was generate for text file, thumbnail image url */
|
|
34
|
+
thumbnailUrl?: string;
|
|
35
|
+
};
|
|
36
|
+
export type TextMetadataFiles = {
|
|
37
|
+
name: string;
|
|
38
|
+
/** File that holds the text, and is the primary media */
|
|
39
|
+
mediaUrlFile: File;
|
|
40
|
+
/** Thumbnail image preview of the text */
|
|
41
|
+
thumbnailFile: File;
|
|
42
|
+
};
|
|
43
|
+
export type MakeMediaMetadataParams = BaseMetadataParams & {
|
|
44
|
+
/** Ipfs url where media is hosted */
|
|
45
|
+
mediaUrl: string;
|
|
46
|
+
/** Ipfs url where thumbnail of media is hosted */
|
|
47
|
+
thumbnailUrl?: string;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ipfs/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,IAAI,CAAC;IACT,UAAU,EAAE,KAAK,CAAC,4BAA4B,CAAC,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,CAAC,EAAE,4BAA4B,EAAE,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,GAAG;IACxD,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,YAAY,EAAE,IAAI,CAAC;IACnB,0CAA0C;IAC1C,aAAa,EAAE,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,GAAG;IACzD,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC"}
|
|
@@ -9,7 +9,7 @@ import { MakeMintParametersArgumentsBase, MakePremintMintParametersArguments, Mi
|
|
|
9
9
|
import { PremintFromApi } from "./conversions";
|
|
10
10
|
import { SimulateContractParametersWithAccount } from "src/types";
|
|
11
11
|
type PremintedV2LogType = DecodeEventLogReturnType<typeof zoraCreator1155PremintExecutorImplABI, "PremintedV2">["args"];
|
|
12
|
-
type URLSReturnType = {
|
|
12
|
+
export type URLSReturnType = {
|
|
13
13
|
explorer: null | string;
|
|
14
14
|
zoraCollect: null | string;
|
|
15
15
|
zoraManage: null | string;
|
|
@@ -1520,6 +1520,7 @@ type PremintReturn<T extends PremintConfigVersion> = {
|
|
|
1520
1520
|
signAndSubmit: (params: SignAndSubmitParams) => Promise<SignAndSubmitReturn>;
|
|
1521
1521
|
/** For the case where the premint is signed externally, takes the signature for the Premint, and submits it and the Premint to the Zora Premint API */
|
|
1522
1522
|
submit: (params: SubmitParams) => Promise<void>;
|
|
1523
|
+
urls: URLSReturnType;
|
|
1523
1524
|
} & PremintConfigWithVersion<T>;
|
|
1524
1525
|
/** CREATE */
|
|
1525
1526
|
type CreatePremintParameters = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"premint-client.d.ts","sourceRoot":"","sources":["../../src/premint/premint-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,OAAO,EACP,GAAG,EACH,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACb,MAAM,MAAM,CAAC;AACd,OAAO,EACL,uBAAuB,EAGvB,qCAAqC,EACtC,MAAM,gCAAgC,CAAC;AAgBxC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EAGzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,MAAM,CAAC;AAGrD,OAAO,EAGL,YAAY,EACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,+BAA+B,EAChC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,+BAA+B,EAC/B,kCAAkC,EAClC,SAAS,EACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,qCAAqC,EAAE,MAAM,WAAW,CAAC;AAElE,KAAK,kBAAkB,GAAG,wBAAwB,CAChD,OAAO,qCAAqC,EAC5C,aAAa,CACd,CAAC,MAAM,CAAC,CAAC;AAEV,
|
|
1
|
+
{"version":3,"file":"premint-client.d.ts","sourceRoot":"","sources":["../../src/premint/premint-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,OAAO,EACP,GAAG,EACH,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,EACb,MAAM,MAAM,CAAC;AACd,OAAO,EACL,uBAAuB,EAGvB,qCAAqC,EACtC,MAAM,gCAAgC,CAAC;AAgBxC,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EAGzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,MAAM,CAAC;AAGrD,OAAO,EAGL,YAAY,EACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,+BAA+B,EAChC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,+BAA+B,EAC/B,kCAAkC,EAClC,SAAS,EACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,qCAAqC,EAAE,MAAM,WAAW,CAAC;AAElE,KAAK,kBAAkB,GAAG,wBAAwB,CAChD,OAAO,qCAAqC,EAC5C,aAAa,CACd,CAAC,MAAM,CAAC,CAAC;AAEV,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC;IACxB,WAAW,EAAE,IAAI,GAAG,MAAM,CAAC;IAC3B,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,iCAAiC,QAAO,KACnD,qBAAqB,EACrB,kBAAkB,GAAG,UAAU,GAAG,kBAAkB,CASpD,CAAC;AA2CH,eAAO,MAAM,iCAAiC,QAAO,KACnD,qBAAqB,EACrB,kBAAkB,GAAG,UAAU,GAAG,iBAAiB,GAAG,gBAAgB,CAQtE,CAAC;AAEH,KAAK,gBAAgB,GAAG;IACtB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,iJAAiJ;IACjJ,eAAe,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qGAAqG;IACrG,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,2GAA2G;IAC3G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oIAAoI;IACpI,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0HAA0H;IAC1H,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4GAA4G;IAC5G,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAuCF;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,kBAAkB,GAC1B,kBAAkB,GAAG,SAAS,CAahC;AACD;;GAEG;AACH,qBAAa,aAAa;IACxB,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,EACV,OAAO,EACP,YAAY,EACZ,UAAU,GACX,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,EAAE,WAAW,CAAC;KACzB;IAMD,yBAAyB,CACvB,OAAO,EAAE,kBAAkB,EAC3B,gBAAgB,CAAC,EAAE,MAAM;;;;;;;;;;;;;IAK3B;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAS3E;;;;;OAKG;IACG,aAAa,CACjB,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAS9B;;;;;OAKG;IACG,aAAa,CACjB,UAAU,EAAE,uBAAuB,GAClC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAS9B;;;;;;OAMG;IACG,UAAU,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;;;;;;;IAOpE;;;;OAIG;IACG,oBAAoB,CAAC,UAAU,EAAE,sBAAsB;IAOvD,YAAY,CAAC,EACjB,aAAa,EACb,cAAc,EACd,aAAa,GACd,EAAE;QACD,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,OAAO,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,SAAS,CAAC;IAStB;;;;;;OAMG;IACG,kBAAkB,CAAC,EACvB,aAAa,EACb,aAAa,EACb,GAAG,EACH,aAAa,EACb,WAAW,GACZ,EAAE,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAc/B;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,gBAAgB,CAAC,EAAE,MAAM;;;;;;;;;;;;EAc1B;AAQD,4BAA4B;AAE5B,MAAM,MAAM,mBAAmB,GAAG;IAChC,gDAAgD;IAChD,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,oBAAoB,CAAC;AAEzB,MAAM,MAAM,mBAAmB,GAAG;IAChC,oCAAoC;IACpC,SAAS,EAAE,GAAG,CAAC;IACf,0CAA0C;IAC1C,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC5B;IACE,gFAAgF;IAChF,cAAc,EAAE,IAAI,CAAC;IACrB,sCAAsC;IACtC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;CAC5B,GACD;IACE,gFAAgF;IAChF,cAAc,CAAC,EAAE,KAAK,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;CAC7B,CAAC;AAEN,MAAM,MAAM,YAAY,GAAG;IACzB,mCAAmC;IACnC,SAAS,EAAE,GAAG,CAAC;CAChB,GAAG,oBAAoB,CAAC;AAEzB,KAAK,aAAa,CAAC,CAAC,SAAS,oBAAoB,IAAI;IACnD,gFAAgF;IAChF,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,0DAA0D;IAC1D,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kFAAkF;IAClF,aAAa,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC7E,uJAAuJ;IACvJ,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,EAAE,cAAc,CAAC;CACtB,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAC;AAqHhC,aAAa;AAEb,KAAK,uBAAuB,GAAG;IAC7B,2GAA2G;IAC3G,KAAK,EAAE,gBAAgB,CAAC;IACxB,uFAAuF;IACvF,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,+BAA+B,CAAC;AAwFpC,aAAa;AAEb,MAAM,MAAM,mBAAmB,GAAG;IAChC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,kBAAkB,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAClD,CAAC;AAwCF,aAAa;AAEb,MAAM,MAAM,mBAAmB,GAAG;IAChC,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,UAAU,EAAE,OAAO,CAAC;CACrB,CAAC;AAuCF,MAAM,MAAM,2BAA2B,GAAG;IACxC,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,+BAA+B;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,kCAAkC;IAClC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC;IACjC,uBAAuB;IACvB,aAAa,CAAC,EAAE;QACd,iCAAiC;QACjC,cAAc,EAAE,MAAM,CAAC;QACvB,iCAAiC;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kDAAkD;QAClD,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,2CAA2C;QAC3C,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,gCAAgC;AAEhC,wBAAsB,cAAc,CAAC,EACnC,GAAG,EACH,aAAa,EACb,aAAa,EACb,cAAc,EACd,WAAgB,EAChB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,aAAa,EACb,YAAY,GACb,EAAE,IAAI,CAAC,kCAAkC,EAAE,UAAU,CAAC,GAAG;IACxD,aAAa,EAAE,cAAc,CAAC;IAC9B,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,OAAO,CACT,0BAA0B,CACxB,OAAO,qCAAqC,EAC5C,SAAS,EACT,GAAG,EACH,GAAG,EACH,GAAG,EACH,OAAO,GAAG,OAAO,CAClB,CACF,CA2BA;AAED,eAAO,MAAM,oBAAoB;;;;aAetB,KACP,cAAc,EACd,YAAY,GAAG,mBAAmB,GAAG,SAAS,GAAG,WAAW,CAC7D;aACQ,MAAM;MACb,qCAgDH,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EACH,OAAO,EACP,OAAO,EACP,OAAO,EACP,gBAAgB,GACjB,EAAE;IACD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,cAAc,CAwBjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoralabs/protocol-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"repository": "https://github.com/ourzora/zora-protocol",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"viem": "^2.11.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
+
"@fleekhq/fleek-storage-js": "^1.0.24",
|
|
35
36
|
"@lavamoat/preinstall-always-fail": "2.0.0",
|
|
36
37
|
"@reservoir0x/relay-sdk": "^0.3.8",
|
|
37
38
|
"@reservoir0x/reservoir-sdk": "^2.0.11",
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isArweaveURL } from "./arweave";
|
|
2
|
+
import { isNormalizeableIPFSUrl, normalizeIPFSUrl } from "./ipfs";
|
|
3
|
+
|
|
4
|
+
const IPFS_GATEWAY = "https://magic.decentralized-content.com";
|
|
5
|
+
|
|
6
|
+
const ARWEAVE_GATEWAY = "https://arweave.net";
|
|
7
|
+
|
|
8
|
+
export function arweaveGatewayUrl(normalizedArweaveUrl: string | null) {
|
|
9
|
+
if (!normalizedArweaveUrl || typeof normalizedArweaveUrl !== "string")
|
|
10
|
+
return null;
|
|
11
|
+
return normalizedArweaveUrl.replace("ar://", `${ARWEAVE_GATEWAY}/`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function ipfsGatewayUrl(url: string | null) {
|
|
15
|
+
if (!url || typeof url !== "string") return null;
|
|
16
|
+
const normalizedIPFSUrl = normalizeIPFSUrl(url);
|
|
17
|
+
if (normalizedIPFSUrl) {
|
|
18
|
+
return normalizedIPFSUrl.replace("ipfs://", `${IPFS_GATEWAY}/ipfs/`);
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getFetchableUrl(uri: string | null | undefined): string | null {
|
|
24
|
+
if (!uri || typeof uri !== "string") return null;
|
|
25
|
+
|
|
26
|
+
// Prevent fetching from insecure URLs
|
|
27
|
+
if (uri.startsWith("http://")) return null;
|
|
28
|
+
|
|
29
|
+
// If it is an IPFS HTTP or ipfs:// url
|
|
30
|
+
if (isNormalizeableIPFSUrl(uri)) {
|
|
31
|
+
// Return a fetchable gateway url
|
|
32
|
+
return ipfsGatewayUrl(uri);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If it is a ar:// url
|
|
36
|
+
if (isArweaveURL(uri)) {
|
|
37
|
+
// Return a fetchable gateway url
|
|
38
|
+
return arweaveGatewayUrl(uri);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If it is already a url (or blob or data-uri)
|
|
42
|
+
if (/^(https|data|blob):/.test(uri)) {
|
|
43
|
+
// Return the URI
|
|
44
|
+
return uri;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return null;
|
|
48
|
+
}
|
package/src/ipfs/ipfs.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { CID } from "multiformats/cid";
|
|
2
|
+
|
|
3
|
+
export type IPFSUrl = `ipfs://${string}`;
|
|
4
|
+
|
|
5
|
+
export function isCID(str: string | null | undefined): boolean {
|
|
6
|
+
if (!str) return false;
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
CID.parse(str);
|
|
10
|
+
return true;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
if (/^(bafy|Qm)/.test(str)) return true;
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function normalizeIPFSUrl(
|
|
18
|
+
url: string | null | undefined,
|
|
19
|
+
): IPFSUrl | null {
|
|
20
|
+
if (!url || typeof url !== "string") return null;
|
|
21
|
+
|
|
22
|
+
// Handle urls wrapped in quotes
|
|
23
|
+
url = url.replace(/"/g, "");
|
|
24
|
+
|
|
25
|
+
// Check if already a normalized IPFS url
|
|
26
|
+
if (isNormalizedIPFSURL(url)) return url as IPFSUrl;
|
|
27
|
+
|
|
28
|
+
// Check if url is a CID string
|
|
29
|
+
if (isCID(url)) return `ipfs://${url}`;
|
|
30
|
+
|
|
31
|
+
// If url is not either an ipfs gateway or protocol url
|
|
32
|
+
if (!isIPFSUrl(url)) return null;
|
|
33
|
+
|
|
34
|
+
// If url is already a gateway url, parse and normalize
|
|
35
|
+
if (isGatewayIPFSUrl(url)) {
|
|
36
|
+
// Replace leading double-slashes and parse URL
|
|
37
|
+
const parsed = new URL(url.replace(/^\/\//, "http://"));
|
|
38
|
+
// Remove IPFS from the URL
|
|
39
|
+
// http://gateway/ipfs/<CID>?x=y#z -> http://gateway/<CID>?x=y#z
|
|
40
|
+
parsed.pathname = parsed.pathname.replace(/^\/ipfs\//, "");
|
|
41
|
+
// Remove the protocol and host from the URL
|
|
42
|
+
// http://gateway/<CID>?x=y#z -> <CID>?x=y#z
|
|
43
|
+
const cid = parsed
|
|
44
|
+
.toString()
|
|
45
|
+
.replace(`${parsed.protocol}//${parsed.host}/`, "");
|
|
46
|
+
// Prepend ipfs protocol
|
|
47
|
+
return `ipfs://${cid}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function isNormalizedIPFSURL(url: string | null | undefined): boolean {
|
|
54
|
+
return url && typeof url === "string" ? url.startsWith("ipfs://") : false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isGatewayIPFSUrl(url: string | null | undefined): boolean {
|
|
58
|
+
if (url && typeof url === "string") {
|
|
59
|
+
try {
|
|
60
|
+
const parsed = new URL(url.replace(/^"|'(.*)"|'$/, "$1"));
|
|
61
|
+
return (
|
|
62
|
+
!isNormalizedIPFSURL(url) &&
|
|
63
|
+
parsed &&
|
|
64
|
+
parsed.pathname.startsWith("/ipfs/")
|
|
65
|
+
);
|
|
66
|
+
} catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isIPFSUrl(url: string | null | undefined): boolean {
|
|
75
|
+
return url ? isNormalizedIPFSURL(url) || isGatewayIPFSUrl(url) : false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function isNormalizeableIPFSUrl(
|
|
79
|
+
url: string | null | undefined,
|
|
80
|
+
): boolean {
|
|
81
|
+
return url ? isIPFSUrl(url) || isCID(url) : false;
|
|
82
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// text
|
|
2
|
+
const HTML = "text/html";
|
|
3
|
+
const MARKDOWN = "text/markdown";
|
|
4
|
+
const MARKDOWN_UTF8 = "text/markdown; charset=utf-8";
|
|
5
|
+
const TEXT_PLAIN_UTF8 = "text/plain; charset=utf-8";
|
|
6
|
+
export const TEXT_PLAIN = "text/plain";
|
|
7
|
+
const CSV = "text/csv";
|
|
8
|
+
const NUMBERS = ".numbers";
|
|
9
|
+
const EXCEL = ".xlsx";
|
|
10
|
+
const PDF = "application/pdf";
|
|
11
|
+
|
|
12
|
+
// image
|
|
13
|
+
const JPG = "image/jpg";
|
|
14
|
+
const JPEG = "image/jpeg";
|
|
15
|
+
const PNG = "image/png";
|
|
16
|
+
const WEBP = "image/webp";
|
|
17
|
+
const SVG = "image/svg+xml";
|
|
18
|
+
const TIFF = "image/tiff";
|
|
19
|
+
const GIF = "image/gif";
|
|
20
|
+
|
|
21
|
+
export const isImage = (mimeType: string | null | undefined) => {
|
|
22
|
+
if (!mimeType) return false;
|
|
23
|
+
return [JPG, JPEG, PNG, WEBP, SVG, TIFF, GIF].includes(mimeType);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export enum MediaType {
|
|
27
|
+
CSV = "CSV",
|
|
28
|
+
NUMBERS = "NUMBERS",
|
|
29
|
+
EXCEL = "EXCEL",
|
|
30
|
+
IMAGE = "IMAGE",
|
|
31
|
+
VIDEO = "VIDEO",
|
|
32
|
+
AUDIO = "AUDIO",
|
|
33
|
+
TIFF = "TIFF",
|
|
34
|
+
TEXT = "TEXT",
|
|
35
|
+
PDF = "PDF",
|
|
36
|
+
MODEL = "MODEL",
|
|
37
|
+
HTML = "HTML",
|
|
38
|
+
ZIP = "ZIP",
|
|
39
|
+
UNKNOWN = "UNKNOWN",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const DEFAULT_THUMBNAIL_CID_HASHES: { [key: string]: string } = {
|
|
43
|
+
[MediaType.AUDIO]:
|
|
44
|
+
"bafkreidir5laqi26ta6ivnpe2zpekgrfcyi4tb5x6vhwmwnledmzxshfb4",
|
|
45
|
+
[MediaType.VIDEO]:
|
|
46
|
+
"bafkreifm4edadl3j5luoyvw4p6elxeqd77la7bulee6vhq5gq4chfk32mu",
|
|
47
|
+
[MediaType.HTML]:
|
|
48
|
+
"bafkreifgvi6xfwqy2l6g45csyokejpaib52ee7zrw6etrxl2tas4xkkclq",
|
|
49
|
+
[MediaType.ZIP]:
|
|
50
|
+
"bafkreihe5rr5jbkwzegisjlhxbb7jw22xw5oilfmgd2re6tz6buo4pasdq", // assuming all zip files are html directories
|
|
51
|
+
[MediaType.TEXT]:
|
|
52
|
+
"bafkreiaez25nfgggzrnza2loxf6xueb2esm44pnyjyulwoslnipowrf56q",
|
|
53
|
+
default: "bafkreihcoahllisbpb4eeypdwtm7go5uh275wxd7wf2tantpxlpjhviok4",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// video
|
|
57
|
+
const MP4 = "video/mp4";
|
|
58
|
+
const QUICKTIME = "video/quicktime";
|
|
59
|
+
const M4V = "video/x-m4v";
|
|
60
|
+
const WEBM = "video/webm";
|
|
61
|
+
|
|
62
|
+
// audio
|
|
63
|
+
const M4A = "audio/x-m4a";
|
|
64
|
+
const MPEG = "audio/mpeg";
|
|
65
|
+
const MP3 = "audio/mp3";
|
|
66
|
+
const WAV = "audio/wav";
|
|
67
|
+
const VND_WAV = "audio/vnd.wav";
|
|
68
|
+
const VND_WAVE = "audio/vnd.wave";
|
|
69
|
+
const WAVE = "audio/wave";
|
|
70
|
+
const X_WAV = "audio/x-wav";
|
|
71
|
+
const AIFF = "audio/aiff";
|
|
72
|
+
|
|
73
|
+
// 3D
|
|
74
|
+
const GLTF = "model/gltf+json";
|
|
75
|
+
const GLB = "model/gltf-binary";
|
|
76
|
+
// File extensions, as some files return '' as the mimetype
|
|
77
|
+
const GLTF_EXT = ".gltf";
|
|
78
|
+
const GLB_EXT = ".glb";
|
|
79
|
+
|
|
80
|
+
// application
|
|
81
|
+
export const JSON_MIME_TYPE = "application/json";
|
|
82
|
+
const ZIP = "application/zip";
|
|
83
|
+
|
|
84
|
+
const mimeToMediaType = {
|
|
85
|
+
[HTML]: MediaType.HTML,
|
|
86
|
+
[JPG]: MediaType.IMAGE,
|
|
87
|
+
[JPEG]: MediaType.IMAGE,
|
|
88
|
+
[PNG]: MediaType.IMAGE,
|
|
89
|
+
[WEBP]: MediaType.IMAGE,
|
|
90
|
+
[SVG]: MediaType.IMAGE,
|
|
91
|
+
[TIFF]: MediaType.TIFF,
|
|
92
|
+
[GIF]: MediaType.IMAGE,
|
|
93
|
+
[MP4]: MediaType.VIDEO,
|
|
94
|
+
[WEBM]: MediaType.VIDEO,
|
|
95
|
+
[QUICKTIME]: MediaType.VIDEO,
|
|
96
|
+
[M4V]: MediaType.VIDEO,
|
|
97
|
+
[MPEG]: MediaType.AUDIO,
|
|
98
|
+
[MP3]: MediaType.AUDIO,
|
|
99
|
+
[M4A]: MediaType.AUDIO,
|
|
100
|
+
[VND_WAV]: MediaType.AUDIO,
|
|
101
|
+
[VND_WAVE]: MediaType.AUDIO,
|
|
102
|
+
[WAV]: MediaType.AUDIO,
|
|
103
|
+
[WAVE]: MediaType.AUDIO,
|
|
104
|
+
[X_WAV]: MediaType.AUDIO,
|
|
105
|
+
[AIFF]: MediaType.AUDIO,
|
|
106
|
+
[TEXT_PLAIN]: MediaType.TEXT,
|
|
107
|
+
[TEXT_PLAIN_UTF8]: MediaType.TEXT,
|
|
108
|
+
[MARKDOWN]: MediaType.TEXT,
|
|
109
|
+
[MARKDOWN_UTF8]: MediaType.TEXT,
|
|
110
|
+
[CSV]: MediaType.CSV,
|
|
111
|
+
[NUMBERS]: MediaType.NUMBERS,
|
|
112
|
+
[EXCEL]: MediaType.EXCEL,
|
|
113
|
+
[PDF]: MediaType.PDF,
|
|
114
|
+
[ZIP]: MediaType.ZIP,
|
|
115
|
+
[GLTF]: MediaType.MODEL,
|
|
116
|
+
[GLTF_EXT]: MediaType.MODEL,
|
|
117
|
+
[GLB]: MediaType.MODEL,
|
|
118
|
+
// GLTF returns 'application/json' as the mimetype,
|
|
119
|
+
// and as the only JSON-encoded media we currently support,
|
|
120
|
+
// we assume that if the mimetype is JSON, it's a GLTF
|
|
121
|
+
[JSON_MIME_TYPE]: MediaType.MODEL,
|
|
122
|
+
[GLB_EXT]: MediaType.MODEL,
|
|
123
|
+
} as const;
|
|
124
|
+
|
|
125
|
+
/** Return a MediaType for the given mime type. If mime type is unknown you can provide a filename as a fallback, where the type will be guessed based on extension. */
|
|
126
|
+
export function mimeTypeToMedia(mimeType?: string | null) {
|
|
127
|
+
if (!mimeType) return MediaType.UNKNOWN;
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
mimeToMediaType[mimeType as keyof typeof mimeToMediaType] ||
|
|
131
|
+
MediaType.UNKNOWN
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function getMimeType(uri?: string) {
|
|
136
|
+
if (!uri) return uri;
|
|
137
|
+
|
|
138
|
+
const res = await fetch(uri, { method: "HEAD" });
|
|
139
|
+
let mimeType = res.headers.get("content-type");
|
|
140
|
+
return mimeType;
|
|
141
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { TextMetadataFiles } from "./types";
|
|
2
|
+
|
|
3
|
+
const CHAR_LIMIT = 1111;
|
|
4
|
+
|
|
5
|
+
const wrapText = ({
|
|
6
|
+
ctx,
|
|
7
|
+
text,
|
|
8
|
+
x,
|
|
9
|
+
y,
|
|
10
|
+
maxWidth,
|
|
11
|
+
lineHeight,
|
|
12
|
+
}: {
|
|
13
|
+
ctx: CanvasRenderingContext2D;
|
|
14
|
+
text: string;
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
maxWidth: number;
|
|
18
|
+
lineHeight: number;
|
|
19
|
+
}) => {
|
|
20
|
+
// Split text into words
|
|
21
|
+
let words = text.replaceAll("\n", " \n ").split(/ +/);
|
|
22
|
+
let line = ""; // This will store the text of the current line
|
|
23
|
+
let testLine = ""; // This will store the text when we add a word, to test if it's too long
|
|
24
|
+
let lineArray = []; // This is an array of lines, which the function will return
|
|
25
|
+
|
|
26
|
+
for (var n = 0; n < words.length; n++) {
|
|
27
|
+
// Measure text sizing
|
|
28
|
+
testLine += `${words[n]} `;
|
|
29
|
+
let metrics = ctx.measureText(testLine);
|
|
30
|
+
let testWidth = metrics.width;
|
|
31
|
+
// If the width of this test line is more than the max width
|
|
32
|
+
if (words[n]?.includes("\n") || (testWidth > maxWidth && n > 0)) {
|
|
33
|
+
// Then the line is finished, push the current line into "lineArray"
|
|
34
|
+
lineArray.push({ text: line, x, y });
|
|
35
|
+
// Start a new line
|
|
36
|
+
y += lineHeight;
|
|
37
|
+
// Update line and test line to use this word as the first word on the next line
|
|
38
|
+
// If it's a newline, then don't add a space
|
|
39
|
+
if (words[n]?.includes("\n")) {
|
|
40
|
+
line = ``;
|
|
41
|
+
testLine = ``;
|
|
42
|
+
} else {
|
|
43
|
+
line = `${words[n]} `;
|
|
44
|
+
testLine = `${words[n]} `;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
// Test line is less than the max width, add the word to the current line
|
|
48
|
+
line += `${words[n]} `;
|
|
49
|
+
}
|
|
50
|
+
// Handle a single line...
|
|
51
|
+
if (n === words.length - 1) {
|
|
52
|
+
lineArray.push({ text: line, x, y });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return lineArray;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
async function generateTextPreview(text: string): Promise<File> {
|
|
59
|
+
// Trim the text to a reasonable max length. Prevent crashes if the user pastes a gigantic string
|
|
60
|
+
const trimmedText = text.trim().slice(0, CHAR_LIMIT);
|
|
61
|
+
|
|
62
|
+
const [width, height] = [500, 500];
|
|
63
|
+
const padding = 20;
|
|
64
|
+
const dpr = 2;
|
|
65
|
+
|
|
66
|
+
const fontFamily = "Inter";
|
|
67
|
+
const [fontSize, lineHeight] = [16, 24];
|
|
68
|
+
const [textColor, backgroundColor] = ["black", "white"];
|
|
69
|
+
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const canvas = document.createElement("canvas");
|
|
72
|
+
canvas.width = width * dpr;
|
|
73
|
+
canvas.height = height * dpr;
|
|
74
|
+
const ctx = canvas.getContext("2d");
|
|
75
|
+
if (!ctx) {
|
|
76
|
+
return reject(new Error("Could not create canvas context"));
|
|
77
|
+
}
|
|
78
|
+
ctx.fillStyle = backgroundColor;
|
|
79
|
+
ctx.fillRect(0, 0, width * dpr, width * dpr);
|
|
80
|
+
ctx.fillStyle = textColor;
|
|
81
|
+
ctx.font = `${fontSize * dpr}px ${fontFamily}`;
|
|
82
|
+
const wrapped = wrapText({
|
|
83
|
+
ctx,
|
|
84
|
+
text: trimmedText,
|
|
85
|
+
x: padding * dpr,
|
|
86
|
+
y: fontSize * dpr + padding * dpr,
|
|
87
|
+
maxWidth: width * dpr - padding * 2 * dpr,
|
|
88
|
+
lineHeight: lineHeight * dpr,
|
|
89
|
+
});
|
|
90
|
+
wrapped.forEach((line) => ctx.fillText(line.text, line.x, line.y));
|
|
91
|
+
canvas.toBlob((blob) => {
|
|
92
|
+
if (!blob) {
|
|
93
|
+
return reject(new Error("Could not create blob"));
|
|
94
|
+
}
|
|
95
|
+
resolve(new File([blob], "thumbnail.png", { type: "image/png" }));
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function generateTextTitle(text: string) {
|
|
101
|
+
const firstLine = text.split("\n")[0]!;
|
|
102
|
+
const firstSentence = firstLine?.split(". ")[0]!;
|
|
103
|
+
|
|
104
|
+
if (firstSentence.length > 50) {
|
|
105
|
+
return firstSentence.slice(0, 50) + "...";
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return firstSentence;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const toTextFile = (text: string) =>
|
|
112
|
+
new File([text], "Untitled.txt", { type: "text/plain" });
|
|
113
|
+
|
|
114
|
+
/** For text nfts, this will generate files that are needed for the metadata json, including the txt.file containing the text, and a thumbnail image containing a preview of the text
|
|
115
|
+
*/
|
|
116
|
+
export async function generateTextNftMetadataFiles(
|
|
117
|
+
text: string,
|
|
118
|
+
): Promise<TextMetadataFiles> {
|
|
119
|
+
const name = generateTextTitle(text);
|
|
120
|
+
const textFile = toTextFile(text);
|
|
121
|
+
const thumbnailFile = await generateTextPreview(text);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
name,
|
|
125
|
+
mediaUrlFile: textFile,
|
|
126
|
+
thumbnailFile,
|
|
127
|
+
};
|
|
128
|
+
}
|