Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error handling for DX #36

Closed
wants to merge 5 commits into from
Closed
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
142 changes: 62 additions & 80 deletions src/datanft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,21 @@ import {
networkConfiguration
} from './config';
import {
checkStatus,
createNftIdentifier,
numberToPaddedHex,
parseDataNft,
validateSpecificParamsViewData
} from './utils';
import minterAbi from './abis/datanftmint.abi.json';
import { NftType, ViewDataReturnType } from './interfaces';
// import {
// ErrDataNftCreation,
// ErrDecodeAttributes,
// ErrFailedOperation,
// ErrAttributeNotSet,
// ErrNetworkConfig
// } from './errors';
import {
ErrAttributeNotSet,
ErrDataNftCreate,
ErrDecodeAttributes,
ErrFetch,
ErrNetworkConfig
} from './errors';

export class DataNft {
readonly tokenIdentifier: string = '';
Expand Down Expand Up @@ -60,6 +61,11 @@ export class DataNft {
* @param env 'devnet' | 'mainnet' | 'testnet'
*/
static setNetworkConfig(env: string) {
if (!(env in EnvironmentsEnum)) {
throw new ErrNetworkConfig(
`Invalid environment: ${env}, Expected: 'devnet' | 'mainnet' | 'testnet'`
);
}
this.env = env;
this.networkConfiguration = networkConfiguration[env as EnvironmentsEnum];
this.apiConfiguration = apiConfiguration[env as EnvironmentsEnum];
Expand All @@ -82,20 +88,19 @@ export class DataNft {
dataNftTokenIdentifier[this.env as EnvironmentsEnum],
token.nonce
);

const response = await fetch(`${this.apiConfiguration}/nfts/${identifier}`);

checkStatus(response);

const data: NftType = await response.json();

try {
const dataNft = parseDataNft(data);

return dataNft;
} catch (error) {
throw error;
// if (error instanceof Error) {
// throw new ErrDataNftCreation(error);
// } else {
// throw ErrDataNftCreation;
// }
} catch (error: any) {
throw new ErrDataNftCreate('Response could not be parsed');
}
}

Expand All @@ -118,24 +123,22 @@ export class DataNft {
nonce
)
);
try {
const response = await fetch(
`${this.apiConfiguration}/nfts?identifiers=${identifiers.join(
','
)}&withSupply=true`
);

const data: NftType[] = await response.json();
const response = await fetch(
`${this.apiConfiguration}/nfts?identifiers=${identifiers.join(
','
)}&withSupply=true`
);

checkStatus(response);

const data: NftType[] = await response.json();

try {
const dataNfts = data.map((value) => parseDataNft(value));
return dataNfts;
} catch (error) {
throw error;
// if (error instanceof Error) {
// throw new ErrDataNftCreation(error);
// } else {
// throw ErrDataNftCreation;
// }
} catch (error: any) {
throw new ErrDataNftCreate('Response could not be parsed');
}
}

Expand All @@ -160,13 +163,8 @@ export class DataNft {
parseNft(payload as NftType);
return dataNfts;
}
} catch (error) {
throw error;
// if (error instanceof Error) {
// throw new ErrDataNftCreation(error);
// } else {
// throw ErrDataNftCreation;
// }
} catch (error: any) {
throw new ErrDataNftCreate('Response could not be parsed');
}
}

Expand Down Expand Up @@ -195,9 +193,8 @@ export class DataNft {
description: decodedAttributes['description'].toString(),
title: decodedAttributes['title'].toString()
};
} catch (error) {
throw error;
// throw ErrDecodeAttributes;
} catch (error: any) {
throw new ErrDecodeAttributes(error.message);
}
}

Expand All @@ -211,22 +208,17 @@ export class DataNft {
identifier = dataNftTokenIdentifier[this.env as EnvironmentsEnum]
): Promise<DataNft[]> {
this.ensureNetworkConfigSet();
try {
const res = await fetch(
`${this.apiConfiguration}/accounts/${address}/nfts?size=10000&collections=${identifier}&withSupply=true`
);
const data = await res.json();
const dataNfts: DataNft[] = this.createFromApiResponseOrBulk(data);

return dataNfts;
} catch (error) {
throw error;
// if (error instanceof Error) {
// throw new ErrFailedOperation(this.ownedByAddress.name, error);
// } else {
// throw ErrFailedOperation;
// }
}
const res = await fetch(
`${this.apiConfiguration}/accounts/${address}/nfts?size=10000&collections=${identifier}&withSupply=true`
);

checkStatus(res);

const data = await res.json();
const dataNfts: DataNft[] = this.createFromApiResponseOrBulk(data);

return dataNfts;
}

/**
Expand All @@ -235,28 +227,22 @@ export class DataNft {
async getMessageToSign(): Promise<string> {
DataNft.ensureNetworkConfigSet();
if (!this.dataMarshal) {
throw new Error('No data marshal set for getMessageToSign');
// throw new ErrAttributeNotSet('dataMarshal');
}
try {
const res = await fetch(
`${this.dataMarshal}/preaccess?chainId=${
DataNft.networkConfiguration.chainID == 'D'
? 'ED'
: DataNft.networkConfiguration.chainID
}`
);
const data = await res.json();

return data.nonce;
} catch (error) {
throw error;
// if (error instanceof Error) {
// throw new ErrFailedOperation(this.getMessageToSign.name, error);
// } else {
// throw ErrFailedOperation;
// }
throw new ErrAttributeNotSet('dataMarshal');
}

const res = await fetch(
`${this.dataMarshal}/preaccess?chainId=${
DataNft.networkConfiguration.chainID == 'D'
? 'ED'
: DataNft.networkConfiguration.chainID
}`
);

checkStatus(res);

const data = await res.json();

return data.nonce;
}

/**
Expand All @@ -280,8 +266,7 @@ export class DataNft {
}): Promise<ViewDataReturnType> {
DataNft.ensureNetworkConfigSet();
if (!this.dataMarshal) {
throw new Error('No data marshal set for viewData');
// throw new ErrAttributeNotSet('dataMarshal');
throw new ErrAttributeNotSet('dataMarshal');
}
const signResult = {
signature: '',
Expand Down Expand Up @@ -510,10 +495,7 @@ export class DataNft {

private static ensureNetworkConfigSet() {
if (!this.env || !this.apiConfiguration) {
throw new Error(
'Network configuration is not set. Call setNetworkConfig static method before calling any method that requires network configuration.'
);
// throw ErrNetworkConfig;
throw new ErrNetworkConfig();
}
}
}
92 changes: 48 additions & 44 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,76 @@
/**
* The base class for exceptions (errors).
*/
export class Err extends Error {
inner: Error | undefined = undefined;

public constructor(message: string, inner?: Error) {
super(message);
this.inner = inner;
export class ErrNetworkConfig extends Error {
public constructor(message?: string) {
super(
message ||
'Network configuration is not set. Call setNetworkConfig static method before calling any method that requires network configuration.'
);
}
}

/**
* Returns a pretty, friendly summary for the error or for the chain of errors (if appropriate).
*/
summary(): any[] {
let result = [];

result.push({ name: this.name, message: this.message });

let inner: any = this.inner;
while (inner) {
result.push({ name: inner.name, message: inner.message });
inner = inner.inner;
}

return result;
export class ErrInvalidArgument extends Error {
public constructor(message: string) {
super(`Invalid argument: ${message}`);
}
}

export class ErrNetworkConfig extends Err {
public constructor() {
export class ErrBadType extends Error {
public constructor(name: string, type: any, value?: any, context?: string) {
super(
'Network configuration is not set. Call setNetworkConfig static method before calling any method that requires network configuration.'
`Bad type of "${name}": ${value}. Expected type: ${type}. Context: ${context}`
);
}
}

export class ErrDataNftCreation extends Err {
public constructor(inner?: Error) {
super(`Could not create DataNft:`, inner);
export class ErrDataNftCreate extends Error {
public constructor(message?: string) {
super(`Failed to create Data NFT: ${message}`);
}
}

export class ErrDecodeAttributes extends Err {
public constructor() {
super('Could not decode attributes');
export class ErrFetch extends Error {
public constructor(status: number, message: string) {
super(`Fetch error with status code: ${status} and message: ${message}`);
}
}

export class ErrAttributeNotSet extends Err {
public constructor(attributeName: string) {
super(`Attribute ${attributeName} is not set`);
export class ErrDecodeAttributes extends Error {
public constructor(message?: string) {
super(`Failed to decode attributes: ${message}`);
}
}

export class ErrArgumentNotSet extends Err {
public constructor(argumentName: string, message: string) {
super(`Argument ${argumentName} is not set. ${message}`);
export class ErrAttributeNotSet extends Error {
public constructor(attribute: string) {
super(`Attribute "${attribute}" is not set`);
}
}

export class ErrFailedOperation extends Err {
public constructor(methodName: string, inner?: Error) {
super(`Function failed: ${methodName}:`, inner);
export class ErrContractQuery extends Error {
public constructor(method: string, message?: string) {
super(`Failed to query contract: Method: ${method} : ${message}`);
}
}

export class ErrContractQuery extends Err {
export class ErrParamValidation extends Error {
public constructor(message: string) {
super(`Contract query failed: ${message}`);
super(`Params have validation issues : ${message}`);
}
}

export class ErrFailedOperation extends Error {
public constructor(method: string, message?: string) {
super(`Failed to perform operation: ${method} : ${message}`);
}
}

export class ErrMissingTrait extends Error {
public constructor(trait: string) {
super(`Missing trait: ${trait}`);
}
}

export class ErrMissingValueForTrait extends Error {
public constructor(trait: string) {
super(`Missing value for trait: ${trait}`);
}
}
Loading