From 593358f8b1f4c473ca70c747b03b9306b4cb664f Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Thu, 14 Aug 2025 20:30:24 -0500 Subject: [PATCH 01/16] sdk v3 --- package-lock.json | 4 +- package.json | 2 +- src/configuration.ts | 3 + src/index.ts | 6 +- src/method.ts | 3 + src/resource.ts | 2 +- src/resources/Account/Attributes.ts | 3 + src/resources/Account/Balances.ts | 3 + src/resources/Account/CardBrands.ts | 3 + src/resources/Account/PaymentInstruments.ts | 3 + src/resources/Account/Payoffs.ts | 3 + src/resources/Account/Products.ts | 14 +- src/resources/Account/Sensitive.ts | 3 + src/resources/Account/Subscriptions.ts | 6 +- src/resources/Account/Transactions.ts | 2 + src/resources/Account/Updates.ts | 3 + src/resources/Account/VerificationSessions.ts | 6 +- src/resources/Account/index.ts | 4 +- src/resources/Account/types.ts | 28 +- src/resources/CardProduct/index.ts | 46 +++ src/resources/Element/Token.ts | 2 + src/resources/Entity/Attributes.ts | 3 + src/resources/Entity/Connect.ts | 3 + src/resources/Entity/CreditScores.ts | 3 + src/resources/Entity/Identities.ts | 3 + src/resources/Entity/Products.ts | 14 +- src/resources/Entity/Subscriptions.ts | 4 + src/resources/Entity/Vehicles.ts | 5 +- src/resources/Entity/VerificationSessions.ts | 4 + src/resources/Entity/index.ts | 2 +- src/resources/Entity/types.ts | 5 +- src/resources/Event/index.ts | 2 +- src/resources/Merchant/index.ts | 4 +- src/resources/Payment/Reversals.ts | 2 +- src/resources/Payment/index.ts | 6 +- src/resources/Report/index.ts | 5 +- .../Simulate/Accounts/Transactions.ts | 1 + .../Simulate/Entities/CreditScores.ts | 1 + src/resources/Simulate/Events.ts | 1 + src/resources/Simulate/Payments.ts | 1 + src/resources/Webhook/index.ts | 6 +- test/config.ts | 2 + test/resources/Account.tests.ts | 259 +++++--------- test/resources/CardProduct.tests.ts | 43 +++ test/resources/Entity.tests.ts | 325 ++++++++++++------ test/resources/Event.tests.ts | 7 +- 46 files changed, 506 insertions(+), 354 deletions(-) create mode 100644 src/resources/CardProduct/index.ts create mode 100644 test/resources/CardProduct.tests.ts diff --git a/package-lock.json b/package-lock.json index 4537d32..2a46423 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "method-node", - "version": "1.2.5", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "method-node", - "version": "1.2.4", + "version": "2.0.0", "license": "ISC", "dependencies": { "axios": "^1.7.4", diff --git a/package.json b/package.json index 94a861b..cee8b8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "method-node", - "version": "1.2.5", + "version": "2.0.0", "description": "Node.js library for the Method API", "main": "dist/index.ts", "module": "dist/index.mjs", diff --git a/src/configuration.ts b/src/configuration.ts index e130694..14804b5 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -59,6 +59,7 @@ export type IAxiosRetryConfig = { export interface IConfigurationOpts { apiKey: string; env: TEnvironments; + prefer?: string | null; httpsAgent?: any; onRequest?: TOnRequest; onResponse?: TOnResponse; @@ -68,6 +69,7 @@ export interface IConfigurationOpts { export default class Configuration { baseURL: string; apiKey: string; + prefer?: string | null; httpsAgent?: any; onResponse: TOnResponse | null; onRequest: TOnRequest | null; @@ -78,6 +80,7 @@ export default class Configuration { this.baseURL = `https://${opts.env}.methodfi.com`; this.apiKey = opts.apiKey; + this.prefer = opts.prefer || null; this.httpsAgent = opts.httpsAgent || null; this.onRequest = opts.onRequest || null; this.onResponse = opts.onResponse || null; diff --git a/src/index.ts b/src/index.ts index efa4ff1..ddaaa56 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,9 +3,13 @@ export { Method as MethodClient } from './method'; export * from './errors'; export * from './configuration'; export { - ResourceStatus, type TResourceStatus, type IResourceListOpts, type IResourceError, + ResourceStatus, + type TResourceStatus, + type IResourceListOpts, + type IResourceError, } from './resource'; export * from './resources/Account'; +export * from './resources/CardProduct'; export * from './resources/Element'; export * from './resources/Entity'; export * from './resources/Event'; diff --git a/src/method.ts b/src/method.ts index 5aec167..659115d 100644 --- a/src/method.ts +++ b/src/method.ts @@ -1,5 +1,6 @@ import Configuration, { IConfigurationOpts, IResponse } from './configuration'; import Account from './resources/Account'; +import CardProduct from './resources/CardProduct'; import Element from './resources/Element'; import Entity from './resources/Entity'; import Event from './resources/Event'; @@ -12,6 +13,7 @@ import Simulate from './resources/Simulate'; export class Method { accounts: Account; + cardProducts: CardProduct; elements: Element; events: Event; entities: Entity; @@ -27,6 +29,7 @@ export class Method { // Resources this.accounts = new Account(config); + this.cardProducts = new CardProduct(config); this.elements = new Element(config); this.events = new Event(config); this.entities = new Entity(config); diff --git a/src/resource.ts b/src/resource.ts index d32b303..a87465f 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -43,7 +43,7 @@ export default class Resource extends ExtensibleFunction { headers: { Authorization: `Bearer ${config.apiKey}`, 'User-Agent': this.getDefaultUserAgent(), - 'method-version': '2024-04-04', + 'method-version': '2025-07-04', }, httpsAgent: config.httpsAgent, }); diff --git a/src/resources/Account/Attributes.ts b/src/resources/Account/Attributes.ts index f99d1f5..1e69cab 100644 --- a/src/resources/Account/Attributes.ts +++ b/src/resources/Account/Attributes.ts @@ -9,6 +9,7 @@ export default class AccountAttributes extends Resource { /** * Retrieves an Attributes record for an Account. + * https://docs.methodfi.com/reference/accounts/attributes/retrieve * * @param acc_attr_id ID of the Attribute * @returns Returns an Account’s Attribute object. @@ -20,6 +21,7 @@ export default class AccountAttributes extends Resource { /** * Retrieves a list of Attributes objects for an account. + * https://docs.methodfi.com/reference/accounts/attributes/list * * @returns Returns a list of Attributes objects. */ @@ -30,6 +32,7 @@ export default class AccountAttributes extends Resource { /** * Creates a new Attributes request to retrieve the Account’s attributes. + * https://docs.methodfi.com/reference/accounts/attributes/create * * @returns Returns an Account’s Attributes object. */ diff --git a/src/resources/Account/Balances.ts b/src/resources/Account/Balances.ts index 35e8142..2e4e14d 100644 --- a/src/resources/Account/Balances.ts +++ b/src/resources/Account/Balances.ts @@ -9,6 +9,7 @@ export default class AccountBalances extends Resource { /** * Retrieve a Balance record for an Account. + * https://docs.methodfi.com/reference/accounts/balances/retrieve * * @param bal_id ID of the balance * @returns Returns a Balance object. @@ -20,6 +21,7 @@ export default class AccountBalances extends Resource { /** * Retrieves a list of Balance objects for an account. + * https://docs.methodfi.com/reference/accounts/balances/list * * @returns Returns a list of Balances. */ @@ -30,6 +32,7 @@ export default class AccountBalances extends Resource { /** * Creates a new Balance request to retrieve the Account’s balance from the financial institution. + * https://docs.methodfi.com/reference/accounts/balances/create * * @returns Returns a Balance object. */ diff --git a/src/resources/Account/CardBrands.ts b/src/resources/Account/CardBrands.ts index 350c206..b852f77 100644 --- a/src/resources/Account/CardBrands.ts +++ b/src/resources/Account/CardBrands.ts @@ -9,6 +9,7 @@ export default class AccountCardBrand extends Resource { /** * Retrieves a Card Brand object. + * https://docs.methodfi.com/reference/accounts/card-brands/retrieve * * @param cbrd_id ID of the Card * @returns Returns a Card object. @@ -20,6 +21,7 @@ export default class AccountCardBrand extends Resource { /** * Retrieves a list of CardBrand objects for an account. + * https://docs.methodfi.com/reference/accounts/card-brands/list * * @returns Returns a list of CardBrand objects. */ @@ -30,6 +32,7 @@ export default class AccountCardBrand extends Resource { /** * Creates a new CardBrand request to retrieve the Account’s card brand. + * https://docs.methodfi.com/reference/accounts/card-brands/create * * @returns Returns a Card object. */ diff --git a/src/resources/Account/PaymentInstruments.ts b/src/resources/Account/PaymentInstruments.ts index 67ec579..27c8ef0 100644 --- a/src/resources/Account/PaymentInstruments.ts +++ b/src/resources/Account/PaymentInstruments.ts @@ -9,6 +9,7 @@ export default class AccountPaymentInstruments extends Resource { /** * Retrieves a Payment Instrument record for an Account. + * https://docs.methodfi.com/reference/accounts/payment-instruments/retrieve * * @param pmt_inst_id ID of the Payment Instrument * @returns Returns an Account’s Payment Instrument object. @@ -20,6 +21,7 @@ export default class AccountPaymentInstruments extends Resource { /** * Retrieves a list of Payment Instrument objects for an account. + * https://docs.methodfi.com/reference/accounts/payment-instruments/list * * @returns Returns a list of Payment Instrument objects. */ @@ -30,6 +32,7 @@ export default class AccountPaymentInstruments extends Resource { /** * Creates a new Payment Instrument request to retrieve the Account’s payment instruments. + * https://docs.methodfi.com/reference/accounts/payment-instruments/create * * @returns Returns an Account’s Payment Instrument object. */ diff --git a/src/resources/Account/Payoffs.ts b/src/resources/Account/Payoffs.ts index 1b563c4..cb0da03 100644 --- a/src/resources/Account/Payoffs.ts +++ b/src/resources/Account/Payoffs.ts @@ -9,6 +9,7 @@ export default class AccountPayoffs extends Resource { /** * Retrieve a Payoff record for an Account. + * https://docs.methodfi.com/reference/accounts/payoffs/retrieve * * @param pyf_id ID of the payoff * @returns Returns a Payoff object. @@ -20,6 +21,7 @@ export default class AccountPayoffs extends Resource { /** * Retrieves a list of Payoff requests for a specific account. + * https://docs.methodfi.com/reference/accounts/payoffs/list * * @returns Returns a list of Payoffs. */ @@ -30,6 +32,7 @@ export default class AccountPayoffs extends Resource { /** * Creates a new Payoff request to retrieve a payoff quote from the Account’s financial institution / lender. + * https://docs.methodfi.com/reference/accounts/payoffs/create * * @returns Returns a Payoff object. */ diff --git a/src/resources/Account/Products.ts b/src/resources/Account/Products.ts index 38a3c43..294e9a1 100644 --- a/src/resources/Account/Products.ts +++ b/src/resources/Account/Products.ts @@ -1,25 +1,15 @@ import Resource from '../../resource'; import Configuration, { IResponse } from '../../configuration'; -import type { IAccountProduct, IAccountProductListResponse } from './types'; +import type { IAccountProductListResponse } from './types'; export default class AccountProducts extends Resource { constructor(config: Configuration) { super(config.addPath('products')); } - /** - * Retrieve an account's product. - * - * @param prd_id ID of the product. - * @returns Returns a Product object. - */ - - async retrieve(prd_id: string) { - return super._getWithId>(prd_id); - } - /** * Retrieve an account's product list. + * https://docs.methodfi.com/reference/accounts/products/list * * @returns Returns a map of Product names to Product objects for an Account. */ diff --git a/src/resources/Account/Sensitive.ts b/src/resources/Account/Sensitive.ts index abf8242..bbb9aa6 100644 --- a/src/resources/Account/Sensitive.ts +++ b/src/resources/Account/Sensitive.ts @@ -9,6 +9,7 @@ export default class AccountSensitive extends Resource { /** * Retrieve a Sensitive record for an Account. + * https://docs.methodfi.com/reference/accounts/sensitive/retrieve * * @param astv_id ID of the Sensitive object * @returns A Sensitive object @@ -20,6 +21,7 @@ export default class AccountSensitive extends Resource { /** * Retrieves a list of Sensitive objects for an account. + * https://docs.methodfi.com/reference/accounts/sensitive/list * * @returns Returns a list of Sensitive objects. */ @@ -30,6 +32,7 @@ export default class AccountSensitive extends Resource { /** * Creates a new Sensitive request to retrieve sensitive Account information. + * https://docs.methodfi.com/reference/accounts/sensitive/create * * @param data Sensitive fields to expand in the response. * @returns A Sensitive object diff --git a/src/resources/Account/Subscriptions.ts b/src/resources/Account/Subscriptions.ts index b9bea0e..84e14ed 100644 --- a/src/resources/Account/Subscriptions.ts +++ b/src/resources/Account/Subscriptions.ts @@ -14,6 +14,7 @@ export default class AccountSubscriptions extends Resource { /** * Retrieves a Subscription record for an Account. + * https://docs.methodfi.com/reference/accounts/subscriptions/retrieve * * @param sub_id ID of the Subscription * @returns IAccountSubscription @@ -25,6 +26,7 @@ export default class AccountSubscriptions extends Resource { /** * Returns a map of Subscriptions names to Subscription objects associated with an Account, or an empty array if none have been created. + * https://docs.methodfi.com/reference/accounts/subscriptions/list * * @returns Returns a map of Subscription names to Subscription objects. */ @@ -35,10 +37,11 @@ export default class AccountSubscriptions extends Resource { /** * Enrolls an Account to a Subscription. Once enrolled, the Subscription name and details will be present on the response object. + * https://docs.methodfi.com/reference/accounts/subscriptions/create * * Note: Subscription requests are processed individually, meaning the success or failure of one subscription does not affect others. The response object will detail any errors encountered. * - * @param data IAccountSubscriptionCreateOpts: https://docs-v2.methodfi.com/reference/accounts/subscriptions/create + * @param data IAccountSubscriptionCreateOpts * @returns Returns a map of Subscription name to Subscription object. */ @@ -50,6 +53,7 @@ export default class AccountSubscriptions extends Resource { /** * Deleting a Subscription means to unsubscribe or unenroll an Account from automatically receiving new Product resources. + * https://docs.methodfi.com/reference/accounts/subscriptions/delete * * @param sub_id ID of the Subscription * @returns Returns a Subscription object. diff --git a/src/resources/Account/Transactions.ts b/src/resources/Account/Transactions.ts index e6a480d..9885054 100644 --- a/src/resources/Account/Transactions.ts +++ b/src/resources/Account/Transactions.ts @@ -9,6 +9,7 @@ export default class AccountTransactions extends Resource { /** * Retrieve a Transaction object for an Account. + * https://docs.methodfi.com/reference/accounts/transactions/retrieve * * @param txn_id ID of the transaction * @returns Returns a Transaction object. @@ -20,6 +21,7 @@ export default class AccountTransactions extends Resource { /** * Retrieve a list of Transactions objects for a specific Account. + * https://docs.methodfi.com/reference/accounts/transactions/list * * @returns Returns a list of transactions for the account. */ diff --git a/src/resources/Account/Updates.ts b/src/resources/Account/Updates.ts index c682eac..fdac516 100644 --- a/src/resources/Account/Updates.ts +++ b/src/resources/Account/Updates.ts @@ -9,6 +9,7 @@ export default class AccountUpdates extends Resource { /** * Retrieve an Update object by its ID. + * https://docs.methodfi.com/reference/accounts/updates/retrieve * * @param upt_id ID of the Update * @returns Returns an Update object. @@ -20,6 +21,7 @@ export default class AccountUpdates extends Resource { /** * Retrieve a list of Updates for a specific Account. + * https://docs.methodfi.com/reference/accounts/updates/list * * @returns Returns a list of Updates. */ @@ -30,6 +32,7 @@ export default class AccountUpdates extends Resource { /** * Creates a new Update for a liability Account. + * https://docs.methodfi.com/reference/accounts/updates/create * * @returns Returns an Update object. */ diff --git a/src/resources/Account/VerificationSessions.ts b/src/resources/Account/VerificationSessions.ts index e8b04d9..42e316e 100644 --- a/src/resources/Account/VerificationSessions.ts +++ b/src/resources/Account/VerificationSessions.ts @@ -13,6 +13,7 @@ export default class AccountVerificationSession extends Resource { /** * Retrieve an AccountVerificationSession object by its ID. + * https://docs.methodfi.com/reference/accounts/verification-sessions/retrieve * * @param avf_id ID of the AccountVerificationSession object. * @returns AccountVerificationSession object. @@ -24,6 +25,7 @@ export default class AccountVerificationSession extends Resource { /** * Retrieves a list of AccountVerificationSession objects for an account. + * https://docs.methodfi.com/reference/accounts/verification-sessions/list * * @returns Returns a list of AccountVerificationSession objects. */ @@ -34,6 +36,7 @@ export default class AccountVerificationSession extends Resource { /** * Creates an AccountVerificationSession of the provided type. + * https://docs.methodfi.com/reference/accounts/verification-sessions/create * * @param data IAccountVerificationSessionCreateOpts: { type: TAccountVerificaionSessionTypes } * @returns AccountVerificationSession object. @@ -42,9 +45,10 @@ export default class AccountVerificationSession extends Resource { async create(data: IAccountVerificationSessionCreateOpts) { return super._create, IAccountVerificationSessionCreateOpts>(data); } - // TODO: Add URL of docs page for this method. + /** * Updates an existing AccountVerificationSession object + * https://docs.methodfi.com/reference/accounts/verification-sessions/overview * * @param avf_id ID of the AccountVerificationSession object. * @param data Update data for the AccountVerificationSession object based on it's type. diff --git a/src/resources/Account/index.ts b/src/resources/Account/index.ts index da13925..d3dc1bd 100644 --- a/src/resources/Account/index.ts +++ b/src/resources/Account/index.ts @@ -79,7 +79,7 @@ export class Account extends Resource { /** * Returns a list of Accounts. * - * @param opts IAccountListOpts: https://docs.methodfi.com/api/core/accounts/list + * @param opts IAccountListOpts: https://docs.methodfi.com/reference/accounts/list * @returns Returns a list of Accounts. */ @@ -94,7 +94,7 @@ export class Account extends Resource { /** * Creates a new Account for an Entity, either ach or liability, based on the parameters provided. An account is a unique representation of an ACH or Liability account. * - * @param data Create options: https://docs.methodfi.com/api/core/accounts/create + * @param data Create options: https://docs.methodfi.com/reference/accounts/create * @param requestConfig Allows for idempotency: { idempotency_key?: string } * @returns Returns an Account object. */ diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index 9cc3024..0dee602 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -50,11 +50,11 @@ export const AccountProductStatuses = { export type TAccountProductStatuses = keyof typeof AccountProductStatuses; export interface IAccountProduct { - id: string; name: string; status: TAccountProductStatuses; status_error: IResourceError | null; latest_request_id: string | null; + latest_successful_request_id: string | null; is_subscribable: boolean; created_at: string; updated_at: string; @@ -298,27 +298,27 @@ export interface IAccountBalance { updated_at: string; }; -export interface IAccountCardBrandInfo { - id: string; - art_id?: string; - url: string; - name: string; -}; - export interface IAccountCardBrand { id: string; account_id: string; - network: string | null; - issuer: string | null; - last4: string | null; brands: IAccountCardBrandInfo[]; - status: 'in_progress' | 'completed' | 'failed'; - shared: boolean; source: 'method' | 'network' | null; + status: 'completed' | 'in_progress' | 'failed'; error: IResourceError | null; created_at: string; updated_at: string; -}; +} + +export interface IAccountCardBrandInfo { + id: string; + card_product_id: string; + description: string; + name: string; + issuer: string; + network: string; + type: 'specific' | 'generic' | 'in_review'; + url: string; +} export interface IAccountPayoff { id: string, diff --git a/src/resources/CardProduct/index.ts b/src/resources/CardProduct/index.ts new file mode 100644 index 0000000..0a0f605 --- /dev/null +++ b/src/resources/CardProduct/index.ts @@ -0,0 +1,46 @@ +import Resource from '../../resource'; +import Configuration, { IResponse } from '../../configuration'; +import { IResourceError } from '../../resource'; + +export const CardProductTypes = { + specific: 'specific', + generic: 'generic', + in_review: 'in_review', +} as const; + +export type TCardProductTypes = keyof typeof CardProductTypes; + +export interface ICardProductBrand { + id: string; + description: string; + network: string; + default_image: string; +} + +export interface ICardProduct { + id: string; + name: string; + issuer: string; + type: TCardProductTypes; + brands: ICardProductBrand[]; + error: IResourceError | null; + created_at: string; + updated_at: string; +} + +export default class CardProduct extends Resource { + constructor(config: Configuration) { + super(config.addPath('card_product')); + } + + /** + * Retrieves a card product by id + * https://docs.methodfi.com/reference/card-products/retrieve + * + * @param pdt_id Method card product id + * @returns ICardProduct + */ + async retrieve(pdt_id: string) { + return super._getWithId>(pdt_id); + } +} diff --git a/src/resources/Element/Token.ts b/src/resources/Element/Token.ts index a76d784..1a50b4a 100644 --- a/src/resources/Element/Token.ts +++ b/src/resources/Element/Token.ts @@ -13,6 +13,7 @@ export default class ElementToken extends Resource { /** * Creates token to be used with Element + * https://docs.methodfi.com/reference/elements/tokens * * @param opts IElementTokenCreateOpts * @returns IElement { element_token: string }; @@ -24,6 +25,7 @@ export default class ElementToken extends Resource { /** * Retrieve the results of an Element session. + * https://docs.methodfi.com/reference/elements/results * * @param pk_elem_id ID of the Element token * @returns Returns an ElementResults object. diff --git a/src/resources/Entity/Attributes.ts b/src/resources/Entity/Attributes.ts index 934288c..c814cdd 100644 --- a/src/resources/Entity/Attributes.ts +++ b/src/resources/Entity/Attributes.ts @@ -9,6 +9,7 @@ export default class EntityAttributes extends Resource { /** * Retrieves an Attributes record for an Entity. + * https://docs.methodfi.com/reference/entities/attributes/retrieve * * @param attr_id ID of the Attribute * @returns Returns an Entity’s Attribute object. @@ -20,6 +21,7 @@ export default class EntityAttributes extends Resource { /** * Retrieves a list of Attributes objects for an entity. + * https://docs.methodfi.com/reference/entities/attributes/list * * @returns Returns a list of Attributes objects. */ @@ -30,6 +32,7 @@ export default class EntityAttributes extends Resource { /** * Creates a new Attributes request to retrieve the Entity’s attributes. + * https://docs.methodfi.com/reference/entities/attributes/create * * @returns Returns an Entity’s Attributes object. */ diff --git a/src/resources/Entity/Connect.ts b/src/resources/Entity/Connect.ts index 8d646e5..8398856 100644 --- a/src/resources/Entity/Connect.ts +++ b/src/resources/Entity/Connect.ts @@ -55,6 +55,7 @@ export default class EntityConnect extends Resource { /** * Retrieves a Connect record for an Entity. + * https://docs.methodfi.com/reference/entities/connect/retrieve * * @param cxn_id ID of the entity connection * @returns Returns a Connect object. @@ -66,6 +67,7 @@ export default class EntityConnect extends Resource { /** * Retrieves a list of Connect objects for an entity. + * https://docs.methodfi.com/reference/entities/connect/list * * @returns Returns a list of Connect objects. */ @@ -76,6 +78,7 @@ export default class EntityConnect extends Resource { /** * Creates a new Connect request to connect all liability accounts for the Entity. + * https://docs.methodfi.com/reference/entities/connect/create * * @returns Returns a Connect object. */ diff --git a/src/resources/Entity/CreditScores.ts b/src/resources/Entity/CreditScores.ts index a906a16..c1285a2 100644 --- a/src/resources/Entity/CreditScores.ts +++ b/src/resources/Entity/CreditScores.ts @@ -9,6 +9,7 @@ export default class EntityCreditScores extends Resource { /** * Retrieves a Credit Score record for an Entity. + * https://docs.methodfi.com/reference/entities/credit-scores/retrieve * * @param crs_id ID of the CreditScore * @returns Returns an Entity’s CreditScore object. @@ -20,6 +21,7 @@ export default class EntityCreditScores extends Resource { /** * Retrieves a list of CreditScore objects for an entity. + * https://docs.methodfi.com/reference/entities/credit-scores/list * * @returns Returns a list of CreditScore objects. */ @@ -30,6 +32,7 @@ export default class EntityCreditScores extends Resource { /** * Creates a new Credit Score request to retrieve the Entity’s credit score. + * https://docs.methodfi.com/reference/entities/credit-scores/create * * @returns Returns an Entity’s CreditScore object. */ diff --git a/src/resources/Entity/Identities.ts b/src/resources/Entity/Identities.ts index 770db79..d694c64 100644 --- a/src/resources/Entity/Identities.ts +++ b/src/resources/Entity/Identities.ts @@ -9,6 +9,7 @@ export default class EntityIdentities extends Resource { /** * Retrieves an Identity request with the matched identity for an Entity. + * https://docs.methodfi.com/reference/entities/identities/retrieve * * @param idn_id ID of the identity * @returns Returns an Identity object. @@ -20,6 +21,7 @@ export default class EntityIdentities extends Resource { /** * Retrieves a list of Identity objects for an entity. + * https://docs.methodfi.com/reference/entities/identities/list * * @returns Returns a list of Identity objects. */ @@ -30,6 +32,7 @@ export default class EntityIdentities extends Resource { /** * Creates a new Identity request to retrieve the identity of an Entity, based off the PII that has been passed in to Method so far. + * https://docs.methodfi.com/reference/entities/identities/create * * @returns Returns an Identity object. */ diff --git a/src/resources/Entity/Products.ts b/src/resources/Entity/Products.ts index 13522a7..387779c 100644 --- a/src/resources/Entity/Products.ts +++ b/src/resources/Entity/Products.ts @@ -1,25 +1,15 @@ import Resource from '../../resource'; import Configuration, { IResponse } from '../../configuration'; -import type { IEntityProduct, IEntityProductListResponse } from './types'; +import type { IEntityProductListResponse } from './types'; export default class EntityProducts extends Resource { constructor(config: Configuration) { super(config.addPath('products')); } - /** - * Retrieve an entity's product. - * - * @param prd_id ID of the product. - * @returns Returns a Product object. - */ - - async retrieve(prd_id: string) { - return super._getWithId>(prd_id); - } - /** * Retrieve an entity's product list. + * https://docs.methodfi.com/reference/entities/products/list * * @returns Returns a map of Product names to Product objects for an Entity. */ diff --git a/src/resources/Entity/Subscriptions.ts b/src/resources/Entity/Subscriptions.ts index d98016c..0f6e7b1 100644 --- a/src/resources/Entity/Subscriptions.ts +++ b/src/resources/Entity/Subscriptions.ts @@ -14,6 +14,7 @@ export default class EntitySubscriptions extends Resource { /** * Retrieves a Subscription record for an Entity. + * https://docs.methodfi.com/reference/entities/subscriptions/retrieve * * @param sub_id ID of the subscription * @@ -26,6 +27,7 @@ export default class EntitySubscriptions extends Resource { /** * Returns a map of Subscriptions names to Subscription objects associated with an Entity, or an empty array if none have been created. + * https://docs.methodfi.com/reference/entities/subscriptions/list * * @returns Returns a map of Subscription names to Subscription objects. */ @@ -37,6 +39,7 @@ export default class EntitySubscriptions extends Resource { /** * Enrolls an Entity to a Subscription. Once enrolled, the Subscription name and details will be present on the response object. * Being enrolled in a Subscription is independent of other Subscriptions. An error won’t prevent the Entity from being enrolled in other Subscriptions. + * https://docs.methodfi.com/reference/entities/subscriptions/create * * @param sub_name A Subscription name to enroll the Entity in. enroll: ['connect', 'credit_score'] * @@ -54,6 +57,7 @@ export default class EntitySubscriptions extends Resource { /** * Deleting a Subscription means to unenroll an Entity from automatically receiving new Product resources. + * https://docs.methodfi.com/reference/entities/subscriptions/delete * * @param sub_id ID of the subscription * @returns Returns a Subscription object. diff --git a/src/resources/Entity/Vehicles.ts b/src/resources/Entity/Vehicles.ts index e8ae2a0..03a3df2 100644 --- a/src/resources/Entity/Vehicles.ts +++ b/src/resources/Entity/Vehicles.ts @@ -9,6 +9,7 @@ export default class EntityVehicles extends Resource { /** * Retrieves a Vehicle record for an Entity. + * https://docs.methodfi.com/reference/entities/vehicles/retrieve * * @param evhl_id ID of the Vehicle * @returns Returns an Entity’s Vehicle object. @@ -20,7 +21,8 @@ export default class EntityVehicles extends Resource { /** * Retrieves a list of Vehicle objects for an entity. - * + * https://docs.methodfi.com/reference/entities/vehicles/list + * * @returns Returns a list of Vehicle objects. */ @@ -30,6 +32,7 @@ export default class EntityVehicles extends Resource { /** * Creates a new Vehicle request to retrieve the Entity’s vehicle. + * https://docs.methodfi.com/reference/entities/vehicles/create * * @returns Returns an Entity’s Vehicle object. */ diff --git a/src/resources/Entity/VerificationSessions.ts b/src/resources/Entity/VerificationSessions.ts index c27bb8a..d2a9049 100644 --- a/src/resources/Entity/VerificationSessions.ts +++ b/src/resources/Entity/VerificationSessions.ts @@ -13,6 +13,7 @@ export default class EntityVerificationSession extends Resource { /** * Retrieves a EntityVerificationSession for an entity. + * https://docs.methodfi.com/reference/entities/verification-sessions/retrieve * * @param evf_id ID of the verification session. * @returns Returns an EntityVerificationSession object. @@ -24,6 +25,7 @@ export default class EntityVerificationSession extends Resource { /** * Retrieves a list of VerificationSession objects for an entity. + * https://docs.methodfi.com/reference/entities/verification-sessions/list * * @returns Returns a list of VerificationSession objects. */ @@ -34,6 +36,7 @@ export default class EntityVerificationSession extends Resource { /** * Create a verification session. + * https://docs.methodfi.com/reference/entities/verification-sessions/overview * * @param data IEntityVerificationSessionCreateOpts * @returns Returns an EntityVerificationSession object. @@ -45,6 +48,7 @@ export default class EntityVerificationSession extends Resource { /** * Update a verification session + * https://docs.methodfi.com/reference/entities/verification-sessions/overview * * @param evf_id ID of the verification session. * @param data IEntityVerificationSessionUpdateOpts diff --git a/src/resources/Entity/index.ts b/src/resources/Entity/index.ts index 30f9ca2..5d90bf2 100644 --- a/src/resources/Entity/index.ts +++ b/src/resources/Entity/index.ts @@ -71,7 +71,7 @@ export class Entity extends Resource { /** * Returns all the Entities associated with your team, or an empty array if none have been created. * - * @param opts IEntityListOpts: https://docs.methodfi.com/api/core/entities/list + * @param opts IEntityListOpts: https://docs.methodfi.com/reference/entities/list * @returns Returns a list of Entities. */ diff --git a/src/resources/Entity/types.ts b/src/resources/Entity/types.ts index e2881d0..e8e7151 100644 --- a/src/resources/Entity/types.ts +++ b/src/resources/Entity/types.ts @@ -3,6 +3,7 @@ import type { TResourceStatus, IResourceListOpts, } from '../../resource'; +import { TAccountProducts, TAccountSubscriptionTypes } from '../Account'; export const CreditReportBureaus = { experian: 'experian', @@ -119,6 +120,8 @@ export interface IEntityConnect { entity_id: string; status: TResourceStatus; accounts: string[] | null; + requested_products: TAccountProducts[]; + requested_subscriptions: TAccountSubscriptionTypes[]; error: IResourceError | null; created_at: string; updated_at: string; @@ -259,11 +262,11 @@ export const EntityProductType = { export type TEntityProductType = keyof typeof EntityProductType; export interface IEntityProduct { - id: string; name: string; status: TEntityProductTypeStatuses; status_error: IResourceError | null; latest_request_id: string | null; + latest_successful_request_id: string | null; is_subscribable: boolean; created_at: string; updated_at: string; diff --git a/src/resources/Event/index.ts b/src/resources/Event/index.ts index 74e6a9e..5409362 100644 --- a/src/resources/Event/index.ts +++ b/src/resources/Event/index.ts @@ -32,7 +32,7 @@ export default class Event extends Resource { /** * Lists all events, optionally filtered by resource_id * - * @param opts IEventListOpts: https://docs.methodfi.com/api/core/events/list + * @param opts IEventListOpts: https://docs.methodfi.com/reference/events/list * @returns Returns a list of Event objects */ async list(opts?: IEventListOpts) { diff --git a/src/resources/Merchant/index.ts b/src/resources/Merchant/index.ts index dae2f7b..5466732 100644 --- a/src/resources/Merchant/index.ts +++ b/src/resources/Merchant/index.ts @@ -39,6 +39,7 @@ export default class Merchant extends Resource { /** * Retrieves a merchant by id + * https://docs.methodfi.com/reference/merchants/retrieve * * @param mch_id Method merchant id * @returns IMerchant @@ -50,8 +51,9 @@ export default class Merchant extends Resource { /** * Lists all merchants + * https://docs.methodfi.com/reference/merchants/list * - * @param opts IMerchantListOpts: https://docs.methodfi.com/api/core/merchants/list + * @param opts IMerchantListOpts * @returns IMerchant[] */ diff --git a/src/resources/Payment/Reversals.ts b/src/resources/Payment/Reversals.ts index 396fd13..94498b0 100644 --- a/src/resources/Payment/Reversals.ts +++ b/src/resources/Payment/Reversals.ts @@ -32,7 +32,7 @@ export default class Reversal extends Resource { * Update a reversal * * @param rvs_id id of the reversal - * @param data IReversalUpdateOpts: https://docs.methodfi.com/api/core/payments/reversals/update + * @param data IReversalUpdateOpts * @returns IReversal */ diff --git a/src/resources/Payment/index.ts b/src/resources/Payment/index.ts index 592d40b..a5ebcc8 100644 --- a/src/resources/Payment/index.ts +++ b/src/resources/Payment/index.ts @@ -30,6 +30,7 @@ export class Payment extends Resource { /** * Retrieves payment by id + * https://docs.methodfi.com/reference/payments/retrieve * * @param pmt_id id of the payment * @returns IPayment @@ -41,8 +42,9 @@ export class Payment extends Resource { /** * Lists all payments + * https://docs.methodfi.com/reference/payments/list * - * @param opts IPaymentListOpts: https://docs.methodfi.com/api/core/payments/list + * @param opts IPaymentListOpts * @returns IPayment[] */ @@ -52,6 +54,7 @@ export class Payment extends Resource { /** * Creates a payment + * https://docs.methodfi.com/reference/payments/create * * @param opts IPaymentCreateOpts * @param requestConfig Idempotency key: { idempotency_key: string} @@ -64,6 +67,7 @@ export class Payment extends Resource { /** * Cancels a payment + * https://docs.methodfi.com/reference/payments/delete * * @param pmt_id id of the payment * @returns IPayment diff --git a/src/resources/Report/index.ts b/src/resources/Report/index.ts index 354cedc..5414047 100644 --- a/src/resources/Report/index.ts +++ b/src/resources/Report/index.ts @@ -46,6 +46,7 @@ export default class Report extends Resource { /** * Retrieves the Report associated with the ID. + * https://docs.methodfi.com/reference/reports/retrieve * * @param rpt_id id of the report * @returns Returns the Report associated with the ID. @@ -57,8 +58,9 @@ export default class Report extends Resource { /** * Creates a new Report for a specific type. Once created, you can retrieve the Report results from the URL returned. + * https://docs.methodfi.com/reference/reports/create * - * @param opts IReportCreateOpts: https://docs.methodfi.com/api/core/reports/create + * @param opts IReportCreateOpts * @param requestConfig Idempotency key: { idempotency_key: string} * @returns Returns a Report object. */ @@ -69,6 +71,7 @@ export default class Report extends Resource { /** * Download a report + * https://docs.methodfi.com/reference/reports/download * * @param rpt_id id of the report * @returns Returns the Report’s results in CSV format. diff --git a/src/resources/Simulate/Accounts/Transactions.ts b/src/resources/Simulate/Accounts/Transactions.ts index 2146912..98284ca 100644 --- a/src/resources/Simulate/Accounts/Transactions.ts +++ b/src/resources/Simulate/Accounts/Transactions.ts @@ -9,6 +9,7 @@ export default class SimulateTransactions extends Resource { /** * For Accounts that have been successfully verified, you may simulate Transactions in the dev environment. + * https://docs.methodfi.com/reference/simulations/transactions/create * * @returns Returns the created Transaction. */ diff --git a/src/resources/Simulate/Entities/CreditScores.ts b/src/resources/Simulate/Entities/CreditScores.ts index 90f070e..8fc9403 100644 --- a/src/resources/Simulate/Entities/CreditScores.ts +++ b/src/resources/Simulate/Entities/CreditScores.ts @@ -12,6 +12,7 @@ export class SimulateCreditScoresInstance extends Resource { /** * For Entities that have been successfully verified, you may simulate Credit Scores in the dev environment. + * https://docs.methodfi.com/reference/simulations/credit-scores/create * * @returns Returns the created Credit Score. */ diff --git a/src/resources/Simulate/Events.ts b/src/resources/Simulate/Events.ts index cf05c54..b3be457 100644 --- a/src/resources/Simulate/Events.ts +++ b/src/resources/Simulate/Events.ts @@ -15,6 +15,7 @@ export default class SimulateEvents extends Resource { /** * Simulates an event. + * https://docs.methodfi.com/reference/simulations/events/create * * @param data The event type and optional entity or account ID. * @returns null diff --git a/src/resources/Simulate/Payments.ts b/src/resources/Simulate/Payments.ts index 5b97d44..82e2afd 100644 --- a/src/resources/Simulate/Payments.ts +++ b/src/resources/Simulate/Payments.ts @@ -14,6 +14,7 @@ export default class SimulatePayments extends Resource { /** * Updates a Payment’s status. + * https://docs.methodfi.com/reference/simulations/payments/update * * @param id ID of the Payment * @param data The desired payment status or error code. diff --git a/src/resources/Webhook/index.ts b/src/resources/Webhook/index.ts index f854de8..c15bc82 100644 --- a/src/resources/Webhook/index.ts +++ b/src/resources/Webhook/index.ts @@ -30,6 +30,7 @@ export const WebhookTypes = { entity_verification_session_update: 'entity_verification_session.update', connect_create: 'connect.create', connect_update: 'connect.update', + connect_available: 'connect.available', balance_create: 'balance.create', balance_update: 'balance.update', identity_create: 'identity.create', @@ -38,6 +39,7 @@ export const WebhookTypes = { account_verification_session_update: 'account_verification_session.update', card_brand_create: 'card_brand.create', card_brand_update: 'card_brand.update', + card_brand_available: 'card_brand.available', sensitive_create: 'sensitive.create', sensitive_update: 'sensitive.update', update_create: 'update.create', @@ -62,6 +64,8 @@ export const WebhookTypes = { attribute_credit_health_payment_history_decreased: 'attribute.credit_health_payment_history.decreased', attribute_credit_health_open_accounts_increased: 'attribute.credit_health_open_accounts.increased', attribute_credit_health_open_accounts_decreased: 'attribute.credit_health_open_accounts.decreased', + method_jwk_create: 'method_jwk.create', + method_jwk_update: 'method_jwk.update', } as const; export type TWebhookTypes = typeof WebhookTypes[keyof typeof WebhookTypes]; @@ -117,7 +121,7 @@ export default class Webhook extends Resource { * Creating a new Webhook means registering a URL to receive updates for a specific event type. * Once a resource is created or updated, your application will be notified via an HTTP POST request with the event information. * - * @param opts IWebhookCreateOpts: https://docs.methodfi.com/api/core/webhooks/create + * @param opts IWebhookCreateOpts: https://docs.methodfi.com/reference/webhooks/create * @param requestConfig Idempotency key: { idempotency_key: string} * @returns Returns the newly created Webhook object. */ diff --git a/test/config.ts b/test/config.ts index faa1a1c..4442ded 100644 --- a/test/config.ts +++ b/test/config.ts @@ -1,3 +1,5 @@ import { MethodClient, Environments } from '../src'; // @ts-ignore export const client = new MethodClient({ apiKey: process.env.TEST_CLIENT_KEY, env: Environments.dev }); +// @ts-ignore +export const clientWithPreferAsync = new MethodClient({ apiKey: process.env.TEST_CLIENT_KEY, env: Environments.dev, prefer: 'respond-async' }); diff --git a/test/resources/Account.tests.ts b/test/resources/Account.tests.ts index 8ce8f7a..e71cde5 100644 --- a/test/resources/Account.tests.ts +++ b/test/resources/Account.tests.ts @@ -146,7 +146,7 @@ describe('Accounts - core methods tests', () => { mask: '8721', ownership: 'unknown', type: 'credit_card', - name: 'Chase Credit Card' + name: 'Chase Sapphire Reserve' }, latest_verification_session: accounts_create_liability_response.latest_verification_session, balance: null, @@ -154,6 +154,7 @@ describe('Accounts - core methods tests', () => { update: accounts_create_liability_response.update, card_brand: null, payment_instrument: null, + payoff: null, products: accounts_create_liability_response.products, restricted_products: accounts_create_liability_response.restricted_products, subscriptions: accounts_create_liability_response.subscriptions, @@ -242,14 +243,14 @@ describe('Accounts - core methods tests', () => { }); it('should successfully retrieve the balance of an account.', async () => { - const getAccountBalances = async () => { - return client + const account_balances_response = async () => { + return await client .accounts(test_credit_card_account.id) .balances .retrieve(balances_create_response.id); - } + }; - const account_balances = await awaitResults(getAccountBalances); + const account_balances = await awaitResults(account_balances_response); const expect_results: IAccountBalance = { id: balances_create_response.id, @@ -265,14 +266,10 @@ describe('Accounts - core methods tests', () => { }); it('should successfully list balances for an account.', async () => { - const listAccountBalances = async () => { - return client - .accounts(test_credit_card_account.id) - .balances - .list(); - }; - - const account_balances = await awaitResults(listAccountBalances); + const account_balances = await client + .accounts(test_credit_card_account.id) + .balances + .list(); const expect_results = { id: balances_create_response.id, @@ -290,43 +287,41 @@ describe('Accounts - core methods tests', () => { describe('accounts.cardBrands', () => { it('should successfully create a card for an account.', async () => { + // @ts-ignore card_create_response = await client .accounts(test_credit_card_account.id) .cardBrands .create(); - const expect_results: IAccountCardBrand = { - id: card_create_response.id, - account_id: test_credit_card_account.id, - network: 'visa', - status: 'in_progress', - issuer: card_create_response.issuer, - last4: '1580', - brands: card_create_response.brands, - shared: false, - source: card_create_response.source, - error: null, - created_at: card_create_response.created_at, - updated_at: card_create_response.updated_at - }; + const expect_results: IAccountCardBrand = { + id: card_create_response.id, + account_id: test_credit_card_account.id, + brands: [], + status: 'in_progress', + source: null, + error: null, + created_at: card_create_response.created_at, + updated_at: card_create_response.updated_at + } card_create_response.should.be.eql(expect_results); await new Promise(r => setTimeout(r, 2000)) }); it('should successfully retrieve a card for an account.', async () => { - const card_retrieve_response = await client + // @ts-ignore + const cardRetrieveResponse = async () => { + return await client .accounts(test_credit_card_account.id) .cardBrands .retrieve(card_create_response.id); + }; + + const card_retrieve_response = await awaitResults(cardRetrieveResponse); expect(card_retrieve_response.id).to.equal(card_create_response.id); expect(card_retrieve_response.account_id).to.equal(test_credit_card_account.id); - expect(card_retrieve_response.network).to.equal('visa'); expect(card_retrieve_response.status).to.equal('completed'); - expect(card_retrieve_response.issuer).to.equal(card_create_response.issuer); - expect(card_retrieve_response.last4).to.equal('1580'); - expect(card_retrieve_response.shared).to.equal(false); expect(card_retrieve_response.source).to.equal('network'); expect(card_retrieve_response.error).to.be.null; expect(card_retrieve_response.created_at).to.be.a('string'); @@ -334,41 +329,42 @@ describe('Accounts - core methods tests', () => { const brand = card_retrieve_response.brands?.[0]; expect(brand).to.exist; - expect(brand.id).to.equal('brand_UBwVzXjpP4PJ6'); + expect(brand.id).to.equal('pdt_15_brd_1'); + expect(brand.card_product_id).to.equal('pdt_15'); + expect(brand.description).to.equal('Chase Sapphire Reserve'); expect(brand.name).to.equal('Chase Sapphire Reserve'); + expect(brand.issuer).to.equal('Chase'); + expect(brand.network).to.equal('visa'); + expect(brand.type).to.equal('specific'); expect(brand.url).to.equal('https://static.methodfi.com/card_brands/1b7ccaba6535cb837f802d968add4700.png'); - expect(brand.art_id).to.be.a('string').and.match(/^art_/); }); it('should successfully list card brands for an account.', async () => { - const listCardBrands = async () => { - return client - .accounts(test_credit_card_account.id) - .cardBrands - .list(); - }; + const card_brands = await client + .accounts(test_credit_card_account.id) + .cardBrands + .list(); - const card_brands = await awaitResults(listCardBrands); const result = card_brands[0]; expect(result.id).to.equal(card_create_response.id); expect(result.account_id).to.equal(test_credit_card_account.id); - expect(result.network).to.equal('visa'); expect(result.status).to.equal('completed'); - expect(result.issuer).to.equal(card_create_response.issuer); - expect(result.last4).to.equal('1580'); - expect(result.shared).to.equal(false); expect(result.source).to.equal('network'); expect(result.error).to.be.null; expect(result.created_at).to.be.a('string'); expect(result.updated_at).to.be.a('string'); - + const brand = result.brands?.[0]; expect(brand).to.exist; - expect(brand.id).to.equal('brand_UBwVzXjpP4PJ6'); + expect(brand.id).to.equal('pdt_15_brd_1'); + expect(brand.card_product_id).to.equal('pdt_15'); + expect(brand.description).to.equal('Chase Sapphire Reserve'); expect(brand.name).to.equal('Chase Sapphire Reserve'); + expect(brand.issuer).to.equal('Chase'); + expect(brand.network).to.equal('visa'); + expect(brand.type).to.equal('specific'); expect(brand.url).to.equal('https://static.methodfi.com/card_brands/1b7ccaba6535cb837f802d968add4700.png'); - expect(brand.art_id).to.be.a('string').and.match(/^art_/); }); }); @@ -395,14 +391,14 @@ describe('Accounts - core methods tests', () => { }); it('should successfully retrieve a payoff for an account.', async () => { - const getPayoffQuotes = async () =>{ + const payoff_quote_response = async () => { return await client - .accounts(test_auto_loan_account.id) - .payoffs - .retrieve(payoff_create_response.id); + .accounts(test_auto_loan_account.id) + .payoffs + .retrieve(payoff_create_response.id); }; - const payoff_quote = await awaitResults(getPayoffQuotes); + const payoff_quote = await awaitResults(payoff_quote_response); const expect_results: IAccountPayoff = { id: payoff_create_response.id, @@ -420,14 +416,10 @@ describe('Accounts - core methods tests', () => { }); it('should successfully list payoffs for an account.', async () => { - const listPayoffQuotes = async () => { - return await client - .accounts(test_auto_loan_account.id) - .payoffs - .list(); - }; - - const payoffs = await awaitResults(listPayoffQuotes); + const payoffs = await client + .accounts(test_auto_loan_account.id) + .payoffs + .list(); const expect_results = { id: payoff_create_response.id, @@ -517,14 +509,10 @@ describe('Accounts - core methods tests', () => { }); it('should successfully retrieve a verification session for an account.', async () => { - const getVerificationSession = async () => { - return await client - .accounts(test_credit_card_account.id) - .verificationSessions - .retrieve(verification_session_update.id); - }; - - const verification_session = await awaitResults(getVerificationSession); + const verification_session = await client + .accounts(test_credit_card_account.id) + .verificationSessions + .retrieve(verification_session_update.id); const expect_results: IAccountVerificationSession = { id: verification_session_update.id, @@ -551,14 +539,10 @@ describe('Accounts - core methods tests', () => { }); it('should successfully list verification sessions for an account.', async () => { - const listVerificationSessions = async () => { - return await client - .accounts(test_credit_card_account.id) - .verificationSessions - .list(); - }; - - const verification_sessions = await awaitResults(listVerificationSessions); + const verification_sessions = await client + .accounts(test_credit_card_account.id) + .verificationSessions + .list(); const expect_results: IAccountVerificationSession = { id: verification_session_update.id, @@ -618,14 +602,10 @@ describe('Accounts - core methods tests', () => { }); it('should successfully list sensitive data for an account.', async () => { - const listSensitiveData = async () => { - return await client - .accounts(test_credit_card_account.id) - .sensitive - .list(); - }; - - const sensitive_data = await awaitResults(listSensitiveData); + const sensitive_data = await client + .accounts(test_credit_card_account.id) + .sensitive + .list(); sensitive_data[0].should.be.eql(sensitive_data_response); }); @@ -945,13 +925,13 @@ describe('Accounts - core methods tests', () => { it('should successfully retrieve results of an updates request', async () => { const getAccountUpdates = async () => { return await client - .accounts(test_credit_card_account.id) - .updates - .retrieve(create_updates_response.id); + .accounts(test_credit_card_account.id) + .updates + .retrieve(create_updates_response.id); }; const retrieve_updates_response = await awaitResults(getAccountUpdates); - + const expect_results: IAccountUpdate = { id: create_updates_response.id, account_id: test_credit_card_account.id, @@ -1080,91 +1060,91 @@ describe('Accounts - core methods tests', () => { const expect_results: IAccountProductListResponse = { balance: { - id: accounts_retrieve_product_list_response.balance?.id || '', name: 'balance', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.balance?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.balance?.latest_successful_request_id || null, is_subscribable: false, created_at: accounts_retrieve_product_list_response.balance?.created_at || '', updated_at: accounts_retrieve_product_list_response.balance?.updated_at || '' }, payment: { - id: accounts_retrieve_product_list_response.payment?.id || '', name: 'payment', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.payment?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.payment?.latest_successful_request_id || null, is_subscribable: false, created_at: accounts_retrieve_product_list_response.payment?.created_at || '', updated_at: accounts_retrieve_product_list_response.payment?.updated_at || '' }, sensitive: { - id: accounts_retrieve_product_list_response.sensitive?.id || '', name: 'sensitive', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.sensitive?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.sensitive?.latest_successful_request_id || null, is_subscribable: false, created_at: accounts_retrieve_product_list_response.sensitive?.created_at || '', updated_at: accounts_retrieve_product_list_response.sensitive?.updated_at || '' }, update: { - id: accounts_retrieve_product_list_response.update?.id || '', name: 'update', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.update?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.update?.latest_successful_request_id || null, is_subscribable: true, created_at: accounts_retrieve_product_list_response.update?.created_at || '', updated_at: accounts_retrieve_product_list_response.update?.updated_at || '' }, attribute: { - id: accounts_retrieve_product_list_response.attribute?.id || '', name: 'attribute', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.attribute?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.attribute?.latest_successful_request_id || null, is_subscribable: false, created_at: accounts_retrieve_product_list_response.attribute?.created_at || '', updated_at: accounts_retrieve_product_list_response.attribute?.updated_at || '' }, transaction: { - id: accounts_retrieve_product_list_response.transaction?.id || '', name: 'transaction', status: 'unavailable', status_error: accounts_retrieve_product_list_response.transaction?.status_error || null, latest_request_id: accounts_retrieve_product_list_response.transaction?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.transaction?.latest_successful_request_id || null, is_subscribable: true, created_at: accounts_retrieve_product_list_response.transaction?.created_at || '', updated_at: accounts_retrieve_product_list_response.transaction?.updated_at || '' }, card_brand: { - id: accounts_retrieve_product_list_response.card_brand?.id || '', name: 'card_brand', status: 'available', status_error: null, latest_request_id: accounts_retrieve_product_list_response.card_brand?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.card_brand?.latest_successful_request_id || null, is_subscribable: true, created_at: accounts_retrieve_product_list_response.card_brand?.created_at || '', updated_at: accounts_retrieve_product_list_response.card_brand?.updated_at || '' }, payoff: { - id: accounts_retrieve_product_list_response.payoff?.id || '', name: 'payoff', status: 'unavailable', status_error: accounts_retrieve_product_list_response.payoff?.status_error || null, latest_request_id: accounts_retrieve_product_list_response.payoff?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.payoff?.latest_successful_request_id || null, is_subscribable: false, created_at: accounts_retrieve_product_list_response.payoff?.created_at || '', updated_at: accounts_retrieve_product_list_response.payoff?.updated_at || '' }, payment_instrument: { - id: accounts_retrieve_product_list_response.payment_instrument?.id || '', name: 'payment_instrument', status: 'restricted', status_error: accounts_retrieve_product_list_response.payment_instrument?.status_error || null, latest_request_id: accounts_retrieve_product_list_response.payment_instrument?.latest_request_id || null, + latest_successful_request_id: accounts_retrieve_product_list_response.payment_instrument?.latest_successful_request_id || null, is_subscribable: true, created_at: accounts_retrieve_product_list_response.payment_instrument?.created_at || '', updated_at: accounts_retrieve_product_list_response.payment_instrument?.updated_at || '' @@ -1173,89 +1153,6 @@ describe('Accounts - core methods tests', () => { accounts_retrieve_product_list_response.should.be.eql(expect_results); }); - - it('should successfully retrieve specific products for an account', async () => { - const account_balance_product = await client - .accounts(test_credit_card_account.id) - .products.retrieve(accounts_retrieve_product_list_response.balance?.id || ''); - - const account_payment_product = await client - .accounts(test_credit_card_account.id) - .products.retrieve(accounts_retrieve_product_list_response.payment?.id || ''); - - const account_sensitive_product = await client - .accounts(test_credit_card_account.id) - .products.retrieve(accounts_retrieve_product_list_response.sensitive?.id || ''); - - const account_update_product = await client - .accounts(test_credit_card_account.id) - .products.retrieve(accounts_retrieve_product_list_response.update?.id || ''); - - const account_attribute_product = await client - .accounts(test_credit_card_account.id) - .products.retrieve(accounts_retrieve_product_list_response.attribute?.id || ''); - - const expect_balance_results: IAccountProduct = { - id: accounts_retrieve_product_list_response.balance?.id || '', - name: 'balance', - status: 'available', - status_error: null, - latest_request_id: account_balance_product.latest_request_id, - is_subscribable: false, - created_at: account_balance_product.created_at, - updated_at: account_balance_product.updated_at - }; - - const expect_payment_results: IAccountProduct = { - id: accounts_retrieve_product_list_response.payment?.id || '', - name: 'payment', - status: 'available', - status_error: null, - latest_request_id: account_payment_product.latest_request_id, - is_subscribable: false, - created_at: account_payment_product.created_at, - updated_at: account_payment_product.updated_at - }; - - const expect_sensitive_results: IAccountProduct = { - id: accounts_retrieve_product_list_response.sensitive?.id || '', - name: 'sensitive', - status: 'available', - status_error: null, - latest_request_id: account_sensitive_product.latest_request_id, - is_subscribable: false, - created_at: account_sensitive_product.created_at, - updated_at: account_sensitive_product.updated_at - }; - - const expect_update_results: IAccountProduct = { - id: accounts_retrieve_product_list_response.update?.id || '', - name: 'update', - status: 'available', - status_error: null, - latest_request_id: account_update_product.latest_request_id, - is_subscribable: true, - created_at: account_update_product.created_at, - updated_at: account_update_product.updated_at - }; - - const expect_attribute_results: IAccountProduct = { - id: accounts_retrieve_product_list_response.attribute?.id || '', - name: 'attribute', - status: 'available', - status_error: null, - latest_request_id: account_attribute_product.latest_request_id, - is_subscribable: false, - created_at: account_attribute_product.created_at, - updated_at: account_attribute_product.updated_at - }; - - account_balance_product.should.be.eql(expect_balance_results); - account_payment_product.should.be.eql(expect_payment_results); - account_sensitive_product.should.be.eql(expect_sensitive_results); - account_update_product.should.be.eql(expect_update_results); - account_attribute_product.should.be.eql(expect_attribute_results); - }); }); diff --git a/test/resources/CardProduct.tests.ts b/test/resources/CardProduct.tests.ts new file mode 100644 index 0000000..0fa2c69 --- /dev/null +++ b/test/resources/CardProduct.tests.ts @@ -0,0 +1,43 @@ +import { should } from 'chai'; +import { describe } from 'mocha'; +import { client } from '../config'; +import type { ICardProduct } from '../../src/resources/CardProduct'; +import { IResponse } from '../../src/configuration'; + +should(); + +describe('Card Products - core methods tests', () => { + let card_products_retrieve_response: IResponse; + + describe('cardProducts.retrieve', () => { + it('should successfully retrieve a card product by id.', async () => { + card_products_retrieve_response = await client.cardProducts.retrieve('pdt_15'); + + const expect_results: ICardProduct = { + id: "pdt_17", + name: "Chase Freedom", + issuer: "Chase", + type: "specific", + brands: [ + { + id: "pdt_17_brd_1", + description: "Chase Freedom", + network: "visa", + default_image: "https://static.methodfi.com/card_brands/fb5fbd6a5d45b942752b9dc641b93d1f.png" + }, + { + id: "pdt_17_brd_2", + description: "Chase Freedom", + network: "visa", + default_image: "https://static.methodfi.com/card_brands/6cb697528b0771f982f7c0e8b8869de3.png" + } + ], + error: null, + created_at: card_products_retrieve_response.created_at, + updated_at: card_products_retrieve_response.updated_at, + } + + card_products_retrieve_response.should.be.eql(expect_results); + }); + }); +}); diff --git a/test/resources/Entity.tests.ts b/test/resources/Entity.tests.ts index f5d2573..546981d 100644 --- a/test/resources/Entity.tests.ts +++ b/test/resources/Entity.tests.ts @@ -1,6 +1,6 @@ import { should } from 'chai'; import { describe } from 'mocha'; -import { client } from '../config'; +import { client, clientWithPreferAsync } from '../config'; import { awaitResults } from '../utils'; import type { IEntity, @@ -23,12 +23,15 @@ should(); describe('Entities - core methods tests', () => { let entities_create_response: IResponse; + let entities_create_response_async: IResponse; let entity_with_identity_cap: IResponse; let entity_with_vehicle: IResponse; let entities_retrieve_response: IResponse; let entities_update_response: IResponse; + let entities_update_response_async: IResponse; let entities_list_response: IResponse[]; let entities_connect_create_response: IResponse; + let entities_connect_create_response_async: IResponse; let entities_account_list_response: IResponse[]; let entities_account_ids: string[]; let entities_create_credit_score_response: IResponse; @@ -51,7 +54,14 @@ describe('Entities - core methods tests', () => { metadata: {}, }); + entities_create_response_async = await clientWithPreferAsync.entities.create({ + type: 'individual', + individual: {}, + metadata: {}, + }); + entities_create_response.restricted_subscriptions?.sort(); + entities_create_response_async.restricted_subscriptions?.sort(); const expect_results: IEntity = { id: entities_create_response.id, @@ -101,7 +111,56 @@ describe('Entities - core methods tests', () => { updated_at: entities_create_response.updated_at, }; + const expect_results_async: IEntity = { + id: entities_create_response_async.id, + type: 'individual', + individual: { + first_name: null, + last_name: null, + phone: null, + dob: null, + email: null, + ssn: null, + ssn_4: null, + }, + address: { + line1: null, + line2: null, + city: null, + state: null, + zip: null, + }, + vehicle: null, + verification: { + identity: { + verified: false, + matched: false, + latest_verification_session: null, + methods: ['element', 'opal', 'kba'], + }, + phone: { + verified: false, + latest_verification_session: null, + methods: ['element', 'opal', 'sna', 'sms', 'byo_sms'], + }, + }, + connect: null, + credit_score: null, + attribute: null, + products: [], + restricted_products: entities_create_response_async.restricted_products, + subscriptions: [], + available_subscriptions: [], + restricted_subscriptions: entities_create_response_async.restricted_subscriptions, + status: 'incomplete', + error: null, + metadata: {}, + created_at: entities_create_response_async.created_at, + updated_at: entities_create_response_async.updated_at, + }; + entities_create_response.should.be.eql(expect_results); + entities_create_response_async.should.be.eql(expect_results_async); }); }); @@ -234,6 +293,70 @@ describe('Entities - core methods tests', () => { }; entities_update_response.should.be.eql(expect_results); + + entities_update_response_async = await clientWithPreferAsync.entities.update( + entities_create_response_async.id, + { + individual: { + first_name: 'Kevin', + last_name: 'Doyle', + phone: '+15121231111', + }, + } + ); + + entities_update_response_async.restricted_subscriptions?.sort(); + entities_update_response_async.restricted_products?.sort(); + + const expect_results_async: IEntity = { + id: entities_create_response_async.id, + type: 'individual', + individual: { + first_name: 'Kevin', + last_name: 'Doyle', + phone: '+15121231111', + dob: null, + email: null, + ssn: null, + ssn_4: null, + }, + address: { + line1: null, + line2: null, + city: null, + state: null, + zip: null, + }, + verification: { + identity: { + verified: false, + matched: true, + latest_verification_session: null, + methods: ['element', 'opal', 'kba'], + }, + phone: { + verified: false, + latest_verification_session: null, + methods: ['element', 'opal', 'sna', 'sms', 'byo_sms'], + }, + }, + connect: null, + vehicle: null, + credit_score: null, + attribute: null, + products: entities_update_response_async.products, + restricted_products: entities_update_response_async.restricted_products, + subscriptions: entities_update_response_async.subscriptions, + available_subscriptions: entities_update_response_async.available_subscriptions, + restricted_subscriptions: entities_update_response_async.restricted_subscriptions, + status: 'incomplete', + error: null, + metadata: {}, + created_at: entities_update_response_async.created_at, + updated_at: entities_update_response_async.updated_at, + }; + + entities_update_response_async.should.be.eql(expect_results_async); }); }); @@ -258,6 +381,16 @@ describe('Entities - core methods tests', () => { }, }); + await clientWithPreferAsync + .entities(entities_create_response_async.id) + .verificationSessions.create({ + type: 'phone', + method: 'byo_sms', + byo_sms: { + timestamp: '2021-09-01T00:00:00.000Z', + }, + }); + const expect_results: IEntityVerificationSession = { id: entities_create_phone_verification_session_response.id, entity_id: entities_create_response.id, @@ -288,6 +421,14 @@ describe('Entities - core methods tests', () => { kba: {}, }); + await clientWithPreferAsync + .entities(entities_create_response_async.id) + .verificationSessions.create({ + type: 'identity', + method: 'kba', + kba: {}, + }); + const expect_results: IEntityVerificationSession = { id: entities_create_verification_session_response.id, entity_id: entities_create_response.id, @@ -348,6 +489,8 @@ describe('Entities - core methods tests', () => { entity_id: entities_create_response.id, status: 'completed', accounts: entities_account_ids, + requested_products: [], + requested_subscriptions: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -368,6 +511,8 @@ describe('Entities - core methods tests', () => { entity_id: entities_create_response.id, status: 'completed', accounts: entities_account_ids, + requested_products: [], + requested_subscriptions: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -377,13 +522,10 @@ describe('Entities - core methods tests', () => { }); it('should successfully list connections for an entity', async () => { - const listConnections = async () => { - return await client - .entities(entities_create_response.id) - .connect.list(); - }; + const connections = await client + .entities(entities_create_response.id) + .connect.list(); - const connections = await awaitResults(listConnections); connections[0].accounts = connections[0].accounts?.sort() || null; const expect_results: IEntityConnect = { @@ -391,6 +533,8 @@ describe('Entities - core methods tests', () => { entity_id: entities_create_response.id, status: 'completed', accounts: entities_account_ids, + requested_products: [], + requested_subscriptions: [], error: null, created_at: entities_connect_create_response.created_at, updated_at: entities_connect_create_response.updated_at, @@ -398,6 +542,56 @@ describe('Entities - core methods tests', () => { connections[0].should.be.eql(expect_results); }); + + it('should successfully create a connection for an entity (async).', async () => { + entities_connect_create_response_async = await clientWithPreferAsync + .entities(entities_create_response_async.id) + .connect.create({ + products: ['card_brand'], + subscriptions: ['update'], + }); + + const expect_results: IEntityConnect = { + id: entities_connect_create_response_async.id, + entity_id: entities_create_response_async.id, + status: 'pending', + accounts: null, + requested_products: ['card_brand'], + requested_subscriptions: ['update'], + error: null, + created_at: entities_connect_create_response_async.created_at, + updated_at: entities_connect_create_response_async.updated_at, + }; + + entities_connect_create_response_async.should.be.eql(expect_results); + }); + + it('should successfully retrieve results of a connection for an entity (async).', async () => { + let entitiesConnectRetrieveResponse = async () => { + return await clientWithPreferAsync + .entities(entities_create_response_async.id) + .connect.retrieve(entities_connect_create_response_async.id); + }; + + const entities_connect_results_response_async = await awaitResults(entitiesConnectRetrieveResponse); + + entities_connect_results_response_async.accounts = + entities_connect_results_response_async.accounts?.sort() || null; + + const expect_results: IEntityConnect = { + id: entities_connect_create_response_async.id, + entity_id: entities_create_response_async.id, + status: 'completed', + accounts: entities_connect_results_response_async.accounts, + requested_products: ['card_brand'], + requested_subscriptions: ['update'], + error: null, + created_at: entities_connect_results_response_async.created_at, + updated_at: entities_connect_results_response_async.updated_at, + }; + + entities_connect_results_response_async.should.be.eql(expect_results); + }); }); describe('entities.credit_scores', () => { @@ -744,13 +938,9 @@ describe('Entities - core methods tests', () => { }); it('should successfully retrieve the results of a request for a vehicle', async () => { - const getVehicles = async () => { - return await client + const vehicles = await client .entities(entity_with_vehicle.id) .vehicles.retrieve(entities_create_vehicle_response.id); - }; - - const vehicles = await awaitResults(getVehicles); const expect_results: IEntityVehicles = { id: entities_create_vehicle_response.id, @@ -766,13 +956,9 @@ describe('Entities - core methods tests', () => { }); it('should successfully list vehicles for an entity', async () => { - const listVehicles = async () => { - return await client - .entities(entity_with_vehicle.id) - .vehicles.list(); - }; - - const vehicles = await awaitResults(listVehicles); + const vehicles = await client + .entities(entity_with_vehicle.id) + .vehicles.list(); vehicles[0].should.be.eql(entities_create_vehicle_response); }); @@ -786,13 +972,13 @@ describe('Entities - core methods tests', () => { const expect_results: IEntityProductListResponse = { connect: { - id: entities_retrieve_product_list_response.connect?.id || '', name: 'connect', status: 'available', status_error: null, latest_request_id: entities_retrieve_product_list_response.connect ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.connect?.latest_successful_request_id || null, is_subscribable: true, created_at: entities_retrieve_product_list_response.connect?.created_at || '', @@ -800,13 +986,13 @@ describe('Entities - core methods tests', () => { entities_retrieve_product_list_response.connect?.updated_at || '', }, credit_score: { - id: entities_retrieve_product_list_response.credit_score?.id || '', name: 'credit_score', status: 'available', status_error: null, latest_request_id: entities_retrieve_product_list_response.credit_score ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.credit_score?.latest_successful_request_id || null, is_subscribable: true, created_at: entities_retrieve_product_list_response.credit_score?.created_at || @@ -816,13 +1002,13 @@ describe('Entities - core methods tests', () => { '', }, identity: { - id: entities_retrieve_product_list_response.identity?.id || '', name: 'identity', status: 'available', status_error: null, latest_request_id: entities_retrieve_product_list_response.identity ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.identity?.latest_successful_request_id || null, is_subscribable: false, created_at: entities_retrieve_product_list_response.identity?.created_at || '', @@ -830,13 +1016,13 @@ describe('Entities - core methods tests', () => { entities_retrieve_product_list_response.identity?.updated_at || '', }, attribute: { - id: entities_retrieve_product_list_response.attribute?.id || '', name: 'attribute', status: 'available', status_error: null, latest_request_id: entities_retrieve_product_list_response.attribute ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.attribute?.latest_successful_request_id || null, is_subscribable: true, created_at: entities_retrieve_product_list_response.attribute?.created_at || '', @@ -844,25 +1030,25 @@ describe('Entities - core methods tests', () => { entities_retrieve_product_list_response.attribute?.updated_at || '', }, vehicle: { - id: entities_retrieve_product_list_response.vehicle?.id || '', name: 'vehicle', status: 'available', status_error: null, latest_request_id: entities_retrieve_product_list_response.vehicle ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.vehicle?.latest_successful_request_id || null, is_subscribable: false, created_at: entities_retrieve_product_list_response.vehicle?.created_at || '', updated_at: entities_retrieve_product_list_response.vehicle?.updated_at || '', }, manual_connect: { - id: entities_retrieve_product_list_response.manual_connect?.id || '', name: 'manual_connect', status: 'restricted', status_error: entities_retrieve_product_list_response.manual_connect?.status_error || null, latest_request_id: entities_retrieve_product_list_response.manual_connect ?.latest_request_id || null, + latest_successful_request_id: entities_retrieve_product_list_response.manual_connect?.latest_successful_request_id || null, is_subscribable: false, created_at: entities_retrieve_product_list_response.manual_connect?.created_at || '', updated_at: entities_retrieve_product_list_response.manual_connect?.updated_at || '', @@ -871,95 +1057,6 @@ describe('Entities - core methods tests', () => { entities_retrieve_product_list_response.should.be.eql(expect_results); }); - - it('should retrieve a specific product for an entity', async () => { - const entity_connect_product = await client - .entities(entities_create_response.id) - .products.retrieve( - entities_retrieve_product_list_response.connect?.id || '' - ); - const entity_credit_score_product = await client - .entities(entities_create_response.id) - .products.retrieve( - entities_retrieve_product_list_response.credit_score?.id || '' - ); - const entity_identity_product = await client - .entities(entities_create_response.id) - .products.retrieve( - entities_retrieve_product_list_response.identity?.id || '' - ); - const entity_attribute_product = await client - .entities(entities_create_response.id) - .products.retrieve( - entities_retrieve_product_list_response.attribute?.id || '' - ); - const entity_vehicle_product = await client - .entities(entities_create_response.id) - .products.retrieve( - entities_retrieve_product_list_response.vehicle?.id || '' - ); - - const expect_connect_results: IEntityProduct = { - id: entities_retrieve_product_list_response.connect?.id || '', - name: 'connect', - status: 'available', - status_error: null, - latest_request_id: entity_connect_product.latest_request_id, - is_subscribable: true, - created_at: entity_connect_product.created_at, - updated_at: entity_connect_product.updated_at, - }; - - const expect_credit_score_results: IEntityProduct = { - id: entities_retrieve_product_list_response.credit_score?.id || '', - name: 'credit_score', - status: 'available', - status_error: null, - latest_request_id: entity_credit_score_product.latest_request_id, - is_subscribable: true, - created_at: entity_credit_score_product.created_at, - updated_at: entity_credit_score_product.updated_at, - }; - - const expect_identity_results: IEntityProduct = { - id: entities_retrieve_product_list_response.identity?.id || '', - name: 'identity', - status: 'available', - status_error: null, - latest_request_id: entity_identity_product.latest_request_id, - is_subscribable: false, - created_at: entity_identity_product.created_at, - updated_at: entity_identity_product.updated_at, - }; - - const expect_attribute_results: IEntityProduct = { - id: entities_retrieve_product_list_response.attribute?.id || '', - name: 'attribute', - status: 'available', - status_error: null, - latest_request_id: entity_attribute_product.latest_request_id, - is_subscribable: true, - created_at: entity_attribute_product.created_at, - updated_at: entity_attribute_product.updated_at, - }; - - const expect_vehicle_results: IEntityProduct = { - id: entities_retrieve_product_list_response.vehicle?.id || '', - name: 'vehicle', - status: 'available', - status_error: null, - latest_request_id: entity_vehicle_product.latest_request_id, - is_subscribable: false, - created_at: entity_vehicle_product.created_at, - updated_at: entity_vehicle_product.updated_at, - }; - - entity_vehicle_product.should.be.eql(expect_vehicle_results); - entity_connect_product.should.be.eql(expect_connect_results); - entity_credit_score_product.should.be.eql(expect_credit_score_results); - entity_identity_product.should.be.eql(expect_identity_results); - entity_attribute_product.should.be.eql(expect_attribute_results); - }); }); describe('entities.subscriptions', () => { diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index 4bef6d6..8d4c035 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -14,7 +14,7 @@ import { IResponse } from '../../src/configuration'; should(); -describe('Events - core methods tests', () => { +describe.only('Events - core methods tests', () => { let entity_response: IResponse; let connect_response: IResponse; let attribute_response: IResponse; @@ -63,13 +63,14 @@ describe('Events - core methods tests', () => { describe('simulate.events', () => { it('should simulate an account opened event', async () => { + await client.simulate.events.create({ type: 'account.opened', entity_id: entity_response.id, }); // timeout to allow event to be created - await new Promise((resolve) => { setTimeout(resolve, 5000); }); + await new Promise((resolve) => { setTimeout(resolve, 20000); }); const events_list_response = await client.events.list({ type: 'account.opened', @@ -100,7 +101,7 @@ describe('Events - core methods tests', () => { }); // timeout to allow event to be created - await new Promise((resolve) => { setTimeout(resolve, 5000); }); + await new Promise((resolve) => { setTimeout(resolve, 20000); }); const events_list_response = await client.events.list({ type: 'attribute.credit_health_credit_card_usage.increased', From 59414cdb73c8c8326508f33e0fb436fe007baf4c Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Fri, 15 Aug 2025 16:15:16 -0500 Subject: [PATCH 02/16] utilize requestConfig for setting headers --- src/configuration.ts | 3 --- src/resource.ts | 8 +++++--- src/resources/Entity/Connect.ts | 6 +++--- test/config.ts | 2 -- test/resources/Entity.tests.ts | 20 +++++++++++++------- test/resources/Event.tests.ts | 14 ++++++++++---- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 14804b5..e130694 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -59,7 +59,6 @@ export type IAxiosRetryConfig = { export interface IConfigurationOpts { apiKey: string; env: TEnvironments; - prefer?: string | null; httpsAgent?: any; onRequest?: TOnRequest; onResponse?: TOnResponse; @@ -69,7 +68,6 @@ export interface IConfigurationOpts { export default class Configuration { baseURL: string; apiKey: string; - prefer?: string | null; httpsAgent?: any; onResponse: TOnResponse | null; onRequest: TOnRequest | null; @@ -80,7 +78,6 @@ export default class Configuration { this.baseURL = `https://${opts.env}.methodfi.com`; this.apiKey = opts.apiKey; - this.prefer = opts.prefer || null; this.httpsAgent = opts.httpsAgent || null; this.onRequest = opts.onRequest || null; this.onResponse = opts.onResponse || null; diff --git a/src/resource.ts b/src/resource.ts index a87465f..098ac5a 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -22,6 +22,7 @@ type TSubResources = export interface IRequestConfig { idempotency_key?: string; + headers?: Record; } class ExtensibleFunction extends Function { @@ -212,9 +213,10 @@ export default class Resource extends ExtensibleFunction { requestConfig: IRequestConfig = {}, ): Promise { const _requestConfig = { - headers: requestConfig.idempotency_key - ? { 'Idempotency-Key': requestConfig.idempotency_key } - : {}, + headers: { + ...(requestConfig.idempotency_key ? { 'Idempotency-Key': requestConfig.idempotency_key } : {}), + ...(requestConfig.headers || {}), + }, params, }; diff --git a/src/resources/Entity/Connect.ts b/src/resources/Entity/Connect.ts index 8398856..99acfce 100644 --- a/src/resources/Entity/Connect.ts +++ b/src/resources/Entity/Connect.ts @@ -1,4 +1,4 @@ -import Resource, { IResourceListOpts } from '../../resource'; +import Resource, { IResourceListOpts, IRequestConfig } from '../../resource'; import Configuration, { IResponse } from '../../configuration'; import type { IEntityConnect } from './types'; @@ -83,7 +83,7 @@ export default class EntityConnect extends Resource { * @returns Returns a Connect object. */ - async create(opts: IConnectCreateOpts = {}, params: IExpandableOpts = {}) { - return super._create, IConnectCreateOpts, IExpandableOpts>(opts, params); + async create(opts: IConnectCreateOpts = {}, params: IExpandableOpts = {}, requestConfig: IRequestConfig = {}) { + return super._create, IConnectCreateOpts, IExpandableOpts>(opts, params, requestConfig); } }; diff --git a/test/config.ts b/test/config.ts index 4442ded..faa1a1c 100644 --- a/test/config.ts +++ b/test/config.ts @@ -1,5 +1,3 @@ import { MethodClient, Environments } from '../src'; // @ts-ignore export const client = new MethodClient({ apiKey: process.env.TEST_CLIENT_KEY, env: Environments.dev }); -// @ts-ignore -export const clientWithPreferAsync = new MethodClient({ apiKey: process.env.TEST_CLIENT_KEY, env: Environments.dev, prefer: 'respond-async' }); diff --git a/test/resources/Entity.tests.ts b/test/resources/Entity.tests.ts index 546981d..bc7c645 100644 --- a/test/resources/Entity.tests.ts +++ b/test/resources/Entity.tests.ts @@ -1,6 +1,6 @@ import { should } from 'chai'; import { describe } from 'mocha'; -import { client, clientWithPreferAsync } from '../config'; +import { client } from '../config'; import { awaitResults } from '../utils'; import type { IEntity, @@ -54,7 +54,7 @@ describe('Entities - core methods tests', () => { metadata: {}, }); - entities_create_response_async = await clientWithPreferAsync.entities.create({ + entities_create_response_async = await client.entities.create({ type: 'individual', individual: {}, metadata: {}, @@ -294,7 +294,7 @@ describe('Entities - core methods tests', () => { entities_update_response.should.be.eql(expect_results); - entities_update_response_async = await clientWithPreferAsync.entities.update( + entities_update_response_async = await client.entities.update( entities_create_response_async.id, { individual: { @@ -381,7 +381,7 @@ describe('Entities - core methods tests', () => { }, }); - await clientWithPreferAsync + await client .entities(entities_create_response_async.id) .verificationSessions.create({ type: 'phone', @@ -421,7 +421,7 @@ describe('Entities - core methods tests', () => { kba: {}, }); - await clientWithPreferAsync + await client .entities(entities_create_response_async.id) .verificationSessions.create({ type: 'identity', @@ -544,11 +544,17 @@ describe('Entities - core methods tests', () => { }); it('should successfully create a connection for an entity (async).', async () => { - entities_connect_create_response_async = await clientWithPreferAsync + entities_connect_create_response_async = await client .entities(entities_create_response_async.id) .connect.create({ products: ['card_brand'], subscriptions: ['update'], + }, + {}, + { + headers: { + 'Prefer': 'respond-async', + } }); const expect_results: IEntityConnect = { @@ -568,7 +574,7 @@ describe('Entities - core methods tests', () => { it('should successfully retrieve results of a connection for an entity (async).', async () => { let entitiesConnectRetrieveResponse = async () => { - return await clientWithPreferAsync + return await client .entities(entities_create_response_async.id) .connect.retrieve(entities_connect_create_response_async.id); }; diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index 8d4c035..fc822ef 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -14,7 +14,7 @@ import { IResponse } from '../../src/configuration'; should(); -describe.only('Events - core methods tests', () => { +describe('Events - core methods tests', () => { let entity_response: IResponse; let connect_response: IResponse; let attribute_response: IResponse; @@ -63,19 +63,25 @@ describe.only('Events - core methods tests', () => { describe('simulate.events', () => { it('should simulate an account opened event', async () => { - + console.log('simulating account opened event'); await client.simulate.events.create({ type: 'account.opened', entity_id: entity_response.id, }); + console.log('waiting for event to be created'); + // timeout to allow event to be created - await new Promise((resolve) => { setTimeout(resolve, 20000); }); + await new Promise((resolve) => { setTimeout(resolve, 2000); }); + + console.log('listing events'); const events_list_response = await client.events.list({ type: 'account.opened', }); + console.log('events_list_response', events_list_response); + [event_response] = events_list_response; const response = await client.events.retrieve(event_response.id); @@ -101,7 +107,7 @@ describe.only('Events - core methods tests', () => { }); // timeout to allow event to be created - await new Promise((resolve) => { setTimeout(resolve, 20000); }); + await new Promise((resolve) => { setTimeout(resolve, 2000); }); const events_list_response = await client.events.list({ type: 'attribute.credit_health_credit_card_usage.increased', From 3ef02aedd5c77e91e2468fb78118de8225d9eb32 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Mon, 18 Aug 2025 14:02:50 -0500 Subject: [PATCH 03/16] remove logs --- test/resources/Event.tests.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index fc822ef..ef0744b 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -63,25 +63,18 @@ describe('Events - core methods tests', () => { describe('simulate.events', () => { it('should simulate an account opened event', async () => { - console.log('simulating account opened event'); await client.simulate.events.create({ type: 'account.opened', entity_id: entity_response.id, }); - console.log('waiting for event to be created'); - // timeout to allow event to be created await new Promise((resolve) => { setTimeout(resolve, 2000); }); - console.log('listing events'); - const events_list_response = await client.events.list({ type: 'account.opened', }); - console.log('events_list_response', events_list_response); - [event_response] = events_list_response; const response = await client.events.retrieve(event_response.id); From adc8c51b081ca173883f8bd88795e2af9fb5120c Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Mon, 18 Aug 2025 14:40:49 -0500 Subject: [PATCH 04/16] follow request config pattern --- src/resource.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resource.ts b/src/resource.ts index 098ac5a..1cb3cc6 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -22,7 +22,7 @@ type TSubResources = export interface IRequestConfig { idempotency_key?: string; - headers?: Record; + prefer?: string; } class ExtensibleFunction extends Function { @@ -215,7 +215,7 @@ export default class Resource extends ExtensibleFunction { const _requestConfig = { headers: { ...(requestConfig.idempotency_key ? { 'Idempotency-Key': requestConfig.idempotency_key } : {}), - ...(requestConfig.headers || {}), + ...(requestConfig.prefer ? { 'Prefer': requestConfig.prefer } : {}), }, params, }; From 7710846f793f664e5b5bf9fb3510d48fe144f687 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Mon, 18 Aug 2025 14:42:36 -0500 Subject: [PATCH 05/16] fix card brand test --- test/resources/Account.tests.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/resources/Account.tests.ts b/test/resources/Account.tests.ts index e71cde5..0e49aa0 100644 --- a/test/resources/Account.tests.ts +++ b/test/resources/Account.tests.ts @@ -298,6 +298,7 @@ describe('Accounts - core methods tests', () => { account_id: test_credit_card_account.id, brands: [], status: 'in_progress', + shared: false, source: null, error: null, created_at: card_create_response.created_at, From 9b041e44949b1500c156e4b87517e056ff7fe3b7 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Mon, 18 Aug 2025 15:14:06 -0500 Subject: [PATCH 06/16] card brand shared property --- src/resources/Account/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index 0dee602..d619802 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -304,6 +304,7 @@ export interface IAccountCardBrand { brands: IAccountCardBrandInfo[]; source: 'method' | 'network' | null; status: 'completed' | 'in_progress' | 'failed'; + shared: boolean; error: IResourceError | null; created_at: string; updated_at: string; From 3db9d25497df12da758e203c8e5a57f567a91687 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Tue, 19 Aug 2025 18:45:39 -0500 Subject: [PATCH 07/16] fix tests --- test/index.ts | 1 + test/resources/CardProduct.tests.ts | 2 +- test/resources/Event.tests.ts | 45 +++++++---------------------- 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/test/index.ts b/test/index.ts index 71307ba..d2623a6 100644 --- a/test/index.ts +++ b/test/index.ts @@ -10,3 +10,4 @@ require('./resources/Webhook.tests'); require('./resources/HealthCheck.tests'); require('./resources/Metadata.tests'); require('./resources/Event.tests'); +require('./resources/CardProduct.tests'); diff --git a/test/resources/CardProduct.tests.ts b/test/resources/CardProduct.tests.ts index 0fa2c69..ffee302 100644 --- a/test/resources/CardProduct.tests.ts +++ b/test/resources/CardProduct.tests.ts @@ -11,7 +11,7 @@ describe('Card Products - core methods tests', () => { describe('cardProducts.retrieve', () => { it('should successfully retrieve a card product by id.', async () => { - card_products_retrieve_response = await client.cardProducts.retrieve('pdt_15'); + card_products_retrieve_response = await client.cardProducts.retrieve('pdt_17'); const expect_results: ICardProduct = { id: "pdt_17", diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index ef0744b..9e4cc85 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -71,9 +71,17 @@ describe('Events - core methods tests', () => { // timeout to allow event to be created await new Promise((resolve) => { setTimeout(resolve, 2000); }); - const events_list_response = await client.events.list({ - type: 'account.opened', - }); + const max_retries = 3; + let events_list_response: IEvent[] = []; + for (let i = 0; i < max_retries; i++) { + await new Promise((resolve) => { setTimeout(resolve, 1000); }); + events_list_response = await client.events.list({ + type: 'account.opened', + }); + if (events_list_response.length > 0) { + break; + } + } [event_response] = events_list_response; @@ -92,36 +100,5 @@ describe('Events - core methods tests', () => { response.should.be.eql(expect_results); }); - - it('should simulate an attribute created event', async () => { - await client.simulate.events.create({ - type: 'attribute.credit_health_credit_card_usage.increased', - entity_id: entity_response.id, - }); - - // timeout to allow event to be created - await new Promise((resolve) => { setTimeout(resolve, 2000); }); - - const events_list_response = await client.events.list({ - type: 'attribute.credit_health_credit_card_usage.increased', - }); - - [event_response] = events_list_response; - - const response = await client.events.retrieve(event_response.id); - - const expect_results: IEvent = { - id: event_response.id, - created_at: event_response.created_at, - updated_at: event_response.updated_at, - type: 'attribute.credit_health_credit_card_usage.increased', - resource_id: event_response.resource_id, - resource_type: 'attribute', - data: event_response.data, - diff: event_response.diff, - }; - - response.should.be.eql(expect_results); - }); }); }); From a28f5948e578597328b8cbaac150eea3814b622d Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Tue, 19 Aug 2025 18:47:01 -0500 Subject: [PATCH 08/16] header fix in tests --- test/resources/Entity.tests.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/resources/Entity.tests.ts b/test/resources/Entity.tests.ts index bc7c645..7e8f5e4 100644 --- a/test/resources/Entity.tests.ts +++ b/test/resources/Entity.tests.ts @@ -552,9 +552,7 @@ describe('Entities - core methods tests', () => { }, {}, { - headers: { - 'Prefer': 'respond-async', - } + 'Prefer': 'respond-async', }); const expect_results: IEntityConnect = { From c473926386c43eaae3361d1157df6bb97eafbba3 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Tue, 19 Aug 2025 18:54:22 -0500 Subject: [PATCH 09/16] minor nits --- test/resources/Entity.tests.ts | 2 +- test/resources/Event.tests.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/resources/Entity.tests.ts b/test/resources/Entity.tests.ts index 7e8f5e4..46a37a3 100644 --- a/test/resources/Entity.tests.ts +++ b/test/resources/Entity.tests.ts @@ -552,7 +552,7 @@ describe('Entities - core methods tests', () => { }, {}, { - 'Prefer': 'respond-async', + 'prefer': 'respond-async', }); const expect_results: IEntityConnect = { diff --git a/test/resources/Event.tests.ts b/test/resources/Event.tests.ts index 9e4cc85..165aab1 100644 --- a/test/resources/Event.tests.ts +++ b/test/resources/Event.tests.ts @@ -72,7 +72,7 @@ describe('Events - core methods tests', () => { await new Promise((resolve) => { setTimeout(resolve, 2000); }); const max_retries = 3; - let events_list_response: IEvent[] = []; + let events_list_response: IResponse[] = []; for (let i = 0; i < max_retries; i++) { await new Promise((resolve) => { setTimeout(resolve, 1000); }); events_list_response = await client.events.list({ From 8697d694d734ca3179e8db0f464a8615ab843939 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Fri, 24 Oct 2025 15:59:51 -0500 Subject: [PATCH 10/16] add opal and simulations --- src/index.ts | 1 + src/method.ts | 3 + src/resources/Account/types.ts | 19 +++++++ src/resources/Opal/Token.ts | 24 ++++++++ src/resources/Opal/index.ts | 15 +++++ src/resources/Opal/types.ts | 57 +++++++++++++++++++ src/resources/Simulate/Entities/Attributes.ts | 33 +++++++++++ src/resources/Simulate/Entities/Connect.ts | 33 +++++++++++ src/resources/Simulate/Entities/index.ts | 6 ++ src/resources/Simulate/types.ts | 25 ++++++++ src/resources/Webhook/types.ts | 2 + test/index.ts | 2 +- test/resources/CardProduct.tests.ts | 43 -------------- test/resources/Opal.tests.ts | 42 ++++++++++++++ 14 files changed, 261 insertions(+), 44 deletions(-) create mode 100644 src/resources/Opal/Token.ts create mode 100644 src/resources/Opal/index.ts create mode 100644 src/resources/Opal/types.ts create mode 100644 src/resources/Simulate/Entities/Attributes.ts create mode 100644 src/resources/Simulate/Entities/Connect.ts create mode 100644 src/resources/Simulate/types.ts delete mode 100644 test/resources/CardProduct.tests.ts create mode 100644 test/resources/Opal.tests.ts diff --git a/src/index.ts b/src/index.ts index ddaaa56..abebbd3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,3 +18,4 @@ export * from './resources/Payment'; export * from './resources/Report'; export * from './resources/Simulate'; export * from './resources/Webhook'; +export * from './resources/Opal'; diff --git a/src/method.ts b/src/method.ts index 659115d..32469de 100644 --- a/src/method.ts +++ b/src/method.ts @@ -10,6 +10,7 @@ import Report from './resources/Report'; import Webhook from './resources/Webhook'; import HealthCheck, { IPingResponse } from './resources/HealthCheck'; import Simulate from './resources/Simulate'; +import Opal from './resources/Opal'; export class Method { accounts: Account; @@ -23,6 +24,7 @@ export class Method { webhooks: Webhook; healthcheck: HealthCheck; simulate: Simulate; + opal: Opal; constructor(opts: IConfigurationOpts) { const config = new Configuration(opts); @@ -39,6 +41,7 @@ export class Method { this.webhooks = new Webhook(config); this.healthcheck = new HealthCheck(config); this.simulate = new Simulate(config); + this.opal = new Opal(config); } public async ping(): Promise> { diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index d619802..1252199 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -279,6 +279,7 @@ export interface IAccountLiability { ownership: TAccountOwnership | null; fingerprint: string| null; type: TAccountLiabilityTypes | null; + sub_type: TAccountLiabilitySubTypes | null; name: string | null; }; @@ -702,6 +703,24 @@ export interface IAccountPaymentInstrument { updated_at: Date; } +export const AccountLiabilitySubTypes = { + business: 'business', + unsecured: 'unsecured', + lease: 'lease', + loan: 'loan', + heloc: 'heloc', + charge: 'charge', + flexible_spending: 'flexible_spending', + secured: 'secured', + purchase: 'purchase', + note: 'note', + private: 'private', + federal: 'federal', + rent: 'rent', +} as const; + +export type TAccountLiabilitySubTypes = keyof typeof AccountLiabilitySubTypes; + export interface IAccount { id: string; holder_id: string; diff --git a/src/resources/Opal/Token.ts b/src/resources/Opal/Token.ts new file mode 100644 index 0000000..bf353ba --- /dev/null +++ b/src/resources/Opal/Token.ts @@ -0,0 +1,24 @@ +import Resource from '../../resource'; +import Configuration, { IResponse } from '../../configuration'; +import type { + IOpalToken, + IOpalTokenCreateOpts, +} from './types'; + +export default class OpalToken extends Resource { + constructor(config: Configuration) { + super(config.addPath('token')); + } + + /** + * Creates token to be used with Opal + * https://docs.methodfi.com/reference/opal/create_token + * + * @param opts IOpalTokenCreateOpts + * @returns IOpal { token: string, valid_until: string, session_id: string }; + */ + + async create(opts: IOpalTokenCreateOpts) { + return super._create, IOpalTokenCreateOpts>(opts); + } +}; diff --git a/src/resources/Opal/index.ts b/src/resources/Opal/index.ts new file mode 100644 index 0000000..6de9374 --- /dev/null +++ b/src/resources/Opal/index.ts @@ -0,0 +1,15 @@ +import Resource from '../../resource'; +import Configuration from '../../configuration'; +import Token from './Token'; + +export default class Opal extends Resource { + token: Token; + + constructor(config: Configuration) { + const _config = config.addPath('opal'); + super(_config); + this.token = new Token(_config); + } +}; + +export * from './types'; diff --git a/src/resources/Opal/types.ts b/src/resources/Opal/types.ts new file mode 100644 index 0000000..2cfb9f0 --- /dev/null +++ b/src/resources/Opal/types.ts @@ -0,0 +1,57 @@ +const OpalModes = { + identity_verification: 'identity_verification', + connect: 'connect', + card_connect: 'card_connect', + account_verification: 'account_verification', + transactions: 'transactions', +} as const; + +export type TOpalModes = keyof typeof OpalModes; + +const SkipPII = { + name: 'name', + dob: 'dob', + address: 'address', + ssn_4: 'ssn_4', +} as const; + +export type TSkipPII = keyof typeof SkipPII; + +export interface IOpalIdentityVerificationCreateOpts { + skip_pii: TSkipPII[]; +} + +export interface IOpalConnectCreateOpts { + skip_pii: TSkipPII[]; + selection_type: 'single' | 'multiple' | 'all'; + allowed_account_types: 'credit_card' | 'auto_loan' | 'mortgage' | 'personal_loan' | 'student_loan'; +} + +export interface IOpalCardConnectCreateOpts { + skip_pii: TSkipPII[]; + selection_type: 'single' | 'multiple' | 'all'; +} + +export interface IOpalAccountVerificationCreateOpts { + account_id: string; +} + +export interface IOpalTransactionsCreateOpts { + transactions: {}; +} + +export interface IOpalTokenCreateOpts { + mode: TOpalModes; + entity_id: string; + identity_verification?: IOpalIdentityVerificationCreateOpts; + connect?: IOpalConnectCreateOpts; + card_connect?: IOpalCardConnectCreateOpts; + account_verification?: IOpalAccountVerificationCreateOpts; + transactions?: IOpalTransactionsCreateOpts; +} + +export interface IOpalToken { + token: string; + valid_until: string; + session_id: string; +} \ No newline at end of file diff --git a/src/resources/Simulate/Entities/Attributes.ts b/src/resources/Simulate/Entities/Attributes.ts new file mode 100644 index 0000000..5a59cbf --- /dev/null +++ b/src/resources/Simulate/Entities/Attributes.ts @@ -0,0 +1,33 @@ +import Resource from '../../../resource'; +import Configuration, { IResponse } from '../../../configuration'; +import type { SimulateEntityAttributesOpts } from '../types'; + +export class SimulateAttributesInstance extends Resource { + constructor(entity_id: string, config: Configuration) { + super(config.addPath(entity_id)); + } + + /** + * For Entities that have been successfully verified, you may simulate Attributes in the dev environment. + * https://docs.methodfi.com/reference/simulations/attributes/create + * + * @param opts SimulateEntityAttributesOpts + */ + async create(opts: SimulateEntityAttributesOpts) { + return super._create, SimulateEntityAttributesOpts>(opts); + } +} + +export default interface SimulateAttributes { + (entity_id: string): SimulateAttributesInstance; +} + +export default class SimulateAttributes extends Resource { + constructor(config: Configuration) { + super(config.addPath('attributes')); + } + + protected _call(entity_id: string): SimulateAttributesInstance { + return new SimulateAttributesInstance(entity_id, this.config); + } +} diff --git a/src/resources/Simulate/Entities/Connect.ts b/src/resources/Simulate/Entities/Connect.ts new file mode 100644 index 0000000..617c94a --- /dev/null +++ b/src/resources/Simulate/Entities/Connect.ts @@ -0,0 +1,33 @@ +import Resource from '../../../resource'; +import Configuration, { IResponse } from '../../../configuration'; +import type { SimulateEntityConnectOpts } from '../types'; + +export class SimulateConnectInstance extends Resource { + constructor(entity_id: string, config: Configuration) { + super(config.addPath(entity_id)); + } + + /** + * For Entities that have been successfully verified, you may simulate Connect in the dev environment. + * https://docs.methodfi.com/reference/simulations/connect/create + * + * @param opts SimulateEntityConnectOpts + */ + async create(opts: SimulateEntityConnectOpts) { + return super._create, SimulateEntityConnectOpts>(opts); + } +} + +export default interface SimulateConnect { + (entity_id: string): SimulateConnectInstance; +} + +export default class SimulateConnect extends Resource { + constructor(config: Configuration) { + super(config.addPath('connect')); + } + + protected _call(entity_id: string): SimulateConnectInstance { + return new SimulateConnectInstance(entity_id, this.config); + } +} diff --git a/src/resources/Simulate/Entities/index.ts b/src/resources/Simulate/Entities/index.ts index fc0b384..aefa859 100644 --- a/src/resources/Simulate/Entities/index.ts +++ b/src/resources/Simulate/Entities/index.ts @@ -1,11 +1,17 @@ import Resource from '../../../resource'; import Configuration from '../../../configuration'; import SimulateCreditScores from './CreditScores'; +import SimulateConnect from './Connect'; +import SimulateAttributes from './Attributes'; export class SimulateEntitiesSubResources { creditScores: SimulateCreditScores; + connect: SimulateConnect; + attributes: SimulateAttributes; constructor(entity_id: string, config: Configuration) { this.creditScores = new SimulateCreditScores(config.addPath(entity_id)); + this.connect = new SimulateConnect(config.addPath(entity_id)); + this.attributes = new SimulateAttributes(config.addPath(entity_id)); } } diff --git a/src/resources/Simulate/types.ts b/src/resources/Simulate/types.ts new file mode 100644 index 0000000..5f14217 --- /dev/null +++ b/src/resources/Simulate/types.ts @@ -0,0 +1,25 @@ +export const ConnectBehaviors = { + new_credit_card_account: 'new_credit_card_account', + new_auto_loan_account: 'new_auto_loan_account', + new_mortgage_account: 'new_mortgage_account', + new_student_loan_account: 'new_student_loan_account', + new_personal_loan_account: 'new_personal_loan_account', +} as const; + +export type TConnectBehaviors = + (typeof ConnectBehaviors)[keyof typeof ConnectBehaviors]; + +export type SimulateEntityConnectOpts = { + behaviors: TConnectBehaviors[]; +}; + +export const AttributesBehaviors = { + new_soft_inquiry: 'new_soft_inquiry', +} as const; + +export type TAttributesBehaviors = + (typeof AttributesBehaviors)[keyof typeof AttributesBehaviors]; + +export type SimulateEntityAttributesOpts = { + behaviors: TAttributesBehaviors[]; +}; diff --git a/src/resources/Webhook/types.ts b/src/resources/Webhook/types.ts index acf76b2..791f24f 100644 --- a/src/resources/Webhook/types.ts +++ b/src/resources/Webhook/types.ts @@ -27,6 +27,7 @@ export const WebhookTypes = { entity_verification_session_update: 'entity_verification_session.update', connect_create: 'connect.create', connect_update: 'connect.update', + connect_available: 'connect.available', balance_create: 'balance.create', balance_update: 'balance.update', identity_create: 'identity.create', @@ -35,6 +36,7 @@ export const WebhookTypes = { account_verification_session_update: 'account_verification_session.update', card_brand_create: 'card_brand.create', card_brand_update: 'card_brand.update', + card_brand_available: 'card_brand.available', sensitive_create: 'sensitive.create', sensitive_update: 'sensitive.update', update_create: 'update.create', diff --git a/test/index.ts b/test/index.ts index d2623a6..3bef1b7 100644 --- a/test/index.ts +++ b/test/index.ts @@ -10,4 +10,4 @@ require('./resources/Webhook.tests'); require('./resources/HealthCheck.tests'); require('./resources/Metadata.tests'); require('./resources/Event.tests'); -require('./resources/CardProduct.tests'); +require('./resources/Opal.tests'); diff --git a/test/resources/CardProduct.tests.ts b/test/resources/CardProduct.tests.ts deleted file mode 100644 index ffee302..0000000 --- a/test/resources/CardProduct.tests.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { should } from 'chai'; -import { describe } from 'mocha'; -import { client } from '../config'; -import type { ICardProduct } from '../../src/resources/CardProduct'; -import { IResponse } from '../../src/configuration'; - -should(); - -describe('Card Products - core methods tests', () => { - let card_products_retrieve_response: IResponse; - - describe('cardProducts.retrieve', () => { - it('should successfully retrieve a card product by id.', async () => { - card_products_retrieve_response = await client.cardProducts.retrieve('pdt_17'); - - const expect_results: ICardProduct = { - id: "pdt_17", - name: "Chase Freedom", - issuer: "Chase", - type: "specific", - brands: [ - { - id: "pdt_17_brd_1", - description: "Chase Freedom", - network: "visa", - default_image: "https://static.methodfi.com/card_brands/fb5fbd6a5d45b942752b9dc641b93d1f.png" - }, - { - id: "pdt_17_brd_2", - description: "Chase Freedom", - network: "visa", - default_image: "https://static.methodfi.com/card_brands/6cb697528b0771f982f7c0e8b8869de3.png" - } - ], - error: null, - created_at: card_products_retrieve_response.created_at, - updated_at: card_products_retrieve_response.updated_at, - } - - card_products_retrieve_response.should.be.eql(expect_results); - }); - }); -}); diff --git a/test/resources/Opal.tests.ts b/test/resources/Opal.tests.ts new file mode 100644 index 0000000..709b0b1 --- /dev/null +++ b/test/resources/Opal.tests.ts @@ -0,0 +1,42 @@ +import { should } from 'chai'; +import { describe } from 'mocha'; +import { client } from '../config'; +import type { IEntity } from '../../src/resources/Entity'; +import type { IOpalToken } from '../../src/resources/Opal'; +import { IResponse } from '../../src/configuration'; + +should(); + +describe('Opal - core methods tests', () => { + let entity_1_response: IResponse; + let opal_create_token_response: IResponse; + + before(async () => { + entity_1_response = await client.entities.create({ + type: 'individual', + individual: { + first_name: 'Kevin', + last_name: 'Doyle', + dob: '1930-03-11', + email: 'kevin.doyle@gmail.com', + phone: '+15121231111', + }, + }); + }); + + describe('opal.token.create', () => { + it('should successfully create a opal token.', async () => { + opal_create_token_response = await client.opal.token.create({ + entity_id: entity_1_response.id, + mode: 'identity_verification', + identity_verification: { + skip_pii: ['ssn_4'], + }, + }); + + opal_create_token_response.should.have.property('token'); + opal_create_token_response.should.have.property('valid_until'); + opal_create_token_response.should.have.property('session_id'); + }); + }); +}); From ec9a7c1334ff348746d79fa988b3683921697e65 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Fri, 24 Oct 2025 16:10:27 -0500 Subject: [PATCH 11/16] fix tests? --- src/resource.ts | 4 ++++ src/resources/Account/types.ts | 19 ------------------- src/resources/Simulate/Entities/Attributes.ts | 2 +- src/resources/Simulate/Entities/Connect.ts | 2 +- .../Simulate/Entities/CreditScores.ts | 2 +- 5 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/resource.ts b/src/resource.ts index 4fea954..ffdc99c 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -11,6 +11,8 @@ import { EntitySubResources } from './resources/Entity'; import { SimulateAccountsSubResources } from './resources/Simulate/Accounts'; import { SimulateEntitiesSubResources } from './resources/Simulate/Entities'; import { SimulateCreditScoresInstance } from './resources/Simulate/Entities/CreditScores'; +import { SimulateConnectInstance } from './resources/Simulate/Entities/Connect'; +import { SimulateAttributesInstance } from './resources/Simulate/Entities/Attributes'; type TSubResources = | AccountSubResources @@ -19,6 +21,8 @@ type TSubResources = | SimulateAccountsSubResources | SimulateEntitiesSubResources | SimulateCreditScoresInstance; + | SimulateConnectInstance + | SimulateAttributesInstance export interface IRequestConfig { idempotency_key?: string; diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index 1252199..d619802 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -279,7 +279,6 @@ export interface IAccountLiability { ownership: TAccountOwnership | null; fingerprint: string| null; type: TAccountLiabilityTypes | null; - sub_type: TAccountLiabilitySubTypes | null; name: string | null; }; @@ -703,24 +702,6 @@ export interface IAccountPaymentInstrument { updated_at: Date; } -export const AccountLiabilitySubTypes = { - business: 'business', - unsecured: 'unsecured', - lease: 'lease', - loan: 'loan', - heloc: 'heloc', - charge: 'charge', - flexible_spending: 'flexible_spending', - secured: 'secured', - purchase: 'purchase', - note: 'note', - private: 'private', - federal: 'federal', - rent: 'rent', -} as const; - -export type TAccountLiabilitySubTypes = keyof typeof AccountLiabilitySubTypes; - export interface IAccount { id: string; holder_id: string; diff --git a/src/resources/Simulate/Entities/Attributes.ts b/src/resources/Simulate/Entities/Attributes.ts index 5a59cbf..00e45ec 100644 --- a/src/resources/Simulate/Entities/Attributes.ts +++ b/src/resources/Simulate/Entities/Attributes.ts @@ -18,7 +18,7 @@ export class SimulateAttributesInstance extends Resource { } } -export default interface SimulateAttributes { +export interface SimulateAttributes { (entity_id: string): SimulateAttributesInstance; } diff --git a/src/resources/Simulate/Entities/Connect.ts b/src/resources/Simulate/Entities/Connect.ts index 617c94a..965559c 100644 --- a/src/resources/Simulate/Entities/Connect.ts +++ b/src/resources/Simulate/Entities/Connect.ts @@ -18,7 +18,7 @@ export class SimulateConnectInstance extends Resource { } } -export default interface SimulateConnect { +export interface SimulateConnect { (entity_id: string): SimulateConnectInstance; } diff --git a/src/resources/Simulate/Entities/CreditScores.ts b/src/resources/Simulate/Entities/CreditScores.ts index 8fc9403..c5864d9 100644 --- a/src/resources/Simulate/Entities/CreditScores.ts +++ b/src/resources/Simulate/Entities/CreditScores.ts @@ -21,7 +21,7 @@ export class SimulateCreditScoresInstance extends Resource { } } -export default interface SimulateCreditScores { +export interface SimulateCreditScores { (crs_id: string): SimulateCreditScoresInstance; } From 720806e1f1091223a82b5fbce03595b5910b8d17 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Fri, 24 Oct 2025 16:11:36 -0500 Subject: [PATCH 12/16] nit --- src/resource.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resource.ts b/src/resource.ts index ffdc99c..f7bae6d 100644 --- a/src/resource.ts +++ b/src/resource.ts @@ -20,9 +20,9 @@ type TSubResources = | EntitySubResources | SimulateAccountsSubResources | SimulateEntitiesSubResources - | SimulateCreditScoresInstance; + | SimulateCreditScoresInstance | SimulateConnectInstance - | SimulateAttributesInstance + | SimulateAttributesInstance; export interface IRequestConfig { idempotency_key?: string; From d7c8511f1756447bc5081b99fc7b1ea560ce8711 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Fri, 24 Oct 2025 16:19:35 -0500 Subject: [PATCH 13/16] fix declarations --- src/resources/Simulate/Entities/Attributes.ts | 6 ++++-- src/resources/Simulate/Entities/Connect.ts | 6 ++++-- src/resources/Simulate/Entities/CreditScores.ts | 9 +++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/resources/Simulate/Entities/Attributes.ts b/src/resources/Simulate/Entities/Attributes.ts index 00e45ec..423fed6 100644 --- a/src/resources/Simulate/Entities/Attributes.ts +++ b/src/resources/Simulate/Entities/Attributes.ts @@ -14,7 +14,7 @@ export class SimulateAttributesInstance extends Resource { * @param opts SimulateEntityAttributesOpts */ async create(opts: SimulateEntityAttributesOpts) { - return super._create, SimulateEntityAttributesOpts>(opts); + return super._create, SimulateEntityAttributesOpts>(opts); } } @@ -22,7 +22,7 @@ export interface SimulateAttributes { (entity_id: string): SimulateAttributesInstance; } -export default class SimulateAttributes extends Resource { +export class SimulateAttributes extends Resource { constructor(config: Configuration) { super(config.addPath('attributes')); } @@ -31,3 +31,5 @@ export default class SimulateAttributes extends Resource { return new SimulateAttributesInstance(entity_id, this.config); } } + +export default SimulateAttributes; diff --git a/src/resources/Simulate/Entities/Connect.ts b/src/resources/Simulate/Entities/Connect.ts index 965559c..da26e08 100644 --- a/src/resources/Simulate/Entities/Connect.ts +++ b/src/resources/Simulate/Entities/Connect.ts @@ -14,7 +14,7 @@ export class SimulateConnectInstance extends Resource { * @param opts SimulateEntityConnectOpts */ async create(opts: SimulateEntityConnectOpts) { - return super._create, SimulateEntityConnectOpts>(opts); + return super._create, SimulateEntityConnectOpts>(opts); } } @@ -22,7 +22,7 @@ export interface SimulateConnect { (entity_id: string): SimulateConnectInstance; } -export default class SimulateConnect extends Resource { +export class SimulateConnect extends Resource { constructor(config: Configuration) { super(config.addPath('connect')); } @@ -31,3 +31,5 @@ export default class SimulateConnect extends Resource { return new SimulateConnectInstance(entity_id, this.config); } } + +export default SimulateConnect; diff --git a/src/resources/Simulate/Entities/CreditScores.ts b/src/resources/Simulate/Entities/CreditScores.ts index c5864d9..7b5e97c 100644 --- a/src/resources/Simulate/Entities/CreditScores.ts +++ b/src/resources/Simulate/Entities/CreditScores.ts @@ -17,7 +17,10 @@ export class SimulateCreditScoresInstance extends Resource { * @returns Returns the created Credit Score. */ async create(opts: { scores: IEntityCreditScoresType[] }) { - return super._create, { scores: IEntityCreditScoresType[] }>(opts); + return super._create< + IResponse, + { scores: IEntityCreditScoresType[] } + >(opts); } } @@ -25,7 +28,7 @@ export interface SimulateCreditScores { (crs_id: string): SimulateCreditScoresInstance; } -export default class SimulateCreditScores extends Resource { +export class SimulateCreditScores extends Resource { constructor(config: Configuration) { super(config.addPath('credit_scores')); } @@ -34,3 +37,5 @@ export default class SimulateCreditScores extends Resource { return new SimulateCreditScoresInstance(crs_id, this.config); } } + +export default SimulateCreditScores; From 3c659493b6b2554e2ece8b7efe8f4dd789b58ee6 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Tue, 28 Oct 2025 19:23:00 -0500 Subject: [PATCH 14/16] fix test utils --- test/utils.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/utils.ts b/test/utils.ts index 42a8976..b62c5af 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,10 +1,11 @@ -export const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); +export const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); type AwaitResultsFn = (fn: () => Promise) => Promise; export const awaitResults: AwaitResultsFn = async (fn) => { let result; - let retries = 10; + let retries = 20; while (retries > 0) { try { result = await fn(); @@ -17,7 +18,14 @@ export const awaitResults: AwaitResultsFn = async (fn) => { throw error; // Rethrow the error to fail the test } retries--; - }; + } + + // Throw error if we exhausted retries without getting completed/failed status + if (result && result.status !== 'completed' && result.status !== 'failed') { + throw new Error( + `awaitResults timed out after 10 retries. Final status: ${result.status}` + ); + } return result; }; From e45f5ba9161dd6e306503b2b1ef7eac75bc6dc9a Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Wed, 29 Oct 2025 14:58:13 -0500 Subject: [PATCH 15/16] additional opal types --- src/resources/Opal/types.ts | 39 ++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/resources/Opal/types.ts b/src/resources/Opal/types.ts index 2cfb9f0..dc5ed29 100644 --- a/src/resources/Opal/types.ts +++ b/src/resources/Opal/types.ts @@ -5,7 +5,6 @@ const OpalModes = { account_verification: 'account_verification', transactions: 'transactions', } as const; - export type TOpalModes = keyof typeof OpalModes; const SkipPII = { @@ -14,22 +13,52 @@ const SkipPII = { address: 'address', ssn_4: 'ssn_4', } as const; - export type TSkipPII = keyof typeof SkipPII; +const AccountFiltersAccountTypes = { + credit_card: 'credit_card', + auto_loan: 'auto_loan', + mortgage: 'mortgage', + personal_loan: 'personal_loan', + student_loan: 'student_loan', +} as const; +export type TAccountFiltersAccountTypes = keyof typeof AccountFiltersAccountTypes; + +export type TSelectionType = 'single' | 'multiple' | 'all'; + +export interface IOpalAccountFiltersInclude { + account_types: TAccountFiltersAccountTypes[]; +} + +export interface IOpalAccountFiltersExclude { + account_types: TAccountFiltersAccountTypes[]; + mch_ids: string[]; + unverified_account_numbers: boolean; +} + +export interface IConnectAccountFilters { + include: IOpalAccountFiltersInclude; + exclude: IOpalAccountFiltersExclude; +} + +export interface ICardConnectAccountFilters { + exclude: Omit; +} + export interface IOpalIdentityVerificationCreateOpts { skip_pii: TSkipPII[]; } export interface IOpalConnectCreateOpts { skip_pii: TSkipPII[]; - selection_type: 'single' | 'multiple' | 'all'; - allowed_account_types: 'credit_card' | 'auto_loan' | 'mortgage' | 'personal_loan' | 'student_loan'; + selection_type: TSelectionType; + account_filters: IConnectAccountFilters; } export interface IOpalCardConnectCreateOpts { skip_pii: TSkipPII[]; - selection_type: 'single' | 'multiple' | 'all'; + selection_type: TSelectionType; + account_filters: ICardConnectAccountFilters; } export interface IOpalAccountVerificationCreateOpts { From bae8bb5d1dddeb5f95c2cb8f5048e69b71afc370 Mon Sep 17 00:00:00 2001 From: Bilal Hussain Date: Wed, 29 Oct 2025 15:33:07 -0500 Subject: [PATCH 16/16] add liability sub types --- src/resources/Account/types.ts | 20 ++++++++++++++++++++ test/resources/Account.tests.ts | 1 + 2 files changed, 21 insertions(+) diff --git a/src/resources/Account/types.ts b/src/resources/Account/types.ts index d619802..873e0ca 100644 --- a/src/resources/Account/types.ts +++ b/src/resources/Account/types.ts @@ -279,6 +279,7 @@ export interface IAccountLiability { ownership: TAccountOwnership | null; fingerprint: string| null; type: TAccountLiabilityTypes | null; + sub_type: TAccountLiabilitySubTypes | null; name: string | null; }; @@ -702,6 +703,25 @@ export interface IAccountPaymentInstrument { updated_at: Date; } +export const AccountLiabilitySubTypes = { + business: 'business', + unsecured: 'unsecured', + lease: 'lease', + loan: 'loan', + heloc: 'heloc', + charge: 'charge', + flexible_spending: 'flexible_spending', + secured: 'secured', + purchase: 'purchase', + note: 'note', + private: 'private', + federal: 'federal', + rent: 'rent', +} as const; + +export type TAccountLiabilitySubTypes = keyof typeof AccountLiabilitySubTypes; + + export interface IAccount { id: string; holder_id: string; diff --git a/test/resources/Account.tests.ts b/test/resources/Account.tests.ts index 5b3cfb3..6f07aae 100644 --- a/test/resources/Account.tests.ts +++ b/test/resources/Account.tests.ts @@ -146,6 +146,7 @@ describe('Accounts - core methods tests', () => { mask: '8721', ownership: 'unknown', type: 'credit_card', + sub_type: 'flexible_spending', name: 'Chase Sapphire Reserve' }, latest_verification_session: accounts_create_liability_response.latest_verification_session,