import type { IExecuteFunctions, IDataObject, INodeExecutionData, INodeType, INodeTypeDescription, } from 'n8n-workflow'; import { strikeApiRequest, strikeApiRequestAllItems } from './StrikeApi'; import { balanceOperations, balanceFields, invoiceOperations, invoiceFields, paymentOperations, paymentFields, depositOperations, depositFields, payoutOperations, payoutFields, currencyExchangeOperations, currencyExchangeFields, ratesOperations, ratesFields, accountOperations, accountFields, paymentMethodOperations, paymentMethodFields, eventOperations, eventFields, } from './descriptions'; export class Strike implements INodeType { description: INodeTypeDescription = { displayName: 'Strike', name: 'strike', icon: 'file:strike.png', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Interact with Strike API for Bitcoin and Lightning payments', defaults: { name: 'Strike', }, inputs: ['main'], outputs: ['main'], credentials: [ { name: 'strikeApi', required: true, }, ], properties: [ { displayName: 'Resource', name: 'resource', type: 'options', noDataExpression: true, options: [ { name: 'Account', value: 'account', }, { name: 'Balance', value: 'balance', }, { name: 'Currency Exchange', value: 'currencyExchange', }, { name: 'Deposit', value: 'deposit', }, { name: 'Event', value: 'event', }, { name: 'Invoice', value: 'invoice', }, { name: 'Payment', value: 'payment', }, { name: 'Payment Method', value: 'paymentMethod', }, { name: 'Payout', value: 'payout', }, { name: 'Rates', value: 'rates', }, ], default: 'balance', }, // Operations and fields for each resource ...accountOperations, ...accountFields, ...balanceOperations, ...balanceFields, ...currencyExchangeOperations, ...currencyExchangeFields, ...depositOperations, ...depositFields, ...eventOperations, ...eventFields, ...invoiceOperations, ...invoiceFields, ...paymentOperations, ...paymentFields, ...paymentMethodOperations, ...paymentMethodFields, ...payoutOperations, ...payoutFields, ...ratesOperations, ...ratesFields, ], }; async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const returnData: INodeExecutionData[] = []; const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; for (let i = 0; i < items.length; i++) { try { let responseData: any; // ---------------------------------------- // account // ---------------------------------------- if (resource === 'account') { if (operation === 'getProfile') { const accountId = this.getNodeParameter('accountId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/accounts/${accountId}/profile`); } else if (operation === 'getProfileByHandle') { const handle = this.getNodeParameter('handle', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/accounts/handle/${handle}/profile`); } else if (operation === 'getLimits') { responseData = await strikeApiRequest.call(this, 'GET', '/accounts/limits'); } } // ---------------------------------------- // balance // ---------------------------------------- if (resource === 'balance') { if (operation === 'get') { responseData = await strikeApiRequest.call(this, 'GET', '/balances'); } } // ---------------------------------------- // currencyExchange // ---------------------------------------- if (resource === 'currencyExchange') { if (operation === 'createQuote') { const sell = this.getNodeParameter('sell', i) as string; const buy = this.getNodeParameter('buy', i) as string; const amount = this.getNodeParameter('amount', i) as number; const amountCurrency = this.getNodeParameter('amountCurrency', i) as string; const body: IDataObject = { sell, buy, amount: { amount: amount.toString(), currency: amountCurrency === 'sell' ? sell : buy, }, }; responseData = await strikeApiRequest.call(this, 'POST', '/currency-exchange-quotes', body); } else if (operation === 'getQuote') { const quoteId = this.getNodeParameter('quoteId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/currency-exchange-quotes/${quoteId}`); } else if (operation === 'executeQuote') { const quoteId = this.getNodeParameter('quoteId', i) as string; responseData = await strikeApiRequest.call(this, 'PATCH', `/currency-exchange-quotes/${quoteId}/execute`); } } // ---------------------------------------- // event // ---------------------------------------- if (resource === 'event') { if (operation === 'get') { const eventId = this.getNodeParameter('eventId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/events/${eventId}`); } else if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; const filters = this.getNodeParameter('filters', i) as IDataObject; const query: IDataObject = {}; if (filters.filter) { query.$filter = filters.filter; } if (filters.orderBy) { query.$orderby = filters.orderBy; } if (returnAll) { responseData = await strikeApiRequestAllItems.call(this, 'GET', '/events', {}, query); } else { const limit = this.getNodeParameter('limit', i) as number; query.$top = limit; responseData = await strikeApiRequest.call(this, 'GET', '/events', {}, query); responseData = responseData.items || responseData; } } } // ---------------------------------------- // deposit // ---------------------------------------- if (resource === 'deposit') { if (operation === 'create') { const paymentMethodId = this.getNodeParameter('paymentMethodId', i) as string; const amount = this.getNodeParameter('amount', i) as number; const currency = this.getNodeParameter('currency', i) as string; const body: IDataObject = { paymentMethodId, amount: { amount: amount.toString(), currency, }, }; responseData = await strikeApiRequest.call(this, 'POST', '/deposits', body); } else if (operation === 'get') { const depositId = this.getNodeParameter('depositId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/deposits/${depositId}`); } else if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; const filters = this.getNodeParameter('filters', i) as IDataObject; const query: IDataObject = {}; if (filters.filter) { query.$filter = filters.filter; } if (filters.orderBy) { query.$orderby = filters.orderBy; } if (returnAll) { responseData = await strikeApiRequestAllItems.call(this, 'GET', '/deposits', {}, query); } else { const limit = this.getNodeParameter('limit', i) as number; query.$top = limit; responseData = await strikeApiRequest.call(this, 'GET', '/deposits', {}, query); responseData = responseData.items || responseData; } } else if (operation === 'estimateFee') { const amount = this.getNodeParameter('amount', i) as number; const currency = this.getNodeParameter('currency', i) as string; const feePolicy = this.getNodeParameter('feePolicy', i) as string; const body: IDataObject = { amount: { amount: amount.toString(), currency, }, feePolicy, }; responseData = await strikeApiRequest.call(this, 'POST', '/deposits/fee', body); } } // ---------------------------------------- // invoice // ---------------------------------------- if (resource === 'invoice') { if (operation === 'create') { const correlationId = this.getNodeParameter('correlationId', i) as string; const description = this.getNodeParameter('description', i) as string; const amount = this.getNodeParameter('amount', i) as number; const currency = this.getNodeParameter('currency', i) as string; const body: IDataObject = {}; if (correlationId) { body.correlationId = correlationId; } if (description) { body.description = description; } if (amount > 0) { body.amount = { amount: amount.toString(), currency, }; } responseData = await strikeApiRequest.call(this, 'POST', '/invoices', body); } else if (operation === 'get') { const invoiceId = this.getNodeParameter('invoiceId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/invoices/${invoiceId}`); } else if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; const filters = this.getNodeParameter('filters', i) as IDataObject; const query: IDataObject = {}; if (filters.filter) { query.$filter = filters.filter; } if (filters.orderBy) { query.$orderby = filters.orderBy; } if (returnAll) { responseData = await strikeApiRequestAllItems.call(this, 'GET', '/invoices', {}, query); } else { const limit = this.getNodeParameter('limit', i) as number; query.$top = limit; responseData = await strikeApiRequest.call(this, 'GET', '/invoices', {}, query); responseData = responseData.items || responseData; } } else if (operation === 'createQuote') { const invoiceId = this.getNodeParameter('invoiceId', i) as string; const descriptionHash = this.getNodeParameter('descriptionHash', i) as string; const body: IDataObject = {}; if (descriptionHash) { body.descriptionHash = descriptionHash; } responseData = await strikeApiRequest.call(this, 'POST', `/invoices/${invoiceId}/quote`, body); } else if (operation === 'cancel') { const invoiceId = this.getNodeParameter('invoiceId', i) as string; responseData = await strikeApiRequest.call(this, 'PATCH', `/invoices/${invoiceId}/cancel`); } } // ---------------------------------------- // payment // ---------------------------------------- if (resource === 'payment') { if (operation === 'get') { const paymentId = this.getNodeParameter('paymentId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/payments/${paymentId}`); } else if (operation === 'createLightningQuote') { const lnInvoice = this.getNodeParameter('lnInvoice', i) as string; const sourceCurrency = this.getNodeParameter('sourceCurrency', i) as string; const body: IDataObject = { lnInvoice, sourceCurrency, }; responseData = await strikeApiRequest.call(this, 'POST', '/payment-quotes/lightning', body); } else if (operation === 'createOnchainQuote') { const btcAddress = this.getNodeParameter('btcAddress', i) as string; const sourceCurrency = this.getNodeParameter('sourceCurrency', i) as string; const amount = this.getNodeParameter('amount', i) as number; const amountCurrency = this.getNodeParameter('amountCurrency', i) as string; const body: IDataObject = { btcAddress, sourceCurrency, amount: { amount: amount.toString(), currency: amountCurrency, }, }; responseData = await strikeApiRequest.call(this, 'POST', '/payment-quotes/onchain', body); } else if (operation === 'createLnurlQuote') { const lnAddressOrUrl = this.getNodeParameter('lnAddressOrUrl', i) as string; const amount = this.getNodeParameter('amount', i) as number; const amountCurrency = this.getNodeParameter('amountCurrency', i) as string; const sourceCurrency = this.getNodeParameter('sourceCurrency', i) as string; const body: IDataObject = { lnAddressOrUrl, sourceCurrency, amount: { amount: amount.toString(), currency: amountCurrency, }, }; responseData = await strikeApiRequest.call(this, 'POST', '/payment-quotes/lightning/lnurl', body); } else if (operation === 'getLnurlDetails') { const lnAddressOrUrl = this.getNodeParameter('lnAddressOrUrl', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/payment-quotes/lightning/lnurl/${encodeURIComponent(lnAddressOrUrl)}`); } else if (operation === 'executeQuote') { const paymentQuoteId = this.getNodeParameter('paymentQuoteId', i) as string; responseData = await strikeApiRequest.call(this, 'PATCH', `/payment-quotes/${paymentQuoteId}/execute`); } } // ---------------------------------------- // paymentMethod // ---------------------------------------- if (resource === 'paymentMethod') { if (operation === 'createBank') { const accountNumber = this.getNodeParameter('accountNumber', i) as string; const routingNumber = this.getNodeParameter('routingNumber', i) as string; const accountType = this.getNodeParameter('accountType', i) as string; const body: IDataObject = { accountNumber, routingNumber, accountType, }; responseData = await strikeApiRequest.call(this, 'POST', '/payment-methods/bank', body); } else if (operation === 'get') { const paymentMethodId = this.getNodeParameter('paymentMethodId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/payment-methods/bank/${paymentMethodId}`); } else if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; const options = this.getNodeParameter('options', i) as IDataObject; const query: IDataObject = {}; if (options.depositEligible) { query.depositEligible = true; } if (returnAll) { responseData = await strikeApiRequestAllItems.call(this, 'GET', '/payment-methods/bank', {}, query); } else { const limit = this.getNodeParameter('limit', i) as number; query.$top = limit; responseData = await strikeApiRequest.call(this, 'GET', '/payment-methods/bank', {}, query); responseData = responseData.items || responseData; } } else if (operation === 'delete') { const paymentMethodId = this.getNodeParameter('paymentMethodId', i) as string; responseData = await strikeApiRequest.call(this, 'DELETE', `/payment-methods/bank/${paymentMethodId}`); responseData = { success: true }; } } // ---------------------------------------- // payout // ---------------------------------------- if (resource === 'payout') { if (operation === 'create') { const paymentMethodId = this.getNodeParameter('paymentMethodId', i) as string; const amount = this.getNodeParameter('amount', i) as number; const currency = this.getNodeParameter('currency', i) as string; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const body: IDataObject = { paymentMethodId, amount: { amount: amount.toString(), currency, }, }; if (additionalFields.feePolicy) { body.feePolicy = additionalFields.feePolicy; } if (additionalFields.originatorId) { body.originatorId = additionalFields.originatorId; } responseData = await strikeApiRequest.call(this, 'POST', '/payouts', body); } else if (operation === 'get') { const payoutId = this.getNodeParameter('payoutId', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/payouts/${payoutId}`); } else if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; const filters = this.getNodeParameter('filters', i) as IDataObject; const query: IDataObject = {}; if (filters.filter) { query.$filter = filters.filter; } if (filters.orderBy) { query.$orderby = filters.orderBy; } if (returnAll) { responseData = await strikeApiRequestAllItems.call(this, 'GET', '/payouts', {}, query); } else { const limit = this.getNodeParameter('limit', i) as number; query.$top = limit; responseData = await strikeApiRequest.call(this, 'GET', '/payouts', {}, query); responseData = responseData.items || responseData; } } else if (operation === 'initiate') { const payoutId = this.getNodeParameter('payoutId', i) as string; responseData = await strikeApiRequest.call(this, 'PATCH', `/payouts/${payoutId}/initiate`); } } // ---------------------------------------- // rates // ---------------------------------------- if (resource === 'rates') { if (operation === 'getTicker') { const currencyPair = this.getNodeParameter('currencyPair', i) as string; responseData = await strikeApiRequest.call(this, 'GET', `/rates/ticker/${currencyPair}`); } } // Return data const executionData = this.helpers.constructExecutionMetaData( this.helpers.returnJsonArray(responseData as IDataObject), { itemData: { item: i } }, ); returnData.push(...executionData); } catch (error) { if (this.continueOnFail()) { const executionData = this.helpers.constructExecutionMetaData( this.helpers.returnJsonArray({ error: (error as Error).message }), { itemData: { item: i } }, ); returnData.push(...executionData); continue; } throw error; } } return [returnData]; } }