Skip to content

Commit

Permalink
Merge branch 'floornfts:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
chainparser authored Jul 16, 2024
2 parents 076e358 + 961e571 commit 5916f86
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 125 deletions.
15 changes: 15 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Mint Ingestor: <Platform Name>

### Functionality Supported
* Ingesting from URL: Yes / No
* Ingesting from Contract address: Yes / No
* Supported Networks: Base / Ethereum / Arbitrum / Zora / Polygon / Others..

### Before you submit
- [ ] Ensure your generated MintTemplate works 😄
- [ ] Ensure that your code is restricted to a single folder in `src/ingestors`
- [ ] Ensure that all required assets are included (e.g. ABIs)
- [ ] Ensure ABIs are trimmed to include only methods (1) used in the ingestor or (2) required to mint
- [ ] Ensure that all exported methods are prefixed with the name of your ingestor e.g. `myMintingPlatformGetContractDetails`
- [ ] Ensure that a test exists for generating a MintTemplate that will always succeed
- [ ] Ensure that your code accesses **no external resources** except those passed in the `resources` object
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ Once you've written a Mobile Minting Ingestor, it needs to be Pull Requested to
- [ ] Ensure that your code is restricted to a single folder in `src/ingestors`
- [ ] Ensure that all required assets are included (e.g. ABIs)
- [ ] Ensure ABIs are trimmed to include only methods (1) used in the ingestor or (2) required to mint
- [ ] Ensure that all exported methods are prefixed with the name of your ingestor e.g. `myMintingPlatformGetContractDetails`
- [ ] Ensure that a test exists for generating a MintTemplate that will always succeed
- [ ] Ensure that your code accesses **no external resources** except those passed in the `resources` object

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@floornfts/mobile-minting",
"version": "1.0.6",
"version": "1.0.7",
"repository": "git://github.com/floornfts/mobile-minting.git",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down Expand Up @@ -34,7 +34,7 @@
"lint": "eslint src/**/*.ts",
"format": "eslint src/**/*.ts --fix",
"test": "NODE_OPTIONS=\"--loader ts-node/esm\" c8 mocha --require ts-node/register",
"release": "np",
"release": "npm run build && np",
"dry-run": "ts-node src/dry-run/index.ts"
},
"dependencies": {
Expand Down
27 changes: 1 addition & 26 deletions src/ingestors/fxhash/abi.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,4 @@
export const FXHASH_BASE_FRAME_ABI = [
{
inputs: [
{ internalType: 'address', name: '_token', type: 'address' },
{ internalType: 'uint256', name: '_reserveId', type: 'uint256' },
{ internalType: 'uint256', name: '_amount', type: 'uint256' },
{ internalType: 'address', name: '_to', type: 'address' },
],
name: 'buy',
outputs: [],
stateMutability: 'payable',
type: 'function',
},
{
inputs: [
{ internalType: 'address', name: '', type: 'address' },
{ internalType: 'uint256', name: '', type: 'uint256' },
],
name: 'prices',
outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
stateMutability: 'view',
type: 'function',
}
];

export const FXHASH_BASE_FIXED_PRICE_ABI = [
export const FX_HASH_MINTABLE_ABI = [
{
inputs: [
{ internalType: 'address', name: '_token', type: 'address' },
Expand Down
31 changes: 12 additions & 19 deletions src/ingestors/fxhash/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ import { MintContractOptions, MintIngestor, MintIngestorResources } from '../../
import { MintIngestionErrorName, MintIngestorError } from '../../lib/types/mint-ingestor-error';
import { MintInstructionType, MintTemplate } from '../../lib/types/mint-template';
import { MintTemplateBuilder } from '../../lib/builder/mint-template-builder';
import { FXHASH_BASE_FIXED_PRICE_ABI, FXHASH_BASE_FRAME_ABI } from './abi';
import { getFxHashMintPriceInEth } from './onchain-metadata';
import { getFxhashMintByContract, getFxHashMintsBySlug } from './offchain-metadata';

const BASE_FRAME_CONTRACT_ADDRESS = '0x6e625892C739bFD960671Db5544E260757480725';
const BASE_FIXED_PRICE_CONTRACT_ADDRESS = '0x4bDcaC532143d8d35ed759189EE22E3704580b9D';
import { fxHashContractForPricingType, getFxhashMintByContract, getFxHashMintsBySlug, fxHashGetPricingFromParams } from './offchain-metadata';
import { FX_HASH_MINTABLE_ABI } from './abi';

export class FxHashIngestor implements MintIngestor {
async supportsUrl(_resources: MintIngestorResources, url: string): Promise<boolean> {
Expand Down Expand Up @@ -40,8 +36,15 @@ export class FxHashIngestor implements MintIngestor {
throw new MintIngestorError(MintIngestionErrorName.CouldNotResolveMint, 'Project not found');
}

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 { priceWei, type } = fxHashGetPricingFromParams(token);

if (!type) {
throw new MintIngestorError(MintIngestionErrorName.CouldNotResolveMint, 'Could not resolve mint type');
}

const contractAddress = fxHashContractForPricingType(type);

const abi = FX_HASH_MINTABLE_ABI;

const description = token.metadata?.description || '';
const image = token.metadata?.thumbnailUri || '';
Expand All @@ -57,23 +60,13 @@ export class FxHashIngestor implements MintIngestor {
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,
0,
resources.alchemy,
abi,
);

mintBuilder.setMintInstructions({
chainId: contract.chainId,
contractAddress,
contractMethod: 'buy',
contractParams: `["${contract.contractAddress}", 1, 1, address]`,
abi: abi,
priceWei: totalPriceWei,
priceWei: `${priceWei}`,
});

const liveDate = new Date() > token.mintOpensAt ? new Date() : new Date(token.mintOpensAt);
Expand Down
172 changes: 120 additions & 52 deletions src/ingestors/fxhash/offchain-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
import axios from "axios";
import { MintContractOptions, MintIngestorResources } from "src/lib";

export const getFxhashMintByContract = async (resources: MintIngestorResources, contract: MintContractOptions): Promise<any> => {
const graphQLRes = await resources.fetcher({
url: 'https://api.v2-temp.fxhash.xyz/graphql',
method: 'POST',
headers: {
accept: '*/*',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'application/json',
priority: 'u=1, i',
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
Referer: 'https://www.fxhash.xyz/',
'Referrer-Policy': 'strict-origin-when-cross-origin',
},
headers: fxHashGraphQlheaders,
data: {
query: `
query GenerativeToken($generativeTokenId: String) {
Expand All @@ -30,6 +16,21 @@ export const getFxhashMintByContract = async (resources: MintIngestorResources,
name
mintOpensAt
openEditionsEndsAt
reserves {
method
amount
data
}
pricingFixed {
opensAt
price
}
pricingDutchAuction {
opensAt
levels
decrementDuration
restingPrice
}
author {
account {
profile {
Expand Down Expand Up @@ -73,47 +74,114 @@ export const getFxHashMintsBySlug = async (resources: MintIngestorResources, slu
return acc;
}, '');

const graphQLRes = await resources.fetcher({
url: 'https://api.v2-temp.fxhash.xyz/graphql',
method: 'POST',
headers: {
accept: '*/*',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'application/json',
priority: 'u=1, i',
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
Referer: 'https://www.fxhash.xyz/',
'Referrer-Policy': 'strict-origin-when-cross-origin',
},
data: {
query: `
query GenerativeToken($filters: SearchFilters!) {
search(filters: $filters) {
generativeTokens {
slug
id
chain
isFrame
name
metadata
mintOpensAt
openEditionsEndsAt
try {
const graphQLRes = await resources.fetcher({
url: 'https://api.v2-temp.fxhash.xyz/graphql',
method: 'POST',
headers: fxHashGraphQlheaders,
data: {
query: `
query GenerativeToken($filters: SearchFilters!) {
search(filters: $filters) {
generativeTokens {
slug
id
chain
name
metadata
mintOpensAt
reserves {
method
amount
data
}
pricingFixed {
opensAt
price
}
pricingDutchAuction {
opensAt
levels
decrementDuration
restingPrice
}
openEditionsEndsAt
}
}
`,
variables: {
filters: {
searchQuery_eq: longestSlug,
}
`,
variables: {
filters: {
searchQuery_eq: longestSlug,
},
},
},
},
});
});

return graphQLRes.data.data.search.generativeTokens;
} catch (error) {
return [];
}
}


const fxHashGraphQlheaders = {
accept: '*/*',
'authority': 'api.fxhash.xyz',
'accept-language': 'en-US,en;q=0.9',
'content-type': 'application/json',
priority: 'u=1, i',
'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-site',
Referer: 'https://studio.apollographql.com/sandbox/explorer',
'Referrer-Policy': 'strict-origin-when-cross-origin',
'Origin': 'https://studio.apollographql.com',

};

enum FxHashPricingType {
FIXED = 'FIXED',
DUTCH_AUCTION = 'DUTCH_AUCTION',
FRAME = 'FRAME',
}
export function fxHashGetPricingFromParams(
generativeToken: any
) {
if (!generativeToken) {
throw new Error("generativeToken is null or undefined")
}
const { pricingFixed, pricingDutchAuction, isFrame } = generativeToken;
let price = 0;
let type: FxHashPricingType | undefined = isFrame ? FxHashPricingType.FRAME : undefined;
if (pricingFixed) {
type = type || FxHashPricingType.FIXED;
price = pricingFixed.price;
}
if (pricingDutchAuction) {
type = FxHashPricingType.DUTCH_AUCTION;
price = pricingDutchAuction.restingPrice;
}

return { priceWei: price, type: type }
}

const BASE_FRAME_CONTRACT_ADDRESS = '0x6e625892C739bFD960671Db5544E260757480725';
const BASE_FIXED_PRICE_CONTRACT_ADDRESS = '0x4bDcaC532143d8d35ed759189EE22E3704580b9D';
const BASE_DUTCH_AUCTION_CONTRACT_ADDRESS = '0x9667a1Cf26223c9de22207DD93cfEEc9237b8f4E';

return graphQLRes.data.data.search.generativeTokens;
export function fxHashContractForPricingType(mintType: FxHashPricingType) {
if (mintType === FxHashPricingType.FRAME) {
return BASE_FRAME_CONTRACT_ADDRESS;
}
if (mintType === FxHashPricingType.FIXED) {
return BASE_FIXED_PRICE_CONTRACT_ADDRESS;
}
if (mintType === FxHashPricingType.DUTCH_AUCTION) {
return BASE_DUTCH_AUCTION_CONTRACT_ADDRESS;
}
throw new Error(`Unknown mint type: ${mintType}`);
}
23 changes: 0 additions & 23 deletions src/ingestors/fxhash/onchain-metadata.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/ingestors/prohibition-daily/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class ProhibitionDailyIngestor implements MintIngestor {
if (new URL(url).hostname !== 'daily.prohibition.art') {
return false;
}
const { chainId, contractAddress } = await prohibitionOnchainDataFromUrl(url, resources.fetcher);
const { chainId, contractAddress } = await prohibitionOnchainDataFromUrl(url);
return !!chainId && !!contractAddress;
}

Expand All @@ -36,7 +36,7 @@ export class ProhibitionDailyIngestor implements MintIngestor {
throw new MintIngestorError(MintIngestionErrorName.IncompatibleUrl, 'Incompatible URL');
}

const { chainId, contractAddress } = await prohibitionOnchainDataFromUrl(url, resources.fetcher);
const { chainId, contractAddress } = await prohibitionOnchainDataFromUrl(url);

if (!chainId || !contractAddress) {
throw new MintIngestorError(MintIngestionErrorName.MissingRequiredData, 'Missing required data');
Expand Down
2 changes: 1 addition & 1 deletion src/ingestors/prohibition-daily/offchain-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const urlForValidProhibitionPage = async (chainId: number, contractAddres
}
};

export const prohibitionOnchainDataFromUrl = async (url: string, fetcher: Axios): Promise<{ chainId: number | undefined, contractAddress: string | undefined }> => {
export const prohibitionOnchainDataFromUrl = async (url: string): Promise<{ chainId: number | undefined, contractAddress: string | undefined }> => {
// https://daily.prohibition.art/mint/8453/0x20479b19ca05e0b63875a65acf24d81cd0973331
const urlParts = url.split('/');
const contractAddress = urlParts.pop();
Expand Down

0 comments on commit 5916f86

Please sign in to comment.