@visualizevalue/mint-app-base 0.1.126 → 0.2.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.
@@ -0,0 +1,144 @@
1
+ import { graphqlSource, customSource } from '@1001-digital/dapp-query-core'
2
+ import type { QueryDefinition } from '@1001-digital/dapp-query-core'
3
+ import type { Config } from '@wagmi/core'
4
+ import type { Collection, Token, MintEvent } from '~/utils/types'
5
+ import {
6
+ COLLECTIONS_BY_ARTIST, COLLECTION_BY_ADDRESS,
7
+ ARTIFACTS_BY_COLLECTION, MINTS_BY_ARTIFACT,
8
+ transformCollections, transformCollection,
9
+ transformArtifacts, transformMints, transformProfile,
10
+ rpcFetchProfile, rpcFetchCollections,
11
+ rpcFetchCollection, rpcFetchCollectionTokens,
12
+ rpcFetchTokenMints,
13
+ } from './sources'
14
+
15
+ export interface MintQueries {
16
+ artistProfile: QueryDefinition<Partial<Artist>, [`0x${string}`]>
17
+ artistCollections: QueryDefinition<Collection[], [`0x${string}`]>
18
+ collection: QueryDefinition<Collection, [`0x${string}`]>
19
+ collectionTokens: QueryDefinition<Token[], [`0x${string}`]>
20
+ tokenMints: QueryDefinition<MintEvent[], [`0x${string}`, bigint]>
21
+ }
22
+
23
+ interface CreateQueriesConfig {
24
+ wagmi: Config
25
+ chainId: number
26
+ factory: `0x${string}`
27
+ endpoints: string[]
28
+ }
29
+
30
+ export function createQueries (config: CreateQueriesConfig): MintQueries {
31
+ const { wagmi, chainId, factory, endpoints } = config
32
+ const hasIndexer = endpoints.length > 0
33
+
34
+ const indexerProfileSource = hasIndexer
35
+ ? customSource<Partial<Artist>>({
36
+ id: 'profile-indexer',
37
+ fetch: async (address: unknown) => {
38
+ // Multi-endpoint REST failover
39
+ let lastError: Error | undefined
40
+ for (const endpoint of endpoints) {
41
+ try {
42
+ const base = endpoint.replace(/\/$/, '')
43
+ const res = await fetch(`${base}/profiles/${address}`)
44
+ if (!res.ok) throw new Error(`HTTP ${res.status}`)
45
+ return transformProfile(await res.json())
46
+ } catch (e) {
47
+ lastError = e instanceof Error ? e : new Error(String(e))
48
+ }
49
+ }
50
+ throw lastError ?? new Error('All indexer endpoints failed')
51
+ },
52
+ })
53
+ : null
54
+
55
+ return {
56
+ artistProfile: {
57
+ key: (address) => `profile:${address}`,
58
+ staleTime: 30 * 60 * 1000, // 30 min
59
+ sources: [
60
+ ...(indexerProfileSource ? [indexerProfileSource] : []),
61
+ customSource<Partial<Artist>>({
62
+ id: 'profile-rpc',
63
+ fetch: (address: unknown) => rpcFetchProfile(wagmi, address as `0x${string}`),
64
+ }),
65
+ ],
66
+ },
67
+
68
+ artistCollections: {
69
+ key: (artist) => `collections:${artist}`,
70
+ staleTime: 5 * 60 * 1000,
71
+ sources: [
72
+ ...(hasIndexer ? [graphqlSource<Collection[]>({
73
+ endpoints,
74
+ query: COLLECTIONS_BY_ARTIST,
75
+ variables: (artist: unknown) => ({ artist: (artist as string).toLowerCase() }),
76
+ transform: transformCollections,
77
+ })] : []),
78
+ customSource<Collection[]>({
79
+ id: 'collections-rpc',
80
+ fetch: (artist: unknown) => rpcFetchCollections(wagmi, chainId, artist as `0x${string}`, factory),
81
+ }),
82
+ ],
83
+ },
84
+
85
+ collection: {
86
+ key: (address) => `collection:${address}`,
87
+ staleTime: 5 * 60 * 1000,
88
+ sources: [
89
+ ...(hasIndexer ? [graphqlSource<Collection>({
90
+ endpoints,
91
+ query: COLLECTION_BY_ADDRESS,
92
+ variables: (address: unknown) => ({ address: (address as string).toLowerCase() }),
93
+ transform: transformCollection,
94
+ })] : []),
95
+ customSource<Collection>({
96
+ id: 'collection-rpc',
97
+ fetch: async (address: unknown) => {
98
+ const collection = await rpcFetchCollection(wagmi, chainId, address as `0x${string}`)
99
+ if (!collection) throw new Error('Collection not found via RPC')
100
+ return collection
101
+ },
102
+ }),
103
+ ],
104
+ },
105
+
106
+ collectionTokens: {
107
+ key: (collection) => `tokens:${collection}`,
108
+ staleTime: 5 * 60 * 1000,
109
+ sources: [
110
+ ...(hasIndexer ? [graphqlSource<Token[]>({
111
+ endpoints,
112
+ query: ARTIFACTS_BY_COLLECTION,
113
+ variables: (collection: unknown) => ({ collection: (collection as string).toLowerCase() }),
114
+ transform: transformArtifacts,
115
+ })] : []),
116
+ customSource<Token[]>({
117
+ id: 'tokens-rpc',
118
+ fetch: (collection: unknown) => rpcFetchCollectionTokens(wagmi, chainId, collection as `0x${string}`),
119
+ }),
120
+ ],
121
+ },
122
+
123
+ tokenMints: {
124
+ key: (collection, tokenId) => `mints:${collection}:${tokenId}`,
125
+ staleTime: 60 * 1000, // 1 min — mints change frequently during live mint
126
+ sources: [
127
+ ...(hasIndexer ? [graphqlSource<MintEvent[]>({
128
+ endpoints,
129
+ query: MINTS_BY_ARTIFACT,
130
+ variables: (collection: unknown, tokenId: unknown) => ({
131
+ collection: (collection as string).toLowerCase(),
132
+ artifact: String(tokenId),
133
+ }),
134
+ transform: transformMints,
135
+ })] : []),
136
+ customSource<MintEvent[]>({
137
+ id: 'mints-rpc',
138
+ fetch: (collection: unknown, tokenId: unknown) =>
139
+ rpcFetchTokenMints(wagmi, chainId, collection as `0x${string}`, BigInt(tokenId as string | bigint)),
140
+ }),
141
+ ],
142
+ },
143
+ }
144
+ }
@@ -0,0 +1,417 @@
1
+ import { getBalance, getPublicClient, readContract } from '@wagmi/core'
2
+ import { type GetBalanceReturnType } from '@wagmi/core'
3
+ import { parseAbiItem, type PublicClient } from 'viem'
4
+ import type { Config } from '@wagmi/core'
5
+ import type { Collection, Token, MintEvent } from '~/utils/types'
6
+ import { BLOCKS_PER_DAY } from '@visualizevalue/mint-utils/time'
7
+
8
+ // Sentinel: marks data as fully synced from the indexer.
9
+ export const INDEXER_SYNCED = BigInt(Number.MAX_SAFE_INTEGER)
10
+
11
+ // Ponder response types (bigints come as strings from GraphQL)
12
+
13
+ interface PonderCollection {
14
+ address: string
15
+ artist: { address: string }
16
+ owner: string
17
+ image: string
18
+ name: string
19
+ symbol: string
20
+ description: string
21
+ init_block: string
22
+ latest_token_id: string
23
+ }
24
+
25
+ interface PonderArtifact {
26
+ collection: { address: string }
27
+ id: string
28
+ name: string
29
+ description: string
30
+ image: string
31
+ animation_url: string
32
+ created_block: string
33
+ }
34
+
35
+ interface PonderMint {
36
+ artifact: { id: string }
37
+ hash: string
38
+ block_number: string
39
+ log_index: number
40
+ amount: string
41
+ unit_price: string
42
+ price: string
43
+ account: string
44
+ }
45
+
46
+ interface PonderProfile {
47
+ ens: string | null
48
+ data: {
49
+ avatar: string
50
+ description: string
51
+ links: {
52
+ url: string
53
+ email: string
54
+ twitter: string
55
+ github: string
56
+ }
57
+ }
58
+ }
59
+
60
+
61
+ export const COLLECTIONS_BY_ARTIST = `
62
+ query($artist: String!) {
63
+ collections(
64
+ where: { artist: $artist }
65
+ orderBy: "init_block"
66
+ orderDirection: "desc"
67
+ limit: 1000
68
+ ) {
69
+ items {
70
+ address artist { address } owner image name symbol description
71
+ init_block latest_token_id
72
+ }
73
+ }
74
+ }
75
+ `
76
+
77
+ export const COLLECTION_BY_ADDRESS = `
78
+ query($address: String!) {
79
+ collection(address: $address) {
80
+ address artist { address } owner image name symbol description
81
+ init_block latest_token_id
82
+ }
83
+ }
84
+ `
85
+
86
+ export const ARTIFACTS_BY_COLLECTION = `
87
+ query($collection: String!) {
88
+ artifacts(
89
+ where: { collection: $collection }
90
+ orderBy: "id"
91
+ orderDirection: "desc"
92
+ limit: 1000
93
+ ) {
94
+ items {
95
+ collection { address } id name description image animation_url created_block
96
+ }
97
+ }
98
+ }
99
+ `
100
+
101
+ export const MINTS_BY_ARTIFACT = `
102
+ query($collection: String!, $artifact: BigInt!) {
103
+ mints(
104
+ where: { collection: $collection, artifact: $artifact }
105
+ orderBy: "block_number"
106
+ orderDirection: "desc"
107
+ limit: 1000
108
+ ) {
109
+ items {
110
+ artifact { id } hash block_number log_index
111
+ amount unit_price price account
112
+ }
113
+ }
114
+ }
115
+ `
116
+
117
+
118
+ export function transformCollections (data: { collections: { items: PonderCollection[] } }): Collection[] {
119
+ return data.collections.items.map(toCollection)
120
+ }
121
+
122
+ export function transformCollection (data: { collection: PonderCollection | null }): Collection {
123
+ if (!data.collection) throw new Error('Collection not found in indexer')
124
+ return toCollection(data.collection)
125
+ }
126
+
127
+ export function transformArtifacts (data: { artifacts: { items: PonderArtifact[] } }): Token[] {
128
+ return data.artifacts.items.map(toToken)
129
+ }
130
+
131
+ export function transformMints (data: { mints: { items: PonderMint[] } }): MintEvent[] {
132
+ return data.mints.items.map(toMintEvent)
133
+ }
134
+
135
+
136
+ export function transformProfile (raw: PonderProfile): Partial<Artist> {
137
+ return {
138
+ ens: raw.ens || '',
139
+ avatar: raw.data?.avatar || '',
140
+ description: raw.data?.description || '',
141
+ url: raw.data?.links?.url || '',
142
+ email: raw.data?.links?.email || '',
143
+ twitter: raw.data?.links?.twitter || '',
144
+ github: raw.data?.links?.github || '',
145
+ profileUpdatedAtBlock: INDEXER_SYNCED,
146
+ }
147
+ }
148
+
149
+
150
+ export async function rpcFetchProfile (
151
+ wagmi: Config,
152
+ address: `0x${string}`,
153
+ ): Promise<Partial<Artist>> {
154
+ const client = getPublicClient(wagmi, { chainId: 1 }) as PublicClient
155
+ const block = await client.getBlockNumber()
156
+
157
+ let ens, avatar, description, url, email, twitter, github
158
+
159
+ try {
160
+ ens = await client.getEnsName({ address })
161
+ if (ens) {
162
+ [avatar, description, url, email, twitter, github] = await Promise.all([
163
+ client.getEnsAvatar({ name: ens }),
164
+ client.getEnsText({ name: ens, key: 'description' }),
165
+ client.getEnsText({ name: ens, key: 'url' }),
166
+ client.getEnsText({ name: ens, key: 'email' }),
167
+ client.getEnsText({ name: ens, key: 'com.twitter' }),
168
+ client.getEnsText({ name: ens, key: 'com.github' }),
169
+ ])
170
+ }
171
+ } catch (e) { }
172
+
173
+ return { ens, avatar, description, url, email, twitter, github, profileUpdatedAtBlock: block }
174
+ }
175
+
176
+ export async function rpcFetchCollections (
177
+ wagmi: Config,
178
+ chainId: number,
179
+ artist: `0x${string}`,
180
+ factory: `0x${string}`,
181
+ ): Promise<Collection[]> {
182
+ const addresses: `0x${string}`[] = (await readContract(wagmi, {
183
+ abi: FACTORY_ABI,
184
+ address: factory,
185
+ functionName: 'getCreatorCollections',
186
+ args: [artist],
187
+ chainId,
188
+ })).map((a: `0x${string}`) => a.toLowerCase() as `0x${string}`)
189
+
190
+ const collections = await Promise.all(addresses.map(a => rpcFetchCollection(wagmi, chainId, a)))
191
+ return collections.filter((c): c is Collection => c !== null)
192
+ }
193
+
194
+ export async function rpcFetchCollection (
195
+ wagmi: Config,
196
+ chainId: number,
197
+ address: `0x${string}`,
198
+ ): Promise<Collection | null> {
199
+ try {
200
+ const [data, version, initBlock, latestTokenId, owner, balance] = await Promise.all([
201
+ readContract(wagmi, { abi: MINT_ABI, address, functionName: 'contractURI', chainId }) as Promise<string>,
202
+ readContract(wagmi, { abi: MINT_ABI, address, functionName: 'version', chainId }) as Promise<bigint>,
203
+ readContract(wagmi, { abi: MINT_ABI, address, functionName: 'initBlock', chainId }) as Promise<bigint>,
204
+ readContract(wagmi, { abi: MINT_ABI, address, functionName: 'latestTokenId', chainId }) as Promise<bigint>,
205
+ readContract(wagmi, { abi: MINT_ABI, address, functionName: 'owner', chainId }) as Promise<`0x${string}`>,
206
+ getBalance(wagmi, { address }) as Promise<GetBalanceReturnType>,
207
+ ])
208
+
209
+ const artistAddr = owner.toLowerCase() as `0x${string}`
210
+ const json = Buffer.from(data.substring(29), 'base64').toString()
211
+ const metadata = JSON.parse(json)
212
+
213
+ return {
214
+ image: metadata.image,
215
+ name: metadata.name,
216
+ symbol: metadata.symbol,
217
+ version,
218
+ description: metadata.description,
219
+ address,
220
+ initBlock,
221
+ latestTokenId,
222
+ owner: artistAddr,
223
+ tokens: {},
224
+ balance: balance.value,
225
+ renderers: [],
226
+ }
227
+ } catch (e) {
228
+ console.warn(`RPC: Error fetching collection ${address}`, e)
229
+ return null
230
+ }
231
+ }
232
+
233
+ export async function rpcFetchCollectionTokens (
234
+ wagmi: Config,
235
+ chainId: number,
236
+ collection: `0x${string}`,
237
+ ): Promise<Token[]> {
238
+ const client = getPublicClient(wagmi, { chainId }) as PublicClient
239
+ const [latestTokenId, currentBlock] = await Promise.all([
240
+ readContract(wagmi, {
241
+ abi: MINT_ABI,
242
+ address: collection,
243
+ functionName: 'latestTokenId',
244
+ chainId,
245
+ }) as Promise<bigint>,
246
+ client.getBlock(),
247
+ ])
248
+
249
+ const mintContract = getContract({ address: collection, abi: MINT_ABI, client })
250
+ const tokens: Token[] = []
251
+ const ids: bigint[] = []
252
+ for (let id = latestTokenId; id > 0n; id--) ids.push(id)
253
+
254
+ for (const chunk of chunkArray(ids, 10)) {
255
+ const results = await Promise.allSettled(
256
+ chunk.map(id => rpcFetchSingleToken(mintContract, collection, id, currentBlock))
257
+ )
258
+ for (const r of results) {
259
+ if (r.status === 'fulfilled' && r.value) tokens.push(r.value)
260
+ }
261
+ }
262
+
263
+ return tokens
264
+ }
265
+
266
+ async function rpcFetchSingleToken (
267
+ mintContract: ReturnType<typeof getContract>,
268
+ collection: `0x${string}`,
269
+ tokenId: bigint,
270
+ currentBlock: Awaited<ReturnType<PublicClient['getBlock']>>,
271
+ tries: number = 0,
272
+ ): Promise<Token | null> {
273
+ try {
274
+ const [data, dataUri] = await Promise.all([
275
+ mintContract.read.get([tokenId]) as Promise<[string, string, `0x${string}`[], bigint, bigint, bigint, bigint]>,
276
+ mintContract.read.uri([tokenId], {
277
+ gas: 100_000_000_000,
278
+ gasPrice: currentBlock.baseFeePerGas,
279
+ }) as Promise<string>,
280
+ ])
281
+
282
+ const [_name, _description, _artifact, _renderer, mintedBlock, closeAt, _extraData] = data
283
+
284
+ let metadata
285
+ try {
286
+ const json = Buffer.from(dataUri.substring(29), 'base64').toString()
287
+ metadata = JSON.parse(json)
288
+ } catch (e) {
289
+ metadata = { name: '', description: '', image: '', animation_url: '' }
290
+ }
291
+
292
+ return {
293
+ tokenId,
294
+ collection,
295
+ name: metadata.name,
296
+ description: metadata.description,
297
+ image: metadata.image,
298
+ animationUrl: metadata.animation_url,
299
+ mintedBlock: BigInt(`${mintedBlock}`),
300
+ closeAt,
301
+ mintsBackfilledUntilBlock: 0n,
302
+ mintsFetchedUntilBlock: 0n,
303
+ mints: [],
304
+ }
305
+ } catch (e) {
306
+ if (tries < 3) return rpcFetchSingleToken(mintContract, collection, tokenId, currentBlock, tries + 1)
307
+ return null
308
+ }
309
+ }
310
+
311
+ export async function rpcFetchTokenMints (
312
+ wagmi: Config,
313
+ chainId: number,
314
+ collection: `0x${string}`,
315
+ tokenId: bigint,
316
+ ): Promise<MintEvent[]> {
317
+ const client = getPublicClient(wagmi, { chainId }) as PublicClient
318
+ const mintContract = getContract({ address: collection, abi: MINT_ABI, client })
319
+
320
+ const [tokenData, currentBlock] = await Promise.all([
321
+ mintContract.read.get([tokenId]) as Promise<[string, string, `0x${string}`[], bigint, bigint, bigint, bigint]>,
322
+ client.getBlockNumber(),
323
+ ])
324
+
325
+ const mintedBlock = BigInt(`${tokenData[4]}`)
326
+ const untilBlock = mintedBlock + BLOCKS_PER_DAY
327
+ const toBlock = currentBlock > untilBlock ? untilBlock : currentBlock
328
+
329
+ return loadMintEventsRange(client, collection, tokenId, mintedBlock, toBlock)
330
+ }
331
+
332
+ async function loadMintEventsRange (
333
+ client: PublicClient,
334
+ collection: `0x${string}`,
335
+ tokenId: bigint,
336
+ fromBlock: bigint,
337
+ toBlock: bigint,
338
+ ): Promise<MintEvent[]> {
339
+ try {
340
+ const logs = await client.getLogs({
341
+ address: collection,
342
+ event: parseAbiItem('event NewMint(uint256 indexed tokenId, uint256 unitPrice, uint256 amount, address minter)'),
343
+ args: { tokenId },
344
+ fromBlock,
345
+ toBlock,
346
+ })
347
+
348
+ return logs.map(l => ({
349
+ tokenId,
350
+ address: l.args.minter,
351
+ block: l.blockNumber,
352
+ logIndex: l.logIndex,
353
+ tx: l.transactionHash,
354
+ unitPrice: l.args.unitPrice,
355
+ amount: l.args.amount,
356
+ price: (l.args.amount || 0n) * (l.args.unitPrice || 0n),
357
+ }) as MintEvent).reverse()
358
+ } catch (e) {
359
+ if (toBlock - fromBlock > 100n) {
360
+ const mid = fromBlock + (toBlock - fromBlock) / 2n
361
+ const [a, b] = await Promise.all([
362
+ loadMintEventsRange(client, collection, tokenId, fromBlock, mid),
363
+ loadMintEventsRange(client, collection, tokenId, mid + 1n, toBlock),
364
+ ])
365
+ return [...a, ...b]
366
+ }
367
+ throw e
368
+ }
369
+ }
370
+
371
+
372
+ function toCollection (raw: PonderCollection): Collection {
373
+ return {
374
+ address: raw.address.toLowerCase() as `0x${string}`,
375
+ owner: (raw.owner || raw.artist.address).toLowerCase() as `0x${string}`,
376
+ version: 0n,
377
+ image: raw.image || '',
378
+ name: raw.name || '',
379
+ symbol: raw.symbol || '',
380
+ description: raw.description || '',
381
+ initBlock: BigInt(raw.init_block || '0'),
382
+ latestTokenId: BigInt(raw.latest_token_id || '0'),
383
+ balance: 0n,
384
+ tokens: {},
385
+ renderers: [],
386
+ }
387
+ }
388
+
389
+ function toToken (raw: PonderArtifact): Token {
390
+ const mintedBlock = BigInt(raw.created_block || '0')
391
+ return {
392
+ collection: raw.collection.address.toLowerCase() as `0x${string}`,
393
+ tokenId: BigInt(raw.id),
394
+ name: raw.name || '',
395
+ description: raw.description || '',
396
+ image: raw.image || '',
397
+ animationUrl: raw.animation_url || undefined,
398
+ closeAt: mintedBlock + BLOCKS_PER_DAY,
399
+ mintedBlock,
400
+ mintsFetchedUntilBlock: 0n,
401
+ mintsBackfilledUntilBlock: 0n,
402
+ mints: [],
403
+ }
404
+ }
405
+
406
+ function toMintEvent (raw: PonderMint): MintEvent {
407
+ return {
408
+ tokenId: BigInt(raw.artifact.id),
409
+ address: raw.account.toLowerCase() as `0x${string}`,
410
+ block: BigInt(raw.block_number),
411
+ logIndex: raw.log_index,
412
+ tx: raw.hash,
413
+ unitPrice: BigInt(raw.unit_price || '0'),
414
+ amount: BigInt(raw.amount || '0'),
415
+ price: BigInt(raw.price || '0'),
416
+ }
417
+ }
package/.env.example DELETED
@@ -1,50 +0,0 @@
1
- # =========================
2
- # BASE
3
- # =========================
4
- NITRO_PRESET=node_cluster
5
- NUXT_SSR=false
6
- NUXT_DEVTOOLS=true
7
- NUXT_PUBLIC_DOMAIN=localhost
8
- NUXT_PUBLIC_TITLE=Mint
9
- NUXT_PUBLIC_DESCRIPTION=To mint is a human right.
10
-
11
- # =========================
12
- # MINT DEFAULTS
13
- # =========================
14
- # NUXT_PUBLIC_MINT_AMOUNT=1
15
- # NUXT_PUBLIC_MINT_VALUE=5
16
-
17
- # =========================
18
- # ARTIST SCOPE
19
- # =========================
20
- NUXT_PUBLIC_CREATOR_ADDRESS=0xc8f8e2f59dd95ff67c3d39109eca2e2a017d4c8a
21
-
22
- # =========================
23
- # SERVICES
24
- # =========================
25
- NUXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
26
- NUXT_PUBLIC_IPFS_GATEWAY=
27
- NUXT_PUBLIC_ARWEAVE_GATEWAY=
28
-
29
- # =========================
30
- # MAINNET
31
- # =========================
32
- # NUXT_PUBLIC_BLOCK_EXPLORER=https://etherscan.io
33
- # NUXT_PUBLIC_FACTORY_ADDRESS=0xd717Fe677072807057B03705227EC3E3b467b670
34
- # NUXT_PUBLIC_CHAIN_ID=1
35
- # NUXT_PUBLIC_RPC1=https://eth.llamarpc.com
36
- # NUXT_PUBLIC_RPC2=https://eth.drpc.org
37
- # NUXT_PUBLIC_RPC3=https://1rpc.io/eth
38
-
39
- # This should always be present if on other networks, so we can fetch ENS data
40
- NUXT_PUBLIC_MAINNET_RPC1=https://eth.llamarpc.com
41
-
42
- # =========================
43
- # SEPOLIA
44
- # =========================
45
- NUXT_PUBLIC_BLOCK_EXPLORER=https://sepolia.etherscan.io
46
- NUXT_PUBLIC_FACTORY_ADDRESS=0x750C5a6CFD40C9CaA48C31D87AC2a26101Acd517
47
- NUXT_PUBLIC_CHAIN_ID=11155111
48
- NUXT_PUBLIC_RPC1=https://ethereum-sepolia-rpc.publicnode.com
49
- NUXT_PUBLIC_RPC2=https://sepolia.drpc.org
50
- NUXT_PUBLIC_RPC3=https://1rpc.io/sepolia
package/.nuxtrc DELETED
@@ -1 +0,0 @@
1
- typescript.includeWorkspace = true