@zoralabs/protocol-sdk 0.7.0 → 0.7.2-ALLOWLIST.0

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/allow-list/allow-list-client.d.ts +25 -0
  3. package/dist/allow-list/allow-list-client.d.ts.map +1 -0
  4. package/dist/allow-list/types.d.ts +14 -0
  5. package/dist/allow-list/types.d.ts.map +1 -0
  6. package/dist/apis/generated/allow-list-api-types.d.ts +288 -0
  7. package/dist/apis/generated/allow-list-api-types.d.ts.map +1 -0
  8. package/dist/apis/http-api-base.d.ts.map +1 -1
  9. package/dist/create/1155-create-helper.d.ts +1 -0
  10. package/dist/create/1155-create-helper.d.ts.map +1 -1
  11. package/dist/create/token-setup.d.ts +3 -4
  12. package/dist/create/token-setup.d.ts.map +1 -1
  13. package/dist/create/types.d.ts +24 -4
  14. package/dist/create/types.d.ts.map +1 -1
  15. package/dist/index.cjs +1388 -54
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1382 -51
  20. package/dist/index.js.map +1 -1
  21. package/dist/ipfs/arweave.d.ts +3 -0
  22. package/dist/ipfs/arweave.d.ts.map +1 -0
  23. package/dist/ipfs/gateway.d.ts +4 -0
  24. package/dist/ipfs/gateway.d.ts.map +1 -0
  25. package/dist/ipfs/index.d.ts +4 -0
  26. package/dist/ipfs/index.d.ts.map +1 -0
  27. package/dist/ipfs/ipfs.d.ts +5 -0
  28. package/dist/ipfs/ipfs.d.ts.map +1 -0
  29. package/dist/ipfs/mimeTypes.d.ts +25 -0
  30. package/dist/ipfs/mimeTypes.d.ts.map +1 -0
  31. package/dist/ipfs/text-metadata.d.ts +5 -0
  32. package/dist/ipfs/text-metadata.d.ts.map +1 -0
  33. package/dist/ipfs/token-metadata.d.ts +14 -0
  34. package/dist/ipfs/token-metadata.d.ts.map +1 -0
  35. package/dist/ipfs/types.d.ts +49 -0
  36. package/dist/ipfs/types.d.ts.map +1 -0
  37. package/dist/mint/mint-queries.d.ts +3 -1
  38. package/dist/mint/mint-queries.d.ts.map +1 -1
  39. package/dist/mint/mint-transactions.d.ts +5 -3
  40. package/dist/mint/mint-transactions.d.ts.map +1 -1
  41. package/dist/mint/subgraph-mint-getter.d.ts.map +1 -1
  42. package/dist/mint/subgraph-queries.d.ts +27 -13
  43. package/dist/mint/subgraph-queries.d.ts.map +1 -1
  44. package/dist/mint/types.d.ts +22 -11
  45. package/dist/mint/types.d.ts.map +1 -1
  46. package/dist/premint/premint-client.d.ts +2 -1
  47. package/dist/premint/premint-client.d.ts.map +1 -1
  48. package/package.json +3 -1
  49. package/src/allow-list/allow-list-client.ts +102 -0
  50. package/src/allow-list/types.ts +15 -0
  51. package/src/apis/generated/allow-list-api-types.ts +288 -0
  52. package/src/apis/http-api-base.ts +12 -0
  53. package/src/create/1155-create-helper.ts +17 -0
  54. package/src/create/token-setup.ts +116 -19
  55. package/src/create/types.ts +32 -4
  56. package/src/index.ts +6 -0
  57. package/src/ipfs/arweave.ts +5 -0
  58. package/src/ipfs/gateway.ts +48 -0
  59. package/src/ipfs/index.ts +7 -0
  60. package/src/ipfs/ipfs.ts +82 -0
  61. package/src/ipfs/mimeTypes.ts +141 -0
  62. package/src/ipfs/text-metadata.ts +128 -0
  63. package/src/ipfs/token-metadata.ts +99 -0
  64. package/src/ipfs/types.ts +54 -0
  65. package/src/mint/mint-queries.ts +6 -0
  66. package/src/mint/mint-transactions.ts +72 -6
  67. package/src/mint/subgraph-mint-getter.ts +12 -3
  68. package/src/mint/subgraph-queries.ts +39 -17
  69. package/src/mint/types.ts +38 -12
  70. package/src/premint/premint-client.ts +9 -1
  71. package/yarn-error.log +8602 -0
  72. package/.turbo/turbo-build.log +0 -15
  73. package/src/create/1155-create-helper.test.ts +0 -325
  74. package/src/mint/mint-client.test.ts +0 -263
  75. package/src/mints/mints-contracts.test.ts +0 -529
  76. package/src/mints/mints-eth-unwrapper-and-caller.test.ts +0 -467
  77. package/src/mints/mints-queries.test.ts +0 -105
  78. package/src/premint/premint-client.test.ts +0 -290
  79. package/src/premint/preminter.test.ts +0 -866
  80. package/test-integration/setup-test-contracts.ts +0 -96
  81. package/tsconfig.build.json +0 -10
  82. package/tsup.config.ts +0 -12
@@ -0,0 +1,288 @@
1
+ /**
2
+ * This file was auto-generated by openapi-typescript.
3
+ * Do not make direct changes to the file.
4
+ */
5
+
6
+ export interface paths {
7
+ "/_health": {
8
+ parameters: {
9
+ query?: never;
10
+ header?: never;
11
+ path?: never;
12
+ cookie?: never;
13
+ };
14
+ /** Health */
15
+ get: operations["health__health_get"];
16
+ put?: never;
17
+ post?: never;
18
+ delete?: never;
19
+ options?: never;
20
+ head?: never;
21
+ patch?: never;
22
+ trace?: never;
23
+ };
24
+ "/allowlist": {
25
+ parameters: {
26
+ query?: never;
27
+ header?: never;
28
+ path?: never;
29
+ cookie?: never;
30
+ };
31
+ get?: never;
32
+ put?: never;
33
+ /**
34
+ * Add Allowlist
35
+ * @description This route adds a new allowlist
36
+ */
37
+ post: operations["add_allowlist_allowlist_post"];
38
+ delete?: never;
39
+ options?: never;
40
+ head?: never;
41
+ patch?: never;
42
+ trace?: never;
43
+ };
44
+ "/allowed": {
45
+ parameters: {
46
+ query?: never;
47
+ header?: never;
48
+ path?: never;
49
+ cookie?: never;
50
+ };
51
+ /** Allowed */
52
+ get: operations["allowed_allowed_get"];
53
+ put?: never;
54
+ post?: never;
55
+ delete?: never;
56
+ options?: never;
57
+ head?: never;
58
+ patch?: never;
59
+ trace?: never;
60
+ };
61
+ "/allowlist/{root}": {
62
+ parameters: {
63
+ query?: never;
64
+ header?: never;
65
+ path?: never;
66
+ cookie?: never;
67
+ };
68
+ /** Allowlist */
69
+ get: operations["allowlist_allowlist__root__get"];
70
+ put?: never;
71
+ post?: never;
72
+ delete?: never;
73
+ options?: never;
74
+ head?: never;
75
+ patch?: never;
76
+ trace?: never;
77
+ };
78
+ "/allowlist/{root}/count": {
79
+ parameters: {
80
+ query?: never;
81
+ header?: never;
82
+ path?: never;
83
+ cookie?: never;
84
+ };
85
+ /** Allowlist Count */
86
+ get: operations["allowlist_count_allowlist__root__count_get"];
87
+ put?: never;
88
+ post?: never;
89
+ delete?: never;
90
+ options?: never;
91
+ head?: never;
92
+ patch?: never;
93
+ trace?: never;
94
+ };
95
+ }
96
+ export type webhooks = Record<string, never>;
97
+ export interface components {
98
+ schemas: {
99
+ /**
100
+ * AllowlistEntry
101
+ * @description Currently matches zora-nft-drops model
102
+ */
103
+ AllowlistEntry: {
104
+ /** User */
105
+ user: string;
106
+ /** Price */
107
+ price: string;
108
+ /** Maxcanmint */
109
+ maxCanMint: number;
110
+ };
111
+ /** AllowlistRequest */
112
+ AllowlistRequest: {
113
+ /** Entries */
114
+ entries: components["schemas"]["AllowlistEntry"][];
115
+ /** Contract */
116
+ contract?: string;
117
+ };
118
+ /** HTTPValidationError */
119
+ HTTPValidationError: {
120
+ /** Detail */
121
+ detail?: components["schemas"]["ValidationError"][];
122
+ };
123
+ /** ValidationError */
124
+ ValidationError: {
125
+ /** Location */
126
+ loc: (string | number)[];
127
+ /** Message */
128
+ msg: string;
129
+ /** Error Type */
130
+ type: string;
131
+ };
132
+ };
133
+ responses: never;
134
+ parameters: never;
135
+ requestBodies: never;
136
+ headers: never;
137
+ pathItems: never;
138
+ }
139
+ export type $defs = Record<string, never>;
140
+ export interface operations {
141
+ health__health_get: {
142
+ parameters: {
143
+ query?: never;
144
+ header?: never;
145
+ path?: never;
146
+ cookie?: never;
147
+ };
148
+ requestBody?: never;
149
+ responses: {
150
+ /** @description Successful Response */
151
+ 200: {
152
+ headers: {
153
+ [name: string]: unknown;
154
+ };
155
+ content: {
156
+ "application/json": unknown;
157
+ };
158
+ };
159
+ };
160
+ };
161
+ add_allowlist_allowlist_post: {
162
+ parameters: {
163
+ query?: never;
164
+ header?: never;
165
+ path?: never;
166
+ cookie?: never;
167
+ };
168
+ requestBody: {
169
+ content: {
170
+ "application/json": components["schemas"]["AllowlistRequest"];
171
+ };
172
+ };
173
+ responses: {
174
+ /** @description Successful Response */
175
+ 200: {
176
+ headers: {
177
+ [name: string]: unknown;
178
+ };
179
+ content: {
180
+ "application/json": unknown;
181
+ };
182
+ };
183
+ /** @description Validation Error */
184
+ 422: {
185
+ headers: {
186
+ [name: string]: unknown;
187
+ };
188
+ content: {
189
+ "application/json": components["schemas"]["HTTPValidationError"];
190
+ };
191
+ };
192
+ };
193
+ };
194
+ allowed_allowed_get: {
195
+ parameters: {
196
+ query: {
197
+ user: string;
198
+ root: string;
199
+ };
200
+ header?: never;
201
+ path?: never;
202
+ cookie?: never;
203
+ };
204
+ requestBody?: never;
205
+ responses: {
206
+ /** @description Successful Response */
207
+ 200: {
208
+ headers: {
209
+ [name: string]: unknown;
210
+ };
211
+ content: {
212
+ "application/json": unknown;
213
+ };
214
+ };
215
+ /** @description Validation Error */
216
+ 422: {
217
+ headers: {
218
+ [name: string]: unknown;
219
+ };
220
+ content: {
221
+ "application/json": components["schemas"]["HTTPValidationError"];
222
+ };
223
+ };
224
+ };
225
+ };
226
+ allowlist_allowlist__root__get: {
227
+ parameters: {
228
+ query?: never;
229
+ header?: never;
230
+ path: {
231
+ root: string;
232
+ };
233
+ cookie?: never;
234
+ };
235
+ requestBody?: never;
236
+ responses: {
237
+ /** @description Successful Response */
238
+ 200: {
239
+ headers: {
240
+ [name: string]: unknown;
241
+ };
242
+ content: {
243
+ "application/json": unknown;
244
+ };
245
+ };
246
+ /** @description Validation Error */
247
+ 422: {
248
+ headers: {
249
+ [name: string]: unknown;
250
+ };
251
+ content: {
252
+ "application/json": components["schemas"]["HTTPValidationError"];
253
+ };
254
+ };
255
+ };
256
+ };
257
+ allowlist_count_allowlist__root__count_get: {
258
+ parameters: {
259
+ query?: never;
260
+ header?: never;
261
+ path: {
262
+ root: string;
263
+ };
264
+ cookie?: never;
265
+ };
266
+ requestBody?: never;
267
+ responses: {
268
+ /** @description Successful Response */
269
+ 200: {
270
+ headers: {
271
+ [name: string]: unknown;
272
+ };
273
+ content: {
274
+ "application/json": unknown;
275
+ };
276
+ };
277
+ /** @description Validation Error */
278
+ 422: {
279
+ headers: {
280
+ [name: string]: unknown;
281
+ };
282
+ content: {
283
+ "application/json": components["schemas"]["HTTPValidationError"];
284
+ };
285
+ };
286
+ };
287
+ };
288
+ }
@@ -49,6 +49,15 @@ export const get = async <T>(url: string) => {
49
49
  * @throws Error when HTTP response fails
50
50
  */
51
51
  export const post = async <T>(url: string, data: any) => {
52
+ const controller = new AbortController();
53
+ const { signal } = controller;
54
+
55
+ // 30 minute timeout:
56
+ const timeout = 30 * 60 * 1000;
57
+
58
+ // Set a timeout to automatically abort the request
59
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
60
+
52
61
  const response = await fetch(url, {
53
62
  method: "POST",
54
63
  headers: {
@@ -56,7 +65,10 @@ export const post = async <T>(url: string, data: any) => {
56
65
  accept: "application/json",
57
66
  },
58
67
  body: JSON.stringify(data),
68
+ signal,
59
69
  });
70
+
71
+ clearTimeout(timeoutId);
60
72
  if (response.status !== 200) {
61
73
  let json;
62
74
  try {
@@ -37,6 +37,23 @@ export const getTokenIdFromCreateReceipt = (
37
37
  }
38
38
  };
39
39
 
40
+ export const getContractAddressFromCreateReceipt = (
41
+ receipt: TransactionReceipt,
42
+ ): Address | undefined => {
43
+ for (const data of receipt.logs) {
44
+ try {
45
+ const decodedLog = decodeEventLog({
46
+ abi: zoraCreator1155FactoryImplABI,
47
+ eventName: "SetupNewContract",
48
+ ...data,
49
+ });
50
+ if (decodedLog && decodedLog.eventName === "SetupNewContract") {
51
+ return decodedLog.args.newContract;
52
+ }
53
+ } catch (err: any) {}
54
+ }
55
+ };
56
+
40
57
  type CreateNew1155TokenReturn = {
41
58
  parameters: SimulateContractParameters<
42
59
  any,
@@ -4,13 +4,17 @@ import {
4
4
  zoraCreator1155ImplABI,
5
5
  zoraCreatorFixedPriceSaleStrategyABI,
6
6
  zoraCreatorFixedPriceSaleStrategyAddress,
7
+ zoraCreatorMerkleMinterStrategyABI,
8
+ zoraCreatorMerkleMinterStrategyAddress,
7
9
  } from "@zoralabs/protocol-deployments";
8
10
  import { Address, encodeFunctionData, zeroAddress, Hex } from "viem";
9
11
  import * as semver from "semver";
10
12
  import {
13
+ AllowlistData,
11
14
  ContractProps,
12
15
  CreateNew1155TokenProps,
13
16
  New1155Token,
17
+ SalesConfigOrAllowList,
14
18
  SalesConfigParamsType,
15
19
  } from "./types";
16
20
  import { OPEN_EDITION_MINT_SIZE } from "src/constants";
@@ -24,16 +28,15 @@ type SetupMintersProps = {
24
28
  tokenId: bigint;
25
29
  chainId: number;
26
30
  fundsRecipient: Address;
27
- salesConfig: Concrete<SalesConfigParamsType>;
31
+ salesConfigOrAllowList: SalesConfigOrAllowList;
28
32
  };
29
33
 
30
34
  // Sales end forever amount (uint64 max)
35
+ const SALE_END_FOREVER = 18446744073709551615n;
31
36
 
32
37
  const saleSettingsOrDefault = (
33
38
  saleSettings?: SalesConfigParamsType,
34
39
  ): Concrete<SalesConfigParamsType> => {
35
- const SALE_END_FOREVER = 18446744073709551615n;
36
-
37
40
  const DEFAULT_SALE_SETTINGS: Concrete<SalesConfigParamsType> = {
38
41
  currency: zeroAddress,
39
42
  // Free Mint
@@ -51,6 +54,36 @@ const saleSettingsOrDefault = (
51
54
  };
52
55
  };
53
56
 
57
+ const allowListWithDefaults = (allowlist: AllowlistData) => {
58
+ const defaultAllowListSettings: Concrete<
59
+ Omit<AllowlistData, "presaleMerkleRoot">
60
+ > = {
61
+ // Sale start time – defaults to beginning of unix time
62
+ saleStart: 0n,
63
+ // This is the end of uint64, plenty of time
64
+ saleEnd: SALE_END_FOREVER,
65
+ };
66
+
67
+ return {
68
+ ...defaultAllowListSettings,
69
+ ...allowlist,
70
+ };
71
+ };
72
+
73
+ const getSalesConfigOrAllowListWithDefaults = ({
74
+ salesConfig,
75
+ allowlist,
76
+ }: Pick<CreateNew1155TokenProps, "salesConfig" | "allowlist">) => {
77
+ if (!allowlist) {
78
+ return {
79
+ salesConfig: saleSettingsOrDefault(salesConfig),
80
+ };
81
+ }
82
+ return {
83
+ allowlist: allowListWithDefaults(allowlist),
84
+ };
85
+ };
86
+
54
87
  function applyNew1155Defaults(
55
88
  props: CreateNew1155TokenProps,
56
89
  ownerAddress: Address,
@@ -68,8 +101,11 @@ function applyNew1155Defaults(
68
101
  ? OPEN_EDITION_MINT_SIZE
69
102
  : BigInt(props.maxSupply),
70
103
  royaltyBPS: props.royaltyBPS || 1000,
71
- salesConfig: saleSettingsOrDefault(props.salesConfig),
72
104
  tokenMetadataURI: props.tokenMetadataURI,
105
+ salesConfigOrAllowList: getSalesConfigOrAllowListWithDefaults({
106
+ salesConfig: props.salesConfig,
107
+ allowlist: props.allowlist,
108
+ }),
73
109
  };
74
110
  }
75
111
 
@@ -187,24 +223,84 @@ function setupFixedPriceMinter({
187
223
  };
188
224
  }
189
225
 
190
- export function setupMinters({ salesConfig, ...rest }: SetupMintersProps): {
226
+ function setupAllowListMinter({
227
+ chainId,
228
+ tokenId: nextTokenId,
229
+ allowlist,
230
+ fundsRecipient,
231
+ }: {
232
+ chainId: number;
233
+ tokenId: bigint;
234
+ allowlist: Concrete<AllowlistData>;
235
+ fundsRecipient: Address;
236
+ }) {
237
+ const merkleSaleStrategyAddress =
238
+ zoraCreatorMerkleMinterStrategyAddress[
239
+ chainId as keyof typeof zoraCreatorMerkleMinterStrategyAddress
240
+ ];
241
+
242
+ const merkleApproval = encodeFunctionData({
243
+ abi: zoraCreator1155ImplABI,
244
+ functionName: "addPermission",
245
+ args: [nextTokenId, merkleSaleStrategyAddress, PERMISSION_BITS.MINTER],
246
+ });
247
+
248
+ const merkleRoot = allowlist.presaleMerkleRoot.startsWith("0x")
249
+ ? allowlist.presaleMerkleRoot
250
+ : (`0x${allowlist.presaleMerkleRoot}` as Hex);
251
+
252
+ const saleData = encodeFunctionData({
253
+ abi: zoraCreatorMerkleMinterStrategyABI,
254
+ functionName: "setSale",
255
+ args: [
256
+ BigInt(nextTokenId),
257
+ {
258
+ presaleStart: allowlist.saleStart,
259
+ presaleEnd: allowlist.saleEnd,
260
+ merkleRoot,
261
+ fundsRecipient: fundsRecipient,
262
+ },
263
+ ],
264
+ });
265
+
266
+ const callSaleMerkle = encodeFunctionData({
267
+ abi: zoraCreator1155ImplABI,
268
+ functionName: "callSale",
269
+ args: [BigInt(nextTokenId), merkleSaleStrategyAddress, saleData],
270
+ });
271
+
272
+ return {
273
+ minter: merkleSaleStrategyAddress,
274
+ setupActions: [merkleApproval, callSaleMerkle],
275
+ };
276
+ }
277
+
278
+ export function setupMinters({
279
+ salesConfigOrAllowList: { salesConfig, allowlist },
280
+ ...rest
281
+ }: SetupMintersProps): {
191
282
  minter: Address;
192
283
  setupActions: Hex[];
193
284
  } {
194
- if (!salesConfig) throw new Error("No sales config for token");
195
- const { currency: currencyAddress } = salesConfig;
196
-
197
- if (currencyAddress === zeroAddress) {
198
- return setupFixedPriceMinter({
199
- ...salesConfig,
200
- ...rest,
201
- });
202
- } else {
203
- return setupErc20Minter({
204
- ...salesConfig,
205
- ...rest,
206
- });
285
+ if (salesConfig) {
286
+ const { currency: currencyAddress } = salesConfig;
287
+
288
+ if (currencyAddress === zeroAddress) {
289
+ return setupFixedPriceMinter({
290
+ ...salesConfig,
291
+ ...rest,
292
+ });
293
+ } else {
294
+ return setupErc20Minter({
295
+ ...salesConfig,
296
+ ...rest,
297
+ });
298
+ }
207
299
  }
300
+ return setupAllowListMinter({
301
+ allowlist: allowlist as Concrete<AllowlistData>,
302
+ ...rest,
303
+ });
208
304
  }
209
305
 
210
306
  function buildSetupNewToken({
@@ -335,7 +431,8 @@ export function constructCreate1155TokenCalls(
335
431
  tokenId: nextTokenId,
336
432
  chainId,
337
433
  fundsRecipient: new1155TokenPropsWithDefaults.payoutRecipient,
338
- salesConfig: new1155TokenPropsWithDefaults.salesConfig,
434
+ salesConfigOrAllowList:
435
+ new1155TokenPropsWithDefaults.salesConfigOrAllowList,
339
436
  });
340
437
 
341
438
  const adminMintCall = makeAdminMintCall({
@@ -32,26 +32,54 @@ export type CreateNew1155Params = {
32
32
  token: CreateNew1155TokenProps;
33
33
  };
34
34
 
35
- export interface CreateNew1155TokenProps {
35
+ export type AllowlistData = {
36
+ saleStart?: bigint;
37
+ saleEnd?: bigint;
38
+ presaleMerkleRoot: `0x${string}`;
39
+ };
40
+
41
+ export type CreateNew1155TokenProps = {
36
42
  maxSupply?: bigint | number;
37
43
  tokenMetadataURI: string;
38
44
  royaltyBPS?: number;
39
- salesConfig?: SalesConfigParamsType;
40
45
  createReferral?: Address;
41
46
  mintToCreatorCount?: number;
42
47
  payoutRecipient?: Address;
43
- }
48
+ } & (
49
+ | {
50
+ salesConfig: SalesConfigParamsType;
51
+ allowlist?: undefined;
52
+ }
53
+ | {
54
+ salesConfig?: undefined;
55
+ allowlist: AllowlistData;
56
+ }
57
+ | {
58
+ salesConfig?: undefined;
59
+ allowlist?: undefined;
60
+ }
61
+ );
44
62
 
45
63
  export interface ContractProps {
46
64
  nextTokenId: bigint;
47
65
  contractVersion: string;
48
66
  }
49
67
 
68
+ export type SalesConfigOrAllowList =
69
+ | {
70
+ salesConfig: Concrete<SalesConfigParamsType>;
71
+ allowlist?: undefined;
72
+ }
73
+ | {
74
+ salesConfig: undefined;
75
+ allowlist: Concrete<AllowlistData>;
76
+ };
77
+
50
78
  export type New1155Token = {
51
79
  payoutRecipient: Address;
52
80
  createReferral: Address;
53
81
  maxSupply: bigint;
54
82
  royaltyBPS: number;
55
- salesConfig: Concrete<SalesConfigParamsType>;
56
83
  tokenMetadataURI: string;
84
+ salesConfigOrAllowList: SalesConfigOrAllowList;
57
85
  };
package/src/index.ts CHANGED
@@ -29,3 +29,9 @@ export {
29
29
  export * from "./create/types";
30
30
 
31
31
  export * from "./sdk";
32
+
33
+ export * from "./ipfs";
34
+
35
+ export { createAllowList } from "./allow-list/allow-list-client";
36
+
37
+ export * from "./allow-list/types";
@@ -0,0 +1,5 @@
1
+ export type ArweaveURL = `ar://${string}`;
2
+
3
+ export function isArweaveURL(url: string | null | undefined): boolean {
4
+ return url && typeof url === "string" ? url.startsWith("ar://") : false;
5
+ }
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ export {
2
+ makeMediaTokenMetadata,
3
+ makeTextTokenMetadata,
4
+ } from "./token-metadata";
5
+ export { generateTextNftMetadataFiles } from "./text-metadata";
6
+
7
+ export * from "./types";