n8n-nodes-mypet-stocks
Version:
n8n node for MyPet Stocks quantitative trading system with authentication and quantitative account management support
2,400 lines • 112 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MyPetStocks = void 0;
const n8n_workflow_1 = require("n8n-workflow");
class MyPetStocks {
constructor() {
this.description = {
displayName: 'MyPet Stocks',
name: 'myPetStocks',
icon: 'file:mypet-stocks.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with MyPet Stocks quantitative trading system',
defaults: {
name: 'MyPet Stocks',
},
inputs: ["main" /* NodeConnectionType.Main */],
outputs: ["main" /* NodeConnectionType.Main */],
credentials: [
{
name: 'myPetStocksApi',
required: true,
},
],
requestDefaults: {
baseURL: '={{$credentials.baseUrl}}',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Authentication',
value: 'auth',
},
{
name: 'Trading',
value: 'trading',
},
{
name: 'Quantitative Account',
value: 'quantAccount',
},
],
default: 'auth',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['auth'],
},
},
options: [
{
name: 'Get Token',
value: 'getToken',
description: 'Get authentication token using username and password',
action: 'Get authentication token',
},
],
default: 'getToken',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['trading'],
},
},
options: [
{
name: 'Query Trade Orders',
value: 'queryTradeOrders',
description: 'Query trading orders with various filters',
action: 'Query trade orders',
},
{
name: 'Get Account Trading Details',
value: 'getAccountTradingDetails',
description: 'Get detailed trading statistics for a specific account',
action: 'Get account trading details',
},
{
name: 'List Accounts',
value: 'listAccounts',
description: 'Get list of available trading accounts',
action: 'List trading accounts',
},
{
name: 'Get Account Trading Status',
value: 'getAccountTradingStatus',
description: 'Get real-time trading status for all accounts',
action: 'Get account trading status',
},
{
name: 'Commission Statistics',
value: 'getCommissionStatistics',
description: 'Get commission statistics for selected accounts',
action: 'Get commission statistics',
},
],
default: 'queryTradeOrders',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['quantAccount'],
},
},
options: [
{
name: 'Get All Accounts',
value: 'getAllAccounts',
description: 'Get all quantitative accounts',
action: 'Get all quantitative accounts',
},
{
name: 'Create Account',
value: 'createAccount',
description: 'Create a new quantitative account',
action: 'Create quantitative account',
},
{
name: 'Update Account',
value: 'updateAccount',
description: 'Update an existing quantitative account',
action: 'Update quantitative account',
},
{
name: 'Delete Account',
value: 'deleteAccount',
description: 'Delete a quantitative account',
action: 'Delete quantitative account',
},
],
default: 'getAllAccounts',
},
// 订单查询参数
{
displayName: 'Page Number',
name: 'pageNum',
type: 'number',
default: 1,
description: 'Page number to query',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Page Size',
name: 'pageSize',
type: 'number',
default: 20,
description: 'Number of records per page',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Filter Abnormal Orders',
name: 'filterAbnormal',
type: 'boolean',
default: false,
description: 'Whether to filter abnormal orders',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Stock Account ID',
name: 'stockAccount',
type: 'string',
default: '',
description: 'Quantitative account ID',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Position',
name: 'position',
type: 'options',
options: [
{
name: 'All',
value: 'all',
},
{
name: 'Open Positions',
value: 'open',
},
{
name: 'Closed Positions',
value: 'close',
},
],
default: 'all',
description: 'Position type to query',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Trade Type',
name: 'tradeType',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'Buy (Long)',
value: 'Buy',
},
{
name: 'Sell (Short)',
value: 'Sell',
},
{
name: 'Balance (Deposit/Withdrawal)',
value: 'Balance',
},
],
default: '',
description: 'Trade type to filter',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Symbol',
name: 'symbol',
type: 'string',
default: '',
description: 'Trading symbol to filter (e.g., USDJPY, NAS100)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Ticket Number',
name: 'ticket',
type: 'string',
default: '',
description: 'Trade order ticket number',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Magic Number',
name: 'magic',
type: 'string',
default: '',
description: 'Magic number for EA identification',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Comment',
name: 'comment',
type: 'string',
default: '',
description: 'Order comment to filter',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Open Time Start (Beijing)',
name: 'openTimeStart',
type: 'string',
default: '',
placeholder: '2025-04-01 00:00',
description: 'Start time for open time filter (Beijing time)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Open Time End (Beijing)',
name: 'openTimeEnd',
type: 'string',
default: '',
placeholder: '2025-04-02 23:59',
description: 'End time for open time filter (Beijing time)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Close Time Start (Beijing)',
name: 'closeTimeStart',
type: 'string',
default: '',
placeholder: '2025-04-01 00:00',
description: 'Start time for close time filter (Beijing time)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
{
displayName: 'Close Time End (Beijing)',
name: 'closeTimeEnd',
type: 'string',
default: '',
placeholder: '2025-04-02 23:59',
description: 'End time for close time filter (Beijing time)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['queryTradeOrders'],
},
},
},
// 账户交易详情参数
{
displayName: 'Account',
name: 'accountId',
type: 'options',
required: true,
default: '',
description: 'Select the trading account to query',
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingDetails'],
},
},
},
{
displayName: 'Time Scope',
name: 'scope',
type: 'options',
required: true,
options: [
{
name: 'All Time',
value: 'all',
},
{
name: 'Daily',
value: 'day',
},
{
name: 'Weekly',
value: 'week',
},
{
name: 'Monthly',
value: 'month',
},
{
name: 'Quarterly',
value: 'quarter',
},
{
name: 'Yearly',
value: 'year',
},
{
name: 'Custom Range',
value: 'custom',
},
],
default: 'all',
description: 'Time scope for the trading details query',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingDetails'],
},
},
},
{
displayName: 'Start Date',
name: 'startTime',
type: 'string',
required: true,
default: '',
placeholder: '2025-04-01',
description: 'Start date for custom time range (YYYY-MM-DD format)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingDetails'],
scope: ['custom'],
},
},
},
{
displayName: 'End Date',
name: 'endTime',
type: 'string',
required: true,
default: '',
placeholder: '2025-04-30',
description: 'End date for custom time range (YYYY-MM-DD format)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingDetails'],
scope: ['custom'],
},
},
},
// 账户交易实况参数
{
displayName: 'Page Number',
name: 'pageNum',
type: 'number',
default: 1,
description: 'Page number to query',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Page Size',
name: 'pageSize',
type: 'number',
default: 20,
description: 'Number of records per page',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Filter by Account',
name: 'filterAccountId',
type: 'options',
default: '',
description: 'Filter by specific account (optional)',
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Filter by Name',
name: 'filterName',
type: 'string',
default: '',
description: 'Filter by account name (optional)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Filter by Status',
name: 'filterStatus',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'Active',
value: 'true',
},
{
name: 'Inactive',
value: 'false',
},
],
default: '',
description: 'Filter by account status (optional)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Filter by Account Type',
name: 'filterAccountType',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'MT4',
value: 'mt4',
},
{
name: 'MT5',
value: 'mt5',
},
],
default: '',
description: 'Filter by account type (optional)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
{
displayName: 'Filter by Account Nature',
name: 'filterIsReal',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'Real Account',
value: 'true',
},
{
name: 'Demo Account',
value: 'false',
},
],
default: '',
description: 'Filter by account nature (optional)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getAccountTradingStatus'],
},
},
},
// 佣金统计参数配置
{
displayName: 'Time Scope',
name: 'scope',
type: 'options',
required: true,
options: [
{
name: 'All Time',
value: 'all',
},
{
name: 'Today',
value: 'today',
},
{
name: 'Yesterday',
value: 'yesterday',
},
{
name: 'This Week',
value: 'week',
},
{
name: 'Last Week',
value: 'last_week',
},
{
name: 'This Month',
value: 'month',
},
{
name: 'Last Month',
value: 'last_month',
},
{
name: 'Custom Range',
value: 'custom',
},
],
default: 'all',
description: 'Time scope for commission statistics',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getCommissionStatistics'],
},
},
},
{
displayName: 'Accounts',
name: 'accounts',
type: 'multiOptions',
required: true,
default: [],
description: 'Select quantitative accounts for commission statistics',
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
displayOptions: {
show: {
resource: ['trading'],
operation: ['getCommissionStatistics'],
},
},
},
{
displayName: 'Capital Type',
name: 'capital_type',
type: 'options',
required: true,
options: [
{
name: 'USD (Dollar)',
value: 'usd',
},
{
name: 'Cent',
value: 'cent',
},
],
default: 'usd',
description: 'Commission unit type',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getCommissionStatistics'],
},
},
},
{
displayName: 'Start Date',
name: 'start_time',
type: 'string',
required: true,
default: '',
placeholder: '2025-04-01',
description: 'Start date for custom time range (YYYY-MM-DD format)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getCommissionStatistics'],
scope: ['custom'],
},
},
},
{
displayName: 'End Date',
name: 'end_time',
type: 'string',
required: true,
default: '',
placeholder: '2025-04-30',
description: 'End date for custom time range (YYYY-MM-DD format)',
displayOptions: {
show: {
resource: ['trading'],
operation: ['getCommissionStatistics'],
scope: ['custom'],
},
},
},
// 量化账户参数配置
// 获取所有量化账户的参数
{
displayName: 'Page Number',
name: 'pageNum',
type: 'number',
default: 1,
description: 'Page number to query',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Page Size',
name: 'pageSize',
type: 'number',
default: 20,
description: 'Number of records per page',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Filter by Name',
name: 'name',
type: 'string',
default: '',
description: 'Filter by account name (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Filter by Account ID',
name: 'accountId',
type: 'string',
default: '',
description: 'Filter by quantitative account ID (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Filter by Account Type',
name: 'account_type',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'MT4',
value: 'mt4',
},
{
name: 'MT5',
value: 'mt5',
},
],
default: '',
description: 'Filter by account type (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Filter by Account Nature',
name: 'is_real',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'Real Account',
value: 'true',
},
{
name: 'Demo Account',
value: 'false',
},
],
default: '',
description: 'Filter by account nature (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
{
displayName: 'Filter by Status',
name: 'status',
type: 'options',
options: [
{
name: 'All',
value: '',
},
{
name: 'Active',
value: 'true',
},
{
name: 'Inactive',
value: 'false',
},
],
default: '',
description: 'Filter by account status (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['getAllAccounts'],
},
},
},
// 创建量化账户的参数
{
displayName: 'Account Name',
name: 'name',
type: 'string',
required: true,
default: '',
description: 'Name of the quantitative account',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Account ID',
name: 'accountId',
type: 'string',
required: true,
default: '',
description: 'Quantitative account ID',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Account Type',
name: 'account_type',
type: 'options',
required: true,
options: [
{
name: 'MT4',
value: 'mt4',
},
{
name: 'MT5',
value: 'mt5',
},
],
default: 'mt5',
description: 'Account type',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Is Real Account',
name: 'is_real',
type: 'boolean',
required: true,
default: true,
description: 'Whether this is a real account (true) or demo account (false)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Dealer',
name: 'dealer',
type: 'options',
required: true,
default: '',
description: 'Select the dealer/broker',
typeOptions: {
loadOptionsMethod: 'getDealers',
},
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Server',
name: 'server',
type: 'string',
required: true,
default: '',
description: 'Server name',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Capital Type',
name: 'capital_type',
type: 'options',
required: true,
options: [
{
name: 'USD (Dollar)',
value: 'usd',
},
{
name: 'Cent',
value: 'cent',
},
],
default: 'usd',
description: 'Capital type',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Max Leverage',
name: 'max_lever',
type: 'options',
required: true,
options: [
{
name: '1:2',
value: '1:2',
},
{
name: '1:20',
value: '1:20',
},
{
name: '1:50',
value: '1:50',
},
{
name: '1:100',
value: '1:100',
},
{
name: '1:200',
value: '1:200',
},
{
name: '1:400',
value: '1:400',
},
{
name: '1:500',
value: '1:500',
},
{
name: '1:800',
value: '1:800',
},
{
name: '1:1000',
value: '1:1000',
},
{
name: '1:2000',
value: '1:2000',
},
{
name: '1:无限',
value: '1:无限',
},
],
default: '1:100',
description: 'Maximum leverage',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'View Password',
name: 'view_password',
type: 'string',
default: '',
description: 'View password (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Risk',
name: 'risk',
type: 'number',
required: true,
default: 100,
description: 'Risk value - maximum loss percentage that can be tolerated (not a percentage)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Time Zone',
name: 'time_zone',
type: 'options',
required: true,
options: [
{
name: 'UTC',
value: 'UTC',
},
{
name: 'Europe/Moscow',
value: 'Europe/Moscow',
},
{
name: 'Asia/Shanghai',
value: 'Asia/Shanghai',
},
{
name: 'America/New_York',
value: 'America/New_York',
},
{
name: 'Asia/Tokyo',
value: 'Asia/Tokyo',
},
{
name: 'Africa/Cairo',
value: 'Africa/Cairo',
},
{
name: 'America/Los_Angeles',
value: 'America/Los_Angeles',
},
],
default: 'UTC',
description: 'Time zone',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Status',
name: 'status',
type: 'boolean',
required: true,
default: true,
description: 'Account status - true (active) or false (inactive)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
{
displayName: 'Note',
name: 'note',
type: 'string',
default: '',
description: 'Note (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['createAccount'],
},
},
},
// 更新量化账户的参数 - 复用创建账户的所有参数,但添加ID选择
{
displayName: 'Account to Update',
name: 'updateAccountId',
type: 'string',
required: true,
default: '',
description: 'ID of the quantitative account to update',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Account Name',
name: 'name',
type: 'string',
required: true,
default: '',
description: 'Name of the quantitative account',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Account ID',
name: 'accountId',
type: 'string',
required: true,
default: '',
description: 'Quantitative account ID',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Account Type',
name: 'account_type',
type: 'options',
required: true,
options: [
{
name: 'MT4',
value: 'mt4',
},
{
name: 'MT5',
value: 'mt5',
},
],
default: 'mt5',
description: 'Account type',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Is Real Account',
name: 'is_real',
type: 'boolean',
required: true,
default: true,
description: 'Whether this is a real account (true) or demo account (false)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Dealer',
name: 'dealer',
type: 'options',
required: true,
default: '',
description: 'Select the dealer/broker',
typeOptions: {
loadOptionsMethod: 'getDealers',
},
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Server',
name: 'server',
type: 'string',
required: true,
default: '',
description: 'Server name',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Capital Type',
name: 'capital_type',
type: 'options',
required: true,
options: [
{
name: 'USD (Dollar)',
value: 'usd',
},
{
name: 'Cent',
value: 'cent',
},
],
default: 'usd',
description: 'Capital type',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Max Leverage',
name: 'max_lever',
type: 'options',
required: true,
options: [
{
name: '1:2',
value: '1:2',
},
{
name: '1:20',
value: '1:20',
},
{
name: '1:50',
value: '1:50',
},
{
name: '1:100',
value: '1:100',
},
{
name: '1:200',
value: '1:200',
},
{
name: '1:400',
value: '1:400',
},
{
name: '1:500',
value: '1:500',
},
{
name: '1:800',
value: '1:800',
},
{
name: '1:1000',
value: '1:1000',
},
{
name: '1:2000',
value: '1:2000',
},
{
name: '1:无限',
value: '1:无限',
},
],
default: '1:100',
description: 'Maximum leverage',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'View Password',
name: 'view_password',
type: 'string',
default: '',
description: 'View password (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Risk',
name: 'risk',
type: 'number',
required: true,
default: 100,
description: 'Risk value - maximum loss percentage that can be tolerated (not a percentage)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Time Zone',
name: 'time_zone',
type: 'options',
required: true,
options: [
{
name: 'UTC',
value: 'UTC',
},
{
name: 'Europe/Moscow',
value: 'Europe/Moscow',
},
{
name: 'Asia/Shanghai',
value: 'Asia/Shanghai',
},
{
name: 'America/New_York',
value: 'America/New_York',
},
{
name: 'Asia/Tokyo',
value: 'Asia/Tokyo',
},
{
name: 'Africa/Cairo',
value: 'Africa/Cairo',
},
{
name: 'America/Los_Angeles',
value: 'America/Los_Angeles',
},
],
default: 'UTC',
description: 'Time zone',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Status',
name: 'status',
type: 'boolean',
required: true,
default: true,
description: 'Account status - true (active) or false (inactive)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
{
displayName: 'Note',
name: 'note',
type: 'string',
default: '',
description: 'Note (optional)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['updateAccount'],
},
},
},
// 删除量化账户的参数
{
displayName: 'Account to Delete',
name: 'deleteAccountId',
type: 'string',
required: true,
default: '',
description: 'ID of the quantitative account to delete. Note: Only inactive accounts can be deleted. If you get a 404 error, check if the account exists and is inactive.',
placeholder: 'Enter account ID (e.g., 123)',
displayOptions: {
show: {
resource: ['quantAccount'],
operation: ['deleteAccount'],
},
},
},
],
};
this.methods = {
loadOptions: {
async getAccounts() {
try {
// 获取凭据
const credentials = await this.getCredentials('myPetStocksApi');
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new Error(`Authentication failed: ${loginResponse.message}`);
}
authToken = loginResponse.result.token;
}
// 获取账户列表
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url: `${credentials.baseUrl}/api/v1/portal/stock/account/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new Error(`Failed to fetch accounts: ${response.message}`);
}
// 格式化账户选项
const accounts = response.result.results.map((account) => {
const acc = account;
const statusIcon = acc.status ? '✅活跃' : '❌停用';
const typeIcon = acc.is_real ? '🔴真实' : '🟡模拟';
const displayName = `${acc.accountId} -- ${acc.name} -- ${acc.account_type_name} ${acc.dealername} -- ${statusIcon} -- ${typeIcon}`;
return {
name: displayName,
value: acc.id.toString(), // 使用数据库ID作为值
};
});
// 按账户ID排序
accounts.sort((a, b) => {
const aAccountId = parseInt(a.name.split(' -- ')[0]);
const bAccountId = parseInt(b.name.split(' -- ')[0]);
return aAccountId - bAccountId;
});
return accounts;
}
catch (error) {
// 如果获取账户列表失败,返回空数组
return [];
}
},
async getDealers() {
try {
// 获取凭据
const credentials = await this.getCredentials('myPetStocksApi');
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new Error(`Authentication failed: ${loginResponse.message}`);
}
authToken = loginResponse.result.token;
}
// 获取券商列表
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url: `${credentials.baseUrl}/api/v1/portal/stock/dealer/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new Error(`Failed to fetch dealers: ${response.message}`);
}
// 格式化券商选项
const dealers = response.result.results.map((dealer) => {
const d = dealer;
return {
name: d.name,
value: d.id.toString(),
};
});
return dealers;
}
catch (error) {
// 如果获取券商列表失败,返回空数组
return [];
}
},
},
};
}
async execute() {
var _a, _b, _c;
const items = this.getInputData();
const returnData = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'auth') {
if (operation === 'getToken') {
const credentials = await this.getCredentials('myPetStocksApi');
if (credentials.authMethod !== 'credentials') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'To get token, please use "Username & Password" authentication method in credentials', { itemIndex: i });
}
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'myPetStocksApi', {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
token: response.result.token,
username: response.result.username,
userId: response.result.userId,
message: response.message,
},
pairedItem: { item: i },
});
}
}
else if (resource === 'trading') {
if (operation === 'queryTradeOrders') {
// 获取凭据
const credentials = await this.getCredentials('myPetStocksApi');
if (!credentials) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials found for MyPet Stocks API', { itemIndex: i });
}
// 首先获取认证 token
let authToken;
if (credentials.authMethod === 'token' && credentials.token) {
// 如果已经有 token,直接使用
authToken = `Bearer ${credentials.token}`;
}
else if (credentials.authMethod === 'credentials') {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid authentication method. Please use either username/password or token.', { itemIndex: i });
}
// 获取查询参数
const pageNum = this.getNodeParameter('pageNum', i);
const pageSize = this.getNodeParameter('pageSize', i);
const filterAbnormal = this.getNodeParameter('filterAbnormal', i);
const stockAccount = this.getNodeParameter('stockAccount', i);
const position = this.getNodeParameter('position', i);
const tradeType = this.getNodeParameter('tradeType', i);
const symbol = this.getNodeParameter('symbol', i);
const ticket = this.getNodeParameter('ticket', i);
const magic = this.getNodeParameter('magic', i);
const comment = this.getNodeParameter('comment', i);
const openTimeStart = this.getNodeParameter('openTimeStart', i);
const openTimeEnd = this.getNodeParameter('openTimeEnd', i);
const closeTimeStart = this.getNodeParameter('closeTimeStart', i);
const closeTimeEnd = this.getNodeParameter('closeTimeEnd', i);
// 构建查询参数
const queryParams = {};
if (pageNum)
queryParams.pageNum = pageNum.toString();
if (pageSize)
queryParams.pageSize = pageSize.toString();
if (filterAbnormal !== undefined)
queryParams.filter_abnormal = filterAbnormal.toString();
if (stockAccount)
queryParams.stock_account = stockAccount;
if (position && position !== 'all')
queryParams.position = position;
if (tradeType)
queryParams.tradeType = tradeType;
if (symbol)
queryParams.symbol = symbol;
if (ticket)
queryParams.ticket = ticket;
if (magic)
queryParams.magic = magic;
if (comment)
queryParams.comment = comment;
if (openTimeStart)
queryParams.opentime_bj_start = openTimeStart;
if (openTimeEnd)
queryParams.opentime_bj_end = openTimeEnd;
if (closeTimeStart)
queryParams.closetime_bj_start = closeTimeStart;
if (closeTimeEnd)
queryParams.closetime_bj_end = closeTimeEnd;
// 构建查询字符串
const queryString = new URLSearchParams(queryParams).toString();
const url = `${credentials.baseUrl}/api/v1/portal/stock/tradeOrder/${queryString ? '?' + queryString : ''}`;
// 使用获取的 token 发送请求
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
message: response.message,
code: response.code,
totalCount: response.result.count,
nextPage: response.result.next,
previousPage: response.result.previous,
orders: response.result.results.data,
orderInfo: response.result.results.order_info,
queryParams: queryParams,
authToken: authToken.substring(0, 30) + '...', // 显示部分 token 用于调试
},
pairedItem: { item: i },
});
}
else if (operation === 'getAccountTradingDetails') {
// 获取凭据
const credentials = await this.getCredentials('myPetStocksApi');
if (!credentials) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials found for MyPet Stocks API', { itemIndex: i });
}
// 首先获取认证 token
let authToken;
if (credentials.authMethod === 'token' && credentials.token) {
// 如果已经有 token,直接使用
authToken = `Bearer ${credentials.token}`;
}
else if (credentials.authMethod === 'credentials') {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid authentication method. Please use either username/password or token.', { itemIndex: i });
}
// 获取请求参数
const accountId = this.getNodeParameter('accountId', i);
const scope = this.getNodeParameter('scope', i);
// 构建请求体
const requestBody = {
account_id: accountId,
scope: scope,
};
// 如果是自定义时间范围,添加开始和结束时间
if (scope === 'custom') {
const startTime = this.getNodeParameter('startTime', i);
const endTime = this.getNodeParameter('endTime', i);
if (!startTime || !endTime) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Start time and end time are required for custom scope', { itemIndex: i });
}
requestBody.start_time = startTime;
requestBody.end_time = endTime;
}
// 发送请求
const response = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/stock/accountStatDetail/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
body: requestBody,
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query failed: ${response.message}`, { itemIndex: i });
}
// 构建返回数据
const resultData = {
message: response.message,
code: response.code,
accountId: accountId,
scope: scope,
timeRange: null,
total: response.result.total || null,
details: response.result.detail || [],
summary: {
totalRecords: response.result.detail ? response.result.detail.length : 0,
scopeDescription: (() => {
const scopeMap = {
'all': 'All Time',
'day': 'Daily',
'week': 'Weekly',
'month': 'Monthly',
'quarter': 'Quarterly',
'year': 'Yearly',
'custom': 'Custom Range'
};
return scopeMap[scope] || scope;
})(),
},
};
// 如果是自定义范围,添加时间范围信息
if (scope === 'custom' && requestBody.start_time && requestBody.end_time) {
resultData.timeRange = {
startTime: requestBody.start_time,
endTime: requestBody.end_time
};
}
returnData.push({
json: resultData,
pairedItem: { item: i },
});
}
else if (operation === 'listAccounts') {
// 获取凭据和认证
const credentials = await this.getCredentials('myPetStocksApi');
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
// 获取账户列表
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url: `${credentials.baseUrl}/api/v1/portal/stock/account/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query failed: ${response.message}`, { itemIndex: i });
}
// 格式化账户列表数据
const accounts = response.result.results.map((account) => {
const acc = account;
return {
id: acc.id,
accountId: acc.accountId,
name: acc.name,
accountType: acc.account_type_name,
capitalType: acc.capital_type_name,
dealerName: acc.dealername,
server: acc.server,
maxLever: acc.max_lever,
isReal: acc.is_real,
status: acc.status,
note: acc.note,
addTime: acc.add_time,
modTime: acc.mod_time,
};
});
returnData.push({
json: {
message: response.message,
code: response.code,
totalCount: response.result.count,
accounts: accounts,
summary: {
totalAccounts: accounts.length,
activeAccounts: accounts.filter((acc) => {
const account = acc;
return account.status;
}).length,
realAccounts: accounts.filter((acc) => {
const account = acc;
return account.isReal;
}).length,
demoAccounts: accounts.filter((acc) => {
const account = acc;
return !account.isReal;
}).length,
},
},
pairedItem: { item: i },
});
}
else if (operation === 'getAccountTradingStatus') {
// 获取凭据和认证
const credentials = await this.getCredentials('myPetStocksApi');
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
// 获取请求参数
const pageNum = this.getNodeParameter('pageNum', i);
const pageSize = this.getNodeParameter('pageSize', i);
const filterAccountId = this.getNodeParameter('filterAccountId', i);
const filterName = this.getNodeParameter('filterName', i);
const filterStatus = this.getNodeParameter('filterStatus', i);
const filterAccountType = this.getNodeParameter('filterAccountType', i);
const filterIsReal = this.getNodeParameter('filterIsReal', i);
// 构建查询参数
const queryParams = new URLSearchParams();
if (pageNum)
queryParams.append('pageNum', pageNum.toString());
if (pageSize)
queryParams.append('pageSize', pageSize.toString());
if (filterAccountId)
queryParams.append('accountId', filterAccountId);
if (filterName)
queryParams.append('name', filterName);
if (filterStatus)
queryParams.append('status', filterStatus);
if (filterAccountType)
queryParams.append('account_type', filterAccountType);
if (filterIsReal)
queryParams.append('is_real', filterIsReal);
const queryString = queryParams.toString();
const url = `${credentials.baseUrl}/api/v1/portal/stock/accountStat/${queryString ? '?' + queryString : ''}`;
// 发送请求
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url: url,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query failed: ${response.message}`, { itemIndex: i });
}
// 格式化账户交易实况数据
const accountStats = response.result.results.map((account) => {
const acc = account;
const stat = acc.stat;
const holtStat = stat === null || stat === void 0 ? void 0 : stat.holtStat;
return {
id: acc.id,
username: acc.username,
name: acc.name,
accountId: acc.accountId,
status: acc.status,
isReal: acc.is_real,
capitalType: acc.capital_type,
tradingStats: {
// 账户基本信息
accountBalance: (stat === null || stat === void 0 ? void 0 : stat.accountBalance) || 0,
accountEquity: (stat === null || stat === void 0 ? void 0 : stat.accountEquity) || 0,
accountMargin: (stat === null || stat === void 0 ? void 0 : stat.accountMargin) || 0,
accountFreeMargin: (stat === null || stat === void 0 ? void 0 : stat.accountFreeMargin) || 0,
floatingProfit: (stat === null || stat === void 0 ? void 0 : stat.floatingProfit) || 0,
// 持仓统计
totalLots: (stat === null || stat === void 0 ? void 0 : stat.totalLots) || 0,
totalBuyLots: (stat === null || stat === void 0 ? void 0 : stat.totalBuyLots) || 0,
totalSellLots: (stat === null || stat === void 0 ? void 0 : stat.totalSellLots) || 0,
totalBuyProfit: (stat === null || stat === void 0 ? void 0 : stat.totalBuyProfit) || 0,
totalSellProfit: (stat === null || stat === void 0 ? void 0 : stat.totalSellProfit) || 0,
// 持仓数量统计
holdingStats: {
sellCount: (holtStat === null || holtStat === void 0 ? void 0 : holtStat.sell_count) || 0,
buyCount: (holtStat === null || holtStat === void 0 ? void 0 : holtStat.buy_count) || 0,
total: (holtStat === null || holtStat === void 0 ? void 0 : holtStat.total) || 0,
},
// 其他信息
remoteAddr: stat === null || stat === void 0 ? void 0 : stat.remoteAddr,
lastUpdateTime: stat === null || stat === void 0 ? void 0 : stat.mod_time,
addTime: stat === null || stat === void 0 ? void 0 : stat.add_time,
},
};
});
// 计算汇总统计
const totalBalance = accountStats.reduce((sum, acc) => {
const account = acc;
return sum + (account.tradingStats.accountBalance || 0);
}, 0);
const totalEquity = accountStats.reduce((sum, acc) => {
const account = acc;
return sum + (account.tradingStats.accountEquity || 0);
}, 0);
const totalFloatingProfit = accountStats.reduce((sum, acc) => {
const account = acc;
return sum + (account.tradingStats.floatingProfit || 0);
}, 0);
const totalLots = accountStats.reduce((sum, acc) => {
const account = acc;
return sum + (account.tradingStats.totalLots || 0);
}, 0);
const activeAccounts = accountStats.filter((acc) => {
const account = acc;
return account.status;
}).length;
const realAccounts = accountStats.filter((acc) => {
const account = acc;
return account.isReal;
}).length;
returnData.push({
json: {
message: response.message,
code: response.code,
pagination: {
totalCount: response.result.count,
currentPage: pageNum,
pageSize: pageSize,
hasNext: !!response.result.next,
hasPrevious: !!response.result.previous,
},
accounts: accountStats,
summary: {
totalAccounts: accountStats.length,
activeAccounts: activeAccounts,
realAccounts: realAccounts,
demoAccounts: accountStats.length - realAccounts,
totalBalance: totalBalance,
totalEquity: totalEquity,
totalFloatingProfit: totalFloatingProfit,
totalLots: totalLots,
},
filters: {
accountId: filterAccountId || null,
name: filterName || null,
status: filterStatus || null,
accountType: filterAccountType || null,
isReal: filterIsReal || null,
},
},
pairedItem: { item: i },
});
}
else if (operation === 'getCommissionStatistics') {
// 获取凭据
const credentials = await this.getCredentials('myPetStocksApi');
if (!credentials) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials found for MyPet Stocks API', { itemIndex: i });
}
// 首先获取认证 token
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
// 获取佣金统计参数
const scope = this.getNodeParameter('scope', i);
const accounts = this.getNodeParameter('accounts', i);
const capital_type = this.getNodeParameter('capital_type', i);
const start_time = this.getNodeParameter('start_time', i, '');
const end_time = this.getNodeParameter('end_time', i, '');
// 验证必需参数
if (!accounts || accounts.length === 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one account must be selected', { itemIndex: i });
}
// 构建请求体
const requestBody = {
scope,
accounts: accounts.map(id => parseInt(id, 10)),
capital_type,
};
// 如果是自定义时间范围,添加开始和结束时间
if (scope === 'custom') {
if (!start_time || !end_time) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Start time and end time are required for custom scope', { itemIndex: i });
}
requestBody.start_time = start_time;
requestBody.end_time = end_time;
}
// 发送佣金统计请求
const response = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/stock/commissionStat/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
body: requestBody,
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Commission statistics query failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
message: response.message,
code: response.code,
cardInfo: response.result.card_info,
commissionDetail: response.result.commission_detail,
commissionDayDetail: response.result.commission_day_detail,
queryParams: {
scope,
accounts,
capital_type,
start_time: scope === 'custom' ? start_time : null,
end_time: scope === 'custom' ? end_time : null,
},
},
pairedItem: { item: i },
});
}
}
else if (resource === 'quantAccount') {
// 获取凭据和认证
const credentials = await this.getCredentials('myPetStocksApi');
let authToken;
if (credentials.authMethod === 'token') {
authToken = credentials.token;
}
else {
// 使用用户名密码获取 token
const loginResponse = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/dashlogin/`,
body: {
username: credentials.username,
password: credentials.password,
},
json: true,
});
if (loginResponse.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Authentication failed: ${loginResponse.message}`, { itemIndex: i });
}
authToken = loginResponse.result.token;
}
if (operation === 'getAllAccounts') {
// 获取查询参数
const pageNum = this.getNodeParameter('pageNum', i);
const pageSize = this.getNodeParameter('pageSize', i);
const name = this.getNodeParameter('name', i);
const accountId = this.getNodeParameter('accountId', i);
const account_type = this.getNodeParameter('account_type', i);
const is_real = this.getNodeParameter('is_real', i);
const status = this.getNodeParameter('status', i);
// 构建查询参数
const queryParams = {};
if (pageNum)
queryParams.pageNum = pageNum.toString();
if (pageSize)
queryParams.pageSize = pageSize.toString();
if (name)
queryParams.name = name;
if (accountId)
queryParams.accountId = accountId;
if (account_type)
queryParams.account_type = account_type;
if (is_real)
queryParams.is_real = is_real;
if (status)
queryParams.status = status;
// 构建查询字符串
const queryString = Object.keys(queryParams)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
.join('&');
const url = `${credentials.baseUrl}/api/v1/portal/stock/account/${queryString ? '?' + queryString : ''}`;
// 发送请求
const response = await this.helpers.httpRequest.call(this, {
method: 'GET',
url: url,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
message: response.message,
code: response.code,
pagination: {
totalCount: response.result.count,
nextPage: response.result.next,
previousPage: response.result.previous,
},
accounts: response.result.results,
queryParams: queryParams,
},
pairedItem: { item: i },
});
}
else if (operation === 'createAccount') {
// 获取创建参数
const name = this.getNodeParameter('name', i);
const accountId = this.getNodeParameter('accountId', i);
const account_type = this.getNodeParameter('account_type', i);
const is_real = this.getNodeParameter('is_real', i);
const dealer = this.getNodeParameter('dealer', i);
const server = this.getNodeParameter('server', i);
const capital_type = this.getNodeParameter('capital_type', i);
const max_lever = this.getNodeParameter('max_lever', i);
const view_password = this.getNodeParameter('view_password', i);
const risk = this.getNodeParameter('risk', i);
const time_zone = this.getNodeParameter('time_zone', i);
const status = this.getNodeParameter('status', i);
const note = this.getNodeParameter('note', i);
// 构建请求体
const requestBody = {
name,
accountId,
account_type,
is_real,
dealer,
server,
capital_type,
max_lever,
risk,
time_zone,
status,
};
if (view_password)
requestBody.view_password = view_password;
if (note)
requestBody.note = note;
// 发送创建请求
const response = await this.helpers.httpRequest.call(this, {
method: 'POST',
url: `${credentials.baseUrl}/api/v1/portal/stock/account/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
body: requestBody,
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Create failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
message: response.message,
code: response.code,
account: response.result,
},
pairedItem: { item: i },
});
}
else if (operation === 'updateAccount') {
// 获取更新参数
const updateAccountId = this.getNodeParameter('updateAccountId', i);
const name = this.getNodeParameter('name', i);
const accountId = this.getNodeParameter('accountId', i);
const account_type = this.getNodeParameter('account_type', i);
const is_real = this.getNodeParameter('is_real', i);
const dealer = this.getNodeParameter('dealer', i);
const server = this.getNodeParameter('server', i);
const capital_type = this.getNodeParameter('capital_type', i);
const max_lever = this.getNodeParameter('max_lever', i);
const view_password = this.getNodeParameter('view_password', i);
const risk = this.getNodeParameter('risk', i);
const time_zone = this.getNodeParameter('time_zone', i);
const status = this.getNodeParameter('status', i);
const note = this.getNodeParameter('note', i);
// 构建请求体
const requestBody = {
name,
accountId,
account_type,
is_real,
dealer,
server,
capital_type,
max_lever,
risk,
time_zone,
status,
};
if (view_password)
requestBody.view_password = view_password;
if (note)
requestBody.note = note;
// 发送更新请求
const response = await this.helpers.httpRequest.call(this, {
method: 'PUT',
url: `${credentials.baseUrl}/api/v1/portal/stock/account/${updateAccountId}/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
body: requestBody,
json: true,
});
if (response.code !== 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Update failed: ${response.message}`, { itemIndex: i });
}
returnData.push({
json: {
message: response.message,
code: response.code,
account: response.result,
},
pairedItem: { item: i },
});
}
else if (operation === 'deleteAccount') {
// 获取删除参数
const deleteAccountId = this.getNodeParameter('deleteAccountId', i);
// 验证账户ID
if (!deleteAccountId || deleteAccountId.trim() === '') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Account ID is required for deletion', { itemIndex: i });
}
try {
// 发送删除请求
await this.helpers.httpRequest.call(this, {
method: 'DELETE',
url: `${credentials.baseUrl}/api/v1/portal/stock/account/${deleteAccountId}/`,
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
},
json: true,
});
// 删除成功通常返回204状态码,没有响应体
returnData.push({
json: {
message: 'Account deleted successfully',
accountId: deleteAccountId,
success: true,
},
pairedItem: { item: i },
});
}
catch (deleteError) {
// 处理删除特定的错误
if (((_a = deleteError.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Account with ID '${deleteAccountId}' not found. Please check if the account exists and you have permission to delete it.`, { itemIndex: i });
}
else if (((_b = deleteError.response) === null || _b === void 0 ? void 0 : _b.status) === 400) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Cannot delete account '${deleteAccountId}'. The account might be active or have dependencies. Only inactive accounts can be deleted.`, { itemIndex: i });
}
else if (((_c = deleteError.response) === null || _c === void 0 ? void 0 : _c.status) === 403) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Permission denied. You don't have permission to delete account '${deleteAccountId}'.`, { itemIndex: i });
}
else {
// 重新抛出其他错误
throw deleteError;
}
}
}
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error instanceof Error ? error.message : String(error),
},
pairedItem: { item: i },
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.MyPetStocks = MyPetStocks;