From 88fb3dd3847b1c23ae6c38be9866c873dd656baf Mon Sep 17 00:00:00 2001 From: Chris Maddern Date: Sun, 30 Jun 2024 15:19:01 -0400 Subject: [PATCH] Add setCreator method to builder. Add to FXHash --- src/ingestors/fxhash/index.ts | 59 ++++++----------------- src/ingestors/fxhash/offchain-metadata.ts | 19 ++++++++ src/ingestors/fxhash/onchain-metadata.ts | 1 + src/lib/builder/mint-template-builder.ts | 24 ++++++++- src/lib/types/mint-template.ts | 21 +++++--- test/ingestors/fxhash.test.ts | 3 ++ yarn.lock | 52 +++++++++++--------- 7 files changed, 104 insertions(+), 75 deletions(-) diff --git a/src/ingestors/fxhash/index.ts b/src/ingestors/fxhash/index.ts index 76a8aef..a03af8e 100644 --- a/src/ingestors/fxhash/index.ts +++ b/src/ingestors/fxhash/index.ts @@ -47,13 +47,22 @@ export class FxHashIngestor implements MintIngestor { const image = token.metadata?.thumbnailUri || ''; mintBuilder.setName(token.name).setDescription(description).setFeaturedImageUrl(image); - - // The 1 is reserveId in their contract... not clear what for... but it's always 1 + mintBuilder.setMintOutputContract({ chainId: contract.chainId, address: contract.contractAddress }); + mintBuilder.setCreator({ + name: token.author.account.username, + imageUrl: token.author.account.profile.picture, + walletAddress: token.author.account.wallets?.find((w: any) => w.address.startsWith('0x'))?.address, + websiteUrl: token.author.account.profile.website, + description: token.author.account.profile.description, + twitterUsername: token.author.account.profile.twitter?.split('/').pop(), + }) + + // The 0 is reserveId in their contract... not clear what for... but 0 seems to always work const totalPriceWei = await getFxHashMintPriceInEth( contract.chainId, contractAddress, contract.contractAddress, - 1, + 0, resources.alchemy, abi, ); @@ -82,11 +91,6 @@ export class FxHashIngestor implements MintIngestor { throw new MintIngestorError(MintIngestionErrorName.IncompatibleUrl, 'Incompatible URL'); } - const mintBuilder = new MintTemplateBuilder() - .setMarketingUrl(url) - .setMintInstructionType(MintInstructionType.EVM_MINT) - .setPartnerName('fxhash'); - // Example URL: https://www.fxhash.xyz/generative/slug/allegro // First get the slug from the end const slug = url.split('/').pop(); @@ -106,44 +110,9 @@ export class FxHashIngestor implements MintIngestor { const chainId = token.chain === 'BASE' ? 8453 : null; if (!chainId) { - throw new MintIngestorError(MintIngestionErrorName.CouldNotResolveMint, 'Chain not supported'); + throw new MintIngestorError(MintIngestionErrorName.MintUnsupportedNetwork, 'Chain not supported'); } - const contractAddress = token.isFrame ? BASE_FRAME_CONTRACT_ADDRESS : BASE_FIXED_PRICE_CONTRACT_ADDRESS; - const abi = token.isFrame ? FXHASH_BASE_FRAME_ABI : FXHASH_BASE_FIXED_PRICE_ABI; - - const description = token.metadata?.description || ''; - const image = token.metadata?.thumbnailUri || ''; - - mintBuilder.setName(token.name).setDescription(description).setFeaturedImageUrl(image); - - // The 1 is reserveId in their contract... not clear what for... but it's always 1 - const totalPriceWei = await getFxHashMintPriceInEth( - chainId, - contractAddress, - dropAddress, - 1, - resources.alchemy, - abi, - ); - - mintBuilder.setMintInstructions({ - chainId, - contractAddress, - contractMethod: 'buy', - // Note - the "id" is really the contract address in their system - contractParams: `["${token.id}", 1, 1, address]`, - abi: abi, - priceWei: totalPriceWei, - }); - - const liveDate = new Date() > token.mintOpensAt ? new Date() : new Date(token.mintOpensAt); - mintBuilder - .setAvailableForPurchaseEnd(new Date(token.openEditionsEndsAt || '2030-01-01')) - .setAvailableForPurchaseStart(new Date(token.mintOpensAt || Date.now())) - .setLiveDate(liveDate); - - const output = mintBuilder.build(); - return output; + return this.createMintForContract(resources, { chainId, contractAddress: dropAddress, url }); } } diff --git a/src/ingestors/fxhash/offchain-metadata.ts b/src/ingestors/fxhash/offchain-metadata.ts index 6222342..f2b67de 100644 --- a/src/ingestors/fxhash/offchain-metadata.ts +++ b/src/ingestors/fxhash/offchain-metadata.ts @@ -30,6 +30,25 @@ export const getFxhashMintByContract = async (resources: MintIngestorResources, name mintOpensAt openEditionsEndsAt + author { + account { + profile { + description + farcaster + instagram + picture + twitter + website + } + username + wallets { + address + flag + network + } + id + } + } } } `, diff --git a/src/ingestors/fxhash/onchain-metadata.ts b/src/ingestors/fxhash/onchain-metadata.ts index a96528a..0e97cce 100644 --- a/src/ingestors/fxhash/onchain-metadata.ts +++ b/src/ingestors/fxhash/onchain-metadata.ts @@ -14,6 +14,7 @@ export const getFxHashMintPriceInEth = async ( alchemy: Alchemy, abi: any, ): Promise => { + const contract = await getContract(chainId, contractAddress, alchemy, abi); const tokenPrice = await contract.functions.prices(dropAddress, reserveId); diff --git a/src/lib/builder/mint-template-builder.ts b/src/lib/builder/mint-template-builder.ts index 85497d5..764d98b 100644 --- a/src/lib/builder/mint-template-builder.ts +++ b/src/lib/builder/mint-template-builder.ts @@ -1,4 +1,4 @@ -import { EVMMintInstructions, MintInstructionType, MintTemplate, SolanaMintInstructions } from '../types/mint-template'; +import { CollectionContract, EVMMintInstructions, MintArtistMetadata, MintInstructionType, MintTemplate, SolanaMintInstructions } from '../types/mint-template'; export class MintTemplateBuilder { private mintTemplate: any; @@ -14,11 +14,13 @@ export class MintTemplateBuilder { marketingUrl: null, mintInstructionType: null, mintInstructions: null, + mintOutputContract: null, liveDate: null, availableForPurchaseStart: null, availableForPurchaseEnd: null, partnerName: null, promotionaltext: null, + creator: null, }; } } @@ -92,6 +94,11 @@ export class MintTemplateBuilder { return this; } + setMintOutputContract(mintOutputContract: CollectionContract) { + this.mintTemplate.mintOutputContract = mintOutputContract; + return this; + } + setLiveDate(liveDate: Date) { this.mintTemplate.liveDate = liveDate; return this; @@ -117,6 +124,11 @@ export class MintTemplateBuilder { return this; } + setCreator(creator: MintArtistMetadata) { + this.mintTemplate.creator = creator; + return this; + } + /* Unsetters */ unsetPromotionalText() { @@ -154,6 +166,11 @@ export class MintTemplateBuilder { return this; } + unsetMintOutputContract() { + this.mintTemplate.mintOutputContract = null; + return this; + } + unsetMarketingUrl() { this.mintTemplate.marketingUrl = null; return this; @@ -178,4 +195,9 @@ export class MintTemplateBuilder { this.mintTemplate.images = []; return this; } + + unsetCreator() { + this.mintTemplate.creator = null; + return this; + } } diff --git a/src/lib/types/mint-template.ts b/src/lib/types/mint-template.ts index 2df61d9..2a75dd0 100644 --- a/src/lib/types/mint-template.ts +++ b/src/lib/types/mint-template.ts @@ -10,6 +10,8 @@ export type MintTemplate = { /* Contract details */ mintInstructionType: MintInstructionType; mintInstructions: EVMMintInstructions | SolanaMintInstructions; + /* The address of the NFT contract, if different from the mint contract */ + mintOutputContract: CollectionContract | null; /* Availability */ liveDate: Date | null; @@ -63,12 +65,19 @@ export type MintImage = { export type MintArtistMetadata = { name: string; imageUrl?: string | null; + walletAddress?: string | null; websiteUrl?: string | null; description?: string | null; - twitterHandle?: string | null; - instagram?: string | null; - discord?: string | null; - tikTok?: string | null; - github?: string | null; - farcaster?: string | null; + twitterUsername?: string | null; + floorUsername?: string | null; + instagramUsername?: string | null; + discordUsername?: string | null; + tikTokUsername?: string | null; + githubUsername?: string | null; + farcasterUsername?: string | null; }; + +export type CollectionContract = { + address: string; + chainId: number; +} \ No newline at end of file diff --git a/test/ingestors/fxhash.test.ts b/test/ingestors/fxhash.test.ts index 7edbcd2..0a567b6 100644 --- a/test/ingestors/fxhash.test.ts +++ b/test/ingestors/fxhash.test.ts @@ -69,6 +69,9 @@ describe('fxhash', function () { expect(mintInstructions.priceWei).to.equal('500000000000000'); expect(template.featuredImageUrl).to.equal('ipfs://QmYV4LXoz18youcW7zREFFFVpPf6Tn1j4QRzmTi1cSPinb'); + expect(template.creator?.name).to.equal('P|mll'); + expect(template.creator?.imageUrl).to.not.be.empty; + expect(template.creator?.walletAddress).to.equal('0x6eF478BeFe3f7Ae12E6357311C3826a865626643'); expect(template.marketingUrl).to.equal(url); expect(template.availableForPurchaseStart?.getTime()).to.equal(1718983800000); diff --git a/yarn.lock b/yarn.lock index 04052eb..ca4f4e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -683,14 +683,7 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/chai-as-promised@^7.1.8": - version "7.1.8" - resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" - integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== - dependencies: - "@types/chai" "*" - -"@types/chai@*", "@types/chai@^4.3.16": +"@types/chai@^4.3.16": version "4.3.16" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== @@ -1194,13 +1187,6 @@ camelcase@^7.0.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== -chai-as-promised@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-8.0.0.tgz#7eda823f2a6fe9fd3a76bc76878886e955232e6f" - integrity sha512-sMsGXTrS3FunP/wbqh/KxM8Kj/aLPXQGkNtvE5wPfSToq8wkkvBpTZo1LIiEVmC4BwkKpag+l5h/20lBMk6nUg== - dependencies: - check-error "^2.0.0" - chai@^4.3.9: version "4.4.1" resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" @@ -1266,11 +1252,6 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -check-error@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" - integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== - chokidar@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -3933,7 +3914,7 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3959,6 +3940,15 @@ string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -3975,7 +3965,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4003,6 +3993,13 @@ strip-ansi@^5.1.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -4432,7 +4429,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -4458,6 +4455,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"