Skip to content

Commit

Permalink
refactor!: move asset info type from Cardano to Asset
Browse files Browse the repository at this point in the history
rename Asset->AssetInfo, make AssetInfo.history nullable
  • Loading branch information
mkazlauskas committed Feb 14, 2022
1 parent 8220bfb commit 212b670
Show file tree
Hide file tree
Showing 21 changed files with 142 additions and 133 deletions.
6 changes: 3 additions & 3 deletions packages/blockfrost/src/blockfrostAssetProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { omit } from 'lodash-es';
const mapMetadata = (
onChain: Responses['asset']['onchain_metadata'],
offChain: Responses['asset']['metadata']
): Cardano.TokenMetadata => {
): Asset.TokenMetadata => {
const metadata = { ...onChain, ...offChain };
return {
...util.replaceNullsWithUndefineds(omit(metadata, ['logo', 'image'])),
Expand All @@ -33,11 +33,11 @@ const mapMetadata = (
export const blockfrostAssetProvider = (options: Options): AssetProvider => {
const blockfrost = new BlockFrostAPI(options);

const getAssetHistory = async (assetId: Cardano.AssetId): Promise<Cardano.AssetMintOrBurn[]> =>
const getAssetHistory = async (assetId: Cardano.AssetId): Promise<Asset.AssetMintOrBurn[]> =>
fetchSequentially({
arg: assetId.toString(),
request: blockfrost.assetsHistory.bind<BlockFrostAPI['assetsHistory']>(blockfrost),
responseTranslator: (response): Cardano.AssetMintOrBurn[] =>
responseTranslator: (response): Asset.AssetMintOrBurn[] =>
response.map(({ action, amount, tx_hash }) => ({
quantity: BigInt(amount) * (action === 'minted' ? 1n : -1n),
transactionId: Cardano.TransactionId(tx_hash)
Expand Down
6 changes: 3 additions & 3 deletions packages/blockfrost/test/blockfrostAssetProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable max-len */

import { Asset, Cardano } from '@cardano-sdk/core';
import { BlockFrostAPI, Responses } from '@blockfrost/blockfrost-js';
import { Cardano } from '@cardano-sdk/core';
import { blockfrostAssetProvider } from '../src';
jest.mock('@blockfrost/blockfrost-js');

Expand Down Expand Up @@ -41,7 +41,7 @@ describe('blockfrostAssetProvider', () => {
Cardano.AssetId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e')
);

expect(response).toMatchObject<Cardano.Asset>({
expect(response).toMatchObject<Asset.AssetInfo>({
assetId: Cardano.AssetId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e'),
fingerprint: Cardano.AssetFingerprint('asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w'),
history: [
Expand Down Expand Up @@ -87,7 +87,7 @@ describe('blockfrostAssetProvider', () => {
Cardano.AssetId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e')
);

expect(response).toMatchObject<Cardano.Asset>({
expect(response).toMatchObject<Asset.AssetInfo>({
assetId: Cardano.AssetId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a76e7574636f696e'),
fingerprint: Cardano.AssetFingerprint('asset1pkpwyknlvul7az0xx8czhl60pyel45rpje4z8w'),
history: [
Expand Down
6 changes: 3 additions & 3 deletions packages/cardano-graphql/src/Schema/types/Asset/Asset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Cardano } from '@cardano-sdk/core';
import { Asset as AssetTypes, Cardano } from '@cardano-sdk/core';
import { Directive, Field, Int, ObjectType } from 'type-graphql';
import { Int64 } from '../util';
import { NftMetadata } from './NftMetadata';
Expand Down Expand Up @@ -36,10 +36,10 @@ export class Asset {
@Field(() => String, { description: 'Fingerprint of a native asset for human comparison. CIP-0014' })
fingerprint: Cardano.AssetFingerprint;
@Field(() => [AssetMintOrBurn])
history: Cardano.AssetMintOrBurn[];
history: AssetTypes.AssetMintOrBurn[];
@Directive('@hasInverse(field: asset)')
@Field(() => TokenMetadata, { description: 'CIP-0035', nullable: true })
tokenMetadata?: Cardano.TokenMetadata;
tokenMetadata?: AssetTypes.TokenMetadata;
@Directive('@hasInverse(field: asset)')
@Field(() => NftMetadata, { description: 'CIP-0025', nullable: true })
nftMetadata?: NftMetadata;
Expand Down
2 changes: 1 addition & 1 deletion packages/cardano-graphql/src/Schema/types/Asset/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class Policy {
id: Cardano.PolicyId;
@Directive('@hasInverse(field: policy)')
@Field(() => [Asset])
assets: Cardano.Asset[];
assets: Asset[];
@Field(() => Script)
script: Cardano.Script;
@Field(() => PublicKey)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Asset } from './Asset';
import { Cardano } from '@cardano-sdk/core';
import { Asset as AssetTypes } from '@cardano-sdk/core';
import { Field, Int, ObjectType } from 'type-graphql';

@ObjectType()
Expand Down Expand Up @@ -48,7 +48,7 @@ export class TokenMetadata {
@Field(() => String, { defaultValue: '1.0' })
version: string;
@Field(() => [TokenMetadataSizedIcon])
sizedIcons: Cardano.TokenMetadataSizedIcon[];
sizedIcons: AssetTypes.TokenMetadataSizedIcon[];
@Field(() => Asset)
asset: Asset;
}
2 changes: 1 addition & 1 deletion packages/core/src/Asset/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * as util from './util';
export * from './NftMetadata';
export * from './types';
32 changes: 32 additions & 0 deletions packages/core/src/Asset/types/AssetInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { AssetFingerprint, AssetId, AssetName, PolicyId, TransactionId } from '../../Cardano';
import { NftMetadata } from './NftMetadata';
import { TokenMetadata } from './TokenMetadata';

export interface AssetMintOrBurn {
transactionId: TransactionId;
/**
* Positive = mint
* Negative = burn
*/
quantity: bigint;
}

export interface AssetInfo {
assetId: AssetId;
policyId: PolicyId;
name: AssetName;
fingerprint: AssetFingerprint;
quantity: bigint;
/**
* Sorted by slot
*/
history?: AssetMintOrBurn[];
/**
* CIP-0035
*/
metadata?: TokenMetadata;
/**
* CIP-0025
*/
nftMetadata?: NftMetadata;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable wrap-regex */
import { InvalidStringError } from '../errors';
import { Metadatum, util } from '../Cardano';
import { InvalidStringError } from '../../errors';
import { Metadatum, util } from '../../Cardano';

export type Uri = util.OpaqueString<'Uri'>;
export const Uri = (uri: string) => {
Expand Down
59 changes: 59 additions & 0 deletions packages/core/src/Asset/types/TokenMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export interface TokenMetadataSizedIcon {
/**
* Most likely one of 16, 32, 64, 96, 128
* icons are assumed to be square
*/
size: number;
/**
* MUST be either https, ipfs, or data. icon MUST be a browser supported image format.
*/
icon: string;
}

/**
* Either on-chain or off-chain asset metadata
*
* CIP-0035
* https://github.com/cardano-foundation/CIPs/pull/137
*/
export interface TokenMetadata {
/**
* Asset name
*/
name?: string;
/**
* when present, field and overrides default ticker which is the asset name
*/
ticker?: string;
/**
* MUST be either https, ipfs, or data. icon MUST be a browser supported image format.
*/
icon?: string;
/**
* allows teams to provide icon in different sizes
*/
sizedIcons?: TokenMetadataSizedIcon[];
/**
* https only url that refers to metadata stored offchain.
* The URL SHOULD use the project domain and
* MUST return authenticity metadata in either html or json format (see below)
*/
url?: string;
/**
* additional description that defines the usage of the token
*/
desc?: string;
/**
* how many decimal places should the token support? For ADA, this would be 6 e.g. 1 ADA is 10^6 Lovelace
*/
decimals?: number;
/**
* https only url that holds the metadata in the onchain format.
* The URL SHOULD use the project domain and MUST return the token metadata as described above
*/
ref?: string;
/**
* when not specified, version will default to `1.0`
*/
version?: '1.0';
}
3 changes: 3 additions & 0 deletions packages/core/src/Asset/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './NftMetadata';
export * from './TokenMetadata';
export * from './AssetInfo';
8 changes: 4 additions & 4 deletions packages/core/src/Asset/util/metadatumToCip25.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Asset, Metadatum, MetadatumMap, util } from '../../Cardano';
import { AssetInfo, ImageMediaType, MediaType, NftMetadata, NftMetadataFile, Uri } from '../types';
import { CustomError } from 'ts-custom-error';
import { ImageMediaType, MediaType, NftMetadata, NftMetadataFile, Uri } from '../NftMetadata';
import { Metadatum, MetadatumMap, util } from '../../Cardano';
import { dummyLogger } from 'ts-log';
import { omit } from 'lodash-es';

Expand Down Expand Up @@ -42,7 +42,7 @@ const mapFile = (metadatum: Metadatum): NftMetadataFile => {
/**
* Also considers asset name encoded in utf8 within metadata valid
*/
const getAssetMetadata = (policy: MetadatumMap, asset: Asset) =>
const getAssetMetadata = (policy: MetadatumMap, asset: Pick<AssetInfo, 'name'>) =>
util.metadatum.asMetadatumMap(
policy[asset.name.toString()] || policy[Buffer.from(asset.name, 'hex').toString('utf8')]
);
Expand All @@ -52,7 +52,7 @@ const getAssetMetadata = (policy: MetadatumMap, asset: Asset) =>
* @returns {NftMetadata | undefined} CIP-0025 NFT metadata
*/
export const metadatumToCip25 = (
asset: Asset,
asset: Pick<AssetInfo, 'policyId' | 'name'>,
metadatumMap: MetadatumMap | undefined,
logger = dummyLogger
): NftMetadata | undefined => {
Expand Down
86 changes: 0 additions & 86 deletions packages/core/src/Cardano/types/Asset.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Hash28ByteBase16, OpaqueString, assertIsHexString, typedBech32 } from '../util';
import { InvalidStringError } from '../..';
import { TransactionId } from './Transaction';

export type AssetId = OpaqueString<'AssetId'>;

Expand Down Expand Up @@ -41,88 +40,3 @@ export const PolicyId = (value: string): PolicyId => Hash28ByteBase16(value);
*/
export type AssetFingerprint = OpaqueString<'AssetFingerprint'>;
export const AssetFingerprint = (value: string): AssetFingerprint => typedBech32(value, 'asset', 32);

export interface TokenMetadataSizedIcon {
/**
* Most likely one of 16, 32, 64, 96, 128
* icons are assumed to be square
*/
size: number;
/**
* MUST be either https, ipfs, or data. icon MUST be a browser supported image format.
*/
icon: string;
}

/**
* Either on-chain or off-chain asset metadata
*
* CIP-0035
* https://github.com/cardano-foundation/CIPs/pull/137
*/
export interface TokenMetadata {
/**
* Asset name
*/
name?: string;
/**
* when present, field and overrides default ticker which is the asset name
*/
ticker?: string;
/**
* MUST be either https, ipfs, or data. icon MUST be a browser supported image format.
*/
icon?: string;
/**
* allows teams to provide icon in different sizes
*/
sizedIcons?: TokenMetadataSizedIcon[];
/**
* https only url that refers to metadata stored offchain.
* The URL SHOULD use the project domain and
* MUST return authenticity metadata in either html or json format (see below)
*/
url?: string;
/**
* additional description that defines the usage of the token
*/
desc?: string;
/**
* how many decimal places should the token support? For ADA, this would be 6 e.g. 1 ADA is 10^6 Lovelace
*/
decimals?: number;
/**
* https only url that holds the metadata in the onchain format.
* The URL SHOULD use the project domain and MUST return the token metadata as described above
*/
ref?: string;
/**
* when not specified, version will default to `1.0`
*/
version?: '1.0';
}

export interface AssetMintOrBurn {
transactionId: TransactionId;
/**
* Positive = mint
* Negative = burn
*/
quantity: bigint;
}

export interface Asset {
assetId: AssetId;
policyId: PolicyId;
name: AssetName;
fingerprint: AssetFingerprint;
quantity: bigint;
/**
* Sorted by slot
*/
history: AssetMintOrBurn[];
/**
* CIP-0035
*/
metadata?: TokenMetadata;
}
4 changes: 2 additions & 2 deletions packages/core/src/Provider/AssetProvider/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Cardano } from '../..';
import { Asset, Cardano } from '../..';

export interface AssetProvider {
/**
* @param id asset ID (concatenated hex values of policyId + assetName)
* @throws ProviderError
*/
getAsset: (id: Cardano.AssetId) => Promise<Cardano.Asset>;
getAsset: (id: Cardano.AssetId) => Promise<Asset.AssetInfo>;
}
5 changes: 2 additions & 3 deletions packages/core/src/Provider/NftMetadataProvider/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Asset } from '../../Cardano';
import { NftMetadata } from '../../Asset';
import { AssetInfo, NftMetadata } from '../../Asset';

export interface NftMetadataProvider {
(asset: Asset): Promise<NftMetadata | undefined>;
(asset: AssetInfo): Promise<NftMetadata | undefined>;
}
5 changes: 3 additions & 2 deletions packages/core/test/Asset/util/metadatumToCip25.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Asset, AssetName, MetadatumMap, PolicyId } from '../../../src/Cardano';
import { AssetInfo } from '../../../src/Asset';
import { AssetName, MetadatumMap, PolicyId } from '../../../src/Cardano';
import { metadatumToCip25 } from '../../../src/Asset/util';
import { omit } from 'lodash';

describe('NftMetadata/metadatumToCip25', () => {
const asset = {
name: AssetName('abc123'),
policyId: PolicyId('b0d07d45fe9514f80213f4020e5a61241458be626841cde717cb38a7')
} as Asset;
} as AssetInfo;

const minimalMetadata = {
image: 'ipfs://image',
Expand Down
11 changes: 4 additions & 7 deletions packages/wallet/src/services/AssetsTracker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AssetProvider, Cardano, NftMetadataProvider } from '@cardano-sdk/core';
import { AssetWithNftMetadata, Assets } from '../types';
import { Asset, AssetProvider, Cardano, NftMetadataProvider } from '@cardano-sdk/core';
import { Assets } from '../types';
import { Balance, TransactionalTracker } from './types';
import { RetryBackoffConfig } from 'backoff-rxjs';
import { coldObservableProvider } from './util';
Expand All @@ -15,7 +15,7 @@ export const createAssetService =
export type AssetService = ReturnType<typeof createAssetService>;

export const createNftMetadataService =
(nftMetadataProvider: NftMetadataProvider, retryBackoffConfig: RetryBackoffConfig) => (asset: Cardano.Asset) =>
(nftMetadataProvider: NftMetadataProvider, retryBackoffConfig: RetryBackoffConfig) => (asset: Asset.AssetInfo) =>
coldObservableProvider(
() => nftMetadataProvider(asset),
retryBackoffConfig,
Expand Down Expand Up @@ -47,9 +47,6 @@ export const createAssetsTracker = (
distinct(),
mergeMap((assetId) => assetService(assetId)),
mergeMap((asset) => nftMetadataService(asset).pipe(map((nftMetadata) => ({ ...asset, nftMetadata })))),
scan(
(assets, asset) => new Map([...assets, [asset.assetId, asset]]),
new Map<Cardano.AssetId, AssetWithNftMetadata>()
),
scan((assets, asset) => new Map([...assets, [asset.assetId, asset]]), new Map<Cardano.AssetId, Asset.AssetInfo>()),
startWith({} as Assets)
);
Loading

0 comments on commit 212b670

Please sign in to comment.