diff --git a/package.json b/package.json index b01191d1..9f8f7038 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "bufferutil": "4.0.7", "reconnecting-websocket": "4.4.0", "utf-8-validate": "6.0.3", - "ws": "8.13.0" + "ws": "8.13.0", + "zod": "3.21.4" }, "description": "Coinbase Pro API for Node.js, written in TypeScript and covered by tests.", "devDependencies": { diff --git a/src/transfer/TransferAPI.ts b/src/transfer/TransferAPI.ts index 3a34e994..4987982c 100644 --- a/src/transfer/TransferAPI.ts +++ b/src/transfer/TransferAPI.ts @@ -1,32 +1,8 @@ +import {z} from 'zod'; import {AxiosInstance} from 'axios'; -import {ISO_8601_MS_UTC, PaginatedData, Pagination} from '../payload/common'; +import {PaginatedData, Pagination} from '../payload/common'; import querystring from 'querystring'; -export interface TransferInformation { - account_id: string; - amount: string; - canceled_at?: ISO_8601_MS_UTC; - completed_at?: ISO_8601_MS_UTC; - created_at: ISO_8601_MS_UTC; - details: { - coinbase_account_id?: string; - coinbase_payment_method_id?: string; - coinbase_transaction_id?: string; - coinbase_withdrawal_id?: string; - crypto_address?: string; - crypto_transaction_hash?: string; - crypto_transaction_id?: string; - destination_tag: string; - destination_tag_name?: string; - sent_to_address?: string; - }; - id: string; - processed_at?: ISO_8601_MS_UTC; - type: string; - user_id: string; - user_nonce?: string; -} - export enum TransferType { DEPOSIT = 'deposit', INTERNAL_DEPOSIT = 'internal_deposit', @@ -34,6 +10,37 @@ export enum TransferType { WITHDRAW = 'withdraw', } +export const TransferInformationSchema = z.object({ + account_id: z.string(), + amount: z.string(), + canceled_at: z.string().nullable().or(z.undefined()), + completed_at: z.string().nullable().or(z.undefined()), + created_at: z.string(), + currency: z.string().nullable().or(z.undefined()), + details: z.object({ + coinbase_account_id: z.string().nullable().or(z.undefined()), + coinbase_payment_method_id: z.string().nullable().or(z.undefined()), + coinbase_transaction_id: z.string().nullable().or(z.undefined()), + coinbase_withdrawal_id: z.string().nullable().or(z.undefined()), + crypto_address: z.string().nullable().or(z.undefined()), + crypto_transaction_hash: z.string().nullable().or(z.undefined()), + crypto_transaction_id: z.string().nullable().or(z.undefined()), + destination_tag: z.string().nullable().or(z.undefined()), + destination_tag_name: z.string().nullable().or(z.undefined()), + sent_to_address: z.string().nullable().or(z.undefined()), + tx_service_transaction_id: z.string().optional(), + }), + id: z.string(), + idem: z.string().nullable().or(z.undefined()), + processed_at: z.string().nullable().or(z.undefined()), + profile_id: z.string().nullable().or(z.undefined()), + type: z.nativeEnum(TransferType), + user_id: z.string(), + user_nonce: z.string().nullable().or(z.undefined()), +}); + +export type TransferInformation = z.infer; + export class TransferAPI { static readonly URL = { TRANSFERS: `/transfers`, @@ -67,6 +74,9 @@ export class TransferAPI { params, paramsSerializer: querystring.stringify, }); + + z.array(TransferInformationSchema).parse(response.data); + return { data: response.data, pagination: { @@ -85,6 +95,6 @@ export class TransferAPI { async getTransfer(transferId: string): Promise { const resource = `${TransferAPI.URL.TRANSFERS}/${transferId}`; const response = await this.apiClient.get(resource); - return response.data; + return TransferInformationSchema.parse(response.data); } } diff --git a/yarn.lock b/yarn.lock index 9148535b..8de5ece6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2850,3 +2850,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@3.21.4: + version "3.21.4" + resolved "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==