From 8e7a8016697cf4cafa25379e026f3ac72e1b3d85 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 9 Aug 2023 14:52:15 +0200 Subject: [PATCH 01/18] initial tests --- __tests__/create-charge.test.ts | 35 -------------- __tests__/createCharge.test.ts | 33 +++++++++++++ __tests__/createStaticCharge.test.ts | 31 +++++++++++++ __tests__/createWithdrawalRequest.test.ts | 38 +++++++++++++++ __tests__/get-btcusd.test.ts | 16 ------- __tests__/get-payment.test.ts | 30 ------------ __tests__/get-wallet.test.ts | 16 ------- __tests__/getCharge.test.ts | 31 +++++++++++++ __tests__/getStaticCharge.test.ts | 32 +++++++++++++ __tests__/getWallet.test.ts | 32 +++++++++++++ __tests__/getWithdrawalRequest.test.ts | 32 +++++++++++++ __tests__/updateStaticCharge.test.ts | 35 ++++++++++++++ package-lock.json | 12 ++--- package.json | 2 +- src/types/charges.ts | 24 ++++++++++ src/types/static-charges.ts | 37 ++++++++++++--- src/types/withdrawal.ts | 56 +++++++++++++++++++++-- yarn.lock | 8 ++-- 18 files changed, 382 insertions(+), 118 deletions(-) delete mode 100644 __tests__/create-charge.test.ts create mode 100644 __tests__/createCharge.test.ts create mode 100644 __tests__/createStaticCharge.test.ts create mode 100644 __tests__/createWithdrawalRequest.test.ts delete mode 100644 __tests__/get-btcusd.test.ts delete mode 100644 __tests__/get-payment.test.ts delete mode 100644 __tests__/get-wallet.test.ts create mode 100644 __tests__/getCharge.test.ts create mode 100644 __tests__/getStaticCharge.test.ts create mode 100644 __tests__/getWallet.test.ts create mode 100644 __tests__/getWithdrawalRequest.test.ts create mode 100644 __tests__/updateStaticCharge.test.ts diff --git a/__tests__/create-charge.test.ts b/__tests__/create-charge.test.ts deleted file mode 100644 index e86a5a9..0000000 --- a/__tests__/create-charge.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('createCharge', () => { - it('should create a charge successfully', async () => { - const chargeData = { - amount: '10000', - expiresIn: 300, - description: 'My Charge Description', - callbackUrl: 'https://your-website.com/callback', - internalId: '11af01d092444a317cb33faa6b8304b8', - }; - - const response = await ZBD.createCharge(chargeData); - - expect(response).toBeDefined(); - expect(response.success).toBe(true); - expect(response.message).toBe('Charge created.'); - - const { data } = response; - expect(data.unit).toBe('msats'); - expect(data.amount).toBe(chargeData.amount); - expect(data.description).toBe(chargeData.description); - expect(data.internalId).toBe(chargeData.internalId); - expect(data.callbackUrl).toBe(chargeData.callbackUrl); - - expect(data).toHaveProperty('status'); - expect(data).toHaveProperty('createdAt'); - expect(data).toHaveProperty('expiresAt'); - expect(data).toHaveProperty('id'); - expect(data).toHaveProperty('invoice'); - }); -}); diff --git a/__tests__/createCharge.test.ts b/__tests__/createCharge.test.ts new file mode 100644 index 0000000..c81327c --- /dev/null +++ b/__tests__/createCharge.test.ts @@ -0,0 +1,33 @@ + +import { TEST_API_KEY } from '../src/constants'; +import { zbd } from '../src/zbd'; +import { ChargeDataResponseType, ChargeOptionsType, isChargeResponseType } from '../src/types/charges'; + +const ZBD = new zbd(TEST_API_KEY); + + +describe('createCharge', () => { + it('should successfully create a charge', async () => { + const payload: ChargeOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Charge Test Zapier", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback" + }; + + const response = await ZBD.createCharge(payload); + + expect(isChargeResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.message).toBe("Charge created."); + expect(response.data.amount).toBe(payload.amount); + expect(response.data.description).toBe(payload.description); + }); + + describe('createCharge error scenarios', () => { + + }); + + +}); \ No newline at end of file diff --git a/__tests__/createStaticCharge.test.ts b/__tests__/createStaticCharge.test.ts new file mode 100644 index 0000000..380a262 --- /dev/null +++ b/__tests__/createStaticCharge.test.ts @@ -0,0 +1,31 @@ +import { zbd } from '@zbd/node'; +import { TEST_API_KEY } from '../src/constants'; +import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('createStaticCharge', () => {; + + // Data for creating static charge + const validStaticChargeData: StaticChargeOptionsType = { + allowedSlots: null, + minAmount: "10000", + maxAmount: "20000", + description: "This is my static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment was successful!" + }; + + // Success + it('should successfully create a static charge', async () => { + const response = await ZBD.createStaticCharge(validStaticChargeData); + expect(response.message).toBe("Successfully created Static Charge."); + + // Data Validation + expect(isStaticChargeDataResponseType(response)).toBeTruthy(); + }); + + + +}); diff --git a/__tests__/createWithdrawalRequest.test.ts b/__tests__/createWithdrawalRequest.test.ts new file mode 100644 index 0000000..a0c3be2 --- /dev/null +++ b/__tests__/createWithdrawalRequest.test.ts @@ -0,0 +1,38 @@ +import { TEST_API_KEY } from '../src/constants'; +import { zbd } from '../src/zbd'; +import { CreateWithdrawalRequestDataResponseType, WithdrawalRequestOptionsType, isCreateWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../src/types'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('createWithdrawalRequest', () => { + + const requestBody: WithdrawalRequestOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Withdrawal Description", + internalId: "internalId", + callbackUrl: "https://your-website.com/callback" + }; + + it('should successfully create a withdrawal request', async () => { + + const responseData: CreateWithdrawalRequestDataResponseType = await ZBD.createWithdrawalRequest(requestBody); + + expect(responseData.success).toBe(true); + expect(responseData.message).toBe('Successfully created Withdrawal Request.'); + + // Check if returned data matches request body data + expect(responseData.data.amount).toBe(requestBody.amount); + expect(responseData.data.description).toBe(requestBody.description); + expect(responseData.data.internalId).toBe(requestBody.internalId); + expect(responseData.data.callbackUrl).toBe(requestBody.callbackUrl); + + // Data Validation + expect(isCreateWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); + + }); + + + +}); + diff --git a/__tests__/get-btcusd.test.ts b/__tests__/get-btcusd.test.ts deleted file mode 100644 index a5a091a..0000000 --- a/__tests__/get-btcusd.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('getBTCUSD', () => { - it('should fetch BTC to USD exchange rate data successfully', async () => { - const response = await ZBD.getBtcUsdExchangeRate(); - - expect(response).toBeDefined(); - expect(response.success).toBe(true); - expect(response.data).toHaveProperty('btcUsdPrice'); - expect(response.data).toHaveProperty('btcUsdTimestamp'); - expect(response.message).toBe('Successfully retrieved BTC USD price ticker information.'); - }); -}); diff --git a/__tests__/get-payment.test.ts b/__tests__/get-payment.test.ts deleted file mode 100644 index 201ce4a..0000000 --- a/__tests__/get-payment.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('getPayment', () => { - // it('should fetch payment transaction details successfully', async () => { - // const paymentId = ''; // provide valid paymentId - - // const data = await ZBD.getPayment(paymentId); - // console.log(data) - - // expect(data).toBeDefined(); - // expect(data.paymentId).toBe(paymentId); - // }); - - it('should return an error when an invalid payment ID is provided', async () => { - const invalidPaymentId = 'invalid-id'; - - try { - await ZBD.getPayment(invalidPaymentId); - } catch (error) { - if (error instanceof Error) { - console.log(error) - expect(error.message).toBe('No Payment records found with this ID.') - } - - } - }); -}); \ No newline at end of file diff --git a/__tests__/get-wallet.test.ts b/__tests__/get-wallet.test.ts deleted file mode 100644 index a5a6bfe..0000000 --- a/__tests__/get-wallet.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('getWallet', () => { - it('should fetch wallet data successfully', async () => { - const response = await ZBD.getWallet(); - - expect(response).toBeDefined(); - expect(response.data).toHaveProperty('unit'); - expect(response.data).toHaveProperty('balance'); - expect(response.message).toBe('Successfully retrieved Wallet.'); - }); - -}); diff --git a/__tests__/getCharge.test.ts b/__tests__/getCharge.test.ts new file mode 100644 index 0000000..91b3700 --- /dev/null +++ b/__tests__/getCharge.test.ts @@ -0,0 +1,31 @@ +import { zbd } from '@zbd/node'; +import { TEST_API_KEY } from '../src/constants'; +import { ChargeDataResponseType, isChargeResponseType } from '../src/types/charges'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('getCharge', () => { + const VALID_CHARGE_ID = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; + const INVALID_CHARGE_ID = 'invalid'; + const INVALID_API_KEY = 'INVALID_API_KEY'; + + // Success + it('should fetch charge details for a valid charge ID', async () => { + const data = await ZBD.getCharge(VALID_CHARGE_ID); + expect(data.success).toBe(true); + expect(data.message).toBe("Fetched Charge."); + + // Data Validation + expect(isChargeResponseType(data)).toBeTruthy(); + }); + + // Charge not found + it('should return a 404 for a non-existent charge ID', async () => { + await expect(ZBD.getCharge(INVALID_CHARGE_ID)).rejects.toMatchObject({ + message: "No Charge records found with this ID.", + status: 404 + }); + }); + +}); + diff --git a/__tests__/getStaticCharge.test.ts b/__tests__/getStaticCharge.test.ts new file mode 100644 index 0000000..e869d65 --- /dev/null +++ b/__tests__/getStaticCharge.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../src/constants'; +import { zbd } from '../src/zbd'; +import { StaticChargeDataResponseType, isStaticChargeDataResponseType } from '../src/types/static-charges'; + +const ZBD = new zbd(TEST_API_KEY); + + +describe('getStaticCharge', () => { + + const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; + + it('should successfully fetch Static Charge details', async () => { + + const responseData = await ZBD.getStaticCharge(STATIC_CHARGE_ID); + + expect(responseData.message).toBe('Successfully retrieved Static Charge data.'); + expect(responseData.data.id).toBe(STATIC_CHARGE_ID); + + // Data Validation + expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); + + }); + + // Static Charge not found + it('should return a 404 for a non-existent charge ID', async () => { + const NON_EXISTENT_STATIC_CHARGE_ID = 'invalid' + await expect(ZBD.getCharge(NON_EXISTENT_STATIC_CHARGE_ID)).rejects.toMatchObject({ + message: "No Charge records found with this ID.", + status: 404 + }); + }); +}); diff --git a/__tests__/getWallet.test.ts b/__tests__/getWallet.test.ts new file mode 100644 index 0000000..bb4e8f6 --- /dev/null +++ b/__tests__/getWallet.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../src/constants'; +import { WalletDataResponseType } from '../src/types'; +import { zbd } from '../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +function isWalletDataResponseType(data: any): data is WalletDataResponseType { + return typeof data === 'object' && + data !== null && + typeof data.message === 'string' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.unit === 'string' && + typeof data.data.balance === 'string'; +} + +describe('getWallet', () => { + + it('should fetch wallet details successfully', async () => { + const response = await ZBD.getWallet(); + expect(response).toBeDefined(); + + // Data Validation + expect(isWalletDataResponseType(response)).toBeTruthy(); + + // Additional check for the balance to ensure it's a valid number string + expect(Number(response.data.balance)).not.toBeNaN(); + }); + + + +}); \ No newline at end of file diff --git a/__tests__/getWithdrawalRequest.test.ts b/__tests__/getWithdrawalRequest.test.ts new file mode 100644 index 0000000..500715d --- /dev/null +++ b/__tests__/getWithdrawalRequest.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../src/constants'; +import { zbd } from '../src/zbd'; +import { GetWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../src/types/withdrawal'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('getWithdrawalRequest', () => { + + const WITHDRAWAL_ID = 'e3c7321a-cc06-48da-90a8-589bd175ace9'; + + it('should successfully fetch Withdrawal Request details', async () => { + + const responseData = await ZBD.getWithdrawalRequest(WITHDRAWAL_ID); + + console.log(responseData) + + expect(responseData.data.id).toBe(WITHDRAWAL_ID); + + // Data Validation + expect(isGetWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); + + }); + + // Withdrawal Request not found + it('should return an error for a non-existent withdrawal ID', async () => { + const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' + await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ + message: "Failed to fetch withdrawal request." + }); + }); +}); + diff --git a/__tests__/updateStaticCharge.test.ts b/__tests__/updateStaticCharge.test.ts new file mode 100644 index 0000000..8441e95 --- /dev/null +++ b/__tests__/updateStaticCharge.test.ts @@ -0,0 +1,35 @@ +// import { zbd } from '@zbd/node'; +// import { TEST_API_KEY } from '../src/constants'; +// import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; + +// const ZBD = new zbd(TEST_API_KEY); + +// describe('PATCH Update Static Charge', () => { + +// const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; + +// it('should successfully update a Static Charge', async () => { +// const updateOptions: StaticChargeOptionsType = { +// allowedSlots: null, +// minAmount: "10000", +// maxAmount: "5000000", +// description: "This is my editted static charge", +// internalId: "myInternalId", +// callbackUrl: "https://my-website.com/zbd-callback", +// successMessage: "Congratulations your payment success msg was editted!" +// }; + +// const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); +// console.log(responseData) + +// expect(responseData.message).toBe('Successfully editted Static Charge.'); +// expect(responseData.data.id).toBe(STATIC_CHARGE_ID); +// expect(responseData.data.description).toBe(updateOptions.description); +// // Data Validation +// expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); +// }); + +// // Todo: False cases + +// }); + diff --git a/package-lock.json b/package-lock.json index e0f58bb..10d7749 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@zbd/node", - "version": "0.6.2", + "version": "0.6.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@zbd/node", - "version": "0.6.2", + "version": "0.6.3", "license": "MIT", "dependencies": { - "@zbd/node": "^0.6.2", + "@zbd/node": "^0.6.3", "node-fetch": "^3.3.1" }, "devDependencies": { @@ -2680,9 +2680,9 @@ "dev": true }, "node_modules/@zbd/node": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@zbd/node/-/node-0.6.2.tgz", - "integrity": "sha512-66PesqbnByJFcvNUo9KaIJ3/ISENfQxaKj0fRfUA8c3Z5QEFk7Oqtfquhc4ocs940i5fm8IuoqvmHcnWQuUlmg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@zbd/node/-/node-0.6.3.tgz", + "integrity": "sha512-pKt8f6cJZ7HlbBHtJRXgMOfmp9M1WNIhZtSxuV80zEhZOf+VNVlI3w+cvi0JsHpfK/7lCJEejENs9GjU/SN/9Q==", "engines": { "node": ">=14" } diff --git a/package.json b/package.json index 59e0489..a91e43e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "node": ">=14" }, "dependencies": { - "@zbd/node": "^0.6.2", + "@zbd/node": "^0.6.3", "node-fetch": "^3.3.1" } } diff --git a/src/types/charges.ts b/src/types/charges.ts index 37237e5..7712307 100644 --- a/src/types/charges.ts +++ b/src/types/charges.ts @@ -6,6 +6,7 @@ export interface ChargeOptionsType { callbackUrl: string; } + export interface DecodeChargeOptionsType { invoice: string; } @@ -45,4 +46,27 @@ export interface DecodeChargeResponseType { invoiceDescriptionHash: string | null; } success: boolean; +} + + +export function isChargeResponseType(obj: any): obj is ChargeDataResponseType { + return ( + obj && + typeof obj.success === "boolean" && + typeof obj.message === "string" && + obj.data && + typeof obj.data.id === "string" && + typeof obj.data.unit === "string" && + typeof obj.data.amount === "string" && + typeof obj.data.createdAt === "string" && + typeof obj.data.callbackUrl === "string" && + typeof obj.data.internalId === "string" && + typeof obj.data.description === "string" && + typeof obj.data.expiresAt === "string" && + typeof obj.data.confirmedAt === "string" || obj.data.confirmedAt === null && + typeof obj.data.status === "string" && + obj.data.invoice && + typeof obj.data.invoice.request === "string" && + typeof obj.data.invoice.uri === "string" + ); } \ No newline at end of file diff --git a/src/types/static-charges.ts b/src/types/static-charges.ts index 42feed4..b267382 100644 --- a/src/types/static-charges.ts +++ b/src/types/static-charges.ts @@ -4,7 +4,7 @@ export interface StaticChargeOptionsType { minAmount: string; maxAmount: string; description: string; - internalId: string; + internalId: string | null; callbackUrl: string; successMessage: string; } @@ -13,19 +13,18 @@ export interface StaticChargeDataResponseType { data: { id: string; unit: string; - slots: string; + slots: number; minAmount: string; maxAmount: string; createdAt: string; callbackUrl: string; - internalId: string; + internalId: string | null; + identifier: string | null; description: string; expiresAt: string; - confirmedAt: string; successMessage: string; - allowedSlots: string | null; + allowedSlots: number | null; status: string; - fee: string; invoice: { request: string; uri: string; @@ -33,4 +32,28 @@ export interface StaticChargeDataResponseType { } message: string; } - \ No newline at end of file +export function isStaticChargeDataResponseType(obj: any): obj is StaticChargeDataResponseType { + return ( + typeof obj === 'object' && + obj !== null && + typeof obj.message === 'string' && + typeof obj.data === 'object' && + typeof obj.data.id === 'string' && + typeof obj.data.unit === 'string' && + typeof obj.data.slots === 'number' && + typeof obj.data.minAmount === 'string' && + typeof obj.data.maxAmount === 'string' && + typeof obj.data.createdAt === 'string' && + typeof obj.data.callbackUrl === 'string' && + (typeof obj.data.internalId === 'string' || obj.data.internalId === null) && + typeof obj.data.description === 'string' && + (typeof obj.data.expiresAt === 'string' || obj.data.expiresAt === null) && + (typeof obj.data.identifier === 'string' || obj.data.identifier === null) && // Added identifier check + typeof obj.data.successMessage === 'string' && + (typeof obj.data.allowedSlots === 'number' || obj.data.allowedSlots === null) && + typeof obj.data.status === 'string' && + typeof obj.data.invoice === 'object' && + typeof obj.data.invoice.request === 'string' && + typeof obj.data.invoice.uri === 'string' + ); +} diff --git a/src/types/withdrawal.ts b/src/types/withdrawal.ts index 52b4157..397e5ac 100644 --- a/src/types/withdrawal.ts +++ b/src/types/withdrawal.ts @@ -16,7 +16,6 @@ export interface GetWithdrawalRequestDataResponseType { internalId: string; description: string; expiresAt: string; - confirmedAt: string; status: string; invoice: { request: string; @@ -25,7 +24,7 @@ export interface GetWithdrawalRequestDataResponseType { fastUri: string; } } - message: string; + message: string | null | undefined; success: boolean; } @@ -40,7 +39,6 @@ export interface CreateWithdrawalRequestDataResponseType { internalId: string; description: string; expiresAt: string; - confirmedAt: string; status: string; fee: string; invoice: { @@ -53,3 +51,55 @@ export interface CreateWithdrawalRequestDataResponseType { message: string; success: boolean; } + +export function isGetWithdrawalRequestDataResponseType(obj: any): obj is GetWithdrawalRequestDataResponseType { + return ( + obj && + typeof obj.success === "boolean" && + (!obj.message || typeof obj.message === "string") && // Adjusted this check + obj.data && + typeof obj.data.id === "string" && + typeof obj.data.unit === "string" && + typeof obj.data.amount === "string" && + typeof obj.data.createdAt === "string" && + typeof obj.data.expiresAt === "string" && + typeof obj.data.internalId === "string" && + typeof obj.data.description === "string" && + typeof obj.data.callbackUrl === "string" && + typeof obj.data.status === "string" && + (obj.data.fee === null || typeof obj.data.fee === "number") && + obj.data.invoice && + typeof obj.data.invoice.request === "string" && + typeof obj.data.invoice.uri === "string" && + typeof obj.data.invoice.fastRequest === "string" && + typeof obj.data.invoice.fastUri === "string" + ); +} + + +export function isCreateWithdrawalRequestDataResponseType(obj: any): obj is CreateWithdrawalRequestDataResponseType { + return ( + typeof obj === 'object' && + obj !== null && + typeof obj.success === 'boolean' && + typeof obj.message === 'string' && + typeof obj.data === 'object' && + obj.data !== null && + typeof obj.data.id === 'string' && + typeof obj.data.unit === 'string' && + typeof obj.data.amount === 'string' && + typeof obj.data.createdAt === 'string' && + typeof obj.data.expiresAt === 'string' && + typeof obj.data.callbackUrl === 'string' && + typeof obj.data.internalId === 'string' && + typeof obj.data.description === 'string' && + typeof obj.data.status === 'string' && + (typeof obj.data.fee === 'string' || obj.data.fee === null) && + typeof obj.data.invoice === 'object' && + obj.data.invoice !== null && + typeof obj.data.invoice.request === 'string' && + typeof obj.data.invoice.fastRequest === 'string' && + typeof obj.data.invoice.uri === 'string' && + typeof obj.data.invoice.fastUri === 'string' + ); +} diff --git a/yarn.lock b/yarn.lock index d0441ce..4eb5546 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1543,10 +1543,10 @@ dependencies: "@types/yargs-parser" "*" -"@zbd/node@^0.6.2": - version "0.6.2" - resolved "https://registry.npmjs.org/@zbd/node/-/node-0.6.2.tgz" - integrity sha512-66PesqbnByJFcvNUo9KaIJ3/ISENfQxaKj0fRfUA8c3Z5QEFk7Oqtfquhc4ocs940i5fm8IuoqvmHcnWQuUlmg== +"@zbd/node@^0.6.3": + version "0.6.3" + resolved "https://registry.npmjs.org/@zbd/node/-/node-0.6.3.tgz" + integrity sha512-pKt8f6cJZ7HlbBHtJRXgMOfmp9M1WNIhZtSxuV80zEhZOf+VNVlI3w+cvi0JsHpfK/7lCJEejENs9GjU/SN/9Q== acorn-walk@^8.1.1: version "8.2.0" From a8a2e25dfcfee5e34a8a22958d7ab41e99aa6a2c Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Sun, 13 Aug 2023 13:29:48 +0200 Subject: [PATCH 02/18] Added more tests --- __tests__/createCharge.test.ts | 33 --------- __tests__/createStaticCharge.test.ts | 31 --------- __tests__/createWithdrawalRequest.test.ts | 38 ---------- __tests__/getCharge.test.ts | 31 --------- __tests__/getStaticCharge.test.ts | 32 --------- __tests__/getWallet.test.ts | 32 --------- __tests__/getWithdrawalRequest.test.ts | 32 --------- __tests__/updateStaticCharge.test.ts | 35 ---------- src/types/gamertag.ts | 84 ++++++++++++++++++++++- src/types/internal-transfers.ts | 13 ++++ src/types/keysend.ts | 18 ++++- src/types/lightning.ts | 61 ++++++++++++++++ src/types/misc.ts | 41 +++++++++++ 13 files changed, 213 insertions(+), 268 deletions(-) delete mode 100644 __tests__/createCharge.test.ts delete mode 100644 __tests__/createStaticCharge.test.ts delete mode 100644 __tests__/createWithdrawalRequest.test.ts delete mode 100644 __tests__/getCharge.test.ts delete mode 100644 __tests__/getStaticCharge.test.ts delete mode 100644 __tests__/getWallet.test.ts delete mode 100644 __tests__/getWithdrawalRequest.test.ts delete mode 100644 __tests__/updateStaticCharge.test.ts diff --git a/__tests__/createCharge.test.ts b/__tests__/createCharge.test.ts deleted file mode 100644 index c81327c..0000000 --- a/__tests__/createCharge.test.ts +++ /dev/null @@ -1,33 +0,0 @@ - -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; -import { ChargeDataResponseType, ChargeOptionsType, isChargeResponseType } from '../src/types/charges'; - -const ZBD = new zbd(TEST_API_KEY); - - -describe('createCharge', () => { - it('should successfully create a charge', async () => { - const payload: ChargeOptionsType = { - expiresIn: 300, - amount: "10000", - description: "My Charge Test Zapier", - internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" - }; - - const response = await ZBD.createCharge(payload); - - expect(isChargeResponseType(response)).toBeTruthy(); - expect(response.success).toBe(true); - expect(response.message).toBe("Charge created."); - expect(response.data.amount).toBe(payload.amount); - expect(response.data.description).toBe(payload.description); - }); - - describe('createCharge error scenarios', () => { - - }); - - -}); \ No newline at end of file diff --git a/__tests__/createStaticCharge.test.ts b/__tests__/createStaticCharge.test.ts deleted file mode 100644 index 380a262..0000000 --- a/__tests__/createStaticCharge.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { zbd } from '@zbd/node'; -import { TEST_API_KEY } from '../src/constants'; -import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('createStaticCharge', () => {; - - // Data for creating static charge - const validStaticChargeData: StaticChargeOptionsType = { - allowedSlots: null, - minAmount: "10000", - maxAmount: "20000", - description: "This is my static charge", - internalId: "myInternalId1", - callbackUrl: "https://my-website.com/zbd-callback", - successMessage: "Congratulations your payment was successful!" - }; - - // Success - it('should successfully create a static charge', async () => { - const response = await ZBD.createStaticCharge(validStaticChargeData); - expect(response.message).toBe("Successfully created Static Charge."); - - // Data Validation - expect(isStaticChargeDataResponseType(response)).toBeTruthy(); - }); - - - -}); diff --git a/__tests__/createWithdrawalRequest.test.ts b/__tests__/createWithdrawalRequest.test.ts deleted file mode 100644 index a0c3be2..0000000 --- a/__tests__/createWithdrawalRequest.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; -import { CreateWithdrawalRequestDataResponseType, WithdrawalRequestOptionsType, isCreateWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../src/types'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('createWithdrawalRequest', () => { - - const requestBody: WithdrawalRequestOptionsType = { - expiresIn: 300, - amount: "10000", - description: "My Withdrawal Description", - internalId: "internalId", - callbackUrl: "https://your-website.com/callback" - }; - - it('should successfully create a withdrawal request', async () => { - - const responseData: CreateWithdrawalRequestDataResponseType = await ZBD.createWithdrawalRequest(requestBody); - - expect(responseData.success).toBe(true); - expect(responseData.message).toBe('Successfully created Withdrawal Request.'); - - // Check if returned data matches request body data - expect(responseData.data.amount).toBe(requestBody.amount); - expect(responseData.data.description).toBe(requestBody.description); - expect(responseData.data.internalId).toBe(requestBody.internalId); - expect(responseData.data.callbackUrl).toBe(requestBody.callbackUrl); - - // Data Validation - expect(isCreateWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); - - }); - - - -}); - diff --git a/__tests__/getCharge.test.ts b/__tests__/getCharge.test.ts deleted file mode 100644 index 91b3700..0000000 --- a/__tests__/getCharge.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { zbd } from '@zbd/node'; -import { TEST_API_KEY } from '../src/constants'; -import { ChargeDataResponseType, isChargeResponseType } from '../src/types/charges'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('getCharge', () => { - const VALID_CHARGE_ID = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; - const INVALID_CHARGE_ID = 'invalid'; - const INVALID_API_KEY = 'INVALID_API_KEY'; - - // Success - it('should fetch charge details for a valid charge ID', async () => { - const data = await ZBD.getCharge(VALID_CHARGE_ID); - expect(data.success).toBe(true); - expect(data.message).toBe("Fetched Charge."); - - // Data Validation - expect(isChargeResponseType(data)).toBeTruthy(); - }); - - // Charge not found - it('should return a 404 for a non-existent charge ID', async () => { - await expect(ZBD.getCharge(INVALID_CHARGE_ID)).rejects.toMatchObject({ - message: "No Charge records found with this ID.", - status: 404 - }); - }); - -}); - diff --git a/__tests__/getStaticCharge.test.ts b/__tests__/getStaticCharge.test.ts deleted file mode 100644 index e869d65..0000000 --- a/__tests__/getStaticCharge.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; -import { StaticChargeDataResponseType, isStaticChargeDataResponseType } from '../src/types/static-charges'; - -const ZBD = new zbd(TEST_API_KEY); - - -describe('getStaticCharge', () => { - - const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; - - it('should successfully fetch Static Charge details', async () => { - - const responseData = await ZBD.getStaticCharge(STATIC_CHARGE_ID); - - expect(responseData.message).toBe('Successfully retrieved Static Charge data.'); - expect(responseData.data.id).toBe(STATIC_CHARGE_ID); - - // Data Validation - expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); - - }); - - // Static Charge not found - it('should return a 404 for a non-existent charge ID', async () => { - const NON_EXISTENT_STATIC_CHARGE_ID = 'invalid' - await expect(ZBD.getCharge(NON_EXISTENT_STATIC_CHARGE_ID)).rejects.toMatchObject({ - message: "No Charge records found with this ID.", - status: 404 - }); - }); -}); diff --git a/__tests__/getWallet.test.ts b/__tests__/getWallet.test.ts deleted file mode 100644 index bb4e8f6..0000000 --- a/__tests__/getWallet.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { WalletDataResponseType } from '../src/types'; -import { zbd } from '../src/zbd'; - -const ZBD = new zbd(TEST_API_KEY); - -function isWalletDataResponseType(data: any): data is WalletDataResponseType { - return typeof data === 'object' && - data !== null && - typeof data.message === 'string' && - typeof data.data === 'object' && - data.data !== null && - typeof data.data.unit === 'string' && - typeof data.data.balance === 'string'; -} - -describe('getWallet', () => { - - it('should fetch wallet details successfully', async () => { - const response = await ZBD.getWallet(); - expect(response).toBeDefined(); - - // Data Validation - expect(isWalletDataResponseType(response)).toBeTruthy(); - - // Additional check for the balance to ensure it's a valid number string - expect(Number(response.data.balance)).not.toBeNaN(); - }); - - - -}); \ No newline at end of file diff --git a/__tests__/getWithdrawalRequest.test.ts b/__tests__/getWithdrawalRequest.test.ts deleted file mode 100644 index 500715d..0000000 --- a/__tests__/getWithdrawalRequest.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { TEST_API_KEY } from '../src/constants'; -import { zbd } from '../src/zbd'; -import { GetWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../src/types/withdrawal'; - -const ZBD = new zbd(TEST_API_KEY); - -describe('getWithdrawalRequest', () => { - - const WITHDRAWAL_ID = 'e3c7321a-cc06-48da-90a8-589bd175ace9'; - - it('should successfully fetch Withdrawal Request details', async () => { - - const responseData = await ZBD.getWithdrawalRequest(WITHDRAWAL_ID); - - console.log(responseData) - - expect(responseData.data.id).toBe(WITHDRAWAL_ID); - - // Data Validation - expect(isGetWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); - - }); - - // Withdrawal Request not found - it('should return an error for a non-existent withdrawal ID', async () => { - const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' - await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ - message: "Failed to fetch withdrawal request." - }); - }); -}); - diff --git a/__tests__/updateStaticCharge.test.ts b/__tests__/updateStaticCharge.test.ts deleted file mode 100644 index 8441e95..0000000 --- a/__tests__/updateStaticCharge.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -// import { zbd } from '@zbd/node'; -// import { TEST_API_KEY } from '../src/constants'; -// import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; - -// const ZBD = new zbd(TEST_API_KEY); - -// describe('PATCH Update Static Charge', () => { - -// const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; - -// it('should successfully update a Static Charge', async () => { -// const updateOptions: StaticChargeOptionsType = { -// allowedSlots: null, -// minAmount: "10000", -// maxAmount: "5000000", -// description: "This is my editted static charge", -// internalId: "myInternalId", -// callbackUrl: "https://my-website.com/zbd-callback", -// successMessage: "Congratulations your payment success msg was editted!" -// }; - -// const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); -// console.log(responseData) - -// expect(responseData.message).toBe('Successfully editted Static Charge.'); -// expect(responseData.data.id).toBe(STATIC_CHARGE_ID); -// expect(responseData.data.description).toBe(updateOptions.description); -// // Data Validation -// expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); -// }); - -// // Todo: False cases - -// }); - diff --git a/src/types/gamertag.ts b/src/types/gamertag.ts index 9d9e552..c7d8f7f 100644 --- a/src/types/gamertag.ts +++ b/src/types/gamertag.ts @@ -16,7 +16,7 @@ export interface FetchGamertagByUserIdDataResponseType { export interface GamertagTransactionDataResponseType { data: { id: string; - receivedId: string; + receiverId: string; amount: string; fee: string; unit: string; @@ -71,4 +71,84 @@ export interface FetchChargeFromGamertagOptionsType { internalId: string; } - \ No newline at end of file + + +export function isSendGamertagPaymentDataResponseType(obj: any): obj is SendGamertagPaymentDataResponseType { + return ( + typeof obj === 'object' && + obj !== null && + typeof obj.success === 'boolean' && + typeof obj.message === 'string' && + typeof obj.data === 'object' && + typeof obj.data.receiverId === 'string' && + typeof obj.data.transactionId === 'string' && + typeof obj.data.amount === 'string' && + typeof obj.data.comment === 'string' + ); +} + +export function isGamertagTransactionDataResponseType(object: any): object is GamertagTransactionDataResponseType { + return ( + typeof object === 'object' && + object !== null && + typeof object.message === 'string' && + typeof object.success === 'boolean' && + typeof object.data === 'object' && + object.data !== null && + typeof object.data.id === 'string' && + typeof object.data.receiverId === 'string' && + typeof object.data.amount === 'string' && + typeof object.data.fee === 'string' && + typeof object.data.unit === 'string' && + typeof object.data.comment === 'string' && + typeof object.data.status === 'string' && + typeof object.data.confirmedAt === 'string' && + typeof object.data.processedAt === 'string' + ); +} + + +export function isFetchUserIdByGamertagDataResponseType(data: any): data is FetchUserIdByGamertagDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.id === 'string' + ); +} + + +export function isFetchGamertagByUserIDDataResponseType(data: any): data is FetchGamertagByUserIdDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.gamertag === 'string' && + typeof data.message === 'string' + ); +} + + +export function isFetchChargeFromGamertagDataResponseType(data: any): data is FetchChargeFromGamertagDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.unit === 'string' && + typeof data.data.status === 'string' && + typeof data.data.amount === 'string' && + typeof data.data.createdAt === 'string' && + typeof data.data.internalId === 'string' && + typeof data.data.callbackUrl === 'string' && + typeof data.data.description === 'string' && + typeof data.data.invoiceRequest === 'string' && + typeof data.data.invoiceExpiresAt === 'string' && + (typeof data.data.invoiceDescriptionHash === 'string' || data.data.invoiceDescriptionHash === null) + ); +} \ No newline at end of file diff --git a/src/types/internal-transfers.ts b/src/types/internal-transfers.ts index 87b56f6..44a7f72 100644 --- a/src/types/internal-transfers.ts +++ b/src/types/internal-transfers.ts @@ -18,4 +18,17 @@ export interface InternalTransferDataResponseType { export interface InternalTransferOptionsType { amount: string; receiverWalletId: string; +} + +export function isInternalTransferDataResponseType(data: any): data is InternalTransferDataResponseType { + return typeof data.id === 'string' && + typeof data.senderWalletId === 'string' && + typeof data.receiverWalletId === 'string' && + typeof data.userId === 'string' && + typeof data.sendTxId === 'string' && + typeof data.receiveTxId === 'string' && + typeof data.status === 'string' && + typeof data.amount === 'string' && + typeof data.createdAt === 'string' && + typeof data.updatedAt === 'string'; } \ No newline at end of file diff --git a/src/types/keysend.ts b/src/types/keysend.ts index 9ee8af7..9f67ba2 100644 --- a/src/types/keysend.ts +++ b/src/types/keysend.ts @@ -21,7 +21,21 @@ export interface KeysendDataResponseType { export interface KeysendOptionsType { amount: string; pubkey: string; - tlvRecords: string; - metadata: string; + tlvRecords: any[]; + metadata: any; callbackUrl: string; +} + +export function isKeysendDataResponseType(data: any): data is KeysendDataResponseType { + return typeof data.keysendId === 'string' && + typeof data.paymentId === 'string' && + typeof data.transaction.id === 'string' && + typeof data.transaction.walletId === 'string' && + typeof data.transaction.type === 'string' && + typeof data.transaction.totalAmount === 'string' && + typeof data.transaction.fee === 'string' && + typeof data.transaction.amount === 'string' && + typeof data.transaction.description === 'string' && + typeof data.transaction.status === 'string' && + (data.transaction.confirmedAt === null || typeof data.transaction.confirmedAt === 'string'); } \ No newline at end of file diff --git a/src/types/lightning.ts b/src/types/lightning.ts index cd6dba3..d3e87dd 100644 --- a/src/types/lightning.ts +++ b/src/types/lightning.ts @@ -69,3 +69,64 @@ export interface CreateChargeFromLightningAddressOptionsType { lnAddress?: string description: string } + + +export function isSendLightningAddressPaymentDataResponseType(obj: any): obj is SendLightningAddressPaymentDataResponseType { + return ( + obj !== null && + typeof obj === 'object' && + typeof obj.success === 'boolean' && + typeof obj.message === 'string' && + typeof obj.data === 'object' && + + typeof obj.data.id === 'string' && + typeof obj.data.fee === 'string' && + typeof obj.data.unit === 'string' && + typeof obj.data.amount === 'string' && + typeof obj.data.invoice === 'string' && + (obj.data.preimage === null || typeof obj.data.preimage === 'string') && + typeof obj.data.walletId === 'string' && + typeof obj.data.transactionId === 'string' && + typeof obj.data.callbackUrl === 'string' && + typeof obj.data.internalId === 'string' && + typeof obj.data.comment === 'string' && + typeof obj.data.processedAt === 'string' && + typeof obj.data.createdAt === 'string' && + typeof obj.data.status === 'string' + ); +} + +export function isFetchChargeFromLightningAddressResponseType(obj: any): obj is FetchChargeFromLightningAddressDataResponseType { + return ( + obj && + typeof obj.success === 'boolean' && + obj.data && + typeof obj.data.lnaddress === 'string' && + typeof obj.data.amount === 'string' && + obj.data.invoice && + typeof obj.data.invoice.uri === 'string' && + typeof obj.data.invoice.request === 'string' + ); +} + +export function isValidateLightningAddressDataResponseType(obj: any): obj is ValidateLightningAddressDataResponseType { + return ( + obj && + typeof obj.success === 'boolean' && + obj.data && + typeof obj.data.valid === 'boolean' && + obj.data.metadata && + typeof obj.data.metadata.minSendable === 'number' && + typeof obj.data.metadata.maxSendable === 'number' && + typeof obj.data.metadata.commentAllowed === 'number' && + typeof obj.data.metadata.tag === 'string' && + typeof obj.data.metadata.metadata === 'string' && + typeof obj.data.metadata.callback === 'string' && + obj.data.metadata.payerData && + obj.data.metadata.payerData.name && + typeof obj.data.metadata.payerData.name.mandatory === 'boolean' && + obj.data.metadata.payerData.identifier && + typeof obj.data.metadata.payerData.identifier.mandatory === 'boolean' && + typeof obj.data.metadata.disposable === 'boolean' + ); +} diff --git a/src/types/misc.ts b/src/types/misc.ts index f99e92d..fe54fe6 100644 --- a/src/types/misc.ts +++ b/src/types/misc.ts @@ -22,4 +22,45 @@ export interface ProdIPSDataResponseType { ips: [string]; } success: boolean; +} + + +export function isSupportedRegionResponseType(data: any): data is SupportedRegionDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.ipAddress === 'string' && + typeof data.data.isSupported === 'boolean' && + typeof data.data.ipCountry === 'string' && + typeof data.data.ipRegion === 'string' + ); +} + +export function isApiProductionIPsResponseType(data: any): data is ProdIPSDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.data === 'object' && + data.data !== null && + Array.isArray(data.data.ips) && + data.data.ips.every((ip: any) => typeof ip === 'string') + ); +} + + +export function isBtcUsdExchangeRateResponseType(data: any): data is BTCUSDDataResponseType { + return ( + typeof data === 'object' && + data !== null && + typeof data.success === 'boolean' && + typeof data.message === 'string' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.btcUsdPrice === 'string' && + typeof data.data.btcUsdTimestamp === 'string' + ); } \ No newline at end of file From 6686324a62cee77b50b44c804675a17e417423dd Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Sun, 13 Aug 2023 15:04:03 +0200 Subject: [PATCH 03/18] gamertag test suite complete --- __tests__/charges/createCharge.test.ts | 28 ++++++++++++ __tests__/charges/getCharge.test.ts | 31 +++++++++++++ .../gamertag/fetchChargeFromGamertag.test.ts | 44 +++++++++++++++++++ .../gamertag/fetchGamertagByUserID.test.ts | 32 ++++++++++++++ ...etchGamertagTransactionDetailsByID.test.ts | 31 +++++++++++++ .../gamertag/fetchUserIDFromGamertag.test.ts | 28 ++++++++++++ .../gamertag/sendPaymentToGamertag.test.ts | 43 ++++++++++++++++++ .../internalTransfer.test.ts | 27 ++++++++++++ __tests__/keysend/sendKeysendPayment.test.ts | 37 ++++++++++++++++ .../fetchChargeFromLightningAddress.test.ts | 28 ++++++++++++ .../sendPaymentToLightningAddress.test.ts | 30 +++++++++++++ .../validateLightningAddress.test.ts | 22 ++++++++++ __tests__/misc/getAPIProductionIPs.test.ts | 22 ++++++++++ .../misc/getBTCtoUSDExchangeRate.test.ts | 20 +++++++++ __tests__/misc/isSupportedRegion.test.ts | 24 ++++++++++ __tests__/payments/getPaymentDetails.test.ts | 25 +++++++++++ __tests__/payments/payInvoice.test.ts | 29 ++++++++++++ .../static-charges/createStaticCharge.test.ts | 31 +++++++++++++ .../static-charges/getStaticCharge.test.ts | 32 ++++++++++++++ .../static-charges/updateStaticCharge.test.ts | 34 ++++++++++++++ __tests__/wallet/getWallet.test.ts | 32 ++++++++++++++ .../createWithdrawalRequest.test.ts | 38 ++++++++++++++++ .../withdrawal/getWithdrawalRequest.test.ts | 30 +++++++++++++ src/types/gamertag.ts | 4 +- 24 files changed, 700 insertions(+), 2 deletions(-) create mode 100644 __tests__/charges/createCharge.test.ts create mode 100644 __tests__/charges/getCharge.test.ts create mode 100644 __tests__/gamertag/fetchChargeFromGamertag.test.ts create mode 100644 __tests__/gamertag/fetchGamertagByUserID.test.ts create mode 100644 __tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts create mode 100644 __tests__/gamertag/fetchUserIDFromGamertag.test.ts create mode 100644 __tests__/gamertag/sendPaymentToGamertag.test.ts create mode 100644 __tests__/internal-transfer/internalTransfer.test.ts create mode 100644 __tests__/keysend/sendKeysendPayment.test.ts create mode 100644 __tests__/lightning/fetchChargeFromLightningAddress.test.ts create mode 100644 __tests__/lightning/sendPaymentToLightningAddress.test.ts create mode 100644 __tests__/lightning/validateLightningAddress.test.ts create mode 100644 __tests__/misc/getAPIProductionIPs.test.ts create mode 100644 __tests__/misc/getBTCtoUSDExchangeRate.test.ts create mode 100644 __tests__/misc/isSupportedRegion.test.ts create mode 100644 __tests__/payments/getPaymentDetails.test.ts create mode 100644 __tests__/payments/payInvoice.test.ts create mode 100644 __tests__/static-charges/createStaticCharge.test.ts create mode 100644 __tests__/static-charges/getStaticCharge.test.ts create mode 100644 __tests__/static-charges/updateStaticCharge.test.ts create mode 100644 __tests__/wallet/getWallet.test.ts create mode 100644 __tests__/withdrawal/createWithdrawalRequest.test.ts create mode 100644 __tests__/withdrawal/getWithdrawalRequest.test.ts diff --git a/__tests__/charges/createCharge.test.ts b/__tests__/charges/createCharge.test.ts new file mode 100644 index 0000000..257f665 --- /dev/null +++ b/__tests__/charges/createCharge.test.ts @@ -0,0 +1,28 @@ + +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { ChargeDataResponseType, ChargeOptionsType, isChargeResponseType } from '../../src/types/charges'; + +const ZBD = new zbd(TEST_API_KEY); + + +describe('createCharge', () => { + it('should successfully create a charge', async () => { + const payload: ChargeOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Charge Test Zapier", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback" + }; + + const response = await ZBD.createCharge(payload); + + expect(isChargeResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.message).toBe("Charge created."); + expect(response.data.amount).toBe(payload.amount); + expect(response.data.description).toBe(payload.description); + }); + +}); \ No newline at end of file diff --git a/__tests__/charges/getCharge.test.ts b/__tests__/charges/getCharge.test.ts new file mode 100644 index 0000000..0770eba --- /dev/null +++ b/__tests__/charges/getCharge.test.ts @@ -0,0 +1,31 @@ +import { zbd } from '@zbd/node'; +import { TEST_API_KEY } from '../../src/constants'; +import { ChargeDataResponseType, isChargeResponseType } from '../../src/types/charges'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('getCharge', () => { + const VALID_CHARGE_ID = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; + const INVALID_CHARGE_ID = 'invalid'; + const INVALID_API_KEY = 'INVALID_API_KEY'; + + // Success + it('should fetch charge details for a valid charge ID', async () => { + const data = await ZBD.getCharge(VALID_CHARGE_ID); + expect(data.success).toBe(true); + expect(data.message).toBe("Fetched Charge."); + + // Data Validation + expect(isChargeResponseType(data)).toBeTruthy(); + }); + + // Charge not found + it('should return a 404 for a non-existent charge ID', async () => { + await expect(ZBD.getCharge(INVALID_CHARGE_ID)).rejects.toMatchObject({ + message: "No Charge records found with this ID.", + status: 404 + }); + }); + +}); + diff --git a/__tests__/gamertag/fetchChargeFromGamertag.test.ts b/__tests__/gamertag/fetchChargeFromGamertag.test.ts new file mode 100644 index 0000000..7079268 --- /dev/null +++ b/__tests__/gamertag/fetchChargeFromGamertag.test.ts @@ -0,0 +1,44 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { FetchChargeFromGamertagDataResponseType, FetchChargeFromGamertagOptionsType, isFetchChargeFromGamertagDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Fetch Charge from Gamertag', () => { + const requestBody: FetchChargeFromGamertagOptionsType = { + amount: "1000", + gamertag: "andre", + description: "Requesting Charge for Gamertag", + callbackUrl: "https://your-website.com/zbd-callback", + internalId: "test-internal-id" + }; + + it('should successfully create a charge for a gamertag', async () => { + const response = await ZBD.createGamertagCharge(requestBody); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isFetchChargeFromGamertagDataResponseType(response)).toBeTruthy(); + }); + + describe('fetchGamertagByUserID error scenarios', () => { + it('should throw an error given a non-existent user ID', async () => { + + const errorRequestBody: FetchChargeFromGamertagOptionsType = { + amount: "1000", + gamertag: "fakeGamerTagĆ", + description: "Requesting Charge for fake Gamertag", + callbackUrl: "https://your-website.com/zbd-callback", + internalId: "test-internal-id" + }; + + await expect(ZBD.createGamertagCharge(errorRequestBody)).rejects.toMatchObject({ + message: "API request failed", + status: 500, + }) + + }); + }); + + +}); \ No newline at end of file diff --git a/__tests__/gamertag/fetchGamertagByUserID.test.ts b/__tests__/gamertag/fetchGamertagByUserID.test.ts new file mode 100644 index 0000000..94491e1 --- /dev/null +++ b/__tests__/gamertag/fetchGamertagByUserID.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { FetchGamertagByUserIdDataResponseType, isFetchGamertagByUserIDDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Fetch Gamertag By User ID', () => { + const testUserID = "ec9b38d5-b126-4307-9d1e-8aa0dfab5d7e"; + const fakeUserID = "202020" + + it('should successfully fetch a gamertag by user ID', async () => { + const response = await ZBD.getGamertagByUserId(testUserID); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(response.message).toBe("Fetched gamertag from uuid"); + + // Data Validation + expect(isFetchGamertagByUserIDDataResponseType(response)).toBeTruthy(); + }); + + describe('fetchGamertagByUserID error scenarios', () => { + it('should throw an error given a non-existent user ID', async () => { + + await expect(ZBD.getGamertagByUserId(fakeUserID)).rejects.toMatchObject({ + message: "No gamertag found with this uuid", + status: 400, + }) + + }); + }); +}); diff --git a/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts b/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts new file mode 100644 index 0000000..a8daf17 --- /dev/null +++ b/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts @@ -0,0 +1,31 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { GamertagTransactionDataResponseType, isGamertagTransactionDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Fetch Gamertag Transaction Details By ID', () => { + const TEST_TRANSACTION_ID = '3418e871-05f6-4745-b12b-ccd53da9c4d1'; + const NON_EXISTENT_TRANSACTION_ID = '903883f2-67d9-4707-a21b-ddff004fe041'; + + it('should successfully fetch transaction details by ID', async () => { + const response = await ZBD.getGamertagTransaction(TEST_TRANSACTION_ID); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + + expect(isGamertagTransactionDataResponseType(response)).toBeTruthy(); + }); + + describe('fetchGamertagTransactionDetailsByID error scenarios', () => { + it('should fail to fetch transaction details given false ID', async () => { + const response = await ZBD.getGamertagTransaction(NON_EXISTENT_TRANSACTION_ID); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(response.message).toBe("Transaction not found"); + + }) + }); +}); + diff --git a/__tests__/gamertag/fetchUserIDFromGamertag.test.ts b/__tests__/gamertag/fetchUserIDFromGamertag.test.ts new file mode 100644 index 0000000..7908ac5 --- /dev/null +++ b/__tests__/gamertag/fetchUserIDFromGamertag.test.ts @@ -0,0 +1,28 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { FetchUserIdByGamertagDataResponseType, isFetchUserIdByGamertagDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Fetch User ID By Gamertag', () => { + const testGamertag = "foxp2"; + + it('should successfully fetch user ID for a valid gamertag', async () => { + const response = await ZBD.getUserIdByGamertag(testGamertag); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isFetchUserIdByGamertagDataResponseType(response)).toBeTruthy(); + }); + + it('should return an error for an invalid gamertag', async () => { + const invalidGamertag = "nonExistentTagč"; + + await expect(ZBD.getUserIdByGamertag(invalidGamertag)).rejects.toMatchObject({ + message: "No user found with this gamertag", + status: 400, + }) + + }); +}); + diff --git a/__tests__/gamertag/sendPaymentToGamertag.test.ts b/__tests__/gamertag/sendPaymentToGamertag.test.ts new file mode 100644 index 0000000..e8685c5 --- /dev/null +++ b/__tests__/gamertag/sendPaymentToGamertag.test.ts @@ -0,0 +1,43 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { SendGamertagPaymentOptionsType, isSendGamertagPaymentDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Send Payment to Gamertag', () => { + const mockRequestBody: SendGamertagPaymentOptionsType = { + gamertag: "foxp2", + amount: "1000", + description: "Sending to ZBD Gamertag" + }; + + it('should successfully send payment to a gamertag', async () => { + const response = await ZBD.sendGamertagPayment(mockRequestBody); // Assuming ZBD has a method called sendPaymentToGamertag + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(response.message).toBe("Payment done."); + + expect(isSendGamertagPaymentDataResponseType(response)).toBeTruthy() + + }); + + describe('sendPaymentToGamertag error scenarios', () => { + + it('should throw an error given a non-existent gamertag', async () => { + + const errorRequestBody: SendGamertagPaymentOptionsType = { + gamertag: "fakeGamertagĆ", + amount: "1000", + description: "Sending to non-existent Gamertag" + }; + + await expect(ZBD.sendGamertagPayment(errorRequestBody)).rejects.toMatchObject({ + message: "You cannot pay to this user, missing destination", + status: 500, + }) + + }); + + }); +}); diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts new file mode 100644 index 0000000..9dc0b23 --- /dev/null +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -0,0 +1,27 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { InternalTransferOptionsType, isInternalTransferDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Initiate Internal Transfer', () => { + + it('should initiate an internal transfer successfully', async () => { + // Mock parameters + const requestBody: InternalTransferOptionsType = { + amount: "10000", + receiverWalletId: "b904ee02-ec0b-4fd4-b99f-1f2d3d0001a6" + }; + + const response = await ZBD.internalTransfer(requestBody); + console.log(response) + + expect(response.success).toBe(true); + expect(response.message).toBe('Internal Transfer done.'); + + // Data Validation + expect(isInternalTransferDataResponseType(response)).toBeTruthy(); + }); + +}); + diff --git a/__tests__/keysend/sendKeysendPayment.test.ts b/__tests__/keysend/sendKeysendPayment.test.ts new file mode 100644 index 0000000..4ec2758 --- /dev/null +++ b/__tests__/keysend/sendKeysendPayment.test.ts @@ -0,0 +1,37 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { KeysendOptionsType, isKeysendDataResponseType } from '../../src/types'; + + +const ZBD = new zbd(TEST_API_KEY); + +describe('Send Keysend Payment', () => { + + it('should send a keysend payment successfully', async () => { + const requestBody: KeysendOptionsType = { + amount: "1000", + pubkey: "0332d57355d673e217238ce3e4be8491aa6b2a13f95494133ee243e57df1653ace", + tlvRecords: [], + metadata: {}, + callbackUrl: "MOCK_CALLBACK_URL" + }; + + const response = await ZBD.sendKeysendPayment(requestBody); + console.log(response) + + // Data Validation + expect(response.success).toBe(true); + expect(isKeysendDataResponseType(response)).toBeTruthy(); + + }); + + + +describe('createCharge error scenarios', () => { + +}); + + +}); + + diff --git a/__tests__/lightning/fetchChargeFromLightningAddress.test.ts b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts new file mode 100644 index 0000000..6662344 --- /dev/null +++ b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts @@ -0,0 +1,28 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { FetchChargeFromLightningAddressDataResponseType, CreateChargeFromLightningAddressOptionsType, isFetchChargeFromLightningAddressResponseType, } from '../../src/types/lightning'; // Ensure you create this type checker function + +const ZBD = new zbd(TEST_API_KEY); + +describe('fetchChargeFromLightningAddress', () => { + + const payload: CreateChargeFromLightningAddressOptionsType = { + lnAddress: "andre@zbd.gg", + lnaddress: "andre@zbd.gg", + amount: "10000", + description: "Sending to a Lightning Address", + }; + + it('should successfully fetch a charge from Lightning Address', async () => { + const response = await ZBD.createChargeFromLightningAddress(payload); + + + expect(isFetchChargeFromLightningAddressResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.data.amount).toBe(payload.amount); + }); + + describe('fetchChargeFromLightningAddress error scenarios', () => { + + }); +}); diff --git a/__tests__/lightning/sendPaymentToLightningAddress.test.ts b/__tests__/lightning/sendPaymentToLightningAddress.test.ts new file mode 100644 index 0000000..8cf449d --- /dev/null +++ b/__tests__/lightning/sendPaymentToLightningAddress.test.ts @@ -0,0 +1,30 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; + +// Assuming you have created this type checker already +import { SendLightningAddressPaymentDataResponseType, SendLightningAddressPaymentOptionsType, isSendLightningAddressPaymentDataResponseType } from '../../src/types/lightning'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('sendToLightning', () => { + + it('should successfully send a payment to a Lightning Address', async () => { + const payload = { + lnAddress: "andre@zbd.gg", + amount: "10000", + comment: "Sending to a Lightning Address", + callbackUrl: "https://your-domain.com/zbd-callback", + internalId: "uniqueIdFromYourSystem" + }; + + const response = await ZBD.sendLightningAddressPayment(payload); + + expect(isSendLightningAddressPaymentDataResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.data.amount).toBe(payload.amount); + }); + + describe('sendToLightning error scenarios', () => { + + }); +}); diff --git a/__tests__/lightning/validateLightningAddress.test.ts b/__tests__/lightning/validateLightningAddress.test.ts new file mode 100644 index 0000000..3a38442 --- /dev/null +++ b/__tests__/lightning/validateLightningAddress.test.ts @@ -0,0 +1,22 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { ValidateLightningAddressDataResponseType, isValidateLightningAddressDataResponseType } from '../../src/types/lightning'; // Your provided interface + +const ZBD = new zbd(TEST_API_KEY); + +describe('validateLightningAddress', () => { + const mockLightningAddress = 'andre@zbd.gg'; + + it('should successfully validate a Lightning Address', async () => { + const response = await ZBD.validateLightningAddress(mockLightningAddress); + + expect(response.success).toBe(true); + + // Data Validation + expect(isValidateLightningAddressDataResponseType(response)).toBeTruthy(); +}); + + describe('validateLightningAddress error scenarios', () => { + + }); +}); diff --git a/__tests__/misc/getAPIProductionIPs.test.ts b/__tests__/misc/getAPIProductionIPs.test.ts new file mode 100644 index 0000000..dcdd8a7 --- /dev/null +++ b/__tests__/misc/getAPIProductionIPs.test.ts @@ -0,0 +1,22 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { ProdIPSDataResponseType , isApiProductionIPsResponseType } from '../../src/types/misc'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('API Production IPs', () => { + + it('should successfully fetch the list of production IPs', async () => { + const response = await ZBD.getZBDProdIps(); // Assuming ZBD has a method called getProductionIPs + + console.log(response) + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isApiProductionIPsResponseType(response)).toBeTruthy(); + expect(Array.isArray(response.data.ips)).toBe(true); + }); + + describe('getProductionIPs error scenarios', () => { + // Place any error scenario tests here, like handling if the response doesn't contain 'ips', etc. + }); +}); diff --git a/__tests__/misc/getBTCtoUSDExchangeRate.test.ts b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts new file mode 100644 index 0000000..4487ea7 --- /dev/null +++ b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts @@ -0,0 +1,20 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { BTCUSDDataResponseType, isBtcUsdExchangeRateResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('BTC to USD Exchange Rate', () => { + + it('should successfully fetch the latest BTC to USD exchange rate', async () => { + const response = await ZBD.getBtcUsdExchangeRate(); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isBtcUsdExchangeRateResponseType(response)).toBeTruthy(); + expect(response.message).toBe("Successfully retrieved BTC USD price ticker information."); + }); + + describe('getBtcUsdExchangeRate error scenarios', () => { + }); +}); diff --git a/__tests__/misc/isSupportedRegion.test.ts b/__tests__/misc/isSupportedRegion.test.ts new file mode 100644 index 0000000..a551163 --- /dev/null +++ b/__tests__/misc/isSupportedRegion.test.ts @@ -0,0 +1,24 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { SupportedRegionDataResponseType, isSupportedRegionResponseType, } from '../../src/types/misc'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('Is Supported Region', () => { + const ipAddress = "66.109.221.0"; // Mocked IP address for test purposes + + it('should successfully check if an IP address belongs to a supported region', async () => { + const response = await ZBD.isSupportedRegion(ipAddress); // Assuming ZBD has a method called checkSupportedRegion + + console.log(response) + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isSupportedRegionResponseType(response)).toBeTruthy(); + expect(response.data.ipAddress).toBe(ipAddress); + expect(response.data.isSupported).toBe(true); + }); + + describe('checkSupportedRegion error scenarios', () => { + // Place any error scenario tests here, like invalid IP address format, etc. + }); +}); \ No newline at end of file diff --git a/__tests__/payments/getPaymentDetails.test.ts b/__tests__/payments/getPaymentDetails.test.ts new file mode 100644 index 0000000..066697d --- /dev/null +++ b/__tests__/payments/getPaymentDetails.test.ts @@ -0,0 +1,25 @@ +// import { TEST_API_KEY } from '../src/constants'; +// import { zbd } from '../src/zbd'; +// import { isPaymentResponseType } from '../src/types/payments'; // Assuming you've created this function already based on our prior interactions + +// const ZBD = new zbd(TEST_API_KEY); + +// describe('getPaymentDetails', () => { +// // A mock payment ID. Ideally, you'd get this from a prior API call that created a payment. +// const mockPaymentId = 'caafd318-527c-466b-81f2-441d3a092aae'; + +// it('should successfully fetch a payment detail', async () => { +// const response = await ZBD.getPaymentDetails(mockPaymentId); // Assuming ZBD has a method called getPaymentDetails + +// expect(isPaymentResponseType(response)).toBeTruthy(); +// expect(response.success).toBe(true); +// expect(response.message).toBe("Fetched Payment."); +// expect(response.data.id).toBe(mockPaymentId); +// expect(response.data.description).toBe("Custom Payment Description"); +// // ... you can add more assertions for other fields if needed +// }); + +// describe('getPaymentDetails error scenarios', () => { +// // Place any error scenario tests here +// }); +// }); diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts new file mode 100644 index 0000000..e43fdaf --- /dev/null +++ b/__tests__/payments/payInvoice.test.ts @@ -0,0 +1,29 @@ +// import { TEST_API_KEY } from '../src/constants'; +// import { zbd } from '../src/zbd'; +// import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isPaymentResponseType } from '../src/types/payments'; + +// const ZBD = new zbd(TEST_API_KEY); + +// describe('payInvoice', () => { +// it('should successfully pay an invoice', async () => { +// const payload: SendPaymentOptionsType = { +// description: "Custom Payment Description", +// internalId: "11af01d092444a317cb33faa6b8304b8", +// invoice: "lnbc1pjpf53rdqdgdshx6pqg9c8qpp56vu785r8m78dhxj3al58wtx29nxu93l5878hmkegu8aq56lnfzfqsp5w7jrwwwdt9xjrjvyh959hup06qhgjv9y4sc902u54qvfgqtpfzns9qrsgqcqpcxqy8ayqrzjqv06k0m23t593pngl0jt7n9wznp64fqngvctz7vts8nq4tukvtljqz385vqqzqqqqcqqqqqqqqqqqqqq9grzjqtsjy9p55gdceevp36fvdmrkxqvzfhy8ak2tgc5zgtjtra9xlaz97zpq6qqqjjcqqcqqqqqqqqqqqqqq9gsk96h5waj9v6eg7yz5tumhnmfgc4zz3u6p9ted9z4g6rkszz2e4kdj3vhmzmnqy2ardyw3k9ewsrjq636sm38t3s96d7h392x82859cpu9zxzf", +// callbackUrl: "https://my-website.com/callback/zbd", +// amount: "10000" +// }; + +// const response = await ZBD.(payload); + +// expect(isPaymentResponseType(response)).toBeTruthy(); +// expect(response.success).toBe(true); +// expect(response.message).toBe("Payment done."); +// expect(response.data.amount).toBe(String(payload.amount)); +// expect(response.data.description).toBe(payload.description); +// }); + +// describe('payInvoice error scenarios', () => { +// // You can add tests for different error scenarios here +// }); +// }); diff --git a/__tests__/static-charges/createStaticCharge.test.ts b/__tests__/static-charges/createStaticCharge.test.ts new file mode 100644 index 0000000..0a82291 --- /dev/null +++ b/__tests__/static-charges/createStaticCharge.test.ts @@ -0,0 +1,31 @@ +import { zbd } from '@zbd/node'; +import { TEST_API_KEY } from '../../src/constants'; +import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('createStaticCharge', () => {; + + // Data for creating static charge + const validStaticChargeData: StaticChargeOptionsType = { + allowedSlots: null, + minAmount: "10000", + maxAmount: "20000", + description: "This is my static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment was successful!" + }; + + // Success + it('should successfully create a static charge', async () => { + const response = await ZBD.createStaticCharge(validStaticChargeData); + expect(response.message).toBe("Successfully created Static Charge."); + + // Data Validation + expect(isStaticChargeDataResponseType(response)).toBeTruthy(); + }); + + + +}); diff --git a/__tests__/static-charges/getStaticCharge.test.ts b/__tests__/static-charges/getStaticCharge.test.ts new file mode 100644 index 0000000..3c19df8 --- /dev/null +++ b/__tests__/static-charges/getStaticCharge.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { StaticChargeDataResponseType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; + +const ZBD = new zbd(TEST_API_KEY); + + +describe('getStaticCharge', () => { + + const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; + + it('should successfully fetch Static Charge details', async () => { + + const responseData = await ZBD.getStaticCharge(STATIC_CHARGE_ID); + + expect(responseData.message).toBe('Successfully retrieved Static Charge data.'); + expect(responseData.data.id).toBe(STATIC_CHARGE_ID); + + // Data Validation + expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); + + }); + + // Static Charge not found + it('should return a 404 for a non-existent charge ID', async () => { + const NON_EXISTENT_STATIC_CHARGE_ID = 'invalid' + await expect(ZBD.getCharge(NON_EXISTENT_STATIC_CHARGE_ID)).rejects.toMatchObject({ + message: "No Charge records found with this ID.", + status: 404 + }); + }); +}); diff --git a/__tests__/static-charges/updateStaticCharge.test.ts b/__tests__/static-charges/updateStaticCharge.test.ts new file mode 100644 index 0000000..3ec04ad --- /dev/null +++ b/__tests__/static-charges/updateStaticCharge.test.ts @@ -0,0 +1,34 @@ +// import { zbd } from '@zbd/node'; +// import { TEST_API_KEY } from '../src/constants'; +// import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; + +// const ZBD = new zbd(TEST_API_KEY); + +// describe('PATCH Update Static Charge', () => { + +// const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; +// it('should successfully update a Static Charge', async () => { +// const updateOptions: StaticChargeOptionsType = { +// allowedSlots: null, +// minAmount: "10000", +// maxAmount: "5000000", +// description: "This is my editted static charge", +// internalId: "myInternalId", +// callbackUrl: "https://my-website.com/zbd-callback", +// successMessage: "Congratulations your payment success msg was editted!" +// }; + +// const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); +// console.log(responseData) + +// expect(responseData.message).toBe('Successfully editted Static Charge.'); +// expect(responseData.data.id).toBe(STATIC_CHARGE_ID); +// expect(responseData.data.description).toBe(updateOptions.description); +// // Data Validation +// expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); +// }); + +// // Todo: False cases + +// }); + diff --git a/__tests__/wallet/getWallet.test.ts b/__tests__/wallet/getWallet.test.ts new file mode 100644 index 0000000..ab11b44 --- /dev/null +++ b/__tests__/wallet/getWallet.test.ts @@ -0,0 +1,32 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { WalletDataResponseType } from '../../src/types'; +import { zbd } from '../../src/zbd'; + +const ZBD = new zbd(TEST_API_KEY); + +function isWalletDataResponseType(data: any): data is WalletDataResponseType { + return typeof data === 'object' && + data !== null && + typeof data.message === 'string' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.unit === 'string' && + typeof data.data.balance === 'string'; +} + +describe('getWallet', () => { + + it('should fetch wallet details successfully', async () => { + const response = await ZBD.getWallet(); + expect(response).toBeDefined(); + + // Data Validation + expect(isWalletDataResponseType(response)).toBeTruthy(); + + // Additional check for the balance to ensure it's a valid number string + expect(Number(response.data.balance)).not.toBeNaN(); + }); + + + +}); \ No newline at end of file diff --git a/__tests__/withdrawal/createWithdrawalRequest.test.ts b/__tests__/withdrawal/createWithdrawalRequest.test.ts new file mode 100644 index 0000000..5026c35 --- /dev/null +++ b/__tests__/withdrawal/createWithdrawalRequest.test.ts @@ -0,0 +1,38 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { CreateWithdrawalRequestDataResponseType, WithdrawalRequestOptionsType, isCreateWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../../src/types'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('createWithdrawalRequest', () => { + + const requestBody: WithdrawalRequestOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Withdrawal Description", + internalId: "internalId", + callbackUrl: "https://your-website.com/callback" + }; + + it('should successfully create a withdrawal request', async () => { + + const responseData: CreateWithdrawalRequestDataResponseType = await ZBD.createWithdrawalRequest(requestBody); + + expect(responseData.success).toBe(true); + expect(responseData.message).toBe('Successfully created Withdrawal Request.'); + + // Check if returned data matches request body data + expect(responseData.data.amount).toBe(requestBody.amount); + expect(responseData.data.description).toBe(requestBody.description); + expect(responseData.data.internalId).toBe(requestBody.internalId); + expect(responseData.data.callbackUrl).toBe(requestBody.callbackUrl); + + // Data Validation + expect(isCreateWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); + + }); + + + +}); + diff --git a/__tests__/withdrawal/getWithdrawalRequest.test.ts b/__tests__/withdrawal/getWithdrawalRequest.test.ts new file mode 100644 index 0000000..987d35c --- /dev/null +++ b/__tests__/withdrawal/getWithdrawalRequest.test.ts @@ -0,0 +1,30 @@ +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { GetWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../../src/types/withdrawal'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('getWithdrawalRequest', () => { + + const WITHDRAWAL_ID = 'e3c7321a-cc06-48da-90a8-589bd175ace9'; + + it('should successfully fetch Withdrawal Request details', async () => { + + const responseData = await ZBD.getWithdrawalRequest(WITHDRAWAL_ID); + + expect(responseData.data.id).toBe(WITHDRAWAL_ID); + + // Data Validation + expect(isGetWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); + + }); + + // Withdrawal Request not found + it('should return an error for a non-existent withdrawal ID', async () => { + const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' + await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ + message: "Failed to fetch withdrawal request." + }); + }); +}); + diff --git a/src/types/gamertag.ts b/src/types/gamertag.ts index c7d8f7f..eeaaf89 100644 --- a/src/types/gamertag.ts +++ b/src/types/gamertag.ts @@ -25,7 +25,7 @@ export interface GamertagTransactionDataResponseType { confirmedAt: string; processedAt: string; } - message: string; + message: string | undefined; success: boolean; } @@ -91,7 +91,7 @@ export function isGamertagTransactionDataResponseType(object: any): object is Ga return ( typeof object === 'object' && object !== null && - typeof object.message === 'string' && + (typeof object.message === 'string' || object.message === undefined) && typeof object.success === 'boolean' && typeof object.data === 'object' && object.data !== null && From 5e78c9dad120f121cff1e35776499ca8e01202c4 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Mon, 14 Aug 2023 10:57:24 +0200 Subject: [PATCH 04/18] charges test suite complete --- __tests__/charges/createCharge.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/__tests__/charges/createCharge.test.ts b/__tests__/charges/createCharge.test.ts index 257f665..27dbb76 100644 --- a/__tests__/charges/createCharge.test.ts +++ b/__tests__/charges/createCharge.test.ts @@ -25,4 +25,23 @@ describe('createCharge', () => { expect(response.data.description).toBe(payload.description); }); + describe('fetchGamertagByUserID error scenarios', () => { + it('should throw an error given an erroneous payload (amount = 0)', async () => { + + const erroneousPayload: ChargeOptionsType = { + expiresIn: 100, + amount: "0", + description: "My Charge Test Zapier", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback" + }; + + await expect(ZBD.createCharge(erroneousPayload)).rejects.toMatchObject({ + message: "Request has missing or mismatch params.", + status: 400, + }) + + }); + }); + }); \ No newline at end of file From e6d2213a714cc73874e79c82f97bc80c7b6abcda Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Mon, 14 Aug 2023 11:12:46 +0200 Subject: [PATCH 05/18] lighning test suite complete --- .../internalTransfer.test.ts | 21 +++++++++++++++++-- .../fetchChargeFromLightningAddress.test.ts | 17 ++++++++++++++- .../sendPaymentToLightningAddress.test.ts | 21 +++++++++++++++++-- .../validateLightningAddress.test.ts | 7 +++++++ 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index 9dc0b23..a251fa0 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -9,11 +9,12 @@ describe('Initiate Internal Transfer', () => { it('should initiate an internal transfer successfully', async () => { // Mock parameters const requestBody: InternalTransferOptionsType = { - amount: "10000", - receiverWalletId: "b904ee02-ec0b-4fd4-b99f-1f2d3d0001a6" + amount: "1000", + receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6" }; const response = await ZBD.internalTransfer(requestBody); + console.log(response) expect(response.success).toBe(true); @@ -23,5 +24,21 @@ describe('Initiate Internal Transfer', () => { expect(isInternalTransferDataResponseType(response)).toBeTruthy(); }); + describe('internalTransfer error scenarios', () => { + it('should throw an error given an invalid receiver wallet ID', async () => { + + const errorBody: InternalTransferOptionsType = { + amount: "100000", + receiverWalletId: "1234" + }; + + await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ + message: "Error processing transfer.", + status: 400, + }) + + }); + }); + }); diff --git a/__tests__/lightning/fetchChargeFromLightningAddress.test.ts b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts index 6662344..fe893c4 100644 --- a/__tests__/lightning/fetchChargeFromLightningAddress.test.ts +++ b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts @@ -23,6 +23,21 @@ describe('fetchChargeFromLightningAddress', () => { }); describe('fetchChargeFromLightningAddress error scenarios', () => { - + const errorPayload: CreateChargeFromLightningAddressOptionsType = { + lnAddress: "aol@lol.xqz", + lnaddress: "aol@lol.xqz", + amount: "10000", + description: "Sending to a Lightning Address", + }; + + it('should throw an error when given invalid Lightning Address', async () => { + + await expect(ZBD.createChargeFromLightningAddress(errorPayload)).rejects.toMatchObject({ + message: "Could not get lighning address info.", + status: 400, + }) + + + }); }); }); diff --git a/__tests__/lightning/sendPaymentToLightningAddress.test.ts b/__tests__/lightning/sendPaymentToLightningAddress.test.ts index 8cf449d..f76a865 100644 --- a/__tests__/lightning/sendPaymentToLightningAddress.test.ts +++ b/__tests__/lightning/sendPaymentToLightningAddress.test.ts @@ -9,7 +9,7 @@ const ZBD = new zbd(TEST_API_KEY); describe('sendToLightning', () => { it('should successfully send a payment to a Lightning Address', async () => { - const payload = { + const payload: SendLightningAddressPaymentOptionsType = { lnAddress: "andre@zbd.gg", amount: "10000", comment: "Sending to a Lightning Address", @@ -25,6 +25,23 @@ describe('sendToLightning', () => { }); describe('sendToLightning error scenarios', () => { - + const errorPayload: SendLightningAddressPaymentOptionsType = { + lnAddress: "aol@lol.xqz", + amount: "10000", + comment: "Sending to a Lightning Address", + callbackUrl: "https://your-domain.com/zbd-callback", + internalId: "uniqueIdFromYourSystem" + }; + + it('should throw an error when given invalid Lightning Address', async () => { + + await expect(ZBD.sendLightningAddressPayment(errorPayload)).rejects.toMatchObject({ + message: "Could not get lighning address info.", + status: 400, + }) + + + }); + }); }); diff --git a/__tests__/lightning/validateLightningAddress.test.ts b/__tests__/lightning/validateLightningAddress.test.ts index 3a38442..bd32dd7 100644 --- a/__tests__/lightning/validateLightningAddress.test.ts +++ b/__tests__/lightning/validateLightningAddress.test.ts @@ -17,6 +17,13 @@ describe('validateLightningAddress', () => { }); describe('validateLightningAddress error scenarios', () => { + const errorLightningAddress = "aol@lol.xqz"; + it('should say valid is false given invalid Lightning Address', async () => { + const response = await ZBD.validateLightningAddress(errorLightningAddress); + expect(response.data.valid).toBe(false); + expect(response.success).toBe(true); + + }); }); }); From 19775ad16529e50058151ac1abf09ed35fc8a2d2 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Mon, 14 Aug 2023 11:19:24 +0200 Subject: [PATCH 06/18] misc test suite complete --- __tests__/misc/getAPIProductionIPs.test.ts | 5 +--- .../misc/getBTCtoUSDExchangeRate.test.ts | 2 -- __tests__/misc/isSupportedRegion.test.ts | 29 +++++++++++++++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/__tests__/misc/getAPIProductionIPs.test.ts b/__tests__/misc/getAPIProductionIPs.test.ts index dcdd8a7..5d3a449 100644 --- a/__tests__/misc/getAPIProductionIPs.test.ts +++ b/__tests__/misc/getAPIProductionIPs.test.ts @@ -7,7 +7,7 @@ const ZBD = new zbd(TEST_API_KEY); describe('API Production IPs', () => { it('should successfully fetch the list of production IPs', async () => { - const response = await ZBD.getZBDProdIps(); // Assuming ZBD has a method called getProductionIPs + const response = await ZBD.getZBDProdIps(); console.log(response) expect(response).toBeDefined(); @@ -16,7 +16,4 @@ describe('API Production IPs', () => { expect(Array.isArray(response.data.ips)).toBe(true); }); - describe('getProductionIPs error scenarios', () => { - // Place any error scenario tests here, like handling if the response doesn't contain 'ips', etc. - }); }); diff --git a/__tests__/misc/getBTCtoUSDExchangeRate.test.ts b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts index 4487ea7..0444ec1 100644 --- a/__tests__/misc/getBTCtoUSDExchangeRate.test.ts +++ b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts @@ -15,6 +15,4 @@ describe('BTC to USD Exchange Rate', () => { expect(response.message).toBe("Successfully retrieved BTC USD price ticker information."); }); - describe('getBtcUsdExchangeRate error scenarios', () => { - }); }); diff --git a/__tests__/misc/isSupportedRegion.test.ts b/__tests__/misc/isSupportedRegion.test.ts index a551163..22e91da 100644 --- a/__tests__/misc/isSupportedRegion.test.ts +++ b/__tests__/misc/isSupportedRegion.test.ts @@ -5,12 +5,13 @@ import { zbd } from '../../src/zbd'; const ZBD = new zbd(TEST_API_KEY); describe('Is Supported Region', () => { - const ipAddress = "66.109.221.0"; // Mocked IP address for test purposes + const ipAddress = "66.109.221.0"; + const unsupportedIpAddress = "176.57.67.255"; + const errorIpAddress = "11111.11111"; - it('should successfully check if an IP address belongs to a supported region', async () => { - const response = await ZBD.isSupportedRegion(ipAddress); // Assuming ZBD has a method called checkSupportedRegion + it('should successfully check that given IP address belongs to a supported region', async () => { + const response = await ZBD.isSupportedRegion(ipAddress); - console.log(response) expect(response).toBeDefined(); expect(response.success).toBe(true); expect(isSupportedRegionResponseType(response)).toBeTruthy(); @@ -18,7 +19,25 @@ describe('Is Supported Region', () => { expect(response.data.isSupported).toBe(true); }); + it('should successfully check that given IP address does not belong to a supported region', async () => { + const response = await ZBD.isSupportedRegion(unsupportedIpAddress); + + expect(response).toBeDefined(); + expect(response.success).toBe(true); + expect(isSupportedRegionResponseType(response)).toBeTruthy(); + expect(response.data.ipAddress).toBe(unsupportedIpAddress); + expect(response.data.isSupported).toBe(false); + }); + describe('checkSupportedRegion error scenarios', () => { - // Place any error scenario tests here, like invalid IP address format, etc. + + it('should throw error given invalid IP format', async () => { + await expect(ZBD.isSupportedRegion(errorIpAddress)).rejects.toMatchObject({ + message: "Ip Address is not valid.", + status: 400, + }) + }); + + }); }); \ No newline at end of file From b1023f963b50f11141e4c6f75c908a9df721cd0f Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Mon, 14 Aug 2023 12:06:44 +0200 Subject: [PATCH 07/18] static charge test suite complete --- __tests__/payments/getPaymentDetails.test.ts | 40 ++++----- __tests__/payments/payInvoice.test.ts | 75 ++++++++++------- .../static-charges/createStaticCharge.test.ts | 25 +++++- .../static-charges/updateStaticCharge.test.ts | 82 ++++++++++++------- src/types/payments.ts | 24 +++++- src/types/static-charges.ts | 4 +- 6 files changed, 167 insertions(+), 83 deletions(-) diff --git a/__tests__/payments/getPaymentDetails.test.ts b/__tests__/payments/getPaymentDetails.test.ts index 066697d..3c28f9d 100644 --- a/__tests__/payments/getPaymentDetails.test.ts +++ b/__tests__/payments/getPaymentDetails.test.ts @@ -1,25 +1,25 @@ -// import { TEST_API_KEY } from '../src/constants'; -// import { zbd } from '../src/zbd'; -// import { isPaymentResponseType } from '../src/types/payments'; // Assuming you've created this function already based on our prior interactions +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { isInvoicePaymentDataResponseType } from '../../src/types/payments'; // Assuming you've created this function already based on our prior interactions -// const ZBD = new zbd(TEST_API_KEY); +const ZBD = new zbd(TEST_API_KEY); -// describe('getPaymentDetails', () => { -// // A mock payment ID. Ideally, you'd get this from a prior API call that created a payment. -// const mockPaymentId = 'caafd318-527c-466b-81f2-441d3a092aae'; +describe('getPaymentDetails', () => { + const mockPaymentId = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; -// it('should successfully fetch a payment detail', async () => { -// const response = await ZBD.getPaymentDetails(mockPaymentId); // Assuming ZBD has a method called getPaymentDetails + it('should successfully fetch a payment detail', async () => { + const response = await ZBD.getPayment(mockPaymentId); + console.log(response) -// expect(isPaymentResponseType(response)).toBeTruthy(); -// expect(response.success).toBe(true); -// expect(response.message).toBe("Fetched Payment."); -// expect(response.data.id).toBe(mockPaymentId); -// expect(response.data.description).toBe("Custom Payment Description"); -// // ... you can add more assertions for other fields if needed -// }); + expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.message).toBe("Fetched Payment."); + expect(response.data.id).toBe(mockPaymentId); + expect(response.data.description).toBe("Custom Payment Description"); -// describe('getPaymentDetails error scenarios', () => { -// // Place any error scenario tests here -// }); -// }); + }); + + describe('getPaymentDetails error scenarios', () => { + + }); +}); diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts index e43fdaf..74afe49 100644 --- a/__tests__/payments/payInvoice.test.ts +++ b/__tests__/payments/payInvoice.test.ts @@ -1,29 +1,48 @@ -// import { TEST_API_KEY } from '../src/constants'; -// import { zbd } from '../src/zbd'; -// import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isPaymentResponseType } from '../src/types/payments'; - -// const ZBD = new zbd(TEST_API_KEY); - -// describe('payInvoice', () => { -// it('should successfully pay an invoice', async () => { -// const payload: SendPaymentOptionsType = { -// description: "Custom Payment Description", -// internalId: "11af01d092444a317cb33faa6b8304b8", -// invoice: "lnbc1pjpf53rdqdgdshx6pqg9c8qpp56vu785r8m78dhxj3al58wtx29nxu93l5878hmkegu8aq56lnfzfqsp5w7jrwwwdt9xjrjvyh959hup06qhgjv9y4sc902u54qvfgqtpfzns9qrsgqcqpcxqy8ayqrzjqv06k0m23t593pngl0jt7n9wznp64fqngvctz7vts8nq4tukvtljqz385vqqzqqqqcqqqqqqqqqqqqqq9grzjqtsjy9p55gdceevp36fvdmrkxqvzfhy8ak2tgc5zgtjtra9xlaz97zpq6qqqjjcqqcqqqqqqqqqqqqqq9gsk96h5waj9v6eg7yz5tumhnmfgc4zz3u6p9ted9z4g6rkszz2e4kdj3vhmzmnqy2ardyw3k9ewsrjq636sm38t3s96d7h392x82859cpu9zxzf", -// callbackUrl: "https://my-website.com/callback/zbd", -// amount: "10000" -// }; - -// const response = await ZBD.(payload); +import { TEST_API_KEY } from '../../src/constants'; +import { zbd } from '../../src/zbd'; +import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isInvoicePaymentDataResponseType } from '../../src/types/payments'; + +const ZBD = new zbd(TEST_API_KEY); + +describe('payInvoice', () => { + it('should successfully pay an invoice', async () => { + const payload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: "lnbc100n1pjdxlpvpp5r7uhh2m3dq48ysxvs8xmcph9tdkmrrlj6jyqa4arq2t9k0u6khmsdpzf4ujqsmgv9exwefq23jhxapqtfshq6t9wgcqzzsxqzfvsp56zkq022rqw5kvm08veluk9lfv7st6q7vkl3tm0d6p4weswmp3kus9qyyssqxjlqr0f0k4jswwz9v95cs5tslgmxl9ujuf8mxf09mddctd3haqr4dxxjuxalkjru3ssw26a88gs2r6tms9z9t39698jj3ddx5cctjvqpcacqmx", + callbackUrl: "https://my-website.com/callback/zbd", + amount: "10000" + }; + + const response = await ZBD.sendPayment(payload); + + + + console.log(response) + + // expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); + // expect(response.success).toBe(true); + // expect(response.message).toBe("Payment done."); + // expect(response.data.amount).toBe(String(payload.amount)); + // expect(response.data.description).toBe(payload.description); + }); + + describe('payInvoice error scenarios', () => { + const payload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "11af01d092444a317cb33faa6b8304b8", + invoice: "lnbc1pjpf53rdqdgdshx6pqg9c8qpp56vu785r8m78dhxj3al58wtx29nxu93l5878hmkegu8aq56lnfzfqsp5w7jrwwwdt9xjrjvyh959hup06qhgjv9y4sc902u54qvfgqtpfzns9qrsgqcqpcxqy8ayqrzjqv06k0m23t593pngl0jt7n9wznp64fqngvctz7vts8nq4tukvtljqz385vqqzqqqqcqqqqqqqqqqqqqq9grzjqtsjy9p55gdceevp36fvdmrkxqvzfhy8ak2tgc5zgtjtra9xlaz97zpq6qqqjjcqqcqqqqqqqqqqqqqq9gsk96h5waj9v6eg7yz5tumhnmfgc4zz3u6p9ted9z4g6rkszz2e4kdj3vhmzmnqy2ardyw3k9ewsrjq636sm38t3s96d7h392x82859cpu9zxzf", + callbackUrl: "https://my-website.com/callback/zbd", + amount: "10000" + }; -// expect(isPaymentResponseType(response)).toBeTruthy(); -// expect(response.success).toBe(true); -// expect(response.message).toBe("Payment done."); -// expect(response.data.amount).toBe(String(payload.amount)); -// expect(response.data.description).toBe(payload.description); -// }); - -// describe('payInvoice error scenarios', () => { -// // You can add tests for different error scenarios here -// }); -// }); + it('should return a 404 for a non-existent charge ID', async () => { + await expect(ZBD.sendPayment(payload)).rejects.toMatchObject({ + message: "No Charge records found with this ID.", + status: 404 + }); + }); + + + }); +}); diff --git a/__tests__/static-charges/createStaticCharge.test.ts b/__tests__/static-charges/createStaticCharge.test.ts index 0a82291..90d3ce1 100644 --- a/__tests__/static-charges/createStaticCharge.test.ts +++ b/__tests__/static-charges/createStaticCharge.test.ts @@ -4,11 +4,11 @@ import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDa const ZBD = new zbd(TEST_API_KEY); -describe('createStaticCharge', () => {; +describe('createStaticCharge', () => { // Data for creating static charge const validStaticChargeData: StaticChargeOptionsType = { - allowedSlots: null, + allowedSlots: 0, minAmount: "10000", maxAmount: "20000", description: "This is my static charge", @@ -26,6 +26,27 @@ describe('createStaticCharge', () => {; expect(isStaticChargeDataResponseType(response)).toBeTruthy(); }); + describe('createStaticCharge error scenarios', () => { + it('should throw an error given a faulty payload (no min max amount)', async () => { + + const invalidStaticChargeData: StaticChargeOptionsType = { + allowedSlots: null, + minAmount: "0", + maxAmount: "0", + description: "This is my static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment was successful!" + }; + + await expect(ZBD.createStaticCharge(invalidStaticChargeData)).rejects.toMatchObject({ + message: "Error creating Static Charge.", + status: 400, + }) + + }); + }); + }); diff --git a/__tests__/static-charges/updateStaticCharge.test.ts b/__tests__/static-charges/updateStaticCharge.test.ts index 3ec04ad..6b58662 100644 --- a/__tests__/static-charges/updateStaticCharge.test.ts +++ b/__tests__/static-charges/updateStaticCharge.test.ts @@ -1,34 +1,56 @@ -// import { zbd } from '@zbd/node'; -// import { TEST_API_KEY } from '../src/constants'; -// import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../src/types/static-charges'; +import { zbd } from '@zbd/node'; +import { TEST_API_KEY } from '../../src/constants'; +import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; -// const ZBD = new zbd(TEST_API_KEY); + const ZBD = new zbd(TEST_API_KEY); -// describe('PATCH Update Static Charge', () => { +describe('PATCH Update Static Charge', () => { -// const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; -// it('should successfully update a Static Charge', async () => { -// const updateOptions: StaticChargeOptionsType = { -// allowedSlots: null, -// minAmount: "10000", -// maxAmount: "5000000", -// description: "This is my editted static charge", -// internalId: "myInternalId", -// callbackUrl: "https://my-website.com/zbd-callback", -// successMessage: "Congratulations your payment success msg was editted!" -// }; - -// const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); -// console.log(responseData) - -// expect(responseData.message).toBe('Successfully editted Static Charge.'); -// expect(responseData.data.id).toBe(STATIC_CHARGE_ID); -// expect(responseData.data.description).toBe(updateOptions.description); -// // Data Validation -// expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); -// }); - -// // Todo: False cases - -// }); + const STATIC_CHARGE_ID = '11311e05-c0da-4382-abb1-385a4659908b'; + it('should successfully update a Static Charge', async () => { + const updateOptions: StaticChargeOptionsType = { + allowedSlots: 0, + minAmount: "10000", + maxAmount: "5000000", + description: "This is my editted static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment success msg was editted!" + }; + + + const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); + + expect(responseData.message).toBe('Successfully updated Static Charge.'); + expect(responseData.data.id).toBe(STATIC_CHARGE_ID); + expect(responseData.data.description).toBe(updateOptions.description); + // Data Validation + expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); + }); + + describe('updateStaticCharge error scenarios', () => { + it('should throw an error given a non-existent static Charge ID', async () => { + + const NON_EXISTENT_STATIC_CHARGE_ID = '10101'; + + + const invalidUpdateOptions: StaticChargeOptionsType = { + allowedSlots: 0, + minAmount: "10000", + maxAmount: "5000000", + description: "This is my editted static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment success msg was editted!" + }; + + await expect(ZBD.updateStaticCharge(NON_EXISTENT_STATIC_CHARGE_ID, invalidUpdateOptions)).rejects.toMatchObject({ + message: "Error updating Static Charge data.", + status: 400, + }) + + }); + }); + +}); diff --git a/src/types/payments.ts b/src/types/payments.ts index 64bc454..5e9db86 100644 --- a/src/types/payments.ts +++ b/src/types/payments.ts @@ -23,4 +23,26 @@ export interface SendPaymentOptionsType { callbackUrl: string; amount: string; } - \ No newline at end of file + + +export function isInvoicePaymentDataResponseType(obj: any): obj is InvoicePaymentDataResponseType { + return ( + typeof obj === 'object' && + obj !== null && + typeof obj.success === 'boolean' && + typeof obj.message === 'string' && + typeof obj.data === 'object' && + obj.data !== null && + typeof obj.data.id === 'string' && + typeof obj.data.fee === 'string' && + typeof obj.data.unit === 'string' && + typeof obj.data.amount === 'string' && + typeof obj.data.invoice === 'string' && + typeof obj.data.preimage === 'string' && + typeof obj.data.internalId === 'string' && + typeof obj.data.processedAt === 'string' && + typeof obj.data.confirmedAt === 'string' && + typeof obj.data.description === 'string' && + typeof obj.data.status === 'string' + ); +} diff --git a/src/types/static-charges.ts b/src/types/static-charges.ts index b267382..4d8869a 100644 --- a/src/types/static-charges.ts +++ b/src/types/static-charges.ts @@ -1,6 +1,6 @@ export interface StaticChargeOptionsType { - allowedSlots: string | null; + allowedSlots: number | null; minAmount: string; maxAmount: string; description: string; @@ -40,7 +40,7 @@ export function isStaticChargeDataResponseType(obj: any): obj is StaticChargeDat typeof obj.data === 'object' && typeof obj.data.id === 'string' && typeof obj.data.unit === 'string' && - typeof obj.data.slots === 'number' && + (typeof obj.data.slots === 'number' || obj.data.slots === null) && typeof obj.data.minAmount === 'string' && typeof obj.data.maxAmount === 'string' && typeof obj.data.createdAt === 'string' && From 5aeac8a42c93affc6e6e2ada23162d4422f93cf8 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Mon, 14 Aug 2023 12:10:08 +0200 Subject: [PATCH 08/18] withdrawal test suite complete --- .../createWithdrawalRequest.test.ts | 21 +++++++++++++++++++ .../withdrawal/getWithdrawalRequest.test.ts | 12 ++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/__tests__/withdrawal/createWithdrawalRequest.test.ts b/__tests__/withdrawal/createWithdrawalRequest.test.ts index 5026c35..b95c387 100644 --- a/__tests__/withdrawal/createWithdrawalRequest.test.ts +++ b/__tests__/withdrawal/createWithdrawalRequest.test.ts @@ -32,6 +32,27 @@ describe('createWithdrawalRequest', () => { }); + describe('createWithdrawalRequest error scenarios', () => { + it('should throw an error given a faulty payload (amount invalid)', async () => { + + const faultyRequestBody: WithdrawalRequestOptionsType = { + expiresIn: 300, + amount: "0", + description: "My Withdrawal Description", + internalId: "internalId", + callbackUrl: "https://your-website.com/callback" + }; + + + await expect(ZBD.createWithdrawalRequest(faultyRequestBody)).rejects.toMatchObject({ + message: "The \"amount\" property (in millisatoshis) must be greater than 1 sat.", + status: 400, + }) + + }); + }); + + }); diff --git a/__tests__/withdrawal/getWithdrawalRequest.test.ts b/__tests__/withdrawal/getWithdrawalRequest.test.ts index 987d35c..1281bad 100644 --- a/__tests__/withdrawal/getWithdrawalRequest.test.ts +++ b/__tests__/withdrawal/getWithdrawalRequest.test.ts @@ -19,12 +19,14 @@ describe('getWithdrawalRequest', () => { }); - // Withdrawal Request not found - it('should return an error for a non-existent withdrawal ID', async () => { - const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' - await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ - message: "Failed to fetch withdrawal request." + describe('createWithdrawalRequest error scenarios', () => { + it('should return an error for a non-existent withdrawal ID', async () => { + const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' + await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ + message: "Failed to fetch withdrawal request." + }); }); }); + }); From 85a24505de65b4f40a3d98ada078827b84b3a5c0 Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Mon, 14 Aug 2023 15:31:57 +0100 Subject: [PATCH 09/18] feat: Add OAuth2 authentication URL generation and related methods --- __tests__/get-authentication-url.test.ts | 88 ++++++ package-lock.json | 4 +- src/constants.ts | 52 ++-- src/types/index.ts | 26 +- src/types/zbd-login.ts | 4 + src/zbd.ts | 347 ++++++++++++++++------- yarn.lock | 116 ++++---- 7 files changed, 442 insertions(+), 195 deletions(-) create mode 100644 __tests__/get-authentication-url.test.ts create mode 100644 src/types/zbd-login.ts diff --git a/__tests__/get-authentication-url.test.ts b/__tests__/get-authentication-url.test.ts new file mode 100644 index 0000000..d42efd8 --- /dev/null +++ b/__tests__/get-authentication-url.test.ts @@ -0,0 +1,88 @@ +import { zbd } from "../src/zbd"; +import { TEST_API_KEY } from "../src/constants"; +describe("getAuthenticationUrl", () => { + let ZBD: zbd; + + beforeEach(() => { + ZBD = new zbd(TEST_API_KEY); + ZBD.setClientId("client_id"); + ZBD.setClientSecret("secret123"); + }); + + it("should generate auth url with correct params", async () => { + await ZBD.generatePKCECodes(); // Generate codeChallenge + + const params = { + redirect_uri: "http://localhost:3000/callback", + state: "random_state", + }; + + const authUrl = await ZBD.getAuthenticationUrl(params); + + expect(authUrl).toContain("client_id=client_id"); + expect(authUrl).toContain("redirect_uri=http://localhost:3000/callback"); + expect(authUrl).toContain("scope=user"); + expect(authUrl).toContain("state=random_state"); + expect(authUrl).toContain(`code_challenge=${await ZBD.getCodeChallenge()}`); + expect(authUrl).toContain("code_challenge_method=S256"); + }); + + it("should throw an error if client id is not set", async () => { + // ZBD.setClientId(); + const params = { + redirect_uri: "http://localhost:3000/callback", + state: "random_state", + }; + + await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( + "A code challenge is required. Generate one using .generatePKCE()." + ); + }); + + // it("should throw an error if client secret is not set", async () => { + // // ZBD.setClientSecret(null); + // const params = { + // redirect_uri: "http://localhost:3000/callback", + // state: "random_state", + // }; + + // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( + // "A code challenge is required. Generate one using .generatePKCE()." + // ); + // }); + + // it("should throw an error if code challenge is not generated", async () => { + // const params = { + // redirect_uri: "http://localhost:3000/callback", + // state: "random_state", + // }; + + // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( + // "A code challenge is required." + // ); + // }); + + // it("should throw an error if redirect_uri is missing", async () => { + // const params = { + // redirect_uri: undefined, + // state: "random_state", + // }; + + // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( + // "A redirect uri is required." + // ); + // }); + + // it("should throw an error if state parameter is missing", async () => { + // const params = { + // redirect_uri: "http://localhost:3000/callback", + // state: undefined, // Omitting the state property intentionally + // }; + + // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( + // "A state parameter is required." + // ); + // }); + + // Add more test cases for different scenarios... +}); diff --git a/package-lock.json b/package-lock.json index e0f58bb..191e1da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@zbd/node", - "version": "0.6.2", + "version": "0.6.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@zbd/node", - "version": "0.6.2", + "version": "0.6.3", "license": "MIT", "dependencies": { "@zbd/node": "^0.6.2", diff --git a/src/constants.ts b/src/constants.ts index 2d92300..89e8f8d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,45 +1,53 @@ // BaseUrl -export const API_URL = 'https://api.zebedee.io'; +export const API_URL = "https://api.zebedee.io"; +export const V2_DEFAULT_DOMAIN = "api.zebedee.io/v1/"; // Test API Key -export const TEST_API_KEY = "8qJxln3JVJsQM0IOJhfnJopO0JSiLdlK" +export const TEST_API_KEY: string = "8qJxln3JVJsQM0IOJhfnJopO0JSiLdlK"; // Endpoints export const API = { // Wallet - WALLET_ENDPOINT: '/v0/wallet', + WALLET_ENDPOINT: "/v0/wallet", // Charges (Pay Ins) - CHARGES_ENDPOINT: '/v0/charges', - STATIC_CHARGES_ENDPOINT: '/v0/static-charges', + CHARGES_ENDPOINT: "/v0/charges", + STATIC_CHARGES_ENDPOINT: "/v0/static-charges", // Payments (Pay Outs) - PAYMENTS_ENDPOINT: '/v0/payments', + PAYMENTS_ENDPOINT: "/v0/payments", // Lightning Address - SEND_LN_ADDRESS_PAYMENT_ENDPOINT: '/v0/ln-address/send-payment', - VALIDATE_LN_ADDRESS_ENDPOINT: '/v0/ln-address/validate', - CREATE_CHARGE_FROM_LN_ADDRESS_ENDPOINT: '/v0/ln-address/fetch-charge', + SEND_LN_ADDRESS_PAYMENT_ENDPOINT: "/v0/ln-address/send-payment", + VALIDATE_LN_ADDRESS_ENDPOINT: "/v0/ln-address/validate", + CREATE_CHARGE_FROM_LN_ADDRESS_ENDPOINT: "/v0/ln-address/fetch-charge", // ZBD Gamertags - SEND_GAMERTAG_PAYMENT_ENDPOINT: '/v0/gamertag/send-payment', - GET_GAMERTAG_PAYMENT_ENDPOINT: '/v0/gamertag/transaction', - GET_USERID_FROM_GAMERTAG_ENDPOINT: '/v0/user-id/gamertag', - GET_GAMERTAG_FROM_USERID_ENDPOINT: '/v0/gamertag/user-id', - CREATE_CHARGE_FROM_GAMERTAG_ENDPOINT: '/v0/gamertag/charges', + SEND_GAMERTAG_PAYMENT_ENDPOINT: "/v0/gamertag/send-payment", + GET_GAMERTAG_PAYMENT_ENDPOINT: "/v0/gamertag/transaction", + GET_USERID_FROM_GAMERTAG_ENDPOINT: "/v0/user-id/gamertag", + GET_GAMERTAG_FROM_USERID_ENDPOINT: "/v0/gamertag/user-id", + CREATE_CHARGE_FROM_GAMERTAG_ENDPOINT: "/v0/gamertag/charges", + + // ZBD Login (OAuth2) + GET_AUTHORIZATION_ENDPOINT: "/v1/oauth2/authorize", + FETCH_ACCESS_TOKEN_ENDPOINT: "/v1/oauth2/token", + REFRESH_TOKEN_ENDPOINT: "/v1/oauth2/token", + GET_USER_ENDPOINT: "/v1/oauth2/user", + GET_USER_WALLET_DATA_ENDPOINT: "/v1/oauth2/wallet", // Withdrawal Requests - WITHDRAWAL_REQUESTS_ENDPOINT: '/v0/withdrawal-requests', + WITHDRAWAL_REQUESTS_ENDPOINT: "/v0/withdrawal-requests", // Keysend - KEYSEND_PAYMENT_ENDPOINT: '/v0/keysend-payment', + KEYSEND_PAYMENT_ENDPOINT: "/v0/keysend-payment", // Internal Transfers - INTERNAL_TRANSFER_ENDPOINT: '/v0/internal-transfer', + INTERNAL_TRANSFER_ENDPOINT: "/v0/internal-transfer", // Utilities - IS_SUPPORTED_REGION_ENDPOINT: '/v0/is-supported-region', - DECODE_INVOICE_ENDPOINT: '/v0/decode-invoice', - FETCH_ZBD_PROD_IPS_ENDPOINT: '/v0/prod-ips', - BTCUSD_PRICE_TICKER_ENDPOINT: '/v0/btcusd', -} + IS_SUPPORTED_REGION_ENDPOINT: "/v0/is-supported-region", + DECODE_INVOICE_ENDPOINT: "/v0/decode-invoice", + FETCH_ZBD_PROD_IPS_ENDPOINT: "/v0/prod-ips", + BTCUSD_PRICE_TICKER_ENDPOINT: "/v0/btcusd", +}; diff --git a/src/types/index.ts b/src/types/index.ts index 7d89258..bbe150d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,13 +1,13 @@ -export * from './charges'; -export * from './gamertag'; -export * from './index'; -export * from './internal-transfers'; -export * from './keysend'; -export * from './lightning'; -export * from './misc'; -export * from './payments'; -export * from './static-charges'; -export * from './wallet'; -export * from './withdrawal'; -export * from './zbd-type'; - +export * from "./charges"; +export * from "./gamertag"; +export * from "./index"; +export * from "./internal-transfers"; +export * from "./keysend"; +export * from "./lightning"; +export * from "./misc"; +export * from "./payments"; +export * from "./static-charges"; +export * from "./wallet"; +export * from "./withdrawal"; +export * from "./zbd-type"; +export * from "./zbd-login"; diff --git a/src/types/zbd-login.ts b/src/types/zbd-login.ts new file mode 100644 index 0000000..ee36579 --- /dev/null +++ b/src/types/zbd-login.ts @@ -0,0 +1,4 @@ +export interface OAuth2AuthorizationRequestType { + redirect_uri: string; + state: string; +} diff --git a/src/zbd.ts b/src/zbd.ts index 5cf344b..5d23962 100644 --- a/src/zbd.ts +++ b/src/zbd.ts @@ -1,5 +1,5 @@ -import { API_URL, API } from './constants'; -import { postData, getData, patchData } from './utils'; +import { API_URL, API, V2_DEFAULT_DOMAIN as DEFAULT_DOMAIN } from "./constants"; +import { postData, getData, patchData } from "./utils"; import { ChargeOptionsType, KeysendOptionsType, @@ -32,11 +32,20 @@ import { CreateChargeFromLightningAddressOptionsType, SendGamertagPaymentDataResponseType, FetchChargeFromLightningAddressDataResponseType, -} from './types/index'; + OAuth2AuthorizationRequestType, +} from "./types/index"; +import * as crypto from "crypto"; + +let Encoder: { new (): any; new (): TextEncoder; prototype?: TextEncoder }; +const PKCELength: number = 128; class zbd { apiBaseUrl: string; - apiCoreHeaders: {apikey: string }; + apiCoreHeaders: { apikey: string }; + codeVerifier!: string; + codeChallenge!: string; + clientSecret!: string; + clientId!: string; constructor(apiKey: string) { this.apiBaseUrl = API_URL; @@ -44,15 +53,9 @@ class zbd { } async createCharge(options: ChargeOptionsType) { - const { - amount, - expiresIn, - internalId, - description, - callbackUrl, - } = options; + const { amount, expiresIn, internalId, description, callbackUrl } = options; - const response : ChargeDataResponseType = await postData({ + const response: ChargeDataResponseType = await postData({ url: `${API_URL}${API.CHARGES_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, body: { @@ -72,7 +75,7 @@ class zbd { url: `${API_URL}${API.CHARGES_ENDPOINT}/${chargeId}`, headers: { ...this.apiCoreHeaders }, }); - + return response; } @@ -88,16 +91,10 @@ class zbd { return response; } - async createWithdrawalRequest(options: WithdrawalRequestOptionsType) { - const { - amount, - expiresIn, - internalId, - callbackUrl, - description, - } = options; + async createWithdrawalRequest(options: WithdrawalRequestOptionsType) { + const { amount, expiresIn, internalId, callbackUrl, description } = options; - const response : CreateWithdrawalRequestDataResponseType = await postData({ + const response: CreateWithdrawalRequestDataResponseType = await postData({ url: `${API_URL}${API.WITHDRAWAL_REQUESTS_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, body: { @@ -113,16 +110,16 @@ class zbd { } async getWithdrawalRequest(withdrawalRequestId: string) { - const response : GetWithdrawalRequestDataResponseType = await getData({ + const response: GetWithdrawalRequestDataResponseType = await getData({ url: `${API_URL}${API.WITHDRAWAL_REQUESTS_ENDPOINT}/${withdrawalRequestId}`, headers: { ...this.apiCoreHeaders }, }); - + return response; } - async validateLightningAddress(lightningAddress: string) { - const response : ValidateLightningAddressDataResponseType = await getData({ + async validateLightningAddress(lightningAddress: string) { + const response: ValidateLightningAddressDataResponseType = await getData({ url: `${API_URL}${API.VALIDATE_LN_ADDRESS_ENDPOINT}/${lightningAddress}`, headers: { ...this.apiCoreHeaders }, }); @@ -130,75 +127,69 @@ class zbd { return response; } - async sendLightningAddressPayment(options: SendLightningAddressPaymentOptionsType) { - const { - amount, - comment, - lnAddress, - internalId, - callbackUrl, - } = options; - - const response : SendLightningAddressPaymentDataResponseType = await postData({ - url: `${API_URL}${API.SEND_LN_ADDRESS_PAYMENT_ENDPOINT}`, - headers: { ...this.apiCoreHeaders }, - body: { - amount, - comment, - lnAddress, - internalId, - callbackUrl, - }, - }); + async sendLightningAddressPayment( + options: SendLightningAddressPaymentOptionsType + ) { + const { amount, comment, lnAddress, internalId, callbackUrl } = options; + + const response: SendLightningAddressPaymentDataResponseType = + await postData({ + url: `${API_URL}${API.SEND_LN_ADDRESS_PAYMENT_ENDPOINT}`, + headers: { ...this.apiCoreHeaders }, + body: { + amount, + comment, + lnAddress, + internalId, + callbackUrl, + }, + }); return response; } - async createChargeFromLightningAddress(options: CreateChargeFromLightningAddressOptionsType) { - const { - amount, - lnaddress, - lnAddress, - description, - } = options; - + async createChargeFromLightningAddress( + options: CreateChargeFromLightningAddressOptionsType + ) { + const { amount, lnaddress, lnAddress, description } = options; // Addressing issue on ZBD API where it accepts `lnaddress` property // instead of `lnAddress` property as is standardized let lightningAddress = lnaddress || lnAddress; - const response: FetchChargeFromLightningAddressDataResponseType = await postData({ - url: `${API_URL}${API.CREATE_CHARGE_FROM_LN_ADDRESS_ENDPOINT}`, - headers: { ...this.apiCoreHeaders }, - body: { - amount, - description, - lnaddress: lightningAddress, - }, - }); + const response: FetchChargeFromLightningAddressDataResponseType = + await postData({ + url: `${API_URL}${API.CREATE_CHARGE_FROM_LN_ADDRESS_ENDPOINT}`, + headers: { ...this.apiCoreHeaders }, + body: { + amount, + description, + lnaddress: lightningAddress, + }, + }); return response; } - + async getWallet() { - const response : WalletDataResponseType = await getData({ + const response: WalletDataResponseType = await getData({ url: `${API_URL}${API.WALLET_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, }); - + return response; } - async isSupportedRegion(ipAddress: string) { - const response : SupportedRegionDataResponseType = await getData({ + async isSupportedRegion(ipAddress: string) { + const response: SupportedRegionDataResponseType = await getData({ url: `${API_URL}${API.IS_SUPPORTED_REGION_ENDPOINT}/${ipAddress}`, headers: { ...this.apiCoreHeaders }, }); - + return response; } - async getZBDProdIps() { + async getZBDProdIps() { const response: ProdIPSDataResponseType = await getData({ url: `${API_URL}${API.FETCH_ZBD_PROD_IPS_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, @@ -207,7 +198,7 @@ class zbd { return response; } - async getBtcUsdExchangeRate() { + async getBtcUsdExchangeRate() { const response: BTCUSDDataResponseType = await getData({ url: `${API_URL}${API.BTCUSD_PRICE_TICKER_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, @@ -216,7 +207,7 @@ class zbd { return response; } - async internalTransfer(options: InternalTransferOptionsType) { + async internalTransfer(options: InternalTransferOptionsType) { const { amount, receiverWalletId } = options; const response: InternalTransferDataResponseType = await postData({ @@ -231,14 +222,8 @@ class zbd { return response; } - async sendKeysendPayment(options: KeysendOptionsType) { - const { - amount, - pubkey, - metadata, - tlvRecords, - callbackUrl, - } = options; + async sendKeysendPayment(options: KeysendOptionsType) { + const { amount, pubkey, metadata, tlvRecords, callbackUrl } = options; const response: KeysendDataResponseType = await postData({ url: `${API_URL}${API.KEYSEND_PAYMENT_ENDPOINT}`, @@ -255,16 +240,10 @@ class zbd { return response; } - async sendPayment(options: SendPaymentOptionsType) { - const { - amount, - invoice, - internalId, - description, - callbackUrl, - } = options; + async sendPayment(options: SendPaymentOptionsType) { + const { amount, invoice, internalId, description, callbackUrl } = options; - const response : InvoicePaymentDataResponseType = await postData({ + const response: InvoicePaymentDataResponseType = await postData({ url: `${API_URL}${API.PAYMENTS_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, body: { @@ -276,10 +255,10 @@ class zbd { }, }); - return response; + return response; } - async getPayment(paymentId: string) { + async getPayment(paymentId: string) { const response = await getData({ url: `${API_URL}${API.PAYMENTS_ENDPOINT}/${paymentId}`, headers: { ...this.apiCoreHeaders }, @@ -288,7 +267,7 @@ class zbd { return response; } - async sendGamertagPayment(options: SendGamertagPaymentOptionsType) { + async sendGamertagPayment(options: SendGamertagPaymentOptionsType) { const { amount, gamertag, description } = options; const response: SendGamertagPaymentDataResponseType = await postData({ @@ -304,7 +283,7 @@ class zbd { return response; } - async getGamertagTransaction(transactionId: string) { + async getGamertagTransaction(transactionId: string) { const response: GamertagTransactionDataResponseType = await getData({ url: `${API_URL}${API.GET_GAMERTAG_PAYMENT_ENDPOINT}/${transactionId}`, headers: { ...this.apiCoreHeaders }, @@ -313,7 +292,7 @@ class zbd { return response; } - async getUserIdByGamertag(gamertag: string) { + async getUserIdByGamertag(gamertag: string) { const response: FetchUserIdByGamertagDataResponseType = await getData({ url: `${API_URL}${API.GET_USERID_FROM_GAMERTAG_ENDPOINT}/${gamertag}`, headers: { ...this.apiCoreHeaders }, @@ -322,7 +301,7 @@ class zbd { return response; } - async getGamertagByUserId(userId: string) { + async getGamertagByUserId(userId: string) { const response: FetchGamertagByUserIdDataResponseType = await getData({ url: `${API_URL}${API.GET_GAMERTAG_FROM_USERID_ENDPOINT}/${userId}`, headers: { ...this.apiCoreHeaders }, @@ -331,16 +310,10 @@ class zbd { return response; } - async createGamertagCharge(options: FetchChargeFromGamertagOptionsType) { - const { - amount, - gamertag, - internalId, - description, - callbackUrl, - } = options; + async createGamertagCharge(options: FetchChargeFromGamertagOptionsType) { + const { amount, gamertag, internalId, description, callbackUrl } = options; - const response : FetchChargeFromGamertagDataResponseType = await postData({ + const response: FetchChargeFromGamertagDataResponseType = await postData({ url: `${API_URL}${API.CREATE_CHARGE_FROM_GAMERTAG_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, body: { @@ -355,7 +328,7 @@ class zbd { return response; } - async createStaticCharge(options: StaticChargeOptionsType) { + async createStaticCharge(options: StaticChargeOptionsType) { const { minAmount, maxAmount, @@ -366,7 +339,7 @@ class zbd { successMessage, } = options; - const response : StaticChargeDataResponseType = await postData({ + const response: StaticChargeDataResponseType = await postData({ url: `${API_URL}${API.STATIC_CHARGES_ENDPOINT}`, headers: { ...this.apiCoreHeaders }, body: { @@ -383,7 +356,10 @@ class zbd { return response; } - async updateStaticCharge(staticChargeId: string, updates: StaticChargeOptionsType) { + async updateStaticCharge( + staticChargeId: string, + updates: StaticChargeOptionsType + ) { const response = await patchData({ url: `${API_URL}${API.STATIC_CHARGES_ENDPOINT}/${staticChargeId}`, headers: { ...this.apiCoreHeaders }, @@ -393,7 +369,7 @@ class zbd { return response; } - async getStaticCharge(staticChargeId: string) { + async getStaticCharge(staticChargeId: string) { const response = await getData({ url: `${API_URL}${API.STATIC_CHARGES_ENDPOINT}/${staticChargeId}`, headers: { ...this.apiCoreHeaders }, @@ -401,6 +377,161 @@ class zbd { return response; } + + OAuth2AuthorizationUrl = (domain = DEFAULT_DOMAIN) => { + return `https://${domain}/oauth2/authorize`; + }; + + /** + * Generates an authentication URL for initiating the OAuth2 authorization flow. + * + * @param {OAuth2AuthorizationRequestType} param - An object containing authorization request parameters. + * @returns {Promise} A promise that resolves with the generated authentication URL. + * + * @throws {Error} If any required parameters are missing or if errors occur during URL generation. + * + * @example + * const params = { + * redirect_uri: "http://localhost:3000/callback", + * state: "random_state", + * }; + * const authUrl = await ZBD.getAuthenticationUrl(params); + * console.log(authUrl); // Print the generated authentication URL + */ + async getAuthenticationUrl(param: OAuth2AuthorizationRequestType) { + const { redirect_uri, state } = param; + let scope: string = "user"; + let response_type: string = "code"; + const baseUrl = this.OAuth2AuthorizationUrl(); + const client_id = this.getClientId(); + const client_secret = this.getClientSecret(); + if (!client_id) { + throw new Error( + "A client id is required. You can set the client id using .setClientId()." + ); + } + + if (!redirect_uri) { + throw new Error("A redirect uri is required."); + } + + if (!client_secret) { + throw new Error( + "A client secret is required. You can set the client secret using .setClientSecret()." + ); + } + if (!state) { + throw new Error("A state parameter is required."); + } + + if (!this.codeChallenge) { + throw new Error( + "A code challenge is required. Generate one using .generatePKCE()." + ); + } + let authUrl; + + authUrl = `${baseUrl}?resp_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&state=${state}&code_challenge=${this.codeChallenge}&code_challenge_method=S256`; + + return authUrl; + } + + createBrowserSafeString(toBeConverted: any) { + const convertedString = toBeConverted + .toString("base64") + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g, ""); + return convertedString; + } + + /** + * Sets the client Secret + * @param {String} secret - The client secret + */ + setClientSecret(secret: string) { + this.clientSecret = secret; + } + + /** + * Get the client secret + * @returns {String} Client id + */ + getClientSecret() { + return this.clientSecret; + } + + /** + * Get client ID + * @returns {String} Client id + */ + getClientId() { + return this.clientId; + } + + /** + * Sets client ID + * @param {String} clientId - The client ID + */ + setClientId(clientId: string) { + this.clientId = clientId; + } + + /** + * Sets the code verifier for PKCE flow + * @param {String} codeVerifier - new code verifier + */ + setCodeVerifier(codeVerifier: string) { + this.codeVerifier = codeVerifier; + } + + /** + * Gets the code verifier for PKCE flow + * @returns {String} - code verifier for PKCE + */ + getCodeChallenge() { + return this.codeChallenge; + } + /** + * Generates a random code verifier and code challenge for PKCE + * @returns {Promise} resolves when code challenge is generated + * @throws {Error} if code challenge generation fails + */ + async generateCodeChallenge() { + const encoder = new TextEncoder(); + const codeData = encoder.encode(this.codeVerifier); + let codeChallenge; + if (this.codeVerifier) { + return crypto.subtle.digest("SHA-256", codeData).then((digestedHash) => { + const base64String = btoa( + String.fromCharCode(...new Uint8Array(digestedHash)) + ); + codeChallenge = this.createBrowserSafeString(base64String).substr( + 0, + 128 + ); + this.codeChallenge = codeChallenge; + }); + } + + return Promise.resolve(); + } + + /** + * Generates a random code verifier and corresponding code challenge for PKCE (Proof Key for Code Exchange). + * @returns {Promise} Resolves when the code challenge is generated successfully. + * @throws {Error} If code challenge generation or other steps fail. + */ + async generatePKCECodes() { + let codeVerifier; + + const randomBytes = crypto.randomBytes(PKCELength); + codeVerifier = this.createBrowserSafeString(randomBytes).substr(0, 128); + + this.codeVerifier = codeVerifier; + + return await this.generateCodeChallenge(); + } } export { zbd }; diff --git a/yarn.lock b/yarn.lock index d0441ce..e34ca61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,7 +22,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz" integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== -"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3": +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0", "@babel/core@>=7.0.0-beta.0 <8": version "7.22.9" resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz" integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w== @@ -1249,7 +1249,7 @@ slash "^3.0.0" write-file-atomic "^4.0.2" -"@jest/types@^29.6.1": +"@jest/types@^29.0.0", "@jest/types@^29.6.1": version "29.6.1" resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz" integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw== @@ -1270,7 +1270,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== @@ -1288,23 +1288,15 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.15" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": version "0.3.18" @@ -1314,6 +1306,14 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@rollup/plugin-alias@^3.1.1": version "3.1.9" resolved "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz" @@ -1432,7 +1432,7 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/babel__core@^7.1.14": +"@types/babel__core@^7.1.14", "@types/babel__core@^7.1.9": version "7.20.1" resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz" integrity sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw== @@ -1679,7 +1679,7 @@ axios-mock-adapter@^1.21.5: fast-deep-equal "^3.1.3" is-buffer "^2.0.5" -axios@^1.4.0: +axios@^1.4.0, "axios@>= 0.17.0": version "1.4.0" resolved "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz" integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== @@ -1688,7 +1688,7 @@ axios@^1.4.0: form-data "^4.0.0" proxy-from-env "^1.1.0" -babel-jest@^29.6.1: +babel-jest@^29.0.0, babel-jest@^29.6.1: version "29.6.1" resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz" integrity sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A== @@ -1832,7 +1832,7 @@ brotli-size@^4.0.0: dependencies: duplexer "0.1.1" -browserslist@^4.0.0, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.21.9: +browserslist@^4.0.0, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.21.9, "browserslist@>= 4.21.0": version "4.21.9" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz" integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== @@ -1904,7 +1904,18 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz" integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== -chalk@^1.0.0, chalk@^1.1.3: +chalk@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== @@ -1980,16 +1991,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + colord@^2.9.1: version "2.9.3" resolved "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz" @@ -2029,7 +2040,12 @@ concat-with-sourcemaps@^1.1.0: dependencies: source-map "^0.6.1" -convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.6.0: + version "1.9.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -2246,7 +2262,7 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" -duplexer@0.1.1, duplexer@^0.1.1: +duplexer@^0.1.1, duplexer@0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz" integrity sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q== @@ -2358,7 +2374,12 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -2440,7 +2461,7 @@ fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@^2.1.0, fast-json-stable-stringify@2.x: version "2.1.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -2551,11 +2572,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - function-bind@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" @@ -3229,7 +3245,7 @@ jest-resolve-dependencies@^29.6.1: jest-regex-util "^29.4.3" jest-snapshot "^29.6.1" -jest-resolve@^29.6.1: +jest-resolve@*, jest-resolve@^29.6.1: version "29.6.1" resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz" integrity sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg== @@ -3383,7 +3399,7 @@ jest-worker@^29.6.1: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.6.1: +jest@^29.0.0, jest@^29.6.1: version "29.6.1" resolved "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz" integrity sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw== @@ -3482,7 +3498,7 @@ lodash.debounce@^4.0.8: resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.memoize@4.x, lodash.memoize@^4.1.2: +lodash.memoize@^4.1.2, lodash.memoize@4.x: version "4.1.2" resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -3525,7 +3541,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x, make-error@^1.1.1: +make-error@^1.1.1, make-error@1.x: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4145,7 +4161,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.2.1: +postcss@^8.0.0, postcss@^8.0.9, postcss@^8.1.0, postcss@^8.2.1, postcss@^8.2.15, postcss@^8.2.2, postcss@>=8.0.9, postcss@8.x: version "8.4.27" resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz" integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== @@ -4363,7 +4379,7 @@ rollup-pluginutils@^2.8.2: dependencies: estree-walker "^0.6.1" -rollup@^2.35.1: +"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.30.0, rollup@^2.35.1, rollup@>=1.26.3, "rollup@2.x || 3.x": version "2.79.1" resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz" integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== @@ -4466,14 +4482,6 @@ source-map-js@^1.0.2: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" @@ -4482,6 +4490,14 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" @@ -4721,7 +4737,7 @@ ts-jest@^29.1.1: semver "^7.5.3" yargs-parser "^21.0.1" -ts-node@^10.9.1: +ts-node@^10.9.1, ts-node@>=9.0.0: version "10.9.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== @@ -4794,7 +4810,7 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typescript@^4.1.3, typescript@^4.8.4: +typescript@^4.1.3, typescript@^4.8.4, typescript@>=2.4.0, typescript@>=2.7, "typescript@>=4.3 <6": version "4.9.5" resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== From 3a7dd70dfbfbd6fed7ebdd79a17be9d01257dc6c Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Mon, 14 Aug 2023 16:10:45 +0100 Subject: [PATCH 10/18] refactor: Updated getData to accept queryParams for OAuth2 URL generation --- __tests__/get-authentication-url.test.ts | 46 ------------------------ src/constants.ts | 1 - src/utils.ts | 28 ++++++++------- src/zbd.ts | 35 ++++++++++++++---- 4 files changed, 45 insertions(+), 65 deletions(-) diff --git a/__tests__/get-authentication-url.test.ts b/__tests__/get-authentication-url.test.ts index d42efd8..e24ae48 100644 --- a/__tests__/get-authentication-url.test.ts +++ b/__tests__/get-authentication-url.test.ts @@ -28,7 +28,6 @@ describe("getAuthenticationUrl", () => { }); it("should throw an error if client id is not set", async () => { - // ZBD.setClientId(); const params = { redirect_uri: "http://localhost:3000/callback", state: "random_state", @@ -39,50 +38,5 @@ describe("getAuthenticationUrl", () => { ); }); - // it("should throw an error if client secret is not set", async () => { - // // ZBD.setClientSecret(null); - // const params = { - // redirect_uri: "http://localhost:3000/callback", - // state: "random_state", - // }; - - // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( - // "A code challenge is required. Generate one using .generatePKCE()." - // ); - // }); - - // it("should throw an error if code challenge is not generated", async () => { - // const params = { - // redirect_uri: "http://localhost:3000/callback", - // state: "random_state", - // }; - - // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( - // "A code challenge is required." - // ); - // }); - - // it("should throw an error if redirect_uri is missing", async () => { - // const params = { - // redirect_uri: undefined, - // state: "random_state", - // }; - - // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( - // "A redirect uri is required." - // ); - // }); - - // it("should throw an error if state parameter is missing", async () => { - // const params = { - // redirect_uri: "http://localhost:3000/callback", - // state: undefined, // Omitting the state property intentionally - // }; - - // await expect(ZBD.getAuthenticationUrl(params)).rejects.toThrow( - // "A state parameter is required." - // ); - // }); - // Add more test cases for different scenarios... }); diff --git a/src/constants.ts b/src/constants.ts index 89e8f8d..9eb09e5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,5 @@ // BaseUrl export const API_URL = "https://api.zebedee.io"; -export const V2_DEFAULT_DOMAIN = "api.zebedee.io/v1/"; // Test API Key export const TEST_API_KEY: string = "8qJxln3JVJsQM0IOJhfnJopO0JSiLdlK"; diff --git a/src/utils.ts b/src/utils.ts index 58914f8..3362674 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -9,7 +9,7 @@ export const cleanup = (obj: any) => { } return newObj; -} +}; export async function postData({ url, @@ -23,7 +23,7 @@ export async function postData({ const response = await fetch(url, { method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...headers, }, body: JSON.stringify(cleanup(body)), @@ -33,9 +33,8 @@ export async function postData({ const errorBody = await response.json(); const error = { status: response.status, - message: errorBody.message || 'API request failed', + message: errorBody.message || "API request failed", }; - throw error; } @@ -56,18 +55,17 @@ export async function patchData({ const response = await fetch(url, { method: "PATCH", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...headers, }, body: JSON.stringify(cleanup(body)), }); if (!response.ok) { - const errorBody = await response.json(); const error = { status: response.status, - message: errorBody.message || 'API request failed', + message: errorBody.message || "API request failed", }; throw error; @@ -80,29 +78,35 @@ export async function patchData({ export async function getData({ url, headers, + queryParams, // Add queryParams as a parameter }: { url: string; headers?: any; + queryParams?: Record; // Define queryParams type }) { + // Construct the URL with query parameters if provided + if (queryParams) { + const queryString = new URLSearchParams(queryParams).toString(); + url += `?${queryString}`; + } + const response = await fetch(url, { method: "GET", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", ...headers, }, }); if (!response.ok) { - const errorBody = await response.json(); const error = { status: response.status, - message: errorBody.message || 'API request failed', + message: errorBody.message || "API request failed", }; - throw error; } const result = await response.json(); return result; -} \ No newline at end of file +} diff --git a/src/zbd.ts b/src/zbd.ts index 5d23962..75abfd0 100644 --- a/src/zbd.ts +++ b/src/zbd.ts @@ -1,4 +1,4 @@ -import { API_URL, API, V2_DEFAULT_DOMAIN as DEFAULT_DOMAIN } from "./constants"; +import { API_URL, API } from "./constants"; import { postData, getData, patchData } from "./utils"; import { ChargeOptionsType, @@ -378,8 +378,10 @@ class zbd { return response; } - OAuth2AuthorizationUrl = (domain = DEFAULT_DOMAIN) => { - return `https://${domain}/oauth2/authorize`; + // Authorization + + OAuth2AuthorizationUrl = (domain = API_URL) => { + return `${domain}/v1/oauth2/authorize`; }; /** @@ -429,11 +431,30 @@ class zbd { "A code challenge is required. Generate one using .generatePKCE()." ); } - let authUrl; + let response; + try { + const res = await getData({ + url: `${API_URL}${API.GET_AUTHORIZATION_ENDPOINT}`, + headers: { ...this.apiCoreHeaders }, + queryParams: { + response_type, + client_id, + redirect_uri, + scope, + state, + code_challenge: this.codeChallenge, + code_challenge_method: "S256", + }, + }); + response = res; + } catch (error) { + throw new Error("Error generating authentication URL: " + error); + } + // let authUrl; - authUrl = `${baseUrl}?resp_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&state=${state}&code_challenge=${this.codeChallenge}&code_challenge_method=S256`; + // authUrl = `${baseUrl}?resp_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&state=${state}&code_challenge=${this.codeChallenge}&code_challenge_method=S256`; - return authUrl; + return response; } createBrowserSafeString(toBeConverted: any) { @@ -532,6 +553,8 @@ class zbd { return await this.generateCodeChallenge(); } + + // Fetch Access token } export { zbd }; From ab3df46bf1b613842cfc78ace0f3ad786ca399f2 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Tue, 15 Aug 2023 13:52:12 +0200 Subject: [PATCH 11/18] keysend test suite complete --- __tests__/keysend/sendKeysendPayment.test.ts | 22 ++++++++++++-- src/types/keysend.ts | 32 +++++++++++--------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/__tests__/keysend/sendKeysendPayment.test.ts b/__tests__/keysend/sendKeysendPayment.test.ts index 4ec2758..b6407cf 100644 --- a/__tests__/keysend/sendKeysendPayment.test.ts +++ b/__tests__/keysend/sendKeysendPayment.test.ts @@ -13,11 +13,10 @@ describe('Send Keysend Payment', () => { pubkey: "0332d57355d673e217238ce3e4be8491aa6b2a13f95494133ee243e57df1653ace", tlvRecords: [], metadata: {}, - callbackUrl: "MOCK_CALLBACK_URL" + callbackUrl: "{{callbackURL}}" }; const response = await ZBD.sendKeysendPayment(requestBody); - console.log(response) // Data Validation expect(response.success).toBe(true); @@ -27,7 +26,24 @@ describe('Send Keysend Payment', () => { -describe('createCharge error scenarios', () => { +describe('Send Keysend error scenarios', () => { + + it('should fail keysend payment given an invalid pubkey', async () => { + + const errorBody: KeysendOptionsType = { + amount: "1000", + pubkey: "23", + tlvRecords: [], + metadata: {}, + callbackUrl: "{{callbackURL}}" + }; + + await expect(ZBD.sendKeysendPayment(errorBody)).rejects.toMatchObject({ + message: "Keysend payment failed.", + status: 400, + }) + + }); }); diff --git a/src/types/keysend.ts b/src/types/keysend.ts index 9f67ba2..63ced60 100644 --- a/src/types/keysend.ts +++ b/src/types/keysend.ts @@ -21,21 +21,25 @@ export interface KeysendDataResponseType { export interface KeysendOptionsType { amount: string; pubkey: string; - tlvRecords: any[]; + tlvRecords: any; metadata: any; callbackUrl: string; } -export function isKeysendDataResponseType(data: any): data is KeysendDataResponseType { - return typeof data.keysendId === 'string' && - typeof data.paymentId === 'string' && - typeof data.transaction.id === 'string' && - typeof data.transaction.walletId === 'string' && - typeof data.transaction.type === 'string' && - typeof data.transaction.totalAmount === 'string' && - typeof data.transaction.fee === 'string' && - typeof data.transaction.amount === 'string' && - typeof data.transaction.description === 'string' && - typeof data.transaction.status === 'string' && - (data.transaction.confirmedAt === null || typeof data.transaction.confirmedAt === 'string'); -} \ No newline at end of file +export function isKeysendDataResponseType(obj: any): obj is KeysendDataResponseType { + return obj && + typeof obj.success === 'boolean' && + obj.data && + typeof obj.data.keysendId === 'string' && + typeof obj.data.paymentId === 'string' && + obj.data.transaction && + typeof obj.data.transaction.id === 'string' && + typeof obj.data.transaction.walletId === 'string' && + typeof obj.data.transaction.type === 'string' && + typeof obj.data.transaction.totalAmount === 'string' && + typeof obj.data.transaction.fee === 'string' && + typeof obj.data.transaction.amount === 'string' && + typeof obj.data.transaction.description === 'string' && + typeof obj.data.transaction.status === 'string' && + (obj.data.transaction.confirmedAt === null || typeof obj.data.transaction.confirmedAt === 'string'); +} From 93c4fc3a212135487504a83e85b50ce22800546b Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Tue, 15 Aug 2023 18:10:10 +0100 Subject: [PATCH 12/18] feat: Add access token and user data retrieval functions --- __tests__/fetch-access-token.test.ts | 99 ++++++++++++ __tests__/get-authentication-url.test.ts | 10 +- src/types/zbd-login.ts | 80 +++++++++ src/utils.ts | 8 - src/zbd.ts | 196 ++++++++++++++++++++--- 5 files changed, 355 insertions(+), 38 deletions(-) create mode 100644 __tests__/fetch-access-token.test.ts diff --git a/__tests__/fetch-access-token.test.ts b/__tests__/fetch-access-token.test.ts new file mode 100644 index 0000000..18b54a5 --- /dev/null +++ b/__tests__/fetch-access-token.test.ts @@ -0,0 +1,99 @@ +import { zbd } from "../src/zbd"; +import { API, API_URL, TEST_API_KEY } from "../src/constants"; +import { FetchAccessTokenRes, FetchTokenParam } from "../src/types"; + +const postData = jest.fn(); +describe("fetchAccessToken", () => { + let ZBD: zbd; + + beforeEach(() => { + ZBD = new zbd(TEST_API_KEY); + ZBD.setClientId("client_id"); + ZBD.setClientSecret("secret123"); + }); + + it("should fetch access token successfully", async () => { + await ZBD.generatePKCECodes(); + const code_verifier = ZBD.getCodeChallenge(); + + console.log("Code verifier: ", code_verifier); + // Arrange + const param: FetchTokenParam = { + code: "xxx11xx1-xxxx-xxxx-xxx1-1xx11xx111xx", + redirect_uri: "http://redirect-uri.com", + }; + + const mockAccessTokenResponse: FetchAccessTokenRes = { + access_token: "mockAccessToken", + token_type: "Bearer", + expires_in: 3600, + refresh_token: "mockRefreshToken", + refresh_token_expires_in: 7200, + scope: "read write", + }; + + postData.mockResolvedValue(mockAccessTokenResponse); + + // Act + const result = await ZBD.fetchAccessToken(param); + console.log("Client id: ", ZBD.clientId); + + // Assert + // expect(result).toEqual(mockAccessTokenResponse); + // expect(postData).toHaveBeenCalledWith({ + // url: `${API_URL}${API.FETCH_ACCESS_TOKEN_ENDPOINT}`, + // headers: { ...ZBD.apiCoreHeaders }, + // body: { + // client_id: ZBD.clientId, + // client_secret: ZBD.clientSecret, + // grant_type: "authorization_code", + // code: param.code, + // redirect_uri: param.redirect_uri, + // code_verifier: ZBD.codeVerifier, + // }, + // }); + }); + + it("should throw an error if authorization code is missing", async () => { + // Arrange + const param: FetchTokenParam = { + code: "", + redirect_uri: "http://redirect-uri.com", + }; + + // Act and Assert + await expect(ZBD.fetchAccessToken(param)).rejects.toThrow( + "Authorization code is required" + ); + }); + + it("should throw an error if redirect URI is missing", async () => { + // Arrange + const param: FetchTokenParam = { + code: "authorization_code", + redirect_uri: "", + }; + + // Act and Assert + await expect(ZBD.fetchAccessToken(param)).rejects.toThrow( + "Redirect URI is required" + ); + }); + + // Add more test cases for other validation checks + + it("should throw an error if fetching access token fails", async () => { + // Arrange + const param: FetchTokenParam = { + code: "authorization_code", + redirect_uri: "http://redirect-uri.com", + }; + + postData.mockRejectedValue(new Error("Network error")); + + // Act and Assert + await expect(ZBD.fetchAccessToken(param)).rejects.toThrow( + "A code challenge is required. Generate one using .generatePKCE()." + ); + }); +}); diff --git a/__tests__/get-authentication-url.test.ts b/__tests__/get-authentication-url.test.ts index e24ae48..0ea1f8b 100644 --- a/__tests__/get-authentication-url.test.ts +++ b/__tests__/get-authentication-url.test.ts @@ -10,17 +10,17 @@ describe("getAuthenticationUrl", () => { }); it("should generate auth url with correct params", async () => { - await ZBD.generatePKCECodes(); // Generate codeChallenge + await ZBD.generatePKCECodes(); const params = { - redirect_uri: "http://localhost:3000/callback", + redirect_uri: "https://example.com/callback", state: "random_state", }; const authUrl = await ZBD.getAuthenticationUrl(params); expect(authUrl).toContain("client_id=client_id"); - expect(authUrl).toContain("redirect_uri=http://localhost:3000/callback"); + expect(authUrl).toContain("redirect_uri=https://example.com/callback"); expect(authUrl).toContain("scope=user"); expect(authUrl).toContain("state=random_state"); expect(authUrl).toContain(`code_challenge=${await ZBD.getCodeChallenge()}`); @@ -29,7 +29,7 @@ describe("getAuthenticationUrl", () => { it("should throw an error if client id is not set", async () => { const params = { - redirect_uri: "http://localhost:3000/callback", + redirect_uri: "https://example.com/callback", state: "random_state", }; @@ -37,6 +37,4 @@ describe("getAuthenticationUrl", () => { "A code challenge is required. Generate one using .generatePKCE()." ); }); - - // Add more test cases for different scenarios... }); diff --git a/src/types/zbd-login.ts b/src/types/zbd-login.ts index ee36579..a4fd05e 100644 --- a/src/types/zbd-login.ts +++ b/src/types/zbd-login.ts @@ -2,3 +2,83 @@ export interface OAuth2AuthorizationRequestType { redirect_uri: string; state: string; } + +export interface FetchTokenParam { + code: string; + redirect_uri: string; +} + +export interface FetchTokenBody { + client_id: string; + client_secret: string; + code: string; + code_verifier: string; + grant_type: string; + redirect_uri: string; +} + +export interface FetchAccessTokenRes { + access_token: string; + token_type: string; + expires_in: number; + refresh_token: string; + refresh_token_expires_in: number; + scope: string; +} + +export interface RefreshTokenParam { + code: string; + redirect_uri: string; +} + +export interface RefreshTokenBody { + client_id: string; + client_secret: string; + code: string; + code_verifier: string; + grant_type: string; + redirect_uri: string; +} + +export interface RefreshTokenRes { + access_token: string; + token_type: string; + expires_in: number; + refresh_token: string; + refresh_token_expires_in: number; + scope: string; +} + +export interface FetchUserDataParam { + access_token: string; +} + +export interface ZBDUserData { + id: string; + email: string; + gamertag: string; + image?: string | null; + is_verified: boolean; + lightning_address: string; + public_bio: string; + public_static_charge: string; +} + +export interface FetchUserWalletDataParam { + access_token: string; +} + +interface ZBDUserWalletDataLimits { + daily: string; + maxCredit: string; + monthly: string; + weekly: string; +} + +export interface ZBDUserWalletData { + balance: string; + remaining_amount_limits: ZBDUserWalletDataLimits; +} + +// https://api.zebedee.io/v1/oauth2/authorize/v1/oauth2/authorize?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&scope=user&state=random_state&code_challenge=YbajXYJlxPXvDLy0iUN2Z2IpxeUeSCqoAy1XVCsxaOQ&code_challenge_method=S256 +// curl -L -X GET "https://api.zebedee.io/v1/oauth2/authorize?response_type=token&client_id=dummy_client_id&redirect_uri=https://example.com/callback&scope=read%20write&state=dummy_state&code_challenge=dummy_code_challenge&code_challenge_method=S256" diff --git a/src/utils.ts b/src/utils.ts index 3362674..c61ef12 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -78,18 +78,10 @@ export async function patchData({ export async function getData({ url, headers, - queryParams, // Add queryParams as a parameter }: { url: string; headers?: any; - queryParams?: Record; // Define queryParams type }) { - // Construct the URL with query parameters if provided - if (queryParams) { - const queryString = new URLSearchParams(queryParams).toString(); - url += `?${queryString}`; - } - const response = await fetch(url, { method: "GET", headers: { diff --git a/src/zbd.ts b/src/zbd.ts index 75abfd0..1b2c522 100644 --- a/src/zbd.ts +++ b/src/zbd.ts @@ -33,6 +33,16 @@ import { SendGamertagPaymentDataResponseType, FetchChargeFromLightningAddressDataResponseType, OAuth2AuthorizationRequestType, + FetchTokenBody, + FetchTokenParam, + FetchAccessTokenRes, + RefreshTokenParam, + RefreshTokenBody, + RefreshTokenRes, + FetchUserDataParam, + ZBDUserData, + ZBDUserWalletData, + FetchUserWalletDataParam, } from "./types/index"; import * as crypto from "crypto"; @@ -381,7 +391,7 @@ class zbd { // Authorization OAuth2AuthorizationUrl = (domain = API_URL) => { - return `${domain}/v1/oauth2/authorize`; + return `${domain}`; }; /** @@ -431,30 +441,19 @@ class zbd { "A code challenge is required. Generate one using .generatePKCE()." ); } - let response; - try { - const res = await getData({ - url: `${API_URL}${API.GET_AUTHORIZATION_ENDPOINT}`, - headers: { ...this.apiCoreHeaders }, - queryParams: { - response_type, - client_id, - redirect_uri, - scope, - state, - code_challenge: this.codeChallenge, - code_challenge_method: "S256", - }, - }); - response = res; - } catch (error) { - throw new Error("Error generating authentication URL: " + error); - } - // let authUrl; - // authUrl = `${baseUrl}?resp_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&state=${state}&code_challenge=${this.codeChallenge}&code_challenge_method=S256`; + const code_challenge_method = "S256"; - return response; + let url = `${baseUrl}${API.GET_AUTHORIZATION_ENDPOINT}`; + url += `?response_type=${response_type}`; + url += `&client_id=${client_id}`; + url += `&redirect_uri=${redirect_uri}`; + url += `&scope=${scope}`; + url += `&state=${state}`; + url += `&code_challenge=${this.codeChallenge}`; + url += `&code_challenge_method=${code_challenge_method}`; + + return url; } createBrowserSafeString(toBeConverted: any) { @@ -554,7 +553,156 @@ class zbd { return await this.generateCodeChallenge(); } - // Fetch Access token + /** + * Fetches an access token using the provided authorization code and parameters. + * @param param - An object containing parameters for fetching the access token. + * @returns A promise that resolves with the access token response or rejects with an error. + * @throws Error if required parameters are missing or not set. + */ + async fetchAccessToken(param: FetchTokenParam) { + if (!param.code) { + throw new Error("Authorization code is required"); + } + + if (!param.redirect_uri) { + throw new Error("Redirect URI is required"); + } + + if (!this.codeChallenge) { + throw new Error( + "A code challenge is required. Generate one using .generatePKCE()." + ); + } + + if (!this.clientId) { + throw new Error("Client ID is required. Set it using .setClientId()"); + } + + if (!this.clientSecret) { + throw new Error( + "Client Secret is required. Set it using .setClientSecret()" + ); + } + + const body: FetchTokenBody = { + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "authorization_code", + code: param.code, + redirect_uri: param.redirect_uri, + code_verifier: this.codeVerifier, + }; + + console.log( + "URL: ", + `${API_URL}${API.FETCH_ACCESS_TOKEN_ENDPOINT}?Content-Type=application/json` + ); + + const response: FetchAccessTokenRes = await postData({ + url: `${API_URL}${API.FETCH_ACCESS_TOKEN_ENDPOINT}?Content-Type=application/json`, + headers: { ...this.apiCoreHeaders }, + body: body, + }); + + return response; + } + + /** + * Refreshes an access token using the provided refresh token and other required parameters. + * @param param - The RefreshTokenParam object containing the necessary parameters. + * @throws {Error} - Throws an error if any required parameter is missing. + * @returns {Promise} - Returns a promise that resolves with the refreshed token response. + */ + async refreshToken(param: RefreshTokenParam) { + if (!param.code) { + throw new Error("Authorization code is required"); + } + + if (!param.redirect_uri) { + throw new Error("Redirect URI is required"); + } + + if (!this.codeChallenge) { + throw new Error( + "A code challenge is required. Generate one using .generatePKCE()." + ); + } + + if (!this.clientId) { + throw new Error("Client ID is required. Set it using .setClientId()"); + } + + if (!this.clientSecret) { + throw new Error( + "Client Secret is required. Set it using .setClientSecret()" + ); + } + + const body: RefreshTokenBody = { + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "refresh_token", + code: param.code, + redirect_uri: param.redirect_uri, + code_verifier: this.codeVerifier, + }; + + const response: RefreshTokenRes = await postData({ + url: `${API_URL}${API.REFRESH_TOKEN_ENDPOINT}?Content-Type=application/json`, + headers: { ...this.apiCoreHeaders }, + body: body, + }); + + return response; + } + + /** + * Fetches user data using the provided access token. + * @param param - The FetchUserDataParam object containing the required parameters. + * @throws {Error} - Throws an error if the access token is missing. + * @returns {Promise} - Returns a promise that resolves with the fetched user data. + */ + async fetchUserData(param: FetchUserDataParam) { + if (!param.access_token) { + throw new Error("Access token is required"); + } + + const headers = { + ...this.apiCoreHeaders, + usertoken: `Bearer ${param.access_token}`, + }; + + const response: ZBDUserData = await getData({ + url: `${API_URL}${API.GET_USER_ENDPOINT}`, + headers: headers, + }); + + return response; + } + + /** + * Fetches user wallet data using the provided access token. + * @param param - The FetchUserWalletDataParam object containing the required parameters. + * @throws {Error} - Throws an error if the access token is missing. + * @returns {Promise} - Returns a promise that resolves with the fetched user wallet data. + */ + async fetchUserWalletData(param: FetchUserWalletDataParam) { + if (!param.access_token) { + throw new Error("Access token is required"); + } + + const headers = { + ...this.apiCoreHeaders, + usertoken: `Bearer ${param.access_token}`, + }; + + const response: ZBDUserWalletData = await getData({ + url: `${API_URL}${API.GET_USER_WALLET_DATA_ENDPOINT}`, + headers: headers, + }); + + return response; + } } export { zbd }; From 8329cea7f81cd2abf03f0571494a7bf03764dada Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Tue, 15 Aug 2023 18:11:45 +0100 Subject: [PATCH 13/18] fix: removed unnessary comments --- src/types/zbd-login.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types/zbd-login.ts b/src/types/zbd-login.ts index a4fd05e..6adb234 100644 --- a/src/types/zbd-login.ts +++ b/src/types/zbd-login.ts @@ -79,6 +79,3 @@ export interface ZBDUserWalletData { balance: string; remaining_amount_limits: ZBDUserWalletDataLimits; } - -// https://api.zebedee.io/v1/oauth2/authorize/v1/oauth2/authorize?response_type=code&client_id=client_id&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&scope=user&state=random_state&code_challenge=YbajXYJlxPXvDLy0iUN2Z2IpxeUeSCqoAy1XVCsxaOQ&code_challenge_method=S256 -// curl -L -X GET "https://api.zebedee.io/v1/oauth2/authorize?response_type=token&client_id=dummy_client_id&redirect_uri=https://example.com/callback&scope=read%20write&state=dummy_state&code_challenge=dummy_code_challenge&code_challenge_method=S256" From 2fc8e67866d4b54c6ee36842bfd7991de521713f Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 16 Aug 2023 11:19:15 +0200 Subject: [PATCH 14/18] payments test suite complete --- __tests__/charges/createCharge.test.ts | 2 +- .../internalTransfer.test.ts | 1 - __tests__/payments/getPaymentDetails.test.ts | 12 ++- __tests__/payments/payInvoice.test.ts | 97 +++++++++++++++---- .../withdrawal/getWithdrawalRequest.test.ts | 1 - src/constants.ts | 3 + src/types/payments.ts | 2 +- 7 files changed, 91 insertions(+), 27 deletions(-) diff --git a/__tests__/charges/createCharge.test.ts b/__tests__/charges/createCharge.test.ts index 27dbb76..f2aa0f6 100644 --- a/__tests__/charges/createCharge.test.ts +++ b/__tests__/charges/createCharge.test.ts @@ -25,7 +25,7 @@ describe('createCharge', () => { expect(response.data.description).toBe(payload.description); }); - describe('fetchGamertagByUserID error scenarios', () => { + describe('createCharge error scenarios', () => { it('should throw an error given an erroneous payload (amount = 0)', async () => { const erroneousPayload: ChargeOptionsType = { diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index a251fa0..7734589 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -7,7 +7,6 @@ const ZBD = new zbd(TEST_API_KEY); describe('Initiate Internal Transfer', () => { it('should initiate an internal transfer successfully', async () => { - // Mock parameters const requestBody: InternalTransferOptionsType = { amount: "1000", receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6" diff --git a/__tests__/payments/getPaymentDetails.test.ts b/__tests__/payments/getPaymentDetails.test.ts index 3c28f9d..4654dc6 100644 --- a/__tests__/payments/getPaymentDetails.test.ts +++ b/__tests__/payments/getPaymentDetails.test.ts @@ -1,11 +1,11 @@ import { TEST_API_KEY } from '../../src/constants'; import { zbd } from '../../src/zbd'; -import { isInvoicePaymentDataResponseType } from '../../src/types/payments'; // Assuming you've created this function already based on our prior interactions +import { isInvoicePaymentDataResponseType } from '../../src/types/payments'; const ZBD = new zbd(TEST_API_KEY); describe('getPaymentDetails', () => { - const mockPaymentId = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; + const mockPaymentId = '30cba220-e8b0-4df7-81a8-88cbae76b929'; it('should successfully fetch a payment detail', async () => { const response = await ZBD.getPayment(mockPaymentId); @@ -20,6 +20,14 @@ describe('getPaymentDetails', () => { }); describe('getPaymentDetails error scenarios', () => { + it('should throw an error given incorrect payment id', async () => { + const errorPaymentId = 'error'; + await expect(ZBD.getPayment(errorPaymentId)).rejects.toMatchObject({ + message: "No Payment records found with this ID.", + status: 404 + }); + + }); }); }); diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts index 74afe49..a95653c 100644 --- a/__tests__/payments/payInvoice.test.ts +++ b/__tests__/payments/payInvoice.test.ts @@ -1,45 +1,100 @@ -import { TEST_API_KEY } from '../../src/constants'; +import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from '../../src/constants'; import { zbd } from '../../src/zbd'; import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isInvoicePaymentDataResponseType } from '../../src/types/payments'; +import { ChargeOptionsType, isChargeResponseType } from '../../src/types'; -const ZBD = new zbd(TEST_API_KEY); +const payerZBD = new zbd(TEST_API_KEY); +const receiverZBD = new zbd(TEST_RECEIVER_API_KEY) describe('payInvoice', () => { it('should successfully pay an invoice', async () => { - const payload: SendPaymentOptionsType = { - description: "Custom Payment Description", + + // first, create charge with receiver + const chargePayload: ChargeOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Charge Test", internalId: "internalId", - invoice: "lnbc100n1pjdxlpvpp5r7uhh2m3dq48ysxvs8xmcph9tdkmrrlj6jyqa4arq2t9k0u6khmsdpzf4ujqsmgv9exwefq23jhxapqtfshq6t9wgcqzzsxqzfvsp56zkq022rqw5kvm08veluk9lfv7st6q7vkl3tm0d6p4weswmp3kus9qyyssqxjlqr0f0k4jswwz9v95cs5tslgmxl9ujuf8mxf09mddctd3haqr4dxxjuxalkjru3ssw26a88gs2r6tms9z9t39698jj3ddx5cctjvqpcacqmx", - callbackUrl: "https://my-website.com/callback/zbd", - amount: "10000" + callbackUrl: "https://my-website.com/zbd-callback" }; - const response = await ZBD.sendPayment(payload); - + // verify charge + const chargeResponse = await receiverZBD.createCharge(chargePayload); + + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); + expect(chargeResponse.success).toBe(true); + expect(chargeResponse.message).toBe("Charge created."); + expect(chargeResponse.data.amount).toBe(chargePayload.amount); + expect(chargeResponse.data.description).toBe(chargePayload.description); + // create payment and pay it + const paymentPayload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: chargeResponse.data.invoice.request, + callbackUrl: "https://my-website.com/callback/zbd", + amount: chargeResponse.data.amount + }; + const response = await payerZBD.sendPayment(paymentPayload); console.log(response) - // expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); - // expect(response.success).toBe(true); - // expect(response.message).toBe("Payment done."); - // expect(response.data.amount).toBe(String(payload.amount)); - // expect(response.data.description).toBe(payload.description); + expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.message).toBe("Payment done."); + expect(response.data.amount).toBe(String(paymentPayload.amount)); + expect(response.data.description).toBe(paymentPayload.description); }); describe('payInvoice error scenarios', () => { - const payload: SendPaymentOptionsType = { + + it('should throw an error when attempting to pay users own invoice', async () => { + // create charge with user + const chargePayload: ChargeOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Charge Test", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback" + }; + + const chargeResponse = await payerZBD.createCharge(chargePayload); + + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); + expect(chargeResponse.success).toBe(true); + expect(chargeResponse.message).toBe("Charge created."); + expect(chargeResponse.data.amount).toBe(chargePayload.amount); + expect(chargeResponse.data.description).toBe(chargePayload.description); + + + const errorPaymentPayload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: chargeResponse.data.invoice.request, + callbackUrl: "https://my-website.com/callback/zbd", + amount: chargeResponse.data.amount + }; + + await expect(payerZBD.sendPayment(errorPaymentPayload)).rejects.toMatchObject({ + message: "You cannot Pay your own Charge.", + status: 400 + }); + + }) + + it('should throw an error when given non-existent invoice', async () => { + + const errorPayload: SendPaymentOptionsType = { description: "Custom Payment Description", internalId: "11af01d092444a317cb33faa6b8304b8", - invoice: "lnbc1pjpf53rdqdgdshx6pqg9c8qpp56vu785r8m78dhxj3al58wtx29nxu93l5878hmkegu8aq56lnfzfqsp5w7jrwwwdt9xjrjvyh959hup06qhgjv9y4sc902u54qvfgqtpfzns9qrsgqcqpcxqy8ayqrzjqv06k0m23t593pngl0jt7n9wznp64fqngvctz7vts8nq4tukvtljqz385vqqzqqqqcqqqqqqqqqqqqqq9grzjqtsjy9p55gdceevp36fvdmrkxqvzfhy8ak2tgc5zgtjtra9xlaz97zpq6qqqjjcqqcqqqqqqqqqqqqqq9gsk96h5waj9v6eg7yz5tumhnmfgc4zz3u6p9ted9z4g6rkszz2e4kdj3vhmzmnqy2ardyw3k9ewsrjq636sm38t3s96d7h392x82859cpu9zxzf", + invoice: "adsa", callbackUrl: "https://my-website.com/callback/zbd", amount: "10000" }; - - it('should return a 404 for a non-existent charge ID', async () => { - await expect(ZBD.sendPayment(payload)).rejects.toMatchObject({ - message: "No Charge records found with this ID.", - status: 404 + + await expect(payerZBD.sendPayment(errorPayload)).rejects.toMatchObject({ + message: "Could not decode the provided invoice.", + status: 400 }); }); diff --git a/__tests__/withdrawal/getWithdrawalRequest.test.ts b/__tests__/withdrawal/getWithdrawalRequest.test.ts index 1281bad..4297185 100644 --- a/__tests__/withdrawal/getWithdrawalRequest.test.ts +++ b/__tests__/withdrawal/getWithdrawalRequest.test.ts @@ -16,7 +16,6 @@ describe('getWithdrawalRequest', () => { // Data Validation expect(isGetWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); - }); describe('createWithdrawalRequest error scenarios', () => { diff --git a/src/constants.ts b/src/constants.ts index 2d92300..6752217 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,6 +4,9 @@ export const API_URL = 'https://api.zebedee.io'; // Test API Key export const TEST_API_KEY = "8qJxln3JVJsQM0IOJhfnJopO0JSiLdlK" +// Other Test API Key (Receiver) +export const TEST_RECEIVER_API_KEY = "dESXgwgy7GziAbVA7AyN56uATloaburz" + // Endpoints export const API = { // Wallet diff --git a/src/types/payments.ts b/src/types/payments.ts index 5e9db86..caa6e7c 100644 --- a/src/types/payments.ts +++ b/src/types/payments.ts @@ -38,7 +38,7 @@ export function isInvoicePaymentDataResponseType(obj: any): obj is InvoicePaymen typeof obj.data.unit === 'string' && typeof obj.data.amount === 'string' && typeof obj.data.invoice === 'string' && - typeof obj.data.preimage === 'string' && + (typeof obj.data.preimage === 'string' || obj.data.preimage === null) && typeof obj.data.internalId === 'string' && typeof obj.data.processedAt === 'string' && typeof obj.data.confirmedAt === 'string' && From 29a436dc6044c5fe5e09e2db9b273d65ef7ac273 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 16 Aug 2023 17:45:17 +0200 Subject: [PATCH 15/18] keysend test suite complete --- .../internalTransfer.test.ts | 3 +- __tests__/payments/payInvoice.test.ts | 43 ++++++++++++++++++- __tests__/wallet/getWallet.test.ts | 14 ++---- src/types/keysend.ts | 6 +-- src/types/wallet.ts | 10 +++++ 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index 7734589..9479e35 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -13,8 +13,7 @@ describe('Initiate Internal Transfer', () => { }; const response = await ZBD.internalTransfer(requestBody); - - console.log(response) + expect(response.success).toBe(true); expect(response.message).toBe('Internal Transfer done.'); diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts index a95653c..7a64f4b 100644 --- a/__tests__/payments/payInvoice.test.ts +++ b/__tests__/payments/payInvoice.test.ts @@ -1,7 +1,7 @@ import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from '../../src/constants'; import { zbd } from '../../src/zbd'; import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isInvoicePaymentDataResponseType } from '../../src/types/payments'; -import { ChargeOptionsType, isChargeResponseType } from '../../src/types'; +import { ChargeOptionsType, isChargeResponseType, isWalletDataResponseType } from '../../src/types'; const payerZBD = new zbd(TEST_API_KEY); const receiverZBD = new zbd(TEST_RECEIVER_API_KEY) @@ -98,6 +98,47 @@ describe('payInvoice', () => { }); }); + + // Integration test: + it('should throw an error when attempting to pay more than balance allows', async () => { + + + const chargePayload: ChargeOptionsType = { + expiresIn: 300, + amount: "500000000", + description: "My Charge Test", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback" + }; + + // verify charge + const chargeResponse = await receiverZBD.createCharge(chargePayload); + + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); + expect(chargeResponse.success).toBe(true); + expect(chargeResponse.message).toBe("Charge created."); + expect(chargeResponse.data.amount).toBe(chargePayload.amount); + expect(chargeResponse.data.description).toBe(chargePayload.description); + + // create payment and attempt to pay it + const paymentPayload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: chargeResponse.data.invoice.request, + callbackUrl: "https://my-website.com/callback/zbd", + amount: chargeResponse.data.amount + }; + + + await expect(payerZBD.sendPayment(paymentPayload)).rejects.toMatchObject({ + message: "You do not have enough funds for this transaction and fees.", + status: 400, + }) + + }); + + + }); }); diff --git a/__tests__/wallet/getWallet.test.ts b/__tests__/wallet/getWallet.test.ts index ab11b44..4ff40ab 100644 --- a/__tests__/wallet/getWallet.test.ts +++ b/__tests__/wallet/getWallet.test.ts @@ -1,24 +1,16 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { WalletDataResponseType } from '../../src/types'; +import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from '../../src/constants'; +import { isWalletDataResponseType } from '../../src/types'; import { zbd } from '../../src/zbd'; const ZBD = new zbd(TEST_API_KEY); -function isWalletDataResponseType(data: any): data is WalletDataResponseType { - return typeof data === 'object' && - data !== null && - typeof data.message === 'string' && - typeof data.data === 'object' && - data.data !== null && - typeof data.data.unit === 'string' && - typeof data.data.balance === 'string'; -} describe('getWallet', () => { it('should fetch wallet details successfully', async () => { const response = await ZBD.getWallet(); expect(response).toBeDefined(); + console.log(response) // Data Validation expect(isWalletDataResponseType(response)).toBeTruthy(); diff --git a/src/types/keysend.ts b/src/types/keysend.ts index 63ced60..fff87cb 100644 --- a/src/types/keysend.ts +++ b/src/types/keysend.ts @@ -35,11 +35,11 @@ export function isKeysendDataResponseType(obj: any): obj is KeysendDataResponseT obj.data.transaction && typeof obj.data.transaction.id === 'string' && typeof obj.data.transaction.walletId === 'string' && - typeof obj.data.transaction.type === 'string' && + (typeof obj.data.transaction.type === 'string' || obj.data.transaction.type === undefined) && typeof obj.data.transaction.totalAmount === 'string' && typeof obj.data.transaction.fee === 'string' && typeof obj.data.transaction.amount === 'string' && - typeof obj.data.transaction.description === 'string' && + (typeof obj.data.transaction.description === 'string' || obj.data.transaction.description === undefined) && typeof obj.data.transaction.status === 'string' && - (obj.data.transaction.confirmedAt === null || typeof obj.data.transaction.confirmedAt === 'string'); + (obj.data.transaction.confirmedAt === undefined || typeof obj.data.transaction.confirmedAt === 'string'); } diff --git a/src/types/wallet.ts b/src/types/wallet.ts index 328d91f..fe345cd 100644 --- a/src/types/wallet.ts +++ b/src/types/wallet.ts @@ -5,3 +5,13 @@ export interface WalletDataResponseType { } message: string; } + +export function isWalletDataResponseType(data: any): data is WalletDataResponseType { + return typeof data === 'object' && + data !== null && + typeof data.message === 'string' && + typeof data.data === 'object' && + data.data !== null && + typeof data.data.unit === 'string' && + typeof data.data.balance === 'string'; +} \ No newline at end of file From 1024dba19b82f4e702b20e4e1e2c55f5c02f39a1 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 16 Aug 2023 17:52:21 +0200 Subject: [PATCH 16/18] Everything but internal --- .../internalTransfer.test.ts | 26 +++++++++---------- __tests__/payments/payInvoice.test.ts | 1 - 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index 9479e35..cec154e 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -6,28 +6,28 @@ const ZBD = new zbd(TEST_API_KEY); describe('Initiate Internal Transfer', () => { - it('should initiate an internal transfer successfully', async () => { - const requestBody: InternalTransferOptionsType = { - amount: "1000", - receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6" - }; - - const response = await ZBD.internalTransfer(requestBody); + // it('should initiate an internal transfer successfully', async () => { + // const requestBody: InternalTransferOptionsType = { + // amount: "10000", + // receiverWalletId: "cec89aad-6ce5-4ee3-99a3-6810911be604" + // }; + + // const response = await ZBD.internalTransfer(requestBody); - expect(response.success).toBe(true); - expect(response.message).toBe('Internal Transfer done.'); + // expect(response.success).toBe(true); + // expect(response.message).toBe('Internal Transfer done.'); - // Data Validation - expect(isInternalTransferDataResponseType(response)).toBeTruthy(); - }); + // // Data Validation + // expect(isInternalTransferDataResponseType(response)).toBeTruthy(); + // }); describe('internalTransfer error scenarios', () => { it('should throw an error given an invalid receiver wallet ID', async () => { const errorBody: InternalTransferOptionsType = { amount: "100000", - receiverWalletId: "1234" + receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6" }; await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts index 7a64f4b..ae5cb5e 100644 --- a/__tests__/payments/payInvoice.test.ts +++ b/__tests__/payments/payInvoice.test.ts @@ -37,7 +37,6 @@ describe('payInvoice', () => { }; const response = await payerZBD.sendPayment(paymentPayload); - console.log(response) expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); expect(response.success).toBe(true); From 39ec5d7537f33198e288e3695a1d65e1eff0d78b Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 16 Aug 2023 18:17:38 +0200 Subject: [PATCH 17/18] Internal transfer test suite complete --- __tests__/charges/createCharge.test.ts | 1 + .../internalTransfer.test.ts | 48 +++++++++++++------ src/constants.ts | 7 ++- src/types/internal-transfers.ts | 28 ++++++----- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/__tests__/charges/createCharge.test.ts b/__tests__/charges/createCharge.test.ts index f2aa0f6..f6362cb 100644 --- a/__tests__/charges/createCharge.test.ts +++ b/__tests__/charges/createCharge.test.ts @@ -17,6 +17,7 @@ describe('createCharge', () => { }; const response = await ZBD.createCharge(payload); + console.log(response) expect(isChargeResponseType(response)).toBeTruthy(); expect(response.success).toBe(true); diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index cec154e..4e9c727 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -1,26 +1,26 @@ -import { TEST_API_KEY } from '../../src/constants'; +import { INTERNAL_TRANSFER_API_KEY } from '../../src/constants'; import { InternalTransferOptionsType, isInternalTransferDataResponseType } from '../../src/types'; import { zbd } from '../../src/zbd'; -const ZBD = new zbd(TEST_API_KEY); +const ZBD = new zbd(INTERNAL_TRANSFER_API_KEY); + describe('Initiate Internal Transfer', () => { - // it('should initiate an internal transfer successfully', async () => { - // const requestBody: InternalTransferOptionsType = { - // amount: "10000", - // receiverWalletId: "cec89aad-6ce5-4ee3-99a3-6810911be604" - // }; - - // const response = await ZBD.internalTransfer(requestBody); - + it('should initiate an internal transfer successfully', async () => { + const requestBody: InternalTransferOptionsType = { + amount: "1000", + receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea" + }; - // expect(response.success).toBe(true); - // expect(response.message).toBe('Internal Transfer done.'); + const response = await ZBD.internalTransfer(requestBody); - // // Data Validation - // expect(isInternalTransferDataResponseType(response)).toBeTruthy(); - // }); + expect(response.success).toBe(true); + expect(response.message).toBe('Internal Transfer done.'); + + // Data Validation + expect(isInternalTransferDataResponseType(response)).toBeTruthy(); + }); describe('internalTransfer error scenarios', () => { it('should throw an error given an invalid receiver wallet ID', async () => { @@ -36,6 +36,24 @@ describe('Initiate Internal Transfer', () => { }) }); + + it('should throw an error given excess of balance', async () => { + + const errorBody: InternalTransferOptionsType = { + amount: "5000000", + receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea" + }; + + await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ + message: "Error processing transfer.", + status: 400, + }) + + }); + + + + }); }); diff --git a/src/constants.ts b/src/constants.ts index 6752217..7ca283a 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,9 +4,14 @@ export const API_URL = 'https://api.zebedee.io'; // Test API Key export const TEST_API_KEY = "8qJxln3JVJsQM0IOJhfnJopO0JSiLdlK" -// Other Test API Key (Receiver) +// Test API Key 2 (Receiver) export const TEST_RECEIVER_API_KEY = "dESXgwgy7GziAbVA7AyN56uATloaburz" +// Test API Key 3 (Internal Transfer) +export const INTERNAL_TRANSFER_API_KEY = "xqIdOA5pZAb9Ir64Qs4BlDlZZ6WrfWGW" + + + // Endpoints export const API = { // Wallet diff --git a/src/types/internal-transfers.ts b/src/types/internal-transfers.ts index 44a7f72..0a9d520 100644 --- a/src/types/internal-transfers.ts +++ b/src/types/internal-transfers.ts @@ -20,15 +20,19 @@ export interface InternalTransferOptionsType { receiverWalletId: string; } -export function isInternalTransferDataResponseType(data: any): data is InternalTransferDataResponseType { - return typeof data.id === 'string' && - typeof data.senderWalletId === 'string' && - typeof data.receiverWalletId === 'string' && - typeof data.userId === 'string' && - typeof data.sendTxId === 'string' && - typeof data.receiveTxId === 'string' && - typeof data.status === 'string' && - typeof data.amount === 'string' && - typeof data.createdAt === 'string' && - typeof data.updatedAt === 'string'; -} \ No newline at end of file +export function isInternalTransferDataResponseType(obj: any): obj is InternalTransferDataResponseType { + return obj && + typeof obj.success === 'boolean' && + typeof obj.message === 'string' && + obj.data && + typeof obj.data.id === 'string' && + typeof obj.data.senderWalletId === 'string' && + typeof obj.data.receiverWalletId === 'string' && + typeof obj.data.userId === 'string' && + typeof obj.data.sendTxId === 'string' && + typeof obj.data.receiveTxId === 'string' && + typeof obj.data.status === 'string' && + typeof obj.data.amount === 'string' && + typeof obj.data.createdAt === 'string' && + typeof obj.data.updatedAt === 'string'; +} From 178454946642dd3ab5ddc89c83fec3703734d030 Mon Sep 17 00:00:00 2001 From: Harun Curak Date: Wed, 16 Aug 2023 18:27:15 +0200 Subject: [PATCH 18/18] Test suites complete --- __tests__/charges/createCharge.test.ts | 42 ++--- __tests__/charges/getCharge.test.ts | 29 +-- .../gamertag/fetchChargeFromGamertag.test.ts | 40 ++-- .../gamertag/fetchGamertagByUserID.test.ts | 33 ++-- ...etchGamertagTransactionDetailsByID.test.ts | 33 ++-- .../gamertag/fetchUserIDFromGamertag.test.ts | 27 +-- .../gamertag/sendPaymentToGamertag.test.ts | 40 ++-- .../internalTransfer.test.ts | 59 +++--- __tests__/keysend/sendKeysendPayment.test.ts | 58 +++--- .../fetchChargeFromLightningAddress.test.ts | 71 ++++---- .../sendPaymentToLightningAddress.test.ts | 47 ++--- .../validateLightningAddress.test.ts | 34 ++-- __tests__/misc/getAPIProductionIPs.test.ts | 18 +- .../misc/getBTCtoUSDExchangeRate.test.ts | 21 ++- __tests__/misc/isSupportedRegion.test.ts | 40 ++-- __tests__/payments/getPaymentDetails.test.ts | 27 ++- __tests__/payments/payInvoice.test.ts | 172 +++++++++--------- .../static-charges/createStaticCharge.test.ts | 40 ++-- .../static-charges/getStaticCharge.test.ts | 37 ++-- .../static-charges/updateStaticCharge.test.ts | 81 +++++---- __tests__/wallet/getWallet.test.ts | 22 +-- .../createWithdrawalRequest.test.ts | 62 ++++--- .../withdrawal/getWithdrawalRequest.test.ts | 31 ++-- 23 files changed, 531 insertions(+), 533 deletions(-) diff --git a/__tests__/charges/createCharge.test.ts b/__tests__/charges/createCharge.test.ts index f6362cb..c7896ce 100644 --- a/__tests__/charges/createCharge.test.ts +++ b/__tests__/charges/createCharge.test.ts @@ -1,24 +1,25 @@ - -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { ChargeDataResponseType, ChargeOptionsType, isChargeResponseType } from '../../src/types/charges'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + ChargeDataResponseType, + ChargeOptionsType, + isChargeResponseType, +} from "../../src/types/charges"; const ZBD = new zbd(TEST_API_KEY); - -describe('createCharge', () => { - it('should successfully create a charge', async () => { +describe("createCharge", () => { + it("should successfully create a charge", async () => { const payload: ChargeOptionsType = { expiresIn: 300, amount: "10000", description: "My Charge Test Zapier", internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" + callbackUrl: "https://my-website.com/zbd-callback", }; const response = await ZBD.createCharge(payload); - console.log(response) - + expect(isChargeResponseType(response)).toBeTruthy(); expect(response.success).toBe(true); expect(response.message).toBe("Charge created."); @@ -26,23 +27,20 @@ describe('createCharge', () => { expect(response.data.description).toBe(payload.description); }); - describe('createCharge error scenarios', () => { - it('should throw an error given an erroneous payload (amount = 0)', async () => { - + describe("createCharge error scenarios", () => { + it("should throw an error given an erroneous payload (amount = 0)", async () => { const erroneousPayload: ChargeOptionsType = { expiresIn: 100, amount: "0", description: "My Charge Test Zapier", internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" + callbackUrl: "https://my-website.com/zbd-callback", }; - - await expect(ZBD.createCharge(erroneousPayload)).rejects.toMatchObject({ - message: "Request has missing or mismatch params.", - status: 400, - }) - + + await expect(ZBD.createCharge(erroneousPayload)).rejects.toMatchObject({ + message: "Request has missing or mismatch params.", + status: 400, + }); }); }); - -}); \ No newline at end of file +}); diff --git a/__tests__/charges/getCharge.test.ts b/__tests__/charges/getCharge.test.ts index 0770eba..0f01475 100644 --- a/__tests__/charges/getCharge.test.ts +++ b/__tests__/charges/getCharge.test.ts @@ -1,31 +1,32 @@ -import { zbd } from '@zbd/node'; -import { TEST_API_KEY } from '../../src/constants'; -import { ChargeDataResponseType, isChargeResponseType } from '../../src/types/charges'; +import { zbd } from "@zbd/node"; +import { TEST_API_KEY } from "../../src/constants"; +import { + ChargeDataResponseType, + isChargeResponseType, +} from "../../src/types/charges"; const ZBD = new zbd(TEST_API_KEY); -describe('getCharge', () => { - const VALID_CHARGE_ID = '4f0fa38f-efbe-485f-9293-95e697f6fbd4'; - const INVALID_CHARGE_ID = 'invalid'; - const INVALID_API_KEY = 'INVALID_API_KEY'; - +describe("getCharge", () => { + const VALID_CHARGE_ID = "4f0fa38f-efbe-485f-9293-95e697f6fbd4"; + const INVALID_CHARGE_ID = "invalid"; + const INVALID_API_KEY = "INVALID_API_KEY"; + // Success - it('should fetch charge details for a valid charge ID', async () => { + it("should fetch charge details for a valid charge ID", async () => { const data = await ZBD.getCharge(VALID_CHARGE_ID); expect(data.success).toBe(true); expect(data.message).toBe("Fetched Charge."); - + // Data Validation expect(isChargeResponseType(data)).toBeTruthy(); }); // Charge not found - it('should return a 404 for a non-existent charge ID', async () => { + it("should return a 404 for a non-existent charge ID", async () => { await expect(ZBD.getCharge(INVALID_CHARGE_ID)).rejects.toMatchObject({ message: "No Charge records found with this ID.", - status: 404 + status: 404, }); }); - }); - diff --git a/__tests__/gamertag/fetchChargeFromGamertag.test.ts b/__tests__/gamertag/fetchChargeFromGamertag.test.ts index 7079268..c2b6d72 100644 --- a/__tests__/gamertag/fetchChargeFromGamertag.test.ts +++ b/__tests__/gamertag/fetchChargeFromGamertag.test.ts @@ -1,19 +1,23 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { FetchChargeFromGamertagDataResponseType, FetchChargeFromGamertagOptionsType, isFetchChargeFromGamertagDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + FetchChargeFromGamertagDataResponseType, + FetchChargeFromGamertagOptionsType, + isFetchChargeFromGamertagDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Fetch Charge from Gamertag', () => { +describe("Fetch Charge from Gamertag", () => { const requestBody: FetchChargeFromGamertagOptionsType = { amount: "1000", gamertag: "andre", description: "Requesting Charge for Gamertag", callbackUrl: "https://your-website.com/zbd-callback", - internalId: "test-internal-id" + internalId: "test-internal-id", }; - it('should successfully create a charge for a gamertag', async () => { + it("should successfully create a charge for a gamertag", async () => { const response = await ZBD.createGamertagCharge(requestBody); expect(response).toBeDefined(); @@ -21,24 +25,22 @@ describe('Fetch Charge from Gamertag', () => { expect(isFetchChargeFromGamertagDataResponseType(response)).toBeTruthy(); }); - describe('fetchGamertagByUserID error scenarios', () => { - it('should throw an error given a non-existent user ID', async () => { - + describe("fetchGamertagByUserID error scenarios", () => { + it("should throw an error given a non-existent user ID", async () => { const errorRequestBody: FetchChargeFromGamertagOptionsType = { amount: "1000", gamertag: "fakeGamerTagĆ", description: "Requesting Charge for fake Gamertag", callbackUrl: "https://your-website.com/zbd-callback", - internalId: "test-internal-id" + internalId: "test-internal-id", }; - - await expect(ZBD.createGamertagCharge(errorRequestBody)).rejects.toMatchObject({ - message: "API request failed", - status: 500, - }) - + + await expect( + ZBD.createGamertagCharge(errorRequestBody) + ).rejects.toMatchObject({ + message: "API request failed", + status: 500, + }); }); }); - - -}); \ No newline at end of file +}); diff --git a/__tests__/gamertag/fetchGamertagByUserID.test.ts b/__tests__/gamertag/fetchGamertagByUserID.test.ts index 94491e1..2351469 100644 --- a/__tests__/gamertag/fetchGamertagByUserID.test.ts +++ b/__tests__/gamertag/fetchGamertagByUserID.test.ts @@ -1,15 +1,18 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { FetchGamertagByUserIdDataResponseType, isFetchGamertagByUserIDDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + FetchGamertagByUserIdDataResponseType, + isFetchGamertagByUserIDDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Fetch Gamertag By User ID', () => { - const testUserID = "ec9b38d5-b126-4307-9d1e-8aa0dfab5d7e"; - const fakeUserID = "202020" +describe("Fetch Gamertag By User ID", () => { + const testUserID = "ec9b38d5-b126-4307-9d1e-8aa0dfab5d7e"; + const fakeUserID = "202020"; - it('should successfully fetch a gamertag by user ID', async () => { - const response = await ZBD.getGamertagByUserId(testUserID); + it("should successfully fetch a gamertag by user ID", async () => { + const response = await ZBD.getGamertagByUserId(testUserID); expect(response).toBeDefined(); expect(response.success).toBe(true); @@ -19,14 +22,12 @@ describe('Fetch Gamertag By User ID', () => { expect(isFetchGamertagByUserIDDataResponseType(response)).toBeTruthy(); }); - describe('fetchGamertagByUserID error scenarios', () => { - it('should throw an error given a non-existent user ID', async () => { - - await expect(ZBD.getGamertagByUserId(fakeUserID)).rejects.toMatchObject({ - message: "No gamertag found with this uuid", - status: 400, - }) - + describe("fetchGamertagByUserID error scenarios", () => { + it("should throw an error given a non-existent user ID", async () => { + await expect(ZBD.getGamertagByUserId(fakeUserID)).rejects.toMatchObject({ + message: "No gamertag found with this uuid", + status: 400, + }); }); }); }); diff --git a/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts b/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts index a8daf17..9ff4792 100644 --- a/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts +++ b/__tests__/gamertag/fetchGamertagTransactionDetailsByID.test.ts @@ -1,31 +1,34 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { GamertagTransactionDataResponseType, isGamertagTransactionDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + GamertagTransactionDataResponseType, + isGamertagTransactionDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Fetch Gamertag Transaction Details By ID', () => { - const TEST_TRANSACTION_ID = '3418e871-05f6-4745-b12b-ccd53da9c4d1'; - const NON_EXISTENT_TRANSACTION_ID = '903883f2-67d9-4707-a21b-ddff004fe041'; +describe("Fetch Gamertag Transaction Details By ID", () => { + const TEST_TRANSACTION_ID = "3418e871-05f6-4745-b12b-ccd53da9c4d1"; + const NON_EXISTENT_TRANSACTION_ID = "903883f2-67d9-4707-a21b-ddff004fe041"; - it('should successfully fetch transaction details by ID', async () => { + it("should successfully fetch transaction details by ID", async () => { const response = await ZBD.getGamertagTransaction(TEST_TRANSACTION_ID); expect(response).toBeDefined(); expect(response.success).toBe(true); - + expect(isGamertagTransactionDataResponseType(response)).toBeTruthy(); }); - describe('fetchGamertagTransactionDetailsByID error scenarios', () => { - it('should fail to fetch transaction details given false ID', async () => { - const response = await ZBD.getGamertagTransaction(NON_EXISTENT_TRANSACTION_ID); + describe("fetchGamertagTransactionDetailsByID error scenarios", () => { + it("should fail to fetch transaction details given false ID", async () => { + const response = await ZBD.getGamertagTransaction( + NON_EXISTENT_TRANSACTION_ID + ); expect(response).toBeDefined(); expect(response.success).toBe(true); - expect(response.message).toBe("Transaction not found"); - - }) + expect(response.message).toBe("Transaction not found"); + }); }); }); - diff --git a/__tests__/gamertag/fetchUserIDFromGamertag.test.ts b/__tests__/gamertag/fetchUserIDFromGamertag.test.ts index 7908ac5..ea6000c 100644 --- a/__tests__/gamertag/fetchUserIDFromGamertag.test.ts +++ b/__tests__/gamertag/fetchUserIDFromGamertag.test.ts @@ -1,28 +1,31 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { FetchUserIdByGamertagDataResponseType, isFetchUserIdByGamertagDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + FetchUserIdByGamertagDataResponseType, + isFetchUserIdByGamertagDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Fetch User ID By Gamertag', () => { +describe("Fetch User ID By Gamertag", () => { const testGamertag = "foxp2"; - it('should successfully fetch user ID for a valid gamertag', async () => { + it("should successfully fetch user ID for a valid gamertag", async () => { const response = await ZBD.getUserIdByGamertag(testGamertag); - + expect(response).toBeDefined(); expect(response.success).toBe(true); expect(isFetchUserIdByGamertagDataResponseType(response)).toBeTruthy(); }); - it('should return an error for an invalid gamertag', async () => { + it("should return an error for an invalid gamertag", async () => { const invalidGamertag = "nonExistentTagč"; - - await expect(ZBD.getUserIdByGamertag(invalidGamertag)).rejects.toMatchObject({ + + await expect( + ZBD.getUserIdByGamertag(invalidGamertag) + ).rejects.toMatchObject({ message: "No user found with this gamertag", status: 400, - }) - + }); }); }); - diff --git a/__tests__/gamertag/sendPaymentToGamertag.test.ts b/__tests__/gamertag/sendPaymentToGamertag.test.ts index e8685c5..3fba55f 100644 --- a/__tests__/gamertag/sendPaymentToGamertag.test.ts +++ b/__tests__/gamertag/sendPaymentToGamertag.test.ts @@ -1,43 +1,43 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { SendGamertagPaymentOptionsType, isSendGamertagPaymentDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + SendGamertagPaymentOptionsType, + isSendGamertagPaymentDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Send Payment to Gamertag', () => { +describe("Send Payment to Gamertag", () => { const mockRequestBody: SendGamertagPaymentOptionsType = { gamertag: "foxp2", amount: "1000", - description: "Sending to ZBD Gamertag" + description: "Sending to ZBD Gamertag", }; - it('should successfully send payment to a gamertag', async () => { + it("should successfully send payment to a gamertag", async () => { const response = await ZBD.sendGamertagPayment(mockRequestBody); // Assuming ZBD has a method called sendPaymentToGamertag expect(response).toBeDefined(); expect(response.success).toBe(true); expect(response.message).toBe("Payment done."); - expect(isSendGamertagPaymentDataResponseType(response)).toBeTruthy() - + expect(isSendGamertagPaymentDataResponseType(response)).toBeTruthy(); }); - describe('sendPaymentToGamertag error scenarios', () => { - - it('should throw an error given a non-existent gamertag', async () => { - + describe("sendPaymentToGamertag error scenarios", () => { + it("should throw an error given a non-existent gamertag", async () => { const errorRequestBody: SendGamertagPaymentOptionsType = { gamertag: "fakeGamertagĆ", amount: "1000", - description: "Sending to non-existent Gamertag" + description: "Sending to non-existent Gamertag", }; - - await expect(ZBD.sendGamertagPayment(errorRequestBody)).rejects.toMatchObject({ - message: "You cannot pay to this user, missing destination", - status: 500, - }) - - }); + await expect( + ZBD.sendGamertagPayment(errorRequestBody) + ).rejects.toMatchObject({ + message: "You cannot pay to this user, missing destination", + status: 500, + }); + }); }); }); diff --git a/__tests__/internal-transfer/internalTransfer.test.ts b/__tests__/internal-transfer/internalTransfer.test.ts index 4e9c727..b9d354a 100644 --- a/__tests__/internal-transfer/internalTransfer.test.ts +++ b/__tests__/internal-transfer/internalTransfer.test.ts @@ -1,60 +1,51 @@ -import { INTERNAL_TRANSFER_API_KEY } from '../../src/constants'; -import { InternalTransferOptionsType, isInternalTransferDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { INTERNAL_TRANSFER_API_KEY } from "../../src/constants"; +import { + InternalTransferOptionsType, + isInternalTransferDataResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(INTERNAL_TRANSFER_API_KEY); - -describe('Initiate Internal Transfer', () => { - - it('should initiate an internal transfer successfully', async () => { +describe("Initiate Internal Transfer", () => { + it("should initiate an internal transfer successfully", async () => { const requestBody: InternalTransferOptionsType = { amount: "1000", - receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea" + receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea", }; const response = await ZBD.internalTransfer(requestBody); expect(response.success).toBe(true); - expect(response.message).toBe('Internal Transfer done.'); + expect(response.message).toBe("Internal Transfer done."); // Data Validation expect(isInternalTransferDataResponseType(response)).toBeTruthy(); }); - describe('internalTransfer error scenarios', () => { - it('should throw an error given an invalid receiver wallet ID', async () => { - + describe("internalTransfer error scenarios", () => { + it("should throw an error given an invalid receiver wallet ID", async () => { const errorBody: InternalTransferOptionsType = { amount: "100000", - receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6" + receiverWalletId: "b804ee02-ec0b-4fd4-b99f-1f2d3d0001a6", }; - - await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ - message: "Error processing transfer.", - status: 400, - }) - - }); - it('should throw an error given excess of balance', async () => { + await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ + message: "Error processing transfer.", + status: 400, + }); + }); + it("should throw an error given excess of balance", async () => { const errorBody: InternalTransferOptionsType = { amount: "5000000", - receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea" + receiverWalletId: "a96de0a1-6e7f-4247-b755-02ec541449ea", }; - - await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ - message: "Error processing transfer.", - status: 400, - }) - - }); - - - + await expect(ZBD.internalTransfer(errorBody)).rejects.toMatchObject({ + message: "Error processing transfer.", + status: 400, + }); + }); }); - }); - diff --git a/__tests__/keysend/sendKeysendPayment.test.ts b/__tests__/keysend/sendKeysendPayment.test.ts index b6407cf..437d8cc 100644 --- a/__tests__/keysend/sendKeysendPayment.test.ts +++ b/__tests__/keysend/sendKeysendPayment.test.ts @@ -1,19 +1,18 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { KeysendOptionsType, isKeysendDataResponseType } from '../../src/types'; - +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { KeysendOptionsType, isKeysendDataResponseType } from "../../src/types"; const ZBD = new zbd(TEST_API_KEY); -describe('Send Keysend Payment', () => { - - it('should send a keysend payment successfully', async () => { +describe("Send Keysend Payment", () => { + it("should send a keysend payment successfully", async () => { const requestBody: KeysendOptionsType = { amount: "1000", - pubkey: "0332d57355d673e217238ce3e4be8491aa6b2a13f95494133ee243e57df1653ace", + pubkey: + "0332d57355d673e217238ce3e4be8491aa6b2a13f95494133ee243e57df1653ace", tlvRecords: [], metadata: {}, - callbackUrl: "{{callbackURL}}" + callbackUrl: "{{callbackURL}}", }; const response = await ZBD.sendKeysendPayment(requestBody); @@ -21,33 +20,22 @@ describe('Send Keysend Payment', () => { // Data Validation expect(response.success).toBe(true); expect(isKeysendDataResponseType(response)).toBeTruthy(); - }); - - -describe('Send Keysend error scenarios', () => { - - it('should fail keysend payment given an invalid pubkey', async () => { - - const errorBody: KeysendOptionsType = { - amount: "1000", - pubkey: "23", - tlvRecords: [], - metadata: {}, - callbackUrl: "{{callbackURL}}" - }; - - await expect(ZBD.sendKeysendPayment(errorBody)).rejects.toMatchObject({ - message: "Keysend payment failed.", - status: 400, - }) - + describe("Send Keysend error scenarios", () => { + it("should fail keysend payment given an invalid pubkey", async () => { + const errorBody: KeysendOptionsType = { + amount: "1000", + pubkey: "23", + tlvRecords: [], + metadata: {}, + callbackUrl: "{{callbackURL}}", + }; + + await expect(ZBD.sendKeysendPayment(errorBody)).rejects.toMatchObject({ + message: "Keysend payment failed.", + status: 400, + }); + }); }); - }); - - -}); - - diff --git a/__tests__/lightning/fetchChargeFromLightningAddress.test.ts b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts index fe893c4..8ebb11f 100644 --- a/__tests__/lightning/fetchChargeFromLightningAddress.test.ts +++ b/__tests__/lightning/fetchChargeFromLightningAddress.test.ts @@ -1,43 +1,46 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { FetchChargeFromLightningAddressDataResponseType, CreateChargeFromLightningAddressOptionsType, isFetchChargeFromLightningAddressResponseType, } from '../../src/types/lightning'; // Ensure you create this type checker function +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + FetchChargeFromLightningAddressDataResponseType, + CreateChargeFromLightningAddressOptionsType, + isFetchChargeFromLightningAddressResponseType, +} from "../../src/types/lightning"; const ZBD = new zbd(TEST_API_KEY); -describe('fetchChargeFromLightningAddress', () => { - - const payload: CreateChargeFromLightningAddressOptionsType = { - lnAddress: "andre@zbd.gg", - lnaddress: "andre@zbd.gg", - amount: "10000", - description: "Sending to a Lightning Address", - }; +describe("fetchChargeFromLightningAddress", () => { + const payload: CreateChargeFromLightningAddressOptionsType = { + lnAddress: "andre@zbd.gg", + lnaddress: "andre@zbd.gg", + amount: "10000", + description: "Sending to a Lightning Address", + }; - it('should successfully fetch a charge from Lightning Address', async () => { - const response = await ZBD.createChargeFromLightningAddress(payload); - - - expect(isFetchChargeFromLightningAddressResponseType(response)).toBeTruthy(); - expect(response.success).toBe(true); - expect(response.data.amount).toBe(payload.amount); - }); + it("should successfully fetch a charge from Lightning Address", async () => { + const response = await ZBD.createChargeFromLightningAddress(payload); - describe('fetchChargeFromLightningAddress error scenarios', () => { - const errorPayload: CreateChargeFromLightningAddressOptionsType = { - lnAddress: "aol@lol.xqz", - lnaddress: "aol@lol.xqz", - amount: "10000", - description: "Sending to a Lightning Address", - }; - - it('should throw an error when given invalid Lightning Address', async () => { - - await expect(ZBD.createChargeFromLightningAddress(errorPayload)).rejects.toMatchObject({ - message: "Could not get lighning address info.", - status: 400, - }) + expect( + isFetchChargeFromLightningAddressResponseType(response) + ).toBeTruthy(); + expect(response.success).toBe(true); + expect(response.data.amount).toBe(payload.amount); + }); + describe("fetchChargeFromLightningAddress error scenarios", () => { + const errorPayload: CreateChargeFromLightningAddressOptionsType = { + lnAddress: "aol@lol.xqz", + lnaddress: "aol@lol.xqz", + amount: "10000", + description: "Sending to a Lightning Address", + }; - }); + it("should throw an error when given invalid Lightning Address", async () => { + await expect( + ZBD.createChargeFromLightningAddress(errorPayload) + ).rejects.toMatchObject({ + message: "Could not get lighning address info.", + status: 400, + }); }); + }); }); diff --git a/__tests__/lightning/sendPaymentToLightningAddress.test.ts b/__tests__/lightning/sendPaymentToLightningAddress.test.ts index f76a865..733a03f 100644 --- a/__tests__/lightning/sendPaymentToLightningAddress.test.ts +++ b/__tests__/lightning/sendPaymentToLightningAddress.test.ts @@ -1,47 +1,48 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; - -// Assuming you have created this type checker already -import { SendLightningAddressPaymentDataResponseType, SendLightningAddressPaymentOptionsType, isSendLightningAddressPaymentDataResponseType } from '../../src/types/lightning'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + SendLightningAddressPaymentDataResponseType, + SendLightningAddressPaymentOptionsType, + isSendLightningAddressPaymentDataResponseType, +} from "../../src/types/lightning"; const ZBD = new zbd(TEST_API_KEY); -describe('sendToLightning', () => { - - it('should successfully send a payment to a Lightning Address', async () => { +describe("sendToLightning", () => { + it("should successfully send a payment to a Lightning Address", async () => { const payload: SendLightningAddressPaymentOptionsType = { lnAddress: "andre@zbd.gg", amount: "10000", comment: "Sending to a Lightning Address", callbackUrl: "https://your-domain.com/zbd-callback", - internalId: "uniqueIdFromYourSystem" + internalId: "uniqueIdFromYourSystem", }; const response = await ZBD.sendLightningAddressPayment(payload); - - expect(isSendLightningAddressPaymentDataResponseType(response)).toBeTruthy(); + + expect( + isSendLightningAddressPaymentDataResponseType(response) + ).toBeTruthy(); expect(response.success).toBe(true); expect(response.data.amount).toBe(payload.amount); }); - describe('sendToLightning error scenarios', () => { + describe("sendToLightning error scenarios", () => { const errorPayload: SendLightningAddressPaymentOptionsType = { lnAddress: "aol@lol.xqz", amount: "10000", comment: "Sending to a Lightning Address", callbackUrl: "https://your-domain.com/zbd-callback", - internalId: "uniqueIdFromYourSystem" + internalId: "uniqueIdFromYourSystem", }; - it('should throw an error when given invalid Lightning Address', async () => { - - await expect(ZBD.sendLightningAddressPayment(errorPayload)).rejects.toMatchObject({ - message: "Could not get lighning address info.", - status: 400, - }) - - - }); - + it("should throw an error when given invalid Lightning Address", async () => { + await expect( + ZBD.sendLightningAddressPayment(errorPayload) + ).rejects.toMatchObject({ + message: "Could not get lighning address info.", + status: 400, + }); + }); }); }); diff --git a/__tests__/lightning/validateLightningAddress.test.ts b/__tests__/lightning/validateLightningAddress.test.ts index bd32dd7..821b62b 100644 --- a/__tests__/lightning/validateLightningAddress.test.ts +++ b/__tests__/lightning/validateLightningAddress.test.ts @@ -1,29 +1,33 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { ValidateLightningAddressDataResponseType, isValidateLightningAddressDataResponseType } from '../../src/types/lightning'; // Your provided interface +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + ValidateLightningAddressDataResponseType, + isValidateLightningAddressDataResponseType, +} from "../../src/types/lightning"; // Your provided interface const ZBD = new zbd(TEST_API_KEY); -describe('validateLightningAddress', () => { - const mockLightningAddress = 'andre@zbd.gg'; +describe("validateLightningAddress", () => { + const mockLightningAddress = "andre@zbd.gg"; - it('should successfully validate a Lightning Address', async () => { - const response = await ZBD.validateLightningAddress(mockLightningAddress); + it("should successfully validate a Lightning Address", async () => { + const response = await ZBD.validateLightningAddress(mockLightningAddress); expect(response.success).toBe(true); // Data Validation expect(isValidateLightningAddressDataResponseType(response)).toBeTruthy(); -}); + }); - describe('validateLightningAddress error scenarios', () => { + describe("validateLightningAddress error scenarios", () => { const errorLightningAddress = "aol@lol.xqz"; - it('should say valid is false given invalid Lightning Address', async () => { - const response = await ZBD.validateLightningAddress(errorLightningAddress); - expect(response.data.valid).toBe(false); - expect(response.success).toBe(true); - - }); + it("should say valid is false given invalid Lightning Address", async () => { + const response = await ZBD.validateLightningAddress( + errorLightningAddress + ); + expect(response.data.valid).toBe(false); + expect(response.success).toBe(true); + }); }); }); diff --git a/__tests__/misc/getAPIProductionIPs.test.ts b/__tests__/misc/getAPIProductionIPs.test.ts index 5d3a449..52c1941 100644 --- a/__tests__/misc/getAPIProductionIPs.test.ts +++ b/__tests__/misc/getAPIProductionIPs.test.ts @@ -1,19 +1,19 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { ProdIPSDataResponseType , isApiProductionIPsResponseType } from '../../src/types/misc'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + ProdIPSDataResponseType, + isApiProductionIPsResponseType, +} from "../../src/types/misc"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('API Production IPs', () => { +describe("API Production IPs", () => { + it("should successfully fetch the list of production IPs", async () => { + const response = await ZBD.getZBDProdIps(); - it('should successfully fetch the list of production IPs', async () => { - const response = await ZBD.getZBDProdIps(); - - console.log(response) expect(response).toBeDefined(); expect(response.success).toBe(true); expect(isApiProductionIPsResponseType(response)).toBeTruthy(); expect(Array.isArray(response.data.ips)).toBe(true); }); - }); diff --git a/__tests__/misc/getBTCtoUSDExchangeRate.test.ts b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts index 0444ec1..3ad96d0 100644 --- a/__tests__/misc/getBTCtoUSDExchangeRate.test.ts +++ b/__tests__/misc/getBTCtoUSDExchangeRate.test.ts @@ -1,18 +1,21 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { BTCUSDDataResponseType, isBtcUsdExchangeRateResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + BTCUSDDataResponseType, + isBtcUsdExchangeRateResponseType, +} from "../../src/types"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('BTC to USD Exchange Rate', () => { - - it('should successfully fetch the latest BTC to USD exchange rate', async () => { - const response = await ZBD.getBtcUsdExchangeRate(); +describe("BTC to USD Exchange Rate", () => { + it("should successfully fetch the latest BTC to USD exchange rate", async () => { + const response = await ZBD.getBtcUsdExchangeRate(); expect(response).toBeDefined(); expect(response.success).toBe(true); expect(isBtcUsdExchangeRateResponseType(response)).toBeTruthy(); - expect(response.message).toBe("Successfully retrieved BTC USD price ticker information."); + expect(response.message).toBe( + "Successfully retrieved BTC USD price ticker information." + ); }); - }); diff --git a/__tests__/misc/isSupportedRegion.test.ts b/__tests__/misc/isSupportedRegion.test.ts index 22e91da..cd4baaf 100644 --- a/__tests__/misc/isSupportedRegion.test.ts +++ b/__tests__/misc/isSupportedRegion.test.ts @@ -1,16 +1,19 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { SupportedRegionDataResponseType, isSupportedRegionResponseType, } from '../../src/types/misc'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY } from "../../src/constants"; +import { + SupportedRegionDataResponseType, + isSupportedRegionResponseType, +} from "../../src/types/misc"; +import { zbd } from "../../src/zbd"; const ZBD = new zbd(TEST_API_KEY); -describe('Is Supported Region', () => { - const ipAddress = "66.109.221.0"; +describe("Is Supported Region", () => { + const ipAddress = "66.109.221.0"; const unsupportedIpAddress = "176.57.67.255"; const errorIpAddress = "11111.11111"; - it('should successfully check that given IP address belongs to a supported region', async () => { - const response = await ZBD.isSupportedRegion(ipAddress); + it("should successfully check that given IP address belongs to a supported region", async () => { + const response = await ZBD.isSupportedRegion(ipAddress); expect(response).toBeDefined(); expect(response.success).toBe(true); @@ -19,8 +22,8 @@ describe('Is Supported Region', () => { expect(response.data.isSupported).toBe(true); }); - it('should successfully check that given IP address does not belong to a supported region', async () => { - const response = await ZBD.isSupportedRegion(unsupportedIpAddress); + it("should successfully check that given IP address does not belong to a supported region", async () => { + const response = await ZBD.isSupportedRegion(unsupportedIpAddress); expect(response).toBeDefined(); expect(response.success).toBe(true); @@ -29,15 +32,14 @@ describe('Is Supported Region', () => { expect(response.data.isSupported).toBe(false); }); - describe('checkSupportedRegion error scenarios', () => { - - it('should throw error given invalid IP format', async () => { - await expect(ZBD.isSupportedRegion(errorIpAddress)).rejects.toMatchObject({ - message: "Ip Address is not valid.", - status: 400, - }) + describe("checkSupportedRegion error scenarios", () => { + it("should throw error given invalid IP format", async () => { + await expect(ZBD.isSupportedRegion(errorIpAddress)).rejects.toMatchObject( + { + message: "Ip Address is not valid.", + status: 400, + } + ); }); - - }); -}); \ No newline at end of file +}); diff --git a/__tests__/payments/getPaymentDetails.test.ts b/__tests__/payments/getPaymentDetails.test.ts index 4654dc6..11612b8 100644 --- a/__tests__/payments/getPaymentDetails.test.ts +++ b/__tests__/payments/getPaymentDetails.test.ts @@ -1,33 +1,30 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { isInvoicePaymentDataResponseType } from '../../src/types/payments'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { isInvoicePaymentDataResponseType } from "../../src/types/payments"; const ZBD = new zbd(TEST_API_KEY); -describe('getPaymentDetails', () => { - const mockPaymentId = '30cba220-e8b0-4df7-81a8-88cbae76b929'; +describe("getPaymentDetails", () => { + const mockPaymentId = "30cba220-e8b0-4df7-81a8-88cbae76b929"; + + it("should successfully fetch a payment detail", async () => { + const response = await ZBD.getPayment(mockPaymentId); - it('should successfully fetch a payment detail', async () => { - const response = await ZBD.getPayment(mockPaymentId); - console.log(response) - expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); expect(response.success).toBe(true); expect(response.message).toBe("Fetched Payment."); expect(response.data.id).toBe(mockPaymentId); expect(response.data.description).toBe("Custom Payment Description"); - }); - describe('getPaymentDetails error scenarios', () => { - it('should throw an error given incorrect payment id', async () => { - const errorPaymentId = 'error'; + describe("getPaymentDetails error scenarios", () => { + it("should throw an error given incorrect payment id", async () => { + const errorPaymentId = "error"; await expect(ZBD.getPayment(errorPaymentId)).rejects.toMatchObject({ message: "No Payment records found with this ID.", - status: 404 + status: 404, }); - }); }); }); diff --git a/__tests__/payments/payInvoice.test.ts b/__tests__/payments/payInvoice.test.ts index ae5cb5e..ff539ca 100644 --- a/__tests__/payments/payInvoice.test.ts +++ b/__tests__/payments/payInvoice.test.ts @@ -1,26 +1,33 @@ -import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { InvoicePaymentDataResponseType, SendPaymentOptionsType, isInvoicePaymentDataResponseType } from '../../src/types/payments'; -import { ChargeOptionsType, isChargeResponseType, isWalletDataResponseType } from '../../src/types'; +import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + InvoicePaymentDataResponseType, + SendPaymentOptionsType, + isInvoicePaymentDataResponseType, +} from "../../src/types/payments"; +import { + ChargeOptionsType, + isChargeResponseType, + isWalletDataResponseType, +} from "../../src/types"; const payerZBD = new zbd(TEST_API_KEY); -const receiverZBD = new zbd(TEST_RECEIVER_API_KEY) - -describe('payInvoice', () => { - it('should successfully pay an invoice', async () => { +const receiverZBD = new zbd(TEST_RECEIVER_API_KEY); +describe("payInvoice", () => { + it("should successfully pay an invoice", async () => { // first, create charge with receiver const chargePayload: ChargeOptionsType = { expiresIn: 300, amount: "10000", description: "My Charge Test", internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" + callbackUrl: "https://my-website.com/zbd-callback", }; // verify charge const chargeResponse = await receiverZBD.createCharge(chargePayload); - + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); expect(chargeResponse.success).toBe(true); expect(chargeResponse.message).toBe("Charge created."); @@ -33,11 +40,11 @@ describe('payInvoice', () => { internalId: "internalId", invoice: chargeResponse.data.invoice.request, callbackUrl: "https://my-website.com/callback/zbd", - amount: chargeResponse.data.amount + amount: chargeResponse.data.amount, }; const response = await payerZBD.sendPayment(paymentPayload); - + expect(isInvoicePaymentDataResponseType(response)).toBeTruthy(); expect(response.success).toBe(true); expect(response.message).toBe("Payment done."); @@ -45,99 +52,88 @@ describe('payInvoice', () => { expect(response.data.description).toBe(paymentPayload.description); }); - describe('payInvoice error scenarios', () => { - - it('should throw an error when attempting to pay users own invoice', async () => { - // create charge with user - const chargePayload: ChargeOptionsType = { - expiresIn: 300, - amount: "10000", - description: "My Charge Test", - internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" - }; - - const chargeResponse = await payerZBD.createCharge(chargePayload); - - expect(isChargeResponseType(chargeResponse)).toBeTruthy(); - expect(chargeResponse.success).toBe(true); - expect(chargeResponse.message).toBe("Charge created."); - expect(chargeResponse.data.amount).toBe(chargePayload.amount); - expect(chargeResponse.data.description).toBe(chargePayload.description); + describe("payInvoice error scenarios", () => { + it("should throw an error when attempting to pay users own invoice", async () => { + // create charge with user + const chargePayload: ChargeOptionsType = { + expiresIn: 300, + amount: "10000", + description: "My Charge Test", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback", + }; + const chargeResponse = await payerZBD.createCharge(chargePayload); - const errorPaymentPayload: SendPaymentOptionsType = { - description: "Custom Payment Description", - internalId: "internalId", - invoice: chargeResponse.data.invoice.request, - callbackUrl: "https://my-website.com/callback/zbd", - amount: chargeResponse.data.amount - }; + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); + expect(chargeResponse.success).toBe(true); + expect(chargeResponse.message).toBe("Charge created."); + expect(chargeResponse.data.amount).toBe(chargePayload.amount); + expect(chargeResponse.data.description).toBe(chargePayload.description); - await expect(payerZBD.sendPayment(errorPaymentPayload)).rejects.toMatchObject({ - message: "You cannot Pay your own Charge.", - status: 400 - }); + const errorPaymentPayload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: chargeResponse.data.invoice.request, + callbackUrl: "https://my-website.com/callback/zbd", + amount: chargeResponse.data.amount, + }; - }) - - it('should throw an error when given non-existent invoice', async () => { + await expect( + payerZBD.sendPayment(errorPaymentPayload) + ).rejects.toMatchObject({ + message: "You cannot Pay your own Charge.", + status: 400, + }); + }); + it("should throw an error when given non-existent invoice", async () => { const errorPayload: SendPaymentOptionsType = { description: "Custom Payment Description", internalId: "11af01d092444a317cb33faa6b8304b8", invoice: "adsa", callbackUrl: "https://my-website.com/callback/zbd", - amount: "10000" + amount: "10000", }; - await expect(payerZBD.sendPayment(errorPayload)).rejects.toMatchObject({ - message: "Could not decode the provided invoice.", - status: 400 - }); + await expect(payerZBD.sendPayment(errorPayload)).rejects.toMatchObject({ + message: "Could not decode the provided invoice.", + status: 400, }); + }); + + // Integration test: + it("should throw an error when attempting to pay more than balance allows", async () => { + const chargePayload: ChargeOptionsType = { + expiresIn: 300, + amount: "500000000", + description: "My Charge Test", + internalId: "internalId", + callbackUrl: "https://my-website.com/zbd-callback", + }; - - // Integration test: - it('should throw an error when attempting to pay more than balance allows', async () => { - - - const chargePayload: ChargeOptionsType = { - expiresIn: 300, - amount: "500000000", - description: "My Charge Test", - internalId: "internalId", - callbackUrl: "https://my-website.com/zbd-callback" - }; - - // verify charge - const chargeResponse = await receiverZBD.createCharge(chargePayload); - - expect(isChargeResponseType(chargeResponse)).toBeTruthy(); - expect(chargeResponse.success).toBe(true); - expect(chargeResponse.message).toBe("Charge created."); - expect(chargeResponse.data.amount).toBe(chargePayload.amount); - expect(chargeResponse.data.description).toBe(chargePayload.description); + // verify charge + const chargeResponse = await receiverZBD.createCharge(chargePayload); - // create payment and attempt to pay it - const paymentPayload: SendPaymentOptionsType = { - description: "Custom Payment Description", - internalId: "internalId", - invoice: chargeResponse.data.invoice.request, - callbackUrl: "https://my-website.com/callback/zbd", - amount: chargeResponse.data.amount - }; + expect(isChargeResponseType(chargeResponse)).toBeTruthy(); + expect(chargeResponse.success).toBe(true); + expect(chargeResponse.message).toBe("Charge created."); + expect(chargeResponse.data.amount).toBe(chargePayload.amount); + expect(chargeResponse.data.description).toBe(chargePayload.description); - - await expect(payerZBD.sendPayment(paymentPayload)).rejects.toMatchObject({ - message: "You do not have enough funds for this transaction and fees.", - status: 400, - }) + // create payment and attempt to pay it + const paymentPayload: SendPaymentOptionsType = { + description: "Custom Payment Description", + internalId: "internalId", + invoice: chargeResponse.data.invoice.request, + callbackUrl: "https://my-website.com/callback/zbd", + amount: chargeResponse.data.amount, + }; + await expect(payerZBD.sendPayment(paymentPayload)).rejects.toMatchObject({ + message: "You do not have enough funds for this transaction and fees.", + status: 400, }); - - - - + }); }); }); diff --git a/__tests__/static-charges/createStaticCharge.test.ts b/__tests__/static-charges/createStaticCharge.test.ts index 90d3ce1..d4a8f78 100644 --- a/__tests__/static-charges/createStaticCharge.test.ts +++ b/__tests__/static-charges/createStaticCharge.test.ts @@ -1,11 +1,14 @@ -import { zbd } from '@zbd/node'; -import { TEST_API_KEY } from '../../src/constants'; -import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; +import { zbd } from "@zbd/node"; +import { TEST_API_KEY } from "../../src/constants"; +import { + StaticChargeDataResponseType, + StaticChargeOptionsType, + isStaticChargeDataResponseType, +} from "../../src/types/static-charges"; const ZBD = new zbd(TEST_API_KEY); -describe('createStaticCharge', () => { - +describe("createStaticCharge", () => { // Data for creating static charge const validStaticChargeData: StaticChargeOptionsType = { allowedSlots: 0, @@ -14,11 +17,11 @@ describe('createStaticCharge', () => { description: "This is my static charge", internalId: "myInternalId1", callbackUrl: "https://my-website.com/zbd-callback", - successMessage: "Congratulations your payment was successful!" + successMessage: "Congratulations your payment was successful!", }; // Success - it('should successfully create a static charge', async () => { + it("should successfully create a static charge", async () => { const response = await ZBD.createStaticCharge(validStaticChargeData); expect(response.message).toBe("Successfully created Static Charge."); @@ -26,9 +29,8 @@ describe('createStaticCharge', () => { expect(isStaticChargeDataResponseType(response)).toBeTruthy(); }); - describe('createStaticCharge error scenarios', () => { - it('should throw an error given a faulty payload (no min max amount)', async () => { - + describe("createStaticCharge error scenarios", () => { + it("should throw an error given a faulty payload (no min max amount)", async () => { const invalidStaticChargeData: StaticChargeOptionsType = { allowedSlots: null, minAmount: "0", @@ -36,17 +38,15 @@ describe('createStaticCharge', () => { description: "This is my static charge", internalId: "myInternalId1", callbackUrl: "https://my-website.com/zbd-callback", - successMessage: "Congratulations your payment was successful!" + successMessage: "Congratulations your payment was successful!", }; - - await expect(ZBD.createStaticCharge(invalidStaticChargeData)).rejects.toMatchObject({ - message: "Error creating Static Charge.", - status: 400, - }) - + + await expect( + ZBD.createStaticCharge(invalidStaticChargeData) + ).rejects.toMatchObject({ + message: "Error creating Static Charge.", + status: 400, + }); }); }); - - - }); diff --git a/__tests__/static-charges/getStaticCharge.test.ts b/__tests__/static-charges/getStaticCharge.test.ts index 3c19df8..bb8b2fb 100644 --- a/__tests__/static-charges/getStaticCharge.test.ts +++ b/__tests__/static-charges/getStaticCharge.test.ts @@ -1,32 +1,35 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { StaticChargeDataResponseType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + StaticChargeDataResponseType, + isStaticChargeDataResponseType, +} from "../../src/types/static-charges"; const ZBD = new zbd(TEST_API_KEY); +describe("getStaticCharge", () => { + const STATIC_CHARGE_ID = "45c225b1-022b-4a37-98d6-5a5568f78d11"; -describe('getStaticCharge', () => { - - const STATIC_CHARGE_ID = '45c225b1-022b-4a37-98d6-5a5568f78d11'; - - it('should successfully fetch Static Charge details', async () => { - + it("should successfully fetch Static Charge details", async () => { const responseData = await ZBD.getStaticCharge(STATIC_CHARGE_ID); - - expect(responseData.message).toBe('Successfully retrieved Static Charge data.'); + + expect(responseData.message).toBe( + "Successfully retrieved Static Charge data." + ); expect(responseData.data.id).toBe(STATIC_CHARGE_ID); // Data Validation expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); - }); - // Static Charge not found - it('should return a 404 for a non-existent charge ID', async () => { - const NON_EXISTENT_STATIC_CHARGE_ID = 'invalid' - await expect(ZBD.getCharge(NON_EXISTENT_STATIC_CHARGE_ID)).rejects.toMatchObject({ + // Static Charge not found + it("should return a 404 for a non-existent charge ID", async () => { + const NON_EXISTENT_STATIC_CHARGE_ID = "invalid"; + await expect( + ZBD.getCharge(NON_EXISTENT_STATIC_CHARGE_ID) + ).rejects.toMatchObject({ message: "No Charge records found with this ID.", - status: 404 + status: 404, }); }); }); diff --git a/__tests__/static-charges/updateStaticCharge.test.ts b/__tests__/static-charges/updateStaticCharge.test.ts index 6b58662..d2c6184 100644 --- a/__tests__/static-charges/updateStaticCharge.test.ts +++ b/__tests__/static-charges/updateStaticCharge.test.ts @@ -1,13 +1,16 @@ -import { zbd } from '@zbd/node'; -import { TEST_API_KEY } from '../../src/constants'; -import { StaticChargeDataResponseType, StaticChargeOptionsType, isStaticChargeDataResponseType } from '../../src/types/static-charges'; - - const ZBD = new zbd(TEST_API_KEY); - -describe('PATCH Update Static Charge', () => { - - const STATIC_CHARGE_ID = '11311e05-c0da-4382-abb1-385a4659908b'; - it('should successfully update a Static Charge', async () => { +import { zbd } from "@zbd/node"; +import { TEST_API_KEY } from "../../src/constants"; +import { + StaticChargeDataResponseType, + StaticChargeOptionsType, + isStaticChargeDataResponseType, +} from "../../src/types/static-charges"; + +const ZBD = new zbd(TEST_API_KEY); + +describe("PATCH Update Static Charge", () => { + const STATIC_CHARGE_ID = "11311e05-c0da-4382-abb1-385a4659908b"; + it("should successfully update a Static Charge", async () => { const updateOptions: StaticChargeOptionsType = { allowedSlots: 0, minAmount: "10000", @@ -15,42 +18,44 @@ describe('PATCH Update Static Charge', () => { description: "This is my editted static charge", internalId: "myInternalId1", callbackUrl: "https://my-website.com/zbd-callback", - successMessage: "Congratulations your payment success msg was editted!" + successMessage: "Congratulations your payment success msg was editted!", }; + const responseData = await ZBD.updateStaticCharge( + STATIC_CHARGE_ID, + updateOptions + ); - const responseData = await ZBD.updateStaticCharge(STATIC_CHARGE_ID, updateOptions); - - expect(responseData.message).toBe('Successfully updated Static Charge.'); + expect(responseData.message).toBe("Successfully updated Static Charge."); expect(responseData.data.id).toBe(STATIC_CHARGE_ID); expect(responseData.data.description).toBe(updateOptions.description); - // Data Validation + // Data Validation expect(isStaticChargeDataResponseType(responseData)).toBeTruthy(); }); - describe('updateStaticCharge error scenarios', () => { - it('should throw an error given a non-existent static Charge ID', async () => { - - const NON_EXISTENT_STATIC_CHARGE_ID = '10101'; - - - const invalidUpdateOptions: StaticChargeOptionsType = { - allowedSlots: 0, - minAmount: "10000", - maxAmount: "5000000", - description: "This is my editted static charge", - internalId: "myInternalId1", - callbackUrl: "https://my-website.com/zbd-callback", - successMessage: "Congratulations your payment success msg was editted!" - }; - - await expect(ZBD.updateStaticCharge(NON_EXISTENT_STATIC_CHARGE_ID, invalidUpdateOptions)).rejects.toMatchObject({ - message: "Error updating Static Charge data.", - status: 400, - }) - + describe("updateStaticCharge error scenarios", () => { + it("should throw an error given a non-existent static Charge ID", async () => { + const NON_EXISTENT_STATIC_CHARGE_ID = "10101"; + + const invalidUpdateOptions: StaticChargeOptionsType = { + allowedSlots: 0, + minAmount: "10000", + maxAmount: "5000000", + description: "This is my editted static charge", + internalId: "myInternalId1", + callbackUrl: "https://my-website.com/zbd-callback", + successMessage: "Congratulations your payment success msg was editted!", + }; + + await expect( + ZBD.updateStaticCharge( + NON_EXISTENT_STATIC_CHARGE_ID, + invalidUpdateOptions + ) + ).rejects.toMatchObject({ + message: "Error updating Static Charge data.", + status: 400, + }); }); }); - }); - diff --git a/__tests__/wallet/getWallet.test.ts b/__tests__/wallet/getWallet.test.ts index 4ff40ab..52f809d 100644 --- a/__tests__/wallet/getWallet.test.ts +++ b/__tests__/wallet/getWallet.test.ts @@ -1,24 +1,18 @@ -import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from '../../src/constants'; -import { isWalletDataResponseType } from '../../src/types'; -import { zbd } from '../../src/zbd'; +import { TEST_API_KEY, TEST_RECEIVER_API_KEY } from "../../src/constants"; +import { isWalletDataResponseType } from "../../src/types"; +import { zbd } from "../../src/zbd"; -const ZBD = new zbd(TEST_API_KEY); +const ZBD = new zbd(TEST_API_KEY); - -describe('getWallet', () => { - - it('should fetch wallet details successfully', async () => { +describe("getWallet", () => { + it("should fetch wallet details successfully", async () => { const response = await ZBD.getWallet(); expect(response).toBeDefined(); - console.log(response) - + // Data Validation expect(isWalletDataResponseType(response)).toBeTruthy(); // Additional check for the balance to ensure it's a valid number string expect(Number(response.data.balance)).not.toBeNaN(); }); - - - -}); \ No newline at end of file +}); diff --git a/__tests__/withdrawal/createWithdrawalRequest.test.ts b/__tests__/withdrawal/createWithdrawalRequest.test.ts index b95c387..5279336 100644 --- a/__tests__/withdrawal/createWithdrawalRequest.test.ts +++ b/__tests__/withdrawal/createWithdrawalRequest.test.ts @@ -1,26 +1,32 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { CreateWithdrawalRequestDataResponseType, WithdrawalRequestOptionsType, isCreateWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../../src/types'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + CreateWithdrawalRequestDataResponseType, + WithdrawalRequestOptionsType, + isCreateWithdrawalRequestDataResponseType, + isGetWithdrawalRequestDataResponseType, +} from "../../src/types"; const ZBD = new zbd(TEST_API_KEY); -describe('createWithdrawalRequest', () => { - +describe("createWithdrawalRequest", () => { const requestBody: WithdrawalRequestOptionsType = { expiresIn: 300, amount: "10000", description: "My Withdrawal Description", internalId: "internalId", - callbackUrl: "https://your-website.com/callback" + callbackUrl: "https://your-website.com/callback", }; - it('should successfully create a withdrawal request', async () => { - - const responseData: CreateWithdrawalRequestDataResponseType = await ZBD.createWithdrawalRequest(requestBody); - + it("should successfully create a withdrawal request", async () => { + const responseData: CreateWithdrawalRequestDataResponseType = + await ZBD.createWithdrawalRequest(requestBody); + expect(responseData.success).toBe(true); - expect(responseData.message).toBe('Successfully created Withdrawal Request.'); - + expect(responseData.message).toBe( + "Successfully created Withdrawal Request." + ); + // Check if returned data matches request body data expect(responseData.data.amount).toBe(requestBody.amount); expect(responseData.data.description).toBe(requestBody.description); @@ -28,32 +34,28 @@ describe('createWithdrawalRequest', () => { expect(responseData.data.callbackUrl).toBe(requestBody.callbackUrl); // Data Validation - expect(isCreateWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); - + expect( + isCreateWithdrawalRequestDataResponseType(responseData) + ).toBeTruthy(); }); - describe('createWithdrawalRequest error scenarios', () => { - it('should throw an error given a faulty payload (amount invalid)', async () => { - + describe("createWithdrawalRequest error scenarios", () => { + it("should throw an error given a faulty payload (amount invalid)", async () => { const faultyRequestBody: WithdrawalRequestOptionsType = { expiresIn: 300, amount: "0", description: "My Withdrawal Description", internalId: "internalId", - callbackUrl: "https://your-website.com/callback" + callbackUrl: "https://your-website.com/callback", }; - - - await expect(ZBD.createWithdrawalRequest(faultyRequestBody)).rejects.toMatchObject({ - message: "The \"amount\" property (in millisatoshis) must be greater than 1 sat.", - status: 400, - }) - + + await expect( + ZBD.createWithdrawalRequest(faultyRequestBody) + ).rejects.toMatchObject({ + message: + 'The "amount" property (in millisatoshis) must be greater than 1 sat.', + status: 400, + }); }); }); - - - - }); - diff --git a/__tests__/withdrawal/getWithdrawalRequest.test.ts b/__tests__/withdrawal/getWithdrawalRequest.test.ts index 4297185..4b5119c 100644 --- a/__tests__/withdrawal/getWithdrawalRequest.test.ts +++ b/__tests__/withdrawal/getWithdrawalRequest.test.ts @@ -1,15 +1,16 @@ -import { TEST_API_KEY } from '../../src/constants'; -import { zbd } from '../../src/zbd'; -import { GetWithdrawalRequestDataResponseType, isGetWithdrawalRequestDataResponseType } from '../../src/types/withdrawal'; +import { TEST_API_KEY } from "../../src/constants"; +import { zbd } from "../../src/zbd"; +import { + GetWithdrawalRequestDataResponseType, + isGetWithdrawalRequestDataResponseType, +} from "../../src/types/withdrawal"; const ZBD = new zbd(TEST_API_KEY); -describe('getWithdrawalRequest', () => { +describe("getWithdrawalRequest", () => { + const WITHDRAWAL_ID = "e3c7321a-cc06-48da-90a8-589bd175ace9"; - const WITHDRAWAL_ID = 'e3c7321a-cc06-48da-90a8-589bd175ace9'; - - it('should successfully fetch Withdrawal Request details', async () => { - + it("should successfully fetch Withdrawal Request details", async () => { const responseData = await ZBD.getWithdrawalRequest(WITHDRAWAL_ID); expect(responseData.data.id).toBe(WITHDRAWAL_ID); @@ -18,14 +19,14 @@ describe('getWithdrawalRequest', () => { expect(isGetWithdrawalRequestDataResponseType(responseData)).toBeTruthy(); }); - describe('createWithdrawalRequest error scenarios', () => { - it('should return an error for a non-existent withdrawal ID', async () => { - const NON_EXISTENT_WITHDRAWAL_ID = 'invalid-id' - await expect(ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID)).resolves.toMatchObject({ - message: "Failed to fetch withdrawal request." + describe("createWithdrawalRequest error scenarios", () => { + it("should return an error for a non-existent withdrawal ID", async () => { + const NON_EXISTENT_WITHDRAWAL_ID = "invalid-id"; + await expect( + ZBD.getWithdrawalRequest(NON_EXISTENT_WITHDRAWAL_ID) + ).resolves.toMatchObject({ + message: "Failed to fetch withdrawal request.", }); }); }); - }); -