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

3.0.0: Remove IntDecoding as a REST option & support native bigint types in models #852

Merged
merged 6 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion examples/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ async function main() {
const acctInfo = await client.accountInformation(acct1.addr).do();

console.log(
`Account Info: ${JSON.stringify(acctInfo)} Auth Addr: ${
`Account Info: ${algosdk.stringifyJSON(acctInfo)} Auth Addr: ${

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My js is very rusty, but isn't it the case that (in browser anyway) console.log is clever enough to give you a little UI to look at an object if you just log it separately? This is, isn't console.log("Account Info", acctInfo) going to be more helpful?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My experience is that, yes, console.log("Account Info", acctInfo) would expand acctInfo for you in browsers, and it's usually a drop down that you can interact with to see each field. However, if you're not on a browser, it's not a great experience as often you'll just get back a string like [object, object].

acctInfo['auth-addr']
}`
);
Expand Down
4 changes: 2 additions & 2 deletions examples/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ async function main() {
// example: APP_READ_STATE
const appInfo = await algodClient.getApplicationByID(appId).do();
const globalState = appInfo.params.globalState[0];
console.log(`Raw global state - ${JSON.stringify(globalState)}`);
console.log(`Raw global state - ${algosdk.stringifyJSON(globalState)}`);

// decode b64 string key with Buffer
const globalKey = algosdk.base64ToString(globalState.key);
Expand All @@ -147,7 +147,7 @@ async function main() {
.do();

const localState = accountAppInfo.appLocalState.keyValue[0];
console.log(`Raw local state - ${JSON.stringify(localState)}`);
console.log(`Raw local state - ${algosdk.stringifyJSON(localState)}`);

// decode b64 string key with Buffer
const localKey = algosdk.base64ToString(localState.key);
Expand Down
2 changes: 1 addition & 1 deletion examples/asa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function main() {
// example: ASSET_INFO
const assetInfo = await algodClient.getAssetByID(assetIndex).do();
console.log(`Asset Name: ${assetInfo.params.name}`);
console.log(`Asset Params: ${JSON.stringify(assetInfo.params)}`);
console.log(`Asset Params: ${algosdk.stringifyJSON(assetInfo.params)}`);
// example: ASSET_INFO

await new Promise((f) => setTimeout(f, 45000)); // sleep to ensure indexer is caught up
Expand Down
2 changes: 1 addition & 1 deletion examples/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ async function main() {
.notePrefix(new TextEncoder().encode('Hello'))
.do();
console.log(
`Transactions with note prefix "Hello" ${JSON.stringify(
`Transactions with note prefix "Hello" ${algosdk.stringifyJSON(
txnsWithNotePrefix,
undefined,
2
Expand Down
2 changes: 1 addition & 1 deletion examples/overview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function main() {
const { txid } = await algodClient.sendRawTransaction(signedTxn).do();
const result = await algosdk.waitForConfirmation(algodClient, txid, 4);
console.log(result);
console.log(`Transaction Information: ${JSON.stringify(result.txn)}`);
console.log(`Transaction Information: ${algosdk.stringifyJSON(result.txn)}`);
console.log(
`Decoded Note: ${new TextDecoder('utf-8').decode(result.txn.txn.note)}`
);
Expand Down
140 changes: 92 additions & 48 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ export class HTTPClient {
}

/**
* Parse JSON using either the built-in JSON.parse or utils.parseJSON
* depending on whether jsonOptions are provided or not
* Parse JSON using utils.parseJSON
*
* @param text - JSON data
* @param status - Status of the response (used in case parseJSON fails)
Expand All @@ -123,13 +122,13 @@ export class HTTPClient {
public static parseJSON(
text: string,
status: number,
jsonOptions: utils.JSONOptions = {}
jsonOptions: utils.ParseJSONOptions
) {
try {
if (Object.keys(jsonOptions).length === 0) {
return text && JSON.parse(text);
if (!text) {
return null;
}
return text && utils.parseJSON(text, jsonOptions);
return utils.parseJSON(text, jsonOptions);
} catch (err_) {
const err = err_ as ErrorWithAdditionalInfo;
// return the raw response if the response parsing fails
Expand All @@ -156,7 +155,7 @@ export class HTTPClient {
return new Uint8Array(0); // empty Uint8Array
}
if (requestHeaders['content-type'] === 'application/json') {
return new TextEncoder().encode(JSON.stringify(data));
return new TextEncoder().encode(utils.stringifyJSON(data));
}
if (typeof data === 'string') {
return new TextEncoder().encode(data);
Expand All @@ -178,7 +177,7 @@ export class HTTPClient {
res: BaseHTTPClientResponse,
format: 'application/msgpack' | 'application/json',
parseBody: boolean,
jsonOptions: utils.JSONOptions = {}
jsonOptions: utils.ParseJSONOptions
): HTTPClientResponse {
let { body } = res;
let text: string | undefined;
Expand All @@ -205,13 +204,17 @@ export class HTTPClient {
* by adding the status and preparing the internal response
* @private
*/
private static prepareResponseError(err: any) {
private static prepareResponseError(
err: any,
jsonOptions: utils.ParseJSONOptions
) {
if (err.response) {
// eslint-disable-next-line no-param-reassign
err.response = HTTPClient.prepareResponse(
err.response,
'application/json',
true
true,
jsonOptions
);
// eslint-disable-next-line no-param-reassign
err.status = err.response.status;
Expand All @@ -221,24 +224,32 @@ export class HTTPClient {

/**
* Send a GET request.
* @param relativePath - The path of the request.
algorandskiy marked this conversation as resolved.
Show resolved Hide resolved
* @param query - An object containing the query parameters of the request.
* @param requestHeaders - An object containing additional request headers to use.
* @param jsonOptions - Options object to use to decode JSON responses. See
*
* @param options - The options to use for the request.
* @param options.relativePath - The path of the request.
* @param options.jsonOptions - Options object to use to decode JSON responses. See
* utils.parseJSON for the options available.
* @param parseBody - An optional boolean indicating whether the response body should be parsed
* @param options.query - An object containing the query parameters of the request.
* @param options.requestHeaders - An object containing additional request headers to use.
* @param options.parseBody - An optional boolean indicating whether the response body should be parsed
* or not.
* @returns Response object.
*/
async get(
relativePath: string,
query?: Query<any>,
requestHeaders: Record<string, string> = {},
jsonOptions: utils.JSONOptions = {},
parseBody: boolean = true
): Promise<HTTPClientResponse> {
async get({
relativePath,
jsonOptions,
query,
requestHeaders,
parseBody,
}: {
relativePath: string;
jsonOptions: utils.ParseJSONOptions;
query?: Query<any>;
requestHeaders?: Record<string, string>;
parseBody: boolean;
}): Promise<HTTPClientResponse> {
const format = getAcceptFormat(query);
const fullHeaders = { ...requestHeaders, accept: format };
const fullHeaders = { ...(requestHeaders ?? {}), accept: format };

try {
const res = await this.bc.get(
Expand All @@ -249,25 +260,34 @@ export class HTTPClient {

return HTTPClient.prepareResponse(res, format, parseBody, jsonOptions);
} catch (err) {
throw HTTPClient.prepareResponseError(err);
throw HTTPClient.prepareResponseError(err, jsonOptions);
}
}

/**
* Send a POST request.
* If no content-type present, adds the header "content-type: application/json"
* and data is serialized in JSON (if not empty)
* @param options - The options to use for the request.
*/
async post(
relativePath: string,
data: any,
query?: Query<any>,
requestHeaders: Record<string, string> = {},
parseBody: boolean = true
): Promise<HTTPClientResponse> {
async post({
relativePath,
data,
jsonOptions,
query,
requestHeaders,
parseBody,
}: {
relativePath: string;
data: any;
jsonOptions: utils.ParseJSONOptions;
query?: Query<any>;
requestHeaders?: Record<string, string>;
parseBody: boolean;
}): Promise<HTTPClientResponse> {
const fullHeaders = {
'content-type': 'application/json',
...tolowerCaseKeys(requestHeaders),
...tolowerCaseKeys(requestHeaders ?? {}),
};

try {
Expand All @@ -278,35 +298,59 @@ export class HTTPClient {
fullHeaders
);

return HTTPClient.prepareResponse(res, 'application/json', parseBody);
return HTTPClient.prepareResponse(
res,
'application/json',
parseBody,
jsonOptions
);
} catch (err) {
throw HTTPClient.prepareResponseError(err);
throw HTTPClient.prepareResponseError(err, jsonOptions);
}
}

/**
* Send a DELETE request.
* If no content-type present, adds the header "content-type: application/json"
* and data is serialized in JSON (if not empty)
* @param options - The options to use for the request.
*/
async delete(
relativePath: string,
data: any,
requestHeaders: Record<string, string> = {},
parseBody: boolean = true
) {
async delete({
relativePath,
data,
jsonOptions,
requestHeaders,
parseBody,
}: {
relativePath: string;
data: any;
jsonOptions: utils.ParseJSONOptions;
requestHeaders?: Record<string, string>;
parseBody: boolean;
}) {
const fullHeaders = {
'content-type': 'application/json',
...tolowerCaseKeys(requestHeaders),
...tolowerCaseKeys(requestHeaders ?? {}),
};

const res = await this.bc.delete(
relativePath,
HTTPClient.serializeData(data, fullHeaders),
undefined,
fullHeaders
);
try {
const res = await this.bc.delete(
relativePath,
typeof data !== 'undefined'
? HTTPClient.serializeData(data, fullHeaders)
: undefined,
undefined,
fullHeaders
);

return HTTPClient.prepareResponse(res, 'application/json', parseBody);
return HTTPClient.prepareResponse(
res,
'application/json',
parseBody,
jsonOptions
);
} catch (err) {
throw HTTPClient.prepareResponseError(err, jsonOptions);
}
}
}
Loading