Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

wip: Add 'mintType' to AssetContract decoder/query #420

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/lib/nfts/decoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,42 @@ export const ContractRow = <S extends t.Mixed>(storage: S) =>
storage: storage
});

const MintEntrypointBaseSchema = t.type({
'token_metadata:object': t.type({
'token_id:nat': t.literal('nat'),
'token_info:map_flat:string:bytes': t.type({
string: t.literal('bytes')
})
}),
'owner:address': t.literal('address')
});

const MintEntrypointEditionSchema = t.intersection([
MintEntrypointBaseSchema,
t.type({
'amount:nat': t.literal('nat')
})
]);

const MintEntrypointGeneric = <S extends t.Mixed>(schema: S) =>
t.type({
name: t.literal('mint'),
jsonParameters: t.type({ 'schema:list:object': t.array(schema) }),
unused: t.literal(false)
});

export const MintEntrypointBase = MintEntrypointGeneric(
MintEntrypointBaseSchema
);
export const MintEntrypointEdition = MintEntrypointGeneric(
MintEntrypointEditionSchema
);

export const MintEntrypoint = t.union([
MintEntrypointEdition,
MintEntrypointBase
]);

// Generic BigMaps

export const BigMapRow = <K extends t.Mixed, V extends t.Mixed>(props: {
Expand Down Expand Up @@ -195,5 +231,8 @@ export const AssetContract = t.intersection([
ContractRow(t.unknown),
t.type({
metadata: AssetContractMetadata
}),
t.partial({
mintType: t.union([t.literal('basic'), t.literal('editions')])
})
]);
53 changes: 46 additions & 7 deletions src/lib/nfts/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ async function getFixedPriceSalesBigMap(
if (isLeft(t.number.decode(fixedPriceBigMapId))) {
throw Error('Failed to decode `getFixedPriceSales` bigMap ID');
}
const fixedPriceSales = transformFixedPriceSales(await tzkt.getBigMapKeys(fixedPriceBigMapId));
const fixedPriceSales = transformFixedPriceSales(
await tzkt.getBigMapKeys(fixedPriceBigMapId)
);
const decoded = D.FixedPriceSaleBigMap.decode(fixedPriceSales);
if (isLeft(decoded)) {
throw Error('Failed to decode `getFixedPriceSales` response');
Expand Down Expand Up @@ -126,11 +128,41 @@ async function getContract<S extends t.Mixed>(
const contract = await tzkt.getContract(address, params);
const decoded = D.ContractRow(storage).decode(contract);
if (isLeft(decoded)) {
throw Error('Failed to decode `getContracts` response');
throw Error('Failed to decode `getContract` response');
}
return decoded.right;
}

async function getContractEntrypoint<S extends t.Mixed>(
tzkt: TzKt,
address: string,
entrypoint: string,
params: Params,
decoder: S
) {
const contract = await tzkt.getContractEntrypoint(
address,
entrypoint,
params
);
const decoded = decoder.decode(contract);
if (isLeft(decoded)) {
throw Error('Failed to decode `getContractEntrypoint` response');
}
return decoded.right;
}

async function getMintEntrypointType(tzkt: TzKt, address: string) {
const mintEntrypoint = await getContractEntrypoint(
tzkt,
address,
'mint',
{},
D.MintEntrypoint
);
return D.MintEntrypointEdition.is(mintEntrypoint) ? 'editions' : 'basic';
}

//// Main query functions

export async function getContractNfts(
Expand Down Expand Up @@ -189,6 +221,8 @@ export async function getNftAssetContract(
address: string
): Promise<D.AssetContract> {
const contract = await getContract(system.tzkt, address, {}, t.unknown);

const mintType = await getMintEntrypointType(system.tzkt, contract.address);
const metaBigMap = await getAssetMetadataBigMap(system.tzkt, address);
const metaUri = metaBigMap.find(v => v.key === '')?.value;
if (!metaUri) {
Expand All @@ -204,7 +238,7 @@ export async function getNftAssetContract(
if (isLeft(decoded)) {
throw Error('Metadata validation failed');
}
return { ...contract, metadata: decoded.right };
return { ...contract, metadata: decoded.right, mintType };
}

export async function getWalletNftAssetContracts(
Expand Down Expand Up @@ -252,15 +286,20 @@ export async function getWalletNftAssetContracts(
if (!contract) {
continue;
}

try {
const mintType: 'editions' | 'basic' = await getMintEntrypointType(
system.tzkt,
contract.address
).catch(() => 'basic');
const metaUri = row.content.value;
const { metadata } = await system.resolveMetadata(
fromHexString(metaUri),
contract.address
);
const decoded = D.AssetContractMetadata.decode(metadata);
if (!isLeft(decoded)) {
results.push({ ...contract, metadata: decoded.right });
results.push({ ...contract, metadata: decoded.right, mintType });
}
} catch (e) {
console.log(e);
Expand Down Expand Up @@ -333,10 +372,10 @@ export async function getMarketplaceNfts(
return salesWithTokenMetadata;
}

export const loadMarketplaceNft = async (
export async function loadMarketplaceNft(
system: SystemWithToolkit | SystemWithWallet,
tokenLoadData: MarketplaceNftLoadingData
): Promise<MarketplaceNftLoadingData> => {
): Promise<MarketplaceNftLoadingData> {
const { token, loaded, tokenSale, tokenMetadata } = tokenLoadData;
const result = { ...tokenLoadData };

Expand Down Expand Up @@ -389,4 +428,4 @@ export const loadMarketplaceNft = async (
console.error("Couldn't load token", { tokenSale, err });
return result;
}
};
}
33 changes: 33 additions & 0 deletions src/lib/service/tzkt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@ export async function getContract(
return response.data;
}

export async function getContractEntrypoints(
config: Config,
address: string,
params?: Params
) {
const uri = `${
config.tzkt.api
}/v1/contracts/${address}/entrypoints?${mkQueryParams(params)}`;
const response = await axios.get(uri);
return response.data;
}

export async function getContractEntrypoint(
config: Config,
address: string,
entrypoint: string,
params?: Params
) {
const uri = `${
config.tzkt.api
}/v1/contracts/${address}/entrypoints/${entrypoint}?${mkQueryParams(params)}`;
const response = await axios.get(uri);
return response.data;
}

export async function getContractBigMapKeys(
config: Config,
address: string,
Expand Down Expand Up @@ -92,6 +117,14 @@ export class TzKt {
return getContract(this.config, address, params);
}

getContractEntrypoints(address: string, params?: Params) {
return getContractEntrypoints(this.config, address, params);
}

getContractEntrypoint(address: string, entrypoint: string, params?: Params) {
return getContractEntrypoint(this.config, address, entrypoint, params);
}

getContractBigMapKeys(address: string, name: string, params?: Params) {
return getContractBigMapKeys(this.config, address, name, params);
}
Expand Down