diff --git a/src/Model/Currency/Currency.zod.ts b/src/Model/Currency/Currency.zod.ts index 27b46a1..1e99dc5 100644 --- a/src/Model/Currency/Currency.zod.ts +++ b/src/Model/Currency/Currency.zod.ts @@ -12,5 +12,5 @@ export const currencyInterfaceSchema = z.object({ sanctioned: z.boolean(), displayCode: z.string().optional(), chain: z.string().optional(), - maxSupply: z.string().optional(), + maxSupply: z.string().optional() }); diff --git a/src/Model/Invoice/Invoice.ts b/src/Model/Invoice/Invoice.ts index 16bf670..8576a39 100644 --- a/src/Model/Invoice/Invoice.ts +++ b/src/Model/Invoice/Invoice.ts @@ -8,6 +8,7 @@ import { InvoiceUniversalCodes } from './InvoiceUniversalCodes'; import { BitPayExceptionProvider } from '../../Exceptions/BitPayExceptionProvider'; import { MinerFeesItem } from './MinerFeesItem'; import { SupportedTransactionCurrency } from './SupportedTransactionCurrency'; +import { InvoiceRefundAddresses } from './InvoiceRefundAddresses'; export interface InvoiceInterface { // API fields @@ -53,7 +54,7 @@ export interface InvoiceInterface { exceptionStatus?: boolean | string; targetConfirmations?: number; transactions?: InvoiceTransaction[]; - refundAddresses?: unknown; + refundAddresses?: Array<{ [key: string]: InvoiceRefundAddresses }>; refundAddressRequestPending?: boolean; buyerProvidedEmail?: string; buyerProvidedInfo?: InvoiceBuyerProvidedInfo; @@ -129,7 +130,7 @@ export class Invoice implements InvoiceInterface { exceptionStatus?: boolean | string; targetConfirmations?: number; transactions?: InvoiceTransaction[]; - refundAddresses?: unknown; + refundAddresses?: Array<{ [key: string]: InvoiceRefundAddresses }>; refundAddressRequestPending?: boolean; buyerProvidedEmail?: string; buyerProvidedInfo?: InvoiceBuyerProvidedInfo; diff --git a/src/Model/Invoice/Invoice.zod.ts b/src/Model/Invoice/Invoice.zod.ts index f0577c8..9584caf 100644 --- a/src/Model/Invoice/Invoice.zod.ts +++ b/src/Model/Invoice/Invoice.zod.ts @@ -7,6 +7,7 @@ import { refundInfoSchema } from './RefundInfo.zod'; import { shopperSchema } from './Shopper.zod'; import { minerFeesItemSchema } from './MinerFeesItem.zod'; import { supportedTransactionCurrencySchema } from './SupportedTransactionCurrency.zod'; +import { invoiceRefundAddressesSchema } from './InvoiceRefundAddresses.zod'; export const invoiceSchema = z.object({ buyer: buyerInterfaceSchema.optional(), @@ -47,7 +48,7 @@ export const invoiceSchema = z.object({ currentTime: z.number().optional(), exceptionStatus: z.union([z.boolean(), z.string()]).optional(), targetConfirmations: z.number().optional(), - refundAddresses: z.unknown().optional(), + refundAddresses: z.array(z.record(z.string(), invoiceRefundAddressesSchema)).optional(), refundAddressRequestPending: z.boolean().optional(), buyerProvidedEmail: z.string().optional(), billId: z.string().optional(), diff --git a/src/Model/Invoice/InvoiceRefundAddresses.ts b/src/Model/Invoice/InvoiceRefundAddresses.ts new file mode 100644 index 0000000..3f216fb --- /dev/null +++ b/src/Model/Invoice/InvoiceRefundAddresses.ts @@ -0,0 +1,6 @@ +export interface InvoiceRefundAddresses { + type: string; + date: string; + tag?: number; + email?: string; +} diff --git a/src/Model/Invoice/InvoiceRefundAddresses.zod.ts b/src/Model/Invoice/InvoiceRefundAddresses.zod.ts new file mode 100644 index 0000000..2056a73 --- /dev/null +++ b/src/Model/Invoice/InvoiceRefundAddresses.zod.ts @@ -0,0 +1,8 @@ +import { z } from 'zod'; + +export const invoiceRefundAddressesSchema = z.object({ + type: z.string(), + date: z.string(), + tag: z.number().optional().nullable(), + email: z.string().optional().nullable() +}); diff --git a/src/Model/Invoice/InvoiceTransaction.ts b/src/Model/Invoice/InvoiceTransaction.ts index cf7027f..6ae4359 100644 --- a/src/Model/Invoice/InvoiceTransaction.ts +++ b/src/Model/Invoice/InvoiceTransaction.ts @@ -4,4 +4,6 @@ export interface InvoiceTransaction { time?: string; receivedTime?: string; txid?: string; + exRates?: Record; + outputIndex?: number; } diff --git a/src/Model/Invoice/InvoiceTransaction.zod.ts b/src/Model/Invoice/InvoiceTransaction.zod.ts index 25d3331..166d5f9 100644 --- a/src/Model/Invoice/InvoiceTransaction.zod.ts +++ b/src/Model/Invoice/InvoiceTransaction.zod.ts @@ -5,5 +5,7 @@ export const invoiceTransactionSchema = z.object({ confirmations: z.number().optional(), time: z.string().optional(), receivedTime: z.string().optional(), - txid: z.string().optional() + txid: z.string().optional(), + exRates: z.record(z.string(), z.number()).optional(), + outputIndex: z.number().optional() }); diff --git a/src/Model/Payout/PayoutTransaction.ts b/src/Model/Payout/PayoutTransaction.ts index 53c3829..1f89491 100644 --- a/src/Model/Payout/PayoutTransaction.ts +++ b/src/Model/Payout/PayoutTransaction.ts @@ -2,12 +2,14 @@ export interface PayoutTransactionInterface { txid: string; amount: number; date: string; + confirmations?: number; } export class PayoutTransaction implements PayoutTransactionInterface { txid: string; amount: number; date: string; + confirmations?: number; public constructor() {} } diff --git a/src/Model/Payout/PayoutTransaction.zod.ts b/src/Model/Payout/PayoutTransaction.zod.ts index 87cdf18..b3d0963 100644 --- a/src/Model/Payout/PayoutTransaction.zod.ts +++ b/src/Model/Payout/PayoutTransaction.zod.ts @@ -3,5 +3,6 @@ import { z } from 'zod'; export const payoutTransactionInterfaceSchema = z.object({ txid: z.string(), amount: z.number(), - date: z.string() + date: z.string(), + confirmations: z.number().optional() }); diff --git a/src/Model/Webhook/InvoiceBuyerFields.zod.ts b/src/Model/Webhook/InvoiceBuyerFields.zod.ts new file mode 100644 index 0000000..549fa11 --- /dev/null +++ b/src/Model/Webhook/InvoiceBuyerFields.zod.ts @@ -0,0 +1,14 @@ +import { z } from 'zod'; + +export const invoiceWebhookBuyerFieldsInterfaceSchema = z.object({ + buyerName: z.string().optional(), + buyerAddress1: z.string().optional(), + buyerAddress2: z.string().optional(), + buyerCity: z.string().optional(), + buyerState: z.string().optional(), + buyerZip: z.string().optional(), + buyerCountry: z.string().optional(), + buyerPhone: z.string().optional(), + buyerNotify: z.boolean().optional(), + buyerEmail: z.string().optional() +}); diff --git a/src/Model/Webhook/InvoiceWebhook.ts b/src/Model/Webhook/InvoiceWebhook.ts new file mode 100644 index 0000000..d57d54d --- /dev/null +++ b/src/Model/Webhook/InvoiceWebhook.ts @@ -0,0 +1,22 @@ +import { InvoiceWebhookBuyerFieldsInterface } from './InvoiceWebhookBuyerFields'; + +export interface InvoiceWebhook { + id?: string; + url?: string; + posData?: string; + status?: string; + price?: string; + currency?: string; + invoiceTime?: string; + currencyTime?: string; + exceptionStatus?: string; + buyerFields?: InvoiceWebhookBuyerFieldsInterface; + paymentSubtotals?: Record; + paymentTotals?: Record; + exchangeRates?: Record>; + amountPaid?: number; + orderId?: string; + transactionCurrency?: string; + inInvoiceId?: string; + inPaymentRequest?: string; +} diff --git a/src/Model/Webhook/InvoiceWebhook.zod.ts b/src/Model/Webhook/InvoiceWebhook.zod.ts new file mode 100644 index 0000000..75ca64b --- /dev/null +++ b/src/Model/Webhook/InvoiceWebhook.zod.ts @@ -0,0 +1,23 @@ +import { z } from 'zod'; +import { invoiceWebhookBuyerFieldsInterfaceSchema } from './InvoiceBuyerFields.zod'; + +export const invoiceWebhookSchema = z.object({ + id: z.string().optional(), + url: z.string().optional(), + posData: z.string().optional(), + status: z.string().optional(), + price: z.string().optional(), + currency: z.string().optional(), + invoiceTime: z.string().optional(), + currencyTime: z.string().optional(), + exceptionStatus: z.string().optional(), + buyerFields: invoiceWebhookBuyerFieldsInterfaceSchema.optional(), + paymentSubtotals: z.record(z.number()).nullable(), + paymentTotals: z.record(z.number()).nullable(), + exchangeRates: z.record(z.record(z.number())).nullable(), + amountPaid: z.number().optional(), + orderId: z.string().optional(), + transactionCurrency: z.string().optional(), + inInvoiceId: z.string().optional(), + inPaymentRequest: z.string().optional() +}); diff --git a/src/Model/Webhook/InvoiceWebhookBuyerFields.ts b/src/Model/Webhook/InvoiceWebhookBuyerFields.ts new file mode 100644 index 0000000..f8b5601 --- /dev/null +++ b/src/Model/Webhook/InvoiceWebhookBuyerFields.ts @@ -0,0 +1,12 @@ +export interface InvoiceWebhookBuyerFieldsInterface { + buyerName?: string; + buyerAddress1?: string; + buyerAddress2?: string; + buyerCity?: string; + buyerState?: string; + buyerZip?: string; + buyerCountry?: string; + buyerPhone?: string; + buyerNotify?: boolean; + buyerEmail?: string; +} diff --git a/src/Model/Webhook/PayoutWebhook.ts b/src/Model/Webhook/PayoutWebhook.ts new file mode 100644 index 0000000..eccb9d7 --- /dev/null +++ b/src/Model/Webhook/PayoutWebhook.ts @@ -0,0 +1,23 @@ +import { PayoutTransaction } from '../Payout/PayoutTransaction'; + +export interface PayoutWebhookInterface { + id?: string; + recipientId?: string; + shopperId?: string; + price?: number; + currency?: string; + ledgerCurrency?: string; + exchangeRates?: Record>; + email?: string; + reference?: string; + label?: string; + notificationUrl?: string; + notificationEmail?: string; + effectiveDate?: string; + requestDate?: string; + status?: string; + transactions?: PayoutTransaction[]; + accountId?: string; + date?: string; + groupId?: string; +} diff --git a/src/Model/Webhook/PayoutWebhook.zod.ts b/src/Model/Webhook/PayoutWebhook.zod.ts new file mode 100644 index 0000000..d95c37a --- /dev/null +++ b/src/Model/Webhook/PayoutWebhook.zod.ts @@ -0,0 +1,24 @@ +import { z } from 'zod'; +import { payoutTransactionInterfaceSchema } from '../Payout/PayoutTransaction.zod'; + +export const payoutWebhookSchema = z.object({ + id: z.string().optional(), + recipientId: z.string().optional(), + shopperId: z.string().optional(), + price: z.number().optional(), + currency: z.string().optional(), + ledgerCurrency: z.string().optional(), + exchangeRates: z.record(z.record(z.number())).optional(), + email: z.string().optional(), + reference: z.string().optional(), + label: z.string().optional(), + notificationUrl: z.string().optional(), + notificationEmail: z.string().optional(), + effectiveDate: z.string().optional(), + requestDate: z.string().optional(), + status: z.string().optional(), + transactions: z.array(payoutTransactionInterfaceSchema).optional(), + accountId: z.string().optional(), + date: z.string().optional(), + groupId: z.string().optional() +}); diff --git a/src/Model/Webhook/RefundWebhook.ts b/src/Model/Webhook/RefundWebhook.ts new file mode 100644 index 0000000..60ca87c --- /dev/null +++ b/src/Model/Webhook/RefundWebhook.ts @@ -0,0 +1,21 @@ +export interface RefundWebhook { + amount?: number; + buyerPaysRefundFee?: boolean; + currency?: string; + id?: string; + immediate?: boolean; + invoice?: string; + lastRefundNotification?: string; + refundFee?: number; + requestDate?: string; + status?: string; + supportRequest?: string; + reference?: string; + guid?: string; + refundAddress?: string; + type?: string; + txid?: string; + transactionCurrency?: string; + transactionAmount?: number; + transactionRefundFee?: number; +} diff --git a/src/Model/Webhook/RefundWebhook.zod.ts b/src/Model/Webhook/RefundWebhook.zod.ts new file mode 100644 index 0000000..37f824b --- /dev/null +++ b/src/Model/Webhook/RefundWebhook.zod.ts @@ -0,0 +1,23 @@ +import { z } from 'zod'; + +export const refundWebhookSchema = z.object({ + amount: z.number().nullable(), + buyerPaysRefundFee: z.boolean().nullable(), + currency: z.string().nullable(), + id: z.string().nullable(), + immediate: z.boolean().nullable(), + invoice: z.string().nullable(), + lastRefundNotification: z.string().nullable(), + refundFee: z.number().nullable(), + requestDate: z.string().nullable(), + status: z.string().nullable(), + supportRequest: z.string().nullable(), + reference: z.string().nullable(), + guid: z.string().nullable(), + refundAddress: z.string().nullable(), + type: z.string().nullable(), + txid: z.string().nullable(), + transactionCurrency: z.string().nullable(), + transactionAmount: z.number().nullable(), + transactionRefundFee: z.number().nullable() +}); diff --git a/test/clientUnit.spec.ts b/test/clientUnit.spec.ts index 743aa72..eeb6a8a 100644 --- a/test/clientUnit.spec.ts +++ b/test/clientUnit.spec.ts @@ -525,6 +525,7 @@ describe('BitPaySDK.Client', () => { expect(result.url).toBe('https://bitpay.com/invoice?id=G3viJEJgE8Jk2oekSdgT2A'); expect(result.buyerProvidedInfo.emailAddress).toBe('john@doe.com'); expect(result.universalCodes.paymentString).toBe('https://link.bitpay.com/i/G3viJEJgE8Jk2oekSdgT2A'); + expect(result.refundAddresses[0].n2MDYgEhxCAnuoVd1JpPmvxZShE6rQA6zv.type).toBe('buyerSupplied'); }); it('should get invoice', async () => { diff --git a/test/json/createInvoiceResponse.json b/test/json/createInvoiceResponse.json index febdeb8..adbd1e0 100644 --- a/test/json/createInvoiceResponse.json +++ b/test/json/createInvoiceResponse.json @@ -26,7 +26,15 @@ "redirectURL": "https://merchantwebsite.com/shop/return", "autoRedirect": false, "closeURL": "https://merchantwebsite.com/shop/cancel", - "refundAddresses": [], + "refundAddresses": [ + { + "n2MDYgEhxCAnuoVd1JpPmvxZShE6rQA6zv": { + "type": "buyerSupplied", + "date": "2024-01-08T23:50:56.556Z", + "email": "email@email.com" + } + } + ], "refundAddressRequestPending": false, "buyerProvidedEmail": "john@doe.com", "buyerProvidedInfo": {