init commit
This commit is contained in:
264
README.md
264
README.md
@@ -0,0 +1,264 @@
|
|||||||
|
# Cryptocurrency Exchange Platform
|
||||||
|
|
||||||
|
A comprehensive cryptocurrency exchange server built with Node.js, TypeScript, and Express. This platform supports trading of Bitcoin, Ethereum, and Tron cryptocurrencies with Iranian Rial (IRR) support.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Multi-Cryptocurrency Support**: Bitcoin (BTC), Ethereum (ETH), and Tron (TRX)
|
||||||
|
- **User Authentication**: Email and phone verification, session management
|
||||||
|
- **Wallet Management**: Secure wallet operations with support for multiple cryptocurrencies
|
||||||
|
- **Trading System**: Buy/sell orders, offer management, and order matching
|
||||||
|
- **Price Statistics**: Real-time and historical price data (hourly, daily, weekly, monthly, yearly)
|
||||||
|
- **Real-time Updates**: WebSocket integration via Socket.io for live updates
|
||||||
|
- **Admin Panel**: Administrative tools for managing the exchange
|
||||||
|
- **Support Tickets**: Integrated ticketing system for customer support
|
||||||
|
- **Automated Backups**: Daily database backups
|
||||||
|
- **Rate Limiting**: Brute force protection and rate limiting
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Runtime**: Node.js
|
||||||
|
- **Language**: TypeScript
|
||||||
|
- **Framework**: Express.js
|
||||||
|
- **Database**: MongoDB (Mongoose)
|
||||||
|
- **Cache**: Redis
|
||||||
|
- **Message Queue**: AMQP (RabbitMQ)
|
||||||
|
- **Real-time**: Socket.io
|
||||||
|
- **Blockchain Libraries**:
|
||||||
|
- `bitcoin-core` for Bitcoin
|
||||||
|
- `web3` and `ethereumjs-tx` for Ethereum
|
||||||
|
- `tronweb` for Tron
|
||||||
|
- **Other**: Winston (logging), Nodemailer (emails), bcrypt (hashing)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Node.js (v14 or higher)
|
||||||
|
- MongoDB
|
||||||
|
- Redis
|
||||||
|
- RabbitMQ (AMQP)
|
||||||
|
- TypeScript
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Clone the repository:
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd Exchange
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Navigate to the server directory:
|
||||||
|
```bash
|
||||||
|
cd server
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install dependencies:
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Create a `.env` file in the server directory with the following variables:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Database
|
||||||
|
MONGO_DATABASE=mongodb://localhost:27017/exchange
|
||||||
|
MONGO_DATABASE_NAME_TICKETS=trudesk
|
||||||
|
|
||||||
|
# Session
|
||||||
|
SESSION_SECRET=your-session-secret-key
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
REDIS_PORT=6379
|
||||||
|
# REDIS_PASS=your-redis-password
|
||||||
|
|
||||||
|
# AMQP (RabbitMQ)
|
||||||
|
AMQP_URL=amqp://localhost
|
||||||
|
|
||||||
|
# Email (Nodemailer)
|
||||||
|
NODEMAILER_HOST=smtp.gmail.com
|
||||||
|
NODEMAILER_PORT=587
|
||||||
|
NODEMAILER_USER=your-email@gmail.com
|
||||||
|
NODEMAILER_PASS=your-email-password
|
||||||
|
SENDER_ADDRESS=your-email@gmail.com
|
||||||
|
|
||||||
|
# API
|
||||||
|
API=http://localhost:3001
|
||||||
|
|
||||||
|
# External APIs
|
||||||
|
CURRENCY_API_KEY=your-nomics-api-key
|
||||||
|
SMS_API_ACCESS_KEY=your-sms-api-key
|
||||||
|
SMS_API_PHONE_PATTERN_CODE=your-sms-pattern-code
|
||||||
|
SMS_API_DEFINITE_SENDER_NUMBER=your-sms-sender-number
|
||||||
|
|
||||||
|
# Ticket System
|
||||||
|
TICKET_START_CONVERSATION=your-ticket-api-url
|
||||||
|
TICKET_GET_MESSAGES_URL=your-ticket-api-url
|
||||||
|
TICKET_CREATE_TICKET_URL=your-ticket-api-url
|
||||||
|
TICKET_ADD_COMMENT_URL=your-ticket-api-url
|
||||||
|
TICKET_SEND_MESSAGE_URL=your-ticket-api-url
|
||||||
|
SUPPORT_ROLE_ID=your-support-role-id
|
||||||
|
USER_ROLE_ID=your-user-role-id
|
||||||
|
ACCESS_TOKEN=your-access-token
|
||||||
|
|
||||||
|
# Crypto
|
||||||
|
CRYPTO_SECRET=your-crypto-secret
|
||||||
|
SALT_I=10
|
||||||
|
OBJECTID_RIAL=your-rial-currency-object-id
|
||||||
|
|
||||||
|
# Feature Flags
|
||||||
|
BUYFROMOFFERS=true
|
||||||
|
|
||||||
|
# Chart
|
||||||
|
CHART_LIMIT=20
|
||||||
|
|
||||||
|
# Test
|
||||||
|
TEST_API_URL=http://localhost:3001
|
||||||
|
NODE_ENV=development
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Compile TypeScript (if needed):
|
||||||
|
```bash
|
||||||
|
npx tsc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the Application
|
||||||
|
|
||||||
|
### Development Mode
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
The server will start on `http://localhost:3001`
|
||||||
|
|
||||||
|
### Test Mode
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run test-env
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
server/
|
||||||
|
├── api/ # API utilities and integrations
|
||||||
|
│ ├── walletApi/ # Blockchain wallet APIs (Bitcoin, Ethereum, Tron)
|
||||||
|
│ ├── amqp.ts # AMQP message queue configuration
|
||||||
|
│ ├── logger.ts # Winston logger configuration
|
||||||
|
│ ├── redis.ts # Redis client configuration
|
||||||
|
│ └── socket.ts # Socket.io configuration
|
||||||
|
├── db/ # Database models and schemas
|
||||||
|
│ ├── user.ts # User model
|
||||||
|
│ ├── currencies.ts # Currency model
|
||||||
|
│ ├── activeOffers.ts # Active trading offers
|
||||||
|
│ ├── acceptedOffers.ts # Accepted offers
|
||||||
|
│ └── ... # Other models
|
||||||
|
├── middlewares/ # Express middlewares
|
||||||
|
│ ├── auth.ts # Authentication middleware
|
||||||
|
│ ├── validation.ts # Request validation
|
||||||
|
│ ├── errorHandler.ts # Error handling
|
||||||
|
│ └── preventBruteForce.ts # Rate limiting
|
||||||
|
├── routes/ # API routes
|
||||||
|
│ ├── auth.ts # Authentication routes
|
||||||
|
│ ├── user.ts # User routes
|
||||||
|
│ ├── wallet.ts # Wallet routes
|
||||||
|
│ ├── admin.ts # Admin routes
|
||||||
|
│ ├── service.ts # Service routes
|
||||||
|
│ └── tickets.ts # Support ticket routes
|
||||||
|
├── scripts/ # Utility scripts
|
||||||
|
│ ├── priceStats.ts # Price statistics
|
||||||
|
│ ├── currenciesadder.ts # Currency management
|
||||||
|
│ └── localPriceScript.ts # Local price tracking
|
||||||
|
└── test/ # Test files
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Authentication (`/auth`)
|
||||||
|
- `GET /auth` - Check authentication status
|
||||||
|
- `POST /register` - User registration
|
||||||
|
- `POST /login` - User login
|
||||||
|
- `GET /logout` - User logout
|
||||||
|
- `POST /verify` - Verify email/phone
|
||||||
|
|
||||||
|
### User (`/user`)
|
||||||
|
- `GET /getUserWallet` - Get user wallet balance
|
||||||
|
- `GET /getUserOffers` - Get user's trading offers
|
||||||
|
- `POST /createOffer` - Create a new trading offer
|
||||||
|
- `GET /getUserTransactions` - Get user transaction history
|
||||||
|
|
||||||
|
### Wallet (`/wallet`)
|
||||||
|
- `GET /getEtheriumNonce` - Get Ethereum nonce
|
||||||
|
- `POST /transferToExchange` - Transfer cryptocurrency to exchange
|
||||||
|
- `POST /transferFromExchange` - Transfer cryptocurrency from exchange
|
||||||
|
- `POST /transferToExchangeById` - Transfer by transaction ID
|
||||||
|
|
||||||
|
### Service (`/service`)
|
||||||
|
- `GET /getDeafultAcceptedOffers` - Get default accepted offers
|
||||||
|
- `GET /getPriceChart` - Get price chart data
|
||||||
|
- `GET /getCurrencies` - Get supported currencies
|
||||||
|
|
||||||
|
### Admin (`/admin`)
|
||||||
|
- Admin-specific endpoints for managing the exchange
|
||||||
|
|
||||||
|
### Tickets (`/tickets`)
|
||||||
|
- Support ticket management endpoints
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### Automated Tasks
|
||||||
|
- Daily database backups (runs at 11:59 PM)
|
||||||
|
- Continuous price statistics updates
|
||||||
|
- Local price tracking (hourly, daily, weekly, monthly, yearly)
|
||||||
|
- Dollar to Rial price updates
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Session-based authentication
|
||||||
|
- CSRF protection
|
||||||
|
- Rate limiting and brute force protection
|
||||||
|
- Password hashing with bcrypt
|
||||||
|
- Input validation
|
||||||
|
|
||||||
|
### Real-time Features
|
||||||
|
- Socket.io for real-time updates
|
||||||
|
- Online user tracking
|
||||||
|
- Live price updates
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
The application uses Winston for logging. Logs are written to:
|
||||||
|
- `combined.log` - All logs
|
||||||
|
- `error.log` - Error logs
|
||||||
|
- `exceptions.log` - Uncaught exceptions
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
The application uses MongoDB with the following main databases:
|
||||||
|
- `exchange` - Main application data
|
||||||
|
- `trudesk` - Support ticket system
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch
|
||||||
|
3. Make your changes
|
||||||
|
4. Write tests if applicable
|
||||||
|
5. Submit a pull request
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Make sure MongoDB, Redis, and RabbitMQ are running before starting the server
|
||||||
|
- Configure all environment variables in the `.env` file
|
||||||
|
- The application includes automated backup scripts that run daily
|
||||||
|
- Price statistics are updated continuously for real-time trading data
|
||||||
|
|
||||||
|
|||||||
BIN
server/.DS_Store
vendored
Normal file
BIN
server/.DS_Store
vendored
Normal file
Binary file not shown.
57
server/.env
Executable file
57
server/.env
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#API address
|
||||||
|
|
||||||
|
API=http://localhost:3001
|
||||||
|
|
||||||
|
#session
|
||||||
|
SESSION_SECRET=test
|
||||||
|
|
||||||
|
|
||||||
|
#mongo
|
||||||
|
|
||||||
|
MONGO_SECRET=aaaaa
|
||||||
|
MONGO_DATABASE=mongodb://localhost:27017/exchange
|
||||||
|
SALT_I=10
|
||||||
|
MONGO_DATABASE_NAME=exchange
|
||||||
|
|
||||||
|
|
||||||
|
#nodemailer
|
||||||
|
NODEMAILER_HOST=mail.polychain.ir
|
||||||
|
NODEMAILER_PORT=465
|
||||||
|
NODEMAILER_USER=admin@polychain.ir
|
||||||
|
NODEMAILER_PASS=@polychainAdmin
|
||||||
|
SENDER_ADDRESS=<admin@polychain.ir>
|
||||||
|
|
||||||
|
|
||||||
|
#AMQP
|
||||||
|
AMQP_URL=amqp://guest:guest@localhost
|
||||||
|
|
||||||
|
#REDIS
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_HOST=localhost
|
||||||
|
CRYPTO_SECRET=abcde
|
||||||
|
BUYFROMOFFERS=true
|
||||||
|
|
||||||
|
|
||||||
|
MONGO_DATABASE_NAME_TICKETS=trudesk
|
||||||
|
TICKET_GET_MESSAGES_URL=http://localhost:8118/api/v1/users/create
|
||||||
|
TICKET_CREATE_TICKET_URL=http://localhost:8118/api/v1/tickets/create
|
||||||
|
TICKET_ADD_COMMENT_URL=http://localhost:8118/api/v1/tickets/addcomment
|
||||||
|
TICKET_TICKET_URL=http://localhost:8118/api/v1/tickets/
|
||||||
|
ACCESS_TOKEN=556a5e513dc8a4e3c0b1643886a9cf3f636b1945
|
||||||
|
SUPPORT_ROLE_ID=5fb21707795091261c6d2194
|
||||||
|
USER_ROLE_ID=5fb21707795091261c6d2192
|
||||||
|
# CURRENCY_API
|
||||||
|
CURRENCY_API_KEY=6ba4711649395555617a5bd91a416dac
|
||||||
|
|
||||||
|
|
||||||
|
process.env.ADMIN_ETHERIUM_ACCOUNT_ADDRESS=0x868453967f6806ef86de7cf5e57a32ab28b875b4
|
||||||
|
process.env.ADMIN_ETHERIUM_ACCOUNT_PASSWORD=exchange
|
||||||
|
process.env.CLIENT_ETHERIUM_ACCOUNT_ADDRESS=0xC1BC3cB61722c959030aF512883F2E884baF5702
|
||||||
|
process.env.CLIENT_ETHERIUM_ACCOUNT_PRIVATE_KEY=64061456066baa81c5097c895b5176fb3e1452eaf6f6776e2d7bf07ddb9accfe
|
||||||
|
# ObjectIDS
|
||||||
|
OBJECTID_RIAL=5f719d994923c95630df06be
|
||||||
|
|
||||||
|
|
||||||
|
CHART_LIMIT=20
|
||||||
|
|
||||||
|
|
||||||
100
server/api/amqp.js
Executable file
100
server/api/amqp.js
Executable file
@@ -0,0 +1,100 @@
|
|||||||
|
'use strict';
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.publishQueueConnection = void 0;
|
||||||
|
// This script fetches queued messages from RabbitMQ and delivers these to SMTP
|
||||||
|
var nodemailer = require("nodemailer");
|
||||||
|
var amqp = require("amqp");
|
||||||
|
var queueHost = process.env.AMQP_URL;
|
||||||
|
var queueName = 'outgoing';
|
||||||
|
var smtpHost = {
|
||||||
|
host: process.env.NODEMAILER_HOST,
|
||||||
|
port: process.env.NODEMAILER_PORT,
|
||||||
|
// NB! Must be pooled connection, otherwise 'idle' is never fired and nothing gets sent
|
||||||
|
pool: true,
|
||||||
|
auth: {
|
||||||
|
user: process.env.NODEMAILER_USER,
|
||||||
|
pass: process.env.NODEMAILER_PASS
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
// testserver uses self signed certificate, so we need to lax a bit
|
||||||
|
rejectUnauthorized: false
|
||||||
|
},
|
||||||
|
logger: false
|
||||||
|
};
|
||||||
|
// array of prefetched messages waiting for delivery
|
||||||
|
var waiting = [];
|
||||||
|
// Create a SMTP transporter object
|
||||||
|
var transporter = nodemailer.createTransport(smtpHost, {
|
||||||
|
// default message fields
|
||||||
|
from: process.env.SENDER_ADDRESS
|
||||||
|
});
|
||||||
|
// Create connection to RabbitMQ
|
||||||
|
var queueConnection = amqp.createConnection({
|
||||||
|
url: queueHost
|
||||||
|
});
|
||||||
|
queueConnection.on('error', function (e) {
|
||||||
|
console.log('Error from amqp: ', e);
|
||||||
|
});
|
||||||
|
queueConnection.on('ready', function (err) {
|
||||||
|
console.log('AMPQ server is running on port 5672.');
|
||||||
|
queueConnection.queue(queueName, { durable: true }, function (q) {
|
||||||
|
q.bind('#');
|
||||||
|
q.subscribe({
|
||||||
|
ack: true,
|
||||||
|
prefetchCount: 10 // prefetch 10 messages
|
||||||
|
}, function (message, headers, deliveryInfo, ack) {
|
||||||
|
// check if the message object is even valid
|
||||||
|
if (!message || !message.to) {
|
||||||
|
console.log('Invalid message, skipping');
|
||||||
|
// reject, do not requeue
|
||||||
|
return ack.reject();
|
||||||
|
}
|
||||||
|
// push to cache
|
||||||
|
waiting.push({
|
||||||
|
message: message,
|
||||||
|
deliveryTag: deliveryInfo.deliveryTag.toString('hex'),
|
||||||
|
ack: ack
|
||||||
|
});
|
||||||
|
// try to flush cached messages by sending these to SMTP
|
||||||
|
flushWaitingMessages();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Whenever transporter gets into idling, try to send some mail
|
||||||
|
transporter.on('idle', flushWaitingMessages);
|
||||||
|
// Flushes cached messages to nodemailer for delivery
|
||||||
|
function flushWaitingMessages() {
|
||||||
|
// actual send function
|
||||||
|
var send = function (data) {
|
||||||
|
// sendMail does not immediatelly send, instead it tries to allocate a free connection to SMTP server
|
||||||
|
// and if fails, then pushes the message into internal queue. As we only prefetch 10 messages
|
||||||
|
// then the internal queue can never grow into something too large. At most there will be 5 messages
|
||||||
|
// idling in the queue (another 5 are being currently sent by the default number of 5 connections)
|
||||||
|
transporter.sendMail(data.message, function (err, info) {
|
||||||
|
if (err) {
|
||||||
|
console.log('Message failed (%s): %s', data.deliveryTag, err.message);
|
||||||
|
// reject and requeue on error (wait 1 sec. before requeueing)
|
||||||
|
// NB! If the failure is permanent then this approach results in an
|
||||||
|
// infinite loop since failing message is never removed from the queue
|
||||||
|
setTimeout(function () {
|
||||||
|
data.ack.reject(true);
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Message delivered (%s): %s', data.deliveryTag, info.response);
|
||||||
|
data.ack.acknowledge();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// send cached messages if transporter is idling
|
||||||
|
while (transporter.isIdle() && waiting.length) {
|
||||||
|
send(waiting.shift());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.publishQueueConnection = function (mailOptions) {
|
||||||
|
console.log('publishQueueConnection');
|
||||||
|
queueConnection.publish(queueName, mailOptions, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
112
server/api/amqp.ts
Executable file
112
server/api/amqp.ts
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
// This script fetches queued messages from RabbitMQ and delivers these to SMTP
|
||||||
|
|
||||||
|
import * as nodemailer from 'nodemailer'
|
||||||
|
import * as amqp from 'amqp'
|
||||||
|
|
||||||
|
const queueHost = process.env.AMQP_URL
|
||||||
|
const queueName = 'outgoing'
|
||||||
|
|
||||||
|
const smtpHost = {
|
||||||
|
host: process.env.NODEMAILER_HOST,
|
||||||
|
port: process.env.NODEMAILER_PORT,
|
||||||
|
// NB! Must be pooled connection, otherwise 'idle' is never fired and nothing gets sent
|
||||||
|
pool: true,
|
||||||
|
auth: {
|
||||||
|
user: process.env.NODEMAILER_USER,
|
||||||
|
pass: process.env.NODEMAILER_PASS
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
// testserver uses self signed certificate, so we need to lax a bit
|
||||||
|
rejectUnauthorized: false
|
||||||
|
},
|
||||||
|
logger: false
|
||||||
|
}
|
||||||
|
|
||||||
|
// array of prefetched messages waiting for delivery
|
||||||
|
const waiting = []
|
||||||
|
// Create a SMTP transporter object
|
||||||
|
const transporter = nodemailer.createTransport(smtpHost, {
|
||||||
|
// default message fields
|
||||||
|
from: process.env.SENDER_ADDRESS
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create connection to RabbitMQ
|
||||||
|
const queueConnection = amqp.createConnection({
|
||||||
|
url: queueHost
|
||||||
|
})
|
||||||
|
|
||||||
|
queueConnection.on('error', function (e) {
|
||||||
|
console.log('Error from amqp: ', e)
|
||||||
|
})
|
||||||
|
|
||||||
|
queueConnection.on('ready', function (err) {
|
||||||
|
console.log('AMPQ server is running on port 5672.')
|
||||||
|
queueConnection.queue(queueName, { durable: true }, function (q) {
|
||||||
|
q.bind('#')
|
||||||
|
q.subscribe({
|
||||||
|
ack: true, // do not fetch next messages until previous are acked
|
||||||
|
prefetchCount: 10 // prefetch 10 messages
|
||||||
|
}, function (message, headers, deliveryInfo, ack) {
|
||||||
|
// check if the message object is even valid
|
||||||
|
if (!message || !message.to) {
|
||||||
|
console.log('Invalid message, skipping')
|
||||||
|
// reject, do not requeue
|
||||||
|
return ack.reject()
|
||||||
|
}
|
||||||
|
// push to cache
|
||||||
|
waiting.push({
|
||||||
|
message: message,
|
||||||
|
deliveryTag: deliveryInfo.deliveryTag.toString('hex'),
|
||||||
|
ack: ack
|
||||||
|
})
|
||||||
|
// try to flush cached messages by sending these to SMTP
|
||||||
|
flushWaitingMessages()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Whenever transporter gets into idling, try to send some mail
|
||||||
|
transporter.on('idle', flushWaitingMessages)
|
||||||
|
|
||||||
|
// Flushes cached messages to nodemailer for delivery
|
||||||
|
function flushWaitingMessages () {
|
||||||
|
// actual send function
|
||||||
|
var send = function (data) {
|
||||||
|
// sendMail does not immediatelly send, instead it tries to allocate a free connection to SMTP server
|
||||||
|
// and if fails, then pushes the message into internal queue. As we only prefetch 10 messages
|
||||||
|
// then the internal queue can never grow into something too large. At most there will be 5 messages
|
||||||
|
// idling in the queue (another 5 are being currently sent by the default number of 5 connections)
|
||||||
|
transporter.sendMail(data.message, function (err, info) {
|
||||||
|
if (err) {
|
||||||
|
console.log('Message failed (%s): %s', data.deliveryTag, err.message)
|
||||||
|
// reject and requeue on error (wait 1 sec. before requeueing)
|
||||||
|
// NB! If the failure is permanent then this approach results in an
|
||||||
|
// infinite loop since failing message is never removed from the queue
|
||||||
|
setTimeout(function () {
|
||||||
|
data.ack.reject(true)
|
||||||
|
}, 1000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log('Message delivered (%s): %s', data.deliveryTag, info.response)
|
||||||
|
data.ack.acknowledge()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// send cached messages if transporter is idling
|
||||||
|
while (transporter.isIdle() && waiting.length) {
|
||||||
|
send(waiting.shift())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const publishQueueConnection = (mailOptions) => {
|
||||||
|
console.log('publishQueueConnection')
|
||||||
|
queueConnection.publish(queueName, mailOptions, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
46
server/api/logger.js
Executable file
46
server/api/logger.js
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LoggerStream = exports.logger = void 0;
|
||||||
|
var winston = require("winston");
|
||||||
|
var _a = winston.format, combine = _a.combine, timestamp = _a.timestamp, label = _a.label, prettyPrint = _a.prettyPrint, colorize = _a.colorize, json = _a.json, splat = _a.splat;
|
||||||
|
/// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ///////////////////////Winston Logger///////////////////////////////////////
|
||||||
|
/// ////////////////////////////////////////////////////////////////////////////
|
||||||
|
exports.logger = winston.createLogger({
|
||||||
|
exitOnError: false,
|
||||||
|
format: combine(timestamp(), prettyPrint(), colorize(), splat()),
|
||||||
|
level: 'info',
|
||||||
|
// format: winston.format.json(),
|
||||||
|
// defaultMeta: { service: 'user-service' },
|
||||||
|
transports: [
|
||||||
|
//
|
||||||
|
// - Write to all logs with level `info` and below to `combined.log`
|
||||||
|
// - Write all logs error (and below) to `error.log`.
|
||||||
|
//
|
||||||
|
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
||||||
|
new winston.transports.File({ filename: 'combined.log' })
|
||||||
|
],
|
||||||
|
exceptionHandlers: [
|
||||||
|
new winston.transports.File({ filename: 'exceptions.log' })
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'development') {
|
||||||
|
exports.logger.add(new winston.transports.Console({
|
||||||
|
format: winston.format.simple()
|
||||||
|
}));
|
||||||
|
// }
|
||||||
|
// logger.stream = {
|
||||||
|
// write: function (message: string, encoding: any) {
|
||||||
|
// logger.info(message)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
var LoggerStream = /** @class */ (function () {
|
||||||
|
function LoggerStream() {
|
||||||
|
}
|
||||||
|
LoggerStream.prototype.write = function (message) {
|
||||||
|
exports.logger.info(message);
|
||||||
|
};
|
||||||
|
return LoggerStream;
|
||||||
|
}());
|
||||||
|
exports.LoggerStream = LoggerStream;
|
||||||
|
//module.exports = logger
|
||||||
48
server/api/logger.ts
Executable file
48
server/api/logger.ts
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
import * as winston from 'winston'
|
||||||
|
const { combine, timestamp, label, prettyPrint, colorize, json, splat } = winston.format
|
||||||
|
|
||||||
|
/// /////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ///////////////////////Winston Logger///////////////////////////////////////
|
||||||
|
/// ////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
export const logger = winston.createLogger({
|
||||||
|
exitOnError: false,
|
||||||
|
format: combine(
|
||||||
|
timestamp(),
|
||||||
|
prettyPrint(),
|
||||||
|
colorize(),
|
||||||
|
splat()
|
||||||
|
),
|
||||||
|
level: 'info',
|
||||||
|
// format: winston.format.json(),
|
||||||
|
// defaultMeta: { service: 'user-service' },
|
||||||
|
transports: [
|
||||||
|
//
|
||||||
|
// - Write to all logs with level `info` and below to `combined.log`
|
||||||
|
// - Write all logs error (and below) to `error.log`.
|
||||||
|
//
|
||||||
|
new winston.transports.File({ filename: 'error.log', level: 'error' }),
|
||||||
|
new winston.transports.File({ filename: 'combined.log' })
|
||||||
|
],
|
||||||
|
exceptionHandlers: [
|
||||||
|
new winston.transports.File({ filename: 'exceptions.log' })
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'development') {
|
||||||
|
logger.add(new winston.transports.Console({
|
||||||
|
format: winston.format.simple()
|
||||||
|
}))
|
||||||
|
// }
|
||||||
|
// logger.stream = {
|
||||||
|
// write: function (message: string, encoding: any) {
|
||||||
|
// logger.info(message)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
export class LoggerStream {
|
||||||
|
write(message: string) {
|
||||||
|
logger.info(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//module.exports = logger
|
||||||
31
server/api/myError.js
Executable file
31
server/api/myError.js
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
"use strict";
|
||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
exports.__esModule = true;
|
||||||
|
var myError = /** @class */ (function (_super) {
|
||||||
|
__extends(myError, _super);
|
||||||
|
function myError(messageEnglish, statusCode, clientCode, clientMessage, title) {
|
||||||
|
var _newTarget = this.constructor;
|
||||||
|
var _this = _super.call(this, messageEnglish) || this;
|
||||||
|
_this.messageEnglish = messageEnglish;
|
||||||
|
_this.statusCode = statusCode;
|
||||||
|
_this.clientCode = clientCode;
|
||||||
|
_this.clientMessage = clientMessage;
|
||||||
|
_this.title = title;
|
||||||
|
Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return myError;
|
||||||
|
}(Error));
|
||||||
|
exports["default"] = myError;
|
||||||
25
server/api/myError.ts
Executable file
25
server/api/myError.ts
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
import { cli } from "winston/lib/winston/config";
|
||||||
|
|
||||||
|
export default class myError extends Error {
|
||||||
|
messageEnglish: string;
|
||||||
|
statusCode: Number;
|
||||||
|
clientCode: Number;
|
||||||
|
clientMessage: string;
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
messageEnglish ?: string,
|
||||||
|
statusCode?: Number,
|
||||||
|
clientCode?: Number,
|
||||||
|
clientMessage?: string,
|
||||||
|
title?: string
|
||||||
|
) {
|
||||||
|
super(messageEnglish);
|
||||||
|
this.messageEnglish = messageEnglish;
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.clientCode = clientCode;
|
||||||
|
this.clientMessage = clientMessage;
|
||||||
|
this.title = title;
|
||||||
|
Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
|
||||||
|
}
|
||||||
|
}
|
||||||
326
server/api/query.js
Executable file
326
server/api/query.js
Executable file
@@ -0,0 +1,326 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.searchOnActiveOffers = exports.searchOnTxs = void 0;
|
||||||
|
var redis = require("../api/redis");
|
||||||
|
var acceptedOffers_1 = require("../db/acceptedOffers");
|
||||||
|
var ActiveOffers_1 = require("../db/ActiveOffers");
|
||||||
|
exports.searchOnTxs = function (_a) {
|
||||||
|
var curId = _a.curId, txType = _a.txType, rial = _a.rial;
|
||||||
|
var itemsMap = new Map();
|
||||||
|
var items = ['curId'];
|
||||||
|
var definedItems = [];
|
||||||
|
itemsMap.set('curId', curId);
|
||||||
|
items.map(function (element) {
|
||||||
|
if (itemsMap.get(element)) {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var query = [];
|
||||||
|
var queryMap = new Map();
|
||||||
|
queryMap.set('curId', [{ $or: [
|
||||||
|
{ $and: [{ curGivenId: curId }, { curTakenId: rial._id }] },
|
||||||
|
{ $and: [{ curTakenId: curId }, { curGivenId: rial._id }] }
|
||||||
|
] }]);
|
||||||
|
var definedItemsMap = definedItems.map(function (element) {
|
||||||
|
query.push.apply(query, queryMap.get(element));
|
||||||
|
});
|
||||||
|
if (query.length === 0) {
|
||||||
|
query = [{ $or: [{ curTakenId: rial._id }, { curGivenId: rial._id }] }];
|
||||||
|
}
|
||||||
|
console.log('query: ', query);
|
||||||
|
return Promise.all(definedItemsMap)
|
||||||
|
.then(function () {
|
||||||
|
return acceptedOffers_1.Accepted_Offers.find({ $and: query })
|
||||||
|
.then(function (result) {
|
||||||
|
var modifiedResult = [];
|
||||||
|
if (itemsMap.get('curId')) {
|
||||||
|
return redis.hashGetAll(curId.toString())
|
||||||
|
.then(function (curObj) {
|
||||||
|
result.map(function (e) {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString() && txType === 'sell') {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (e.curGivenId.toString() === rial._id.toString() && txType === 'buy') {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (txType === 'all') {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString()) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (e.curGivenId.toString() === rial._id.toString()) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return modifiedResult;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var resultMap = result.map(function (e) {
|
||||||
|
console.log('eeeeeeeee: ', e);
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString() && txType === 'sell') {
|
||||||
|
return redis.hashGetAll(e.curGivenId.toString())
|
||||||
|
.then(function (curGivenObj) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curGivenObj.currencyName,
|
||||||
|
GpersianName: curGivenObj.per_name,
|
||||||
|
GshortName: curGivenObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curGivenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (e.curGivenId.toString() === rial._id.toString() && txType === 'buy') {
|
||||||
|
return redis.hashGetAll(e.curTakenId.toString())
|
||||||
|
.then(function (curTakenObj) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curTakenObj.currencyName,
|
||||||
|
GpersianName: curTakenObj.per_name,
|
||||||
|
GshortName: curTakenObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curTakenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (txType === 'all') {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString()) {
|
||||||
|
return redis.hashGetAll(e.curGivenId.toString())
|
||||||
|
.then(function (curGivenObj) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curGivenObj.currencyName,
|
||||||
|
GpersianName: curGivenObj.per_name,
|
||||||
|
GshortName: curGivenObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curGivenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (e.curGivenId.toString() === rial._id.toString()) {
|
||||||
|
return redis.hashGetAll(e.curTakenId.toString())
|
||||||
|
.then(function (curTakenObj) {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curTakenObj.currencyName,
|
||||||
|
GpersianName: curTakenObj.per_name,
|
||||||
|
GshortName: curTakenObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curTakenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Promise.all(resultMap)
|
||||||
|
.then(function () {
|
||||||
|
return modifiedResult;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.searchOnActiveOffers = function (_a) {
|
||||||
|
var offerId = _a.offerId, curGivenId = _a.curGivenId, curGivenVal = _a.curGivenVal, curTakenId = _a.curTakenId, curTakenVal = _a.curTakenVal, expDate = _a.expDate, created_at = _a.created_at;
|
||||||
|
var itemsMap = new Map();
|
||||||
|
var items = ['offerId', 'curGivenId', 'curGivenVal', 'curTakenId', 'curTakenVal', 'expDate', 'created_at'];
|
||||||
|
var definedItems = [];
|
||||||
|
itemsMap.set('offerId', offerId);
|
||||||
|
itemsMap.set('curGivenId', curGivenId);
|
||||||
|
itemsMap.set('curGivenVal', curGivenVal);
|
||||||
|
itemsMap.set('curTakenId', curTakenId);
|
||||||
|
itemsMap.set('curTakenVal', curTakenVal);
|
||||||
|
itemsMap.set('expDate', expDate);
|
||||||
|
itemsMap.set('created_at', created_at);
|
||||||
|
items.map(function (element) {
|
||||||
|
if (itemsMap.get(element)) {
|
||||||
|
if (element === 'expDate') {
|
||||||
|
if (expDate.from || expDate.to) {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (element === 'created_at') {
|
||||||
|
if (created_at.from || created_at.to) {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (element === 'curGivenVal') {
|
||||||
|
if (curGivenVal.from || curGivenVal.to) {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (element === 'curTakenVal') {
|
||||||
|
if (curTakenVal.from || curTakenVal.to) {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
definedItems.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var query = [{ expDate: { $gt: Date.now() } }];
|
||||||
|
var queryMap = new Map();
|
||||||
|
var queryExpDate;
|
||||||
|
var queryCreatedAt;
|
||||||
|
var queryCurGivenVal;
|
||||||
|
var queryCurTakenVal;
|
||||||
|
if (definedItems.includes('expDate')) {
|
||||||
|
if (expDate.from && expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $gt: expDate.from, $lt: expDate.to } };
|
||||||
|
}
|
||||||
|
else if (expDate.from && !expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $gt: expDate.from } };
|
||||||
|
}
|
||||||
|
else if (!expDate.from && expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $lt: expDate.to } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('created_at')) {
|
||||||
|
if (created_at.from && created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $gt: created_at.from, $lt: created_at.to } };
|
||||||
|
}
|
||||||
|
else if (created_at.from && !created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $gt: created_at.from } };
|
||||||
|
}
|
||||||
|
else if (!created_at.from && created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $lt: created_at.to } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('curGivenVal')) {
|
||||||
|
if (curGivenVal.from && curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $gte: curGivenVal.from, $lte: curGivenVal.to } };
|
||||||
|
}
|
||||||
|
else if (curGivenVal.from && !curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $gte: curGivenVal.from } };
|
||||||
|
}
|
||||||
|
else if (!curGivenVal.from && curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $lte: curGivenVal.to } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('curTakenVal')) {
|
||||||
|
if (curTakenVal.from && curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $gte: curTakenVal.from, $lte: curTakenVal.to } };
|
||||||
|
}
|
||||||
|
else if (curTakenVal.from && !curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $gte: curTakenVal.from } };
|
||||||
|
}
|
||||||
|
else if (!curTakenVal.from && curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $lte: curTakenVal.to } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queryMap.set('offerId', { offerId: offerId });
|
||||||
|
queryMap.set('curGivenId', { curGivenId: curGivenId });
|
||||||
|
queryMap.set('curGivenVal', queryCurGivenVal);
|
||||||
|
queryMap.set('curTakenId', { curTakenId: curTakenId });
|
||||||
|
queryMap.set('curTakenVal', queryCurTakenVal);
|
||||||
|
queryMap.set('expDate', queryExpDate);
|
||||||
|
queryMap.set('created_at', queryCreatedAt);
|
||||||
|
var definedItemsMap = definedItems.map(function (element) {
|
||||||
|
query.push(queryMap.get(element));
|
||||||
|
});
|
||||||
|
return Promise.all(definedItemsMap)
|
||||||
|
.then(function () {
|
||||||
|
return ActiveOffers_1.Active_Offers.find({ $and: query })
|
||||||
|
.then(function (result) {
|
||||||
|
return result;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
334
server/api/query.ts
Executable file
334
server/api/query.ts
Executable file
@@ -0,0 +1,334 @@
|
|||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
|
import * as redis from '../api/redis'
|
||||||
|
|
||||||
|
|
||||||
|
import { Accepted_Offers } from '../db/acceptedOffers';
|
||||||
|
import { Active_Offers } from '../db/ActiveOffers';
|
||||||
|
|
||||||
|
export const searchOnTxs = ({ curId, txType, rial }) => {
|
||||||
|
const itemsMap = new Map()
|
||||||
|
const items = ['curId']
|
||||||
|
const definedItems = []
|
||||||
|
itemsMap.set('curId', curId)
|
||||||
|
|
||||||
|
|
||||||
|
items.map((element) => {
|
||||||
|
if(itemsMap.get(element)) {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let query = []
|
||||||
|
let queryMap = new Map()
|
||||||
|
|
||||||
|
queryMap.set('curId', [ { $or: [
|
||||||
|
{ $and: [{ curGivenId: curId }, { curTakenId: rial._id } ] },
|
||||||
|
{ $and: [{ curTakenId: curId }, { curGivenId: rial._id } ] }
|
||||||
|
] } ] )
|
||||||
|
|
||||||
|
const definedItemsMap = definedItems.map((element) => {
|
||||||
|
query.push.apply(query, queryMap.get(element))
|
||||||
|
})
|
||||||
|
|
||||||
|
if(query.length === 0) {
|
||||||
|
query = [ { $or: [ { curTakenId: rial._id }, { curGivenId: rial._id } ] } ]
|
||||||
|
}
|
||||||
|
console.log('query: ', query)
|
||||||
|
return Promise.all(definedItemsMap)
|
||||||
|
.then(() => {
|
||||||
|
return Accepted_Offers.find({ $and: query })
|
||||||
|
.then((result) => {
|
||||||
|
let modifiedResult = []
|
||||||
|
if(itemsMap.get('curId')) {
|
||||||
|
return redis.hashGetAll(curId.toString())
|
||||||
|
.then((curObj: any) => {
|
||||||
|
result.map((e) => {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString() && txType === 'sell') {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
})
|
||||||
|
} else if (e.curGivenId.toString() === rial._id.toString() && txType === 'buy') {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
})
|
||||||
|
} else if (txType === 'all') {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString()) {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
})
|
||||||
|
} else if (e.curGivenId.toString() === rial._id.toString()) {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curObj.currencyName,
|
||||||
|
GpersianName: curObj.per_name,
|
||||||
|
GshortName: curObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return modifiedResult
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const resultMap = result.map((e) => {
|
||||||
|
console.log('eeeeeeeee: ', e)
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString() && txType === 'sell') {
|
||||||
|
return redis.hashGetAll(e.curGivenId.toString())
|
||||||
|
.then((curGivenObj: any) => {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curGivenObj.currencyName,
|
||||||
|
GpersianName: curGivenObj.per_name,
|
||||||
|
GshortName: curGivenObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curGivenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
} else if (e.curGivenId.toString() === rial._id.toString() && txType === 'buy') {
|
||||||
|
return redis.hashGetAll(e.curTakenId.toString())
|
||||||
|
.then((curTakenObj: any) => {
|
||||||
|
modifiedResult.push({
|
||||||
|
GcurrencyName: curTakenObj.currencyName,
|
||||||
|
GpersianName: curTakenObj.per_name,
|
||||||
|
GshortName: curTakenObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curTakenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
} else if (txType === 'all') {
|
||||||
|
if (e.curTakenId.toString() === rial._id.toString()) {
|
||||||
|
return redis.hashGetAll(e.curGivenId.toString())
|
||||||
|
.then((curGivenObj: any) => {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curGivenObj.currencyName,
|
||||||
|
GpersianName: curGivenObj.per_name,
|
||||||
|
GshortName: curGivenObj.ab_name,
|
||||||
|
Gvalue: e.curGivenVal,
|
||||||
|
Gicon: curGivenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curTakenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'sell'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
} else if (e.curGivenId.toString() === rial._id.toString()) {
|
||||||
|
return redis.hashGetAll(e.curTakenId.toString())
|
||||||
|
.then((curTakenObj: any) => {
|
||||||
|
modifiedResult.push ({
|
||||||
|
GcurrencyName: curTakenObj.currencyName,
|
||||||
|
GpersianName: curTakenObj.per_name,
|
||||||
|
GshortName: curTakenObj.ab_name,
|
||||||
|
Gvalue: e.curTakenVal,
|
||||||
|
Gicon: curTakenObj.icon,
|
||||||
|
acceptedDate: e.created_at,
|
||||||
|
TcurrencyName: rial.currencyName,
|
||||||
|
TpersianName: rial.per_name,
|
||||||
|
TshortName: rial.ab_name,
|
||||||
|
Tvalue: e.curGivenVal,
|
||||||
|
Ticon: rial.icon,
|
||||||
|
txType: 'buy'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Promise.all(resultMap)
|
||||||
|
.then(() => {
|
||||||
|
return modifiedResult
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const searchOnActiveOffers = ({ offerId, curGivenId, curGivenVal, curTakenId, curTakenVal, expDate, created_at }) => {
|
||||||
|
const itemsMap = new Map()
|
||||||
|
const items = ['offerId', 'curGivenId', 'curGivenVal', 'curTakenId', 'curTakenVal', 'expDate', 'created_at']
|
||||||
|
const definedItems = []
|
||||||
|
itemsMap.set('offerId', offerId)
|
||||||
|
itemsMap.set('curGivenId', curGivenId)
|
||||||
|
itemsMap.set('curGivenVal', curGivenVal)
|
||||||
|
itemsMap.set('curTakenId', curTakenId)
|
||||||
|
itemsMap.set('curTakenVal', curTakenVal)
|
||||||
|
itemsMap.set('expDate', expDate)
|
||||||
|
itemsMap.set('created_at', created_at)
|
||||||
|
|
||||||
|
items.map((element) => {
|
||||||
|
if(itemsMap.get(element)) {
|
||||||
|
if (element === 'expDate') {
|
||||||
|
if(expDate.from || expDate.to) {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
} else if (element === 'created_at') {
|
||||||
|
if(created_at.from || created_at.to) {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
} else if (element === 'curGivenVal') {
|
||||||
|
if(curGivenVal.from || curGivenVal.to) {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
} else if (element === 'curTakenVal') {
|
||||||
|
if(curTakenVal.from || curTakenVal.to) {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
definedItems.push(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let query = [ { expDate: { $gt: Date.now() } } ]
|
||||||
|
let queryMap = new Map()
|
||||||
|
let queryExpDate
|
||||||
|
let queryCreatedAt
|
||||||
|
let queryCurGivenVal
|
||||||
|
let queryCurTakenVal
|
||||||
|
|
||||||
|
if (definedItems.includes('expDate')) {
|
||||||
|
if (expDate.from && expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $gt: expDate.from, $lt: expDate.to } }
|
||||||
|
} else if (expDate.from && !expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $gt: expDate.from } }
|
||||||
|
} else if (!expDate.from && expDate.to) {
|
||||||
|
queryExpDate = { expDate: { $lt: expDate.to } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('created_at')) {
|
||||||
|
if (created_at.from && created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $gt: created_at.from, $lt: created_at.to } }
|
||||||
|
} else if (created_at.from && !created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $gt: created_at.from } }
|
||||||
|
} else if (!created_at.from && created_at.to) {
|
||||||
|
queryCreatedAt = { created_at: { $lt: created_at.to } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('curGivenVal')) {
|
||||||
|
if (curGivenVal.from && curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $gte: curGivenVal.from, $lte: curGivenVal.to } }
|
||||||
|
} else if (curGivenVal.from && !curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $gte: curGivenVal.from } }
|
||||||
|
} else if (!curGivenVal.from && curGivenVal.to) {
|
||||||
|
queryCurGivenVal = { curGivenVal: { $lte: curGivenVal.to } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (definedItems.includes('curTakenVal')) {
|
||||||
|
if (curTakenVal.from && curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $gte: curTakenVal.from, $lte: curTakenVal.to } }
|
||||||
|
} else if (curTakenVal.from && !curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $gte: curTakenVal.from } }
|
||||||
|
} else if (!curTakenVal.from && curTakenVal.to) {
|
||||||
|
queryCurTakenVal = { curTakenVal: { $lte: curTakenVal.to } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queryMap.set('offerId', { offerId: offerId })
|
||||||
|
queryMap.set('curGivenId', { curGivenId: curGivenId })
|
||||||
|
queryMap.set('curGivenVal', queryCurGivenVal)
|
||||||
|
queryMap.set('curTakenId', { curTakenId: curTakenId })
|
||||||
|
queryMap.set('curTakenVal', queryCurTakenVal)
|
||||||
|
queryMap.set('expDate', queryExpDate)
|
||||||
|
queryMap.set('created_at', queryCreatedAt)
|
||||||
|
const definedItemsMap = definedItems.map((element) => {
|
||||||
|
query.push(queryMap.get(element))
|
||||||
|
})
|
||||||
|
|
||||||
|
return Promise.all(definedItemsMap)
|
||||||
|
.then(() => {
|
||||||
|
return Active_Offers.find({ $and: query })
|
||||||
|
.then((result) => {
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
116
server/api/redis.js
Executable file
116
server/api/redis.js
Executable file
@@ -0,0 +1,116 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.getCurrentPrice = exports.hashSetMembers = exports.hashHMset = exports.hashGetAll = exports.hashset = exports.hashget = exports.globalRedisClient = void 0;
|
||||||
|
var redis = require("redis");
|
||||||
|
var myError_1 = require("./myError");
|
||||||
|
exports.globalRedisClient = redis.createClient({
|
||||||
|
port: process.env.REDIS_PORT,
|
||||||
|
host: process.env.REDIS_HOST,
|
||||||
|
enable_offline_queue: false
|
||||||
|
});
|
||||||
|
// globalRedisClient.auth(process.env.REDIS_PASS, (err) => {
|
||||||
|
// if (err) console.log(err);
|
||||||
|
// })
|
||||||
|
exports.globalRedisClient.on('connect', function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('Redis-server is connected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
exports.globalRedisClient.on('error', function (err) {
|
||||||
|
console.log('Error ' + err);
|
||||||
|
});
|
||||||
|
exports.hashget = function (tag) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
exports.globalRedisClient.get(tag, function (err, reply) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.hashset = function (tag, val) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
exports.globalRedisClient.set(tag, val, function (err, reply) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.hashGetAll = function (tag) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
exports.globalRedisClient.hgetall(tag, function (err, reply) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.hashHMset = function (tag, val) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
exports.globalRedisClient.hmset(tag, val, function (err, reply) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.hashSetMembers = function (tag) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
exports.globalRedisClient.smembers(tag, function (err, reply) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function getCurrentPrice(currency) {
|
||||||
|
//API for getting current currency price
|
||||||
|
return exports.hashGetAll(currency.toString())
|
||||||
|
.then(function (currencyInfo) {
|
||||||
|
return exports.hashGetAll(currencyInfo.ab_name.toString() + "-g")
|
||||||
|
.then(function (currencyInstantPrice) {
|
||||||
|
if (currencyInstantPrice) {
|
||||||
|
return exports.hashget("dollarPrice")
|
||||||
|
.then(function (rialPrice) {
|
||||||
|
if (rialPrice) {
|
||||||
|
return Number(currencyInstantPrice.current) * Number(rialPrice);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('It is not possible to get price currently!', 400, 11, 'امکان قیمت گیری در حال حاضر وجود ندارد!', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('It is not possible to get price currently!', 400, 11, 'امکان قیمت گیری در حال حاضر وجود ندارد!', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.getCurrentPrice = getCurrentPrice;
|
||||||
127
server/api/redis.ts
Executable file
127
server/api/redis.ts
Executable file
@@ -0,0 +1,127 @@
|
|||||||
|
import * as redis from 'redis'
|
||||||
|
import myError from './myError'
|
||||||
|
export const globalRedisClient = redis.createClient({
|
||||||
|
port: process.env.REDIS_PORT,
|
||||||
|
host: process.env.REDIS_HOST,
|
||||||
|
enable_offline_queue: false
|
||||||
|
})
|
||||||
|
// globalRedisClient.auth(process.env.REDIS_PASS, (err) => {
|
||||||
|
// if (err) console.log(err);
|
||||||
|
// })
|
||||||
|
globalRedisClient.on('connect', function (err) {
|
||||||
|
if(err) {
|
||||||
|
console.log(err)
|
||||||
|
} else {
|
||||||
|
console.log('Redis-server is connected')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
globalRedisClient.on('error', function (err) {
|
||||||
|
console.log('Error ' + err)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const hashget = (tag) => { // It is corresponded to hashset
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
globalRedisClient.get(tag, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashset = (tag, val) => { // value could be only a string
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
globalRedisClient.set(tag, val, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashGetAll = (tag) => { // It is corresponded to hashHMset
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
globalRedisClient.hgetall(tag, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashHMset = (tag, val) => { // value could be object!
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
globalRedisClient.hmset(tag, val, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hashSetMembers = (tag) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
globalRedisClient.smembers(tag, (err, reply) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(reply)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentPrice(currency){
|
||||||
|
//API for getting current currency price
|
||||||
|
return hashGetAll(currency.toString())
|
||||||
|
.then((currencyInfo: any) => {
|
||||||
|
return hashGetAll(currencyInfo.ab_name.toString() + "-g")
|
||||||
|
.then((currencyInstantPrice: any) => {
|
||||||
|
if(currencyInstantPrice) {
|
||||||
|
return hashget("dollarPrice")
|
||||||
|
.then((rialPrice) => {
|
||||||
|
if(rialPrice) {
|
||||||
|
return Number(currencyInstantPrice.current) * Number(rialPrice)
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'It is not possible to get price currently!',
|
||||||
|
400,
|
||||||
|
11,
|
||||||
|
'امکان قیمت گیری در حال حاضر وجود ندارد!',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'It is not possible to get price currently!',
|
||||||
|
400,
|
||||||
|
11,
|
||||||
|
'امکان قیمت گیری در حال حاضر وجود ندارد!',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
52
server/api/socket.js
Executable file
52
server/api/socket.js
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.getonlineNotLoginUsers = exports.getonlineLoginUsers = exports.startIo = void 0;
|
||||||
|
// import * as scocketIo from 'socket.io'
|
||||||
|
var scocketIo = require('socket.io');
|
||||||
|
var redis = require("redis");
|
||||||
|
var client = redis.createClient();
|
||||||
|
var logger_1 = require("./logger");
|
||||||
|
var onlineLoginUsers = null;
|
||||||
|
var onlineNotLoginUsers = null;
|
||||||
|
var socketConnection = function socketConnection(socket) {
|
||||||
|
logger_1.logger.info("Client connected [id=" + socket.id + "]");
|
||||||
|
};
|
||||||
|
var socketDisconnection = function socketDisconnection(socket) {
|
||||||
|
logger_1.logger.info("Client gone [id=" + socket.id + "]");
|
||||||
|
};
|
||||||
|
exports.startIo = function (server) {
|
||||||
|
var io = scocketIo(server, {
|
||||||
|
serveClient: false,
|
||||||
|
cors: {
|
||||||
|
origin: '*'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
io.on('connection', socketConnection);
|
||||||
|
io.on('disconnect', socketDisconnection);
|
||||||
|
onlineLoginUsers = io.of('/onlineLoginUsers');
|
||||||
|
onlineNotLoginUsers = io.of('/onlineNotLoginUsers');
|
||||||
|
onlineLoginUsers.on('connection', function (socket) {
|
||||||
|
logger_1.logger.info("Client connected [id=" + socket.id + "]");
|
||||||
|
console.log('socket.handshake', socket.handshake.session);
|
||||||
|
if (socket.handshake.session.userId) {
|
||||||
|
client.sadd(socket.handshake.session.userId, socket.id, function (err, reply) {
|
||||||
|
if (err)
|
||||||
|
logger_1.logger.warn(err);
|
||||||
|
});
|
||||||
|
logger_1.logger.info("A logged in client connected in :" + socket.id);
|
||||||
|
socket.on('disconnect', function () {
|
||||||
|
logger_1.logger.info("Client gone [id=" + socket.id + "]");
|
||||||
|
client.srem(socket.handshake.session.userId, socket.id, function (err, reply) {
|
||||||
|
logger_1.logger.info("socket with id " + socket.id + " is closed!");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return io;
|
||||||
|
};
|
||||||
|
exports.getonlineLoginUsers = function () {
|
||||||
|
return onlineLoginUsers;
|
||||||
|
};
|
||||||
|
exports.getonlineNotLoginUsers = function () {
|
||||||
|
return onlineNotLoginUsers;
|
||||||
|
};
|
||||||
55
server/api/socket.ts
Executable file
55
server/api/socket.ts
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
// import * as scocketIo from 'socket.io'
|
||||||
|
const scocketIo = require('socket.io')
|
||||||
|
import * as redis from 'redis'
|
||||||
|
var client = redis.createClient()
|
||||||
|
import { logger } from './logger'
|
||||||
|
|
||||||
|
let onlineLoginUsers = null
|
||||||
|
let onlineNotLoginUsers = null
|
||||||
|
|
||||||
|
var socketConnection = function socketConnection (socket) {
|
||||||
|
logger.info(`Client connected [id=${socket.id}]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
var socketDisconnection = function socketDisconnection (socket) {
|
||||||
|
logger.info(`Client gone [id=${socket.id}]`)
|
||||||
|
}
|
||||||
|
export const startIo = (server) => {
|
||||||
|
const io = scocketIo(server, {
|
||||||
|
serveClient: false,
|
||||||
|
cors: {
|
||||||
|
origin: '*',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
io.on('connection', socketConnection)
|
||||||
|
io.on('disconnect', socketDisconnection)
|
||||||
|
onlineLoginUsers = io.of('/onlineLoginUsers')
|
||||||
|
onlineNotLoginUsers = io.of('/onlineNotLoginUsers')
|
||||||
|
onlineLoginUsers.on('connection', function (socket) {
|
||||||
|
logger.info(`Client connected [id=${socket.id}]`)
|
||||||
|
console.log('socket.handshake', socket.handshake.session)
|
||||||
|
if (socket.handshake.session.userId) {
|
||||||
|
client.sadd(socket.handshake.session.userId, socket.id, (err, reply) => {
|
||||||
|
if (err) logger.warn(err)
|
||||||
|
})
|
||||||
|
logger.info(`A logged in client connected in :${socket.id}`)
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
logger.info(`Client gone [id=${socket.id}]`)
|
||||||
|
client.srem(socket.handshake.session.userId, socket.id, (err, reply) => {
|
||||||
|
logger.info(`socket with id ${socket.id} is closed!`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return io
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getonlineLoginUsers = () => {
|
||||||
|
return onlineLoginUsers
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getonlineNotLoginUsers = () => {
|
||||||
|
return onlineNotLoginUsers
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
190
server/api/suggestOffers.js
Executable file
190
server/api/suggestOffers.js
Executable file
@@ -0,0 +1,190 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.prepForKS = exports.knapsack = exports.suggestOffers = exports.normalizing = void 0;
|
||||||
|
var moment = require('moment-timezone');
|
||||||
|
var math = require('mathjs');
|
||||||
|
var ActiveOffers_1 = require("../db/ActiveOffers");
|
||||||
|
function normalizing(arr, asc) {
|
||||||
|
var mArr = math.matrix(arr);
|
||||||
|
var min = math.min(mArr).valueOf();
|
||||||
|
var max = math.max(mArr).valueOf();
|
||||||
|
var nArr = mArr;
|
||||||
|
var i;
|
||||||
|
if (max == min) {
|
||||||
|
for (i = 0; i < math.size(mArr).get([0]); i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), max);
|
||||||
|
}
|
||||||
|
return nArr.valueOf();
|
||||||
|
}
|
||||||
|
if (asc) {
|
||||||
|
for (i = 0; i < math.size(mArr).get([0]); i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), (((mArr.get([i]) - min) / (max - min)) + 1));
|
||||||
|
}
|
||||||
|
return nArr.valueOf();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i = 0; i < math.size(mArr).get([0]); i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), 2 - (((mArr.get([i]) - min) / (max - min))));
|
||||||
|
}
|
||||||
|
return nArr.valueOf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.normalizing = normalizing;
|
||||||
|
function suggestOffers(_a) {
|
||||||
|
var userId = _a.userId, price = _a.price, capacity = _a.capacity, offerType = _a.offerType, currencyId = _a.currencyId, rialId = _a.rialId;
|
||||||
|
if (offerType == 'buy') {
|
||||||
|
// get all offers except the user's offers
|
||||||
|
var maxPrice = price + 0.05 * price;
|
||||||
|
return ActiveOffers_1.Active_Offers.find({ $and: [
|
||||||
|
{ userId: { $ne: userId } },
|
||||||
|
{ expDate: { $gt: Date.now() } },
|
||||||
|
{ curTakenId: currencyId },
|
||||||
|
{ curGivenId: rialId },
|
||||||
|
{ curGivenVal: { $lt: maxPrice } }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(function (offers) {
|
||||||
|
if (offers && Array.isArray(offers) && offers.length > 0) {
|
||||||
|
var offerIds_1 = [];
|
||||||
|
var offerFeatures = [];
|
||||||
|
var prices_1 = [];
|
||||||
|
var values_1 = [];
|
||||||
|
var expDate_1 = [];
|
||||||
|
offers.forEach(function (off) {
|
||||||
|
offerIds_1.push(off._id.toString());
|
||||||
|
prices_1.push(off.curGivenVal);
|
||||||
|
values_1.push(off.curTakenVal);
|
||||||
|
expDate_1.push(Math.round((moment(off.expDate) - moment()) / 60000));
|
||||||
|
});
|
||||||
|
prices_1 = normalizing(prices_1, false);
|
||||||
|
expDate_1 = normalizing(expDate_1, false);
|
||||||
|
var weights = values_1;
|
||||||
|
offerFeatures = math.concat(math.concat(math.reshape(math.matrix(prices_1), [prices_1.length, 1]), math.reshape(math.matrix(values_1), [values_1.length, 1]), 1), math.reshape(math.matrix(expDate_1), [expDate_1.length, 1]), 1).valueOf();
|
||||||
|
var coefs = [[0.3], [0.2], [0.5]];
|
||||||
|
var data = prepForKS(offerIds_1, offerFeatures, weights, coefs);
|
||||||
|
var sugOffers = knapsack(data, capacity);
|
||||||
|
return sugOffers;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("There is no offer to suggest");
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("Error in middlewares/suggestOffers.ts : ", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (offerType == 'sell') {
|
||||||
|
// get all offers except the user's offers
|
||||||
|
var maxPrice = price + 0.05 * price;
|
||||||
|
ActiveOffers_1.Active_Offers.find({ $and: [
|
||||||
|
{ userId: { $ne: userId } },
|
||||||
|
{ expDate: { $gt: Date.now() } },
|
||||||
|
{ curGivenId: currencyId },
|
||||||
|
{ curTakenId: rialId },
|
||||||
|
{ curTakenVal: { $lt: maxPrice } }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(function (offers) {
|
||||||
|
if (offers && Array.isArray(offers) && offers.length > 0) {
|
||||||
|
var offerIds_2 = [];
|
||||||
|
var offerFeatures = [];
|
||||||
|
var prices_2 = [];
|
||||||
|
var values_2 = [];
|
||||||
|
var expDate_2 = [];
|
||||||
|
offers.forEach(function (off) {
|
||||||
|
offerIds_2.push(off._id.toString());
|
||||||
|
prices_2.push(off.curTakenVal);
|
||||||
|
values_2.push(off.curGivenVal);
|
||||||
|
expDate_2.push(Math.round((moment(off.expDate) - moment()) / 60000));
|
||||||
|
});
|
||||||
|
prices_2 = normalizing(prices_2, true);
|
||||||
|
expDate_2 = normalizing(expDate_2, false);
|
||||||
|
var weights = values_2;
|
||||||
|
offerFeatures = math.concat(math.concat(math.reshape(math.matrix(prices_2), [prices_2.length, 1]), math.reshape(math.matrix(values_2), [values_2.length, 1]), 1), math.reshape(math.matrix(expDate_2), [expDate_2.length, 1]), 1).valueOf();
|
||||||
|
var coefs = [[0.3], [0.2], [0.5]];
|
||||||
|
var data = prepForKS(offerIds_2, offerFeatures, weights, coefs);
|
||||||
|
var sugOffers = knapsack(data, capacity);
|
||||||
|
return sugOffers;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("There is no offer to suggest");
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("Error in middlewares/suggestOffers.ts : ", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("offerType must be buy or sell");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.suggestOffers = suggestOffers;
|
||||||
|
function knapsack(items, capacity) {
|
||||||
|
// This implementation uses dynamic programming.
|
||||||
|
// Variable 'memo' is a grid(2-dimentional array) to store optimal solution for sub-problems,
|
||||||
|
// which will be later used as the code execution goes on.
|
||||||
|
// This is called memoization in programming.
|
||||||
|
// The cell will store best solution objects for different capacities and selectable items.
|
||||||
|
var memo = [];
|
||||||
|
// Filling the sub-problem solutions grid.
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
// Variable 'cap' is the capacity for sub-problems. In this example, 'cap' ranges from 1 to 6.
|
||||||
|
var row = [];
|
||||||
|
for (var cap = 1; cap <= capacity; cap++) {
|
||||||
|
row.push(getSolution(i, cap));
|
||||||
|
}
|
||||||
|
memo.push(row);
|
||||||
|
}
|
||||||
|
// The right-bottom-corner cell of the grid contains the final solution for the whole problem.
|
||||||
|
return (getLast());
|
||||||
|
function getLast() {
|
||||||
|
var lastRow = memo[memo.length - 1];
|
||||||
|
return lastRow[lastRow.length - 1];
|
||||||
|
}
|
||||||
|
function getSolution(row, cap) {
|
||||||
|
var NO_SOLUTION = { maxValue: 0, subset: [] };
|
||||||
|
// the column number starts from zero.
|
||||||
|
var col = cap - 1;
|
||||||
|
var lastItem = items[row];
|
||||||
|
// The remaining capacity for the sub-problem to solve.
|
||||||
|
var remaining = cap - lastItem.w;
|
||||||
|
// Refer to the last solution for this capacity,
|
||||||
|
// which is in the cell of the previous row with the same column
|
||||||
|
var lastSolution = row > 0 ? memo[row - 1][col] || NO_SOLUTION : NO_SOLUTION;
|
||||||
|
// Refer to the last solution for the remaining capacity,
|
||||||
|
// which is in the cell of the previous row with the corresponding column
|
||||||
|
var lastSubSolution = row > 0 ? memo[row - 1][remaining - 1] || NO_SOLUTION : NO_SOLUTION;
|
||||||
|
// If any one of the items weights greater than the 'cap', return the last solution
|
||||||
|
if (remaining < 0) {
|
||||||
|
return lastSolution;
|
||||||
|
}
|
||||||
|
// Compare the current best solution for the sub-problem with a specific capacity
|
||||||
|
// to a new solution trial with the lastItem(new item) added
|
||||||
|
var lastValue = lastSolution.maxValue;
|
||||||
|
var lastSubValue = lastSubSolution.maxValue;
|
||||||
|
var newValue = lastSubValue + lastItem.v;
|
||||||
|
if (newValue >= lastValue) {
|
||||||
|
// copy the subset of the last sub-problem solution
|
||||||
|
var _lastSubSet = lastSubSolution.subset.slice();
|
||||||
|
_lastSubSet.push(lastItem);
|
||||||
|
return { maxValue: newValue, subset: _lastSubSet };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return lastSolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.knapsack = knapsack;
|
||||||
|
function prepForKS(offerIds, offerFeatures, weights, coefs) {
|
||||||
|
var values = math.multiply(math.matrix(offerFeatures), math.matrix(coefs));
|
||||||
|
var data = math.concat(math.concat(math.reshape(math.matrix(offerIds), [offerIds.length, 1]), values, 1), math.reshape(math.matrix(weights), [weights.length, 1]), 1).valueOf();
|
||||||
|
var dataObj = Object.values(data.reduce(function (c, _a) {
|
||||||
|
var n = _a[0], v = _a[1], w = _a[2];
|
||||||
|
c[n] = c[n] || { id: n, v: v, w: w };
|
||||||
|
c[n].v = v;
|
||||||
|
c[n].w = w;
|
||||||
|
return c;
|
||||||
|
}, {}));
|
||||||
|
return dataObj;
|
||||||
|
}
|
||||||
|
exports.prepForKS = prepForKS;
|
||||||
201
server/api/suggestOffers.ts
Executable file
201
server/api/suggestOffers.ts
Executable file
@@ -0,0 +1,201 @@
|
|||||||
|
const moment = require( 'moment-timezone')
|
||||||
|
const math = require('mathjs');
|
||||||
|
|
||||||
|
import { Active_Offers } from '../db/ActiveOffers';
|
||||||
|
|
||||||
|
export function normalizing(arr, asc) {
|
||||||
|
|
||||||
|
let mArr = math.matrix(arr)
|
||||||
|
const min = math.min(mArr).valueOf()
|
||||||
|
const max = math.max(mArr).valueOf()
|
||||||
|
let nArr = mArr
|
||||||
|
let i
|
||||||
|
if(max == min){
|
||||||
|
for(i=0; i < math.size(mArr).get([0]);i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), max )
|
||||||
|
}
|
||||||
|
return nArr.valueOf()
|
||||||
|
}
|
||||||
|
if(asc) {
|
||||||
|
for(i=0; i < math.size(mArr).get([0]);i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), (((mArr.get([i]) - min)/(max - min)) + 1))
|
||||||
|
}
|
||||||
|
return nArr.valueOf()
|
||||||
|
} else {
|
||||||
|
for(i=0; i < math.size(mArr).get([0]); i++) {
|
||||||
|
nArr = math.subset(nArr, math.index(i), 2 - (((mArr.get([i]) - min)/(max - min))))
|
||||||
|
}
|
||||||
|
return nArr.valueOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function suggestOffers({ userId, price, capacity, offerType, currencyId, rialId }) {
|
||||||
|
if(offerType == 'buy') {
|
||||||
|
// get all offers except the user's offers
|
||||||
|
let maxPrice = price + 0.05*price
|
||||||
|
return Active_Offers.find({ $and:
|
||||||
|
[
|
||||||
|
{ userId :{ $ne: userId} },
|
||||||
|
{ expDate: { $gt: Date.now() } },
|
||||||
|
{ curTakenId: currencyId },
|
||||||
|
{ curGivenId: rialId },
|
||||||
|
{ curGivenVal: { $lt: maxPrice }}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then((offers) => {
|
||||||
|
if(offers && Array.isArray(offers) && offers.length > 0) {
|
||||||
|
let offerIds = []
|
||||||
|
let offerFeatures = []
|
||||||
|
let prices = []
|
||||||
|
let values = []
|
||||||
|
let expDate = []
|
||||||
|
offers.forEach(off => {
|
||||||
|
offerIds.push(off._id.toString())
|
||||||
|
prices.push(off.curGivenVal)
|
||||||
|
values.push(off.curTakenVal)
|
||||||
|
expDate.push(Math.round((moment(off.expDate) - moment())/60000))
|
||||||
|
})
|
||||||
|
prices = normalizing(prices, false)
|
||||||
|
expDate = normalizing(expDate, false)
|
||||||
|
let weights = values
|
||||||
|
|
||||||
|
offerFeatures = math.concat(math.concat(math.reshape(math.matrix(prices), [prices.length, 1]),
|
||||||
|
math.reshape(math.matrix(values), [values.length, 1]), 1),
|
||||||
|
math.reshape(math.matrix(expDate), [expDate.length, 1]), 1).valueOf()
|
||||||
|
let coefs = [[0.3], [0.2], [0.5]]
|
||||||
|
let data = prepForKS(offerIds, offerFeatures, weights, coefs)
|
||||||
|
let sugOffers = knapsack(data, capacity)
|
||||||
|
return sugOffers
|
||||||
|
} else {
|
||||||
|
console.log("There is no offer to suggest")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Error in middlewares/suggestOffers.ts : ", err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if(offerType == 'sell') {
|
||||||
|
// get all offers except the user's offers
|
||||||
|
let maxPrice = price + 0.05*price
|
||||||
|
Active_Offers.find({ $and:
|
||||||
|
[
|
||||||
|
{ userId :{ $ne: userId} },
|
||||||
|
{ expDate: { $gt: Date.now() } },
|
||||||
|
{ curGivenId: currencyId },
|
||||||
|
{ curTakenId: rialId },
|
||||||
|
{ curTakenVal: { $lt: maxPrice }}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then((offers) => {
|
||||||
|
if(offers && Array.isArray(offers) && offers.length > 0) {
|
||||||
|
let offerIds = []
|
||||||
|
let offerFeatures = []
|
||||||
|
let prices = []
|
||||||
|
let values = []
|
||||||
|
let expDate = []
|
||||||
|
offers.forEach(off => {
|
||||||
|
offerIds.push(off._id.toString())
|
||||||
|
prices.push(off.curTakenVal)
|
||||||
|
values.push(off.curGivenVal)
|
||||||
|
expDate.push(Math.round((moment(off.expDate) - moment())/60000))
|
||||||
|
})
|
||||||
|
prices = normalizing(prices, true)
|
||||||
|
expDate = normalizing(expDate, false)
|
||||||
|
let weights = values
|
||||||
|
|
||||||
|
offerFeatures = math.concat(math.concat(math.reshape(math.matrix(prices), [prices.length, 1]),
|
||||||
|
math.reshape(math.matrix(values), [values.length, 1]), 1),
|
||||||
|
math.reshape(math.matrix(expDate), [expDate.length, 1]), 1).valueOf()
|
||||||
|
let coefs = [[0.3], [0.2], [0.5]]
|
||||||
|
let data = prepForKS(offerIds, offerFeatures, weights, coefs)
|
||||||
|
let sugOffers = knapsack(data, capacity)
|
||||||
|
return sugOffers
|
||||||
|
} else {
|
||||||
|
console.log("There is no offer to suggest")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Error in middlewares/suggestOffers.ts : ", err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log("offerType must be buy or sell")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function knapsack(items, capacity) {
|
||||||
|
// This implementation uses dynamic programming.
|
||||||
|
// Variable 'memo' is a grid(2-dimentional array) to store optimal solution for sub-problems,
|
||||||
|
// which will be later used as the code execution goes on.
|
||||||
|
// This is called memoization in programming.
|
||||||
|
// The cell will store best solution objects for different capacities and selectable items.
|
||||||
|
var memo = [];
|
||||||
|
|
||||||
|
// Filling the sub-problem solutions grid.
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
// Variable 'cap' is the capacity for sub-problems. In this example, 'cap' ranges from 1 to 6.
|
||||||
|
var row = [];
|
||||||
|
for (var cap = 1; cap <= capacity; cap++) {
|
||||||
|
row.push(getSolution(i,cap));
|
||||||
|
}
|
||||||
|
memo.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The right-bottom-corner cell of the grid contains the final solution for the whole problem.
|
||||||
|
return(getLast());
|
||||||
|
|
||||||
|
function getLast(){
|
||||||
|
var lastRow = memo[memo.length - 1];
|
||||||
|
return lastRow[lastRow.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSolution(row,cap){
|
||||||
|
const NO_SOLUTION = {maxValue:0, subset:[]};
|
||||||
|
// the column number starts from zero.
|
||||||
|
var col = cap - 1;
|
||||||
|
var lastItem = items[row];
|
||||||
|
// The remaining capacity for the sub-problem to solve.
|
||||||
|
var remaining = cap - lastItem.w;
|
||||||
|
|
||||||
|
// Refer to the last solution for this capacity,
|
||||||
|
// which is in the cell of the previous row with the same column
|
||||||
|
var lastSolution = row > 0 ? memo[row - 1][col] || NO_SOLUTION : NO_SOLUTION;
|
||||||
|
// Refer to the last solution for the remaining capacity,
|
||||||
|
// which is in the cell of the previous row with the corresponding column
|
||||||
|
var lastSubSolution = row > 0 ? memo[row - 1][remaining - 1] || NO_SOLUTION : NO_SOLUTION;
|
||||||
|
|
||||||
|
// If any one of the items weights greater than the 'cap', return the last solution
|
||||||
|
if(remaining < 0){
|
||||||
|
return lastSolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the current best solution for the sub-problem with a specific capacity
|
||||||
|
// to a new solution trial with the lastItem(new item) added
|
||||||
|
var lastValue = lastSolution.maxValue;
|
||||||
|
var lastSubValue = lastSubSolution.maxValue;
|
||||||
|
|
||||||
|
var newValue = lastSubValue + lastItem.v;
|
||||||
|
if(newValue >= lastValue) {
|
||||||
|
// copy the subset of the last sub-problem solution
|
||||||
|
var _lastSubSet = lastSubSolution.subset.slice();
|
||||||
|
_lastSubSet.push(lastItem);
|
||||||
|
return {maxValue: newValue, subset:_lastSubSet};
|
||||||
|
} else {
|
||||||
|
return lastSolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function prepForKS(offerIds, offerFeatures, weights, coefs) {
|
||||||
|
|
||||||
|
let values = math.multiply(math.matrix(offerFeatures), math.matrix(coefs))
|
||||||
|
let data = math.concat(math.concat(math.reshape(math.matrix(offerIds), [offerIds.length, 1]), values, 1),
|
||||||
|
math.reshape(math.matrix(weights), [weights.length, 1]), 1).valueOf()
|
||||||
|
let dataObj = Object.values(data.reduce((c, [n, v, w]) => {
|
||||||
|
c[n] = c[n] || {id: n, v, w};
|
||||||
|
c[n].v = v
|
||||||
|
c[n].w = w
|
||||||
|
return c;
|
||||||
|
}, {}));
|
||||||
|
return dataObj
|
||||||
|
}
|
||||||
153
server/api/walletApi/bitcoin.js
Executable file
153
server/api/walletApi/bitcoin.js
Executable file
@@ -0,0 +1,153 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.bitcoinTransferToExchangeById = exports.bitcoinTransferFromExchange = void 0;
|
||||||
|
var Client = require('bitcoin-core');
|
||||||
|
var myError_1 = require("../myError");
|
||||||
|
var _ = require("lodash");
|
||||||
|
exports.bitcoinTransferFromExchange = function (value, receiver) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var client, query_options;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
client = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 8332
|
||||||
|
});
|
||||||
|
query_options = {
|
||||||
|
"minimumAmount": value,
|
||||||
|
//"maximumAmount":value,
|
||||||
|
"maximumCount": 1
|
||||||
|
};
|
||||||
|
return [2 /*return*/, client.listUnspent(0, 9999999, [], true, query_options)
|
||||||
|
.then(function (unspentTx) {
|
||||||
|
if (unspentTx[0]) {
|
||||||
|
var txid = unspentTx[0].txid;
|
||||||
|
var vout = unspentTx[0].vout;
|
||||||
|
var txValue = unspentTx[0].amount;
|
||||||
|
var txFee = value * (0.001);
|
||||||
|
var StxFee = txFee.toFixed(8);
|
||||||
|
var totalValue = Number(value) + Number(StxFee);
|
||||||
|
var change = txValue - totalValue;
|
||||||
|
var Schange = change.toFixed(8);
|
||||||
|
var nodeAddress = unspentTx[0].address;
|
||||||
|
var input = [{
|
||||||
|
"txid": txid,
|
||||||
|
"vout": vout
|
||||||
|
}];
|
||||||
|
var output = [];
|
||||||
|
var obj = {};
|
||||||
|
var obj_2 = {};
|
||||||
|
obj[receiver] = value;
|
||||||
|
obj_2[nodeAddress] = Schange;
|
||||||
|
output.push(obj, obj_2);
|
||||||
|
return client.createRawTransaction(input, output)
|
||||||
|
.then(function (txHex) {
|
||||||
|
return client.signRawTransactionWithWallet(txHex)
|
||||||
|
.then(function (sinedHex) {
|
||||||
|
return client.sendRawTransaction(sinedHex.hex)
|
||||||
|
.then(function (txHashOrId) {
|
||||||
|
return txHashOrId;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("error in sendsigned", err);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("error in sign ", err);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("error in create raw tx", err);
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('you do not have unspent trancaction', 400, 5, 'تراکنش خرج نشده پیدا نشد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("error in lisutxo", err);
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
exports.bitcoinTransferToExchangeById = function (txId) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var btcAddress, client;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
btcAddress = ["tb1qfpf6lss60wmle9wanetjxjjt6lc6z65mapk50s"];
|
||||||
|
client = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 8332
|
||||||
|
});
|
||||||
|
return [2 /*return*/, client.getTransaction(txId)
|
||||||
|
.then(function (txInfo) {
|
||||||
|
if (txInfo) {
|
||||||
|
var tx = _.find(txInfo.details, function (i) { return i.category.toString() === "receive" && btcAddress.includes(i.address.toString()); });
|
||||||
|
if (tx) {
|
||||||
|
var status_1;
|
||||||
|
if (txInfo.confirmations >= 6) {
|
||||||
|
status_1 = "Confirmed";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status_1 = "pending";
|
||||||
|
}
|
||||||
|
var info = {
|
||||||
|
"txAddress": tx.address,
|
||||||
|
"txAmount": tx.amount,
|
||||||
|
"status": status_1
|
||||||
|
};
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('tx not found', 400, 5, 'تراکنش یافت نشد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('transaction not found', 400, 5, 'تراکنش مربوطه پیدا نشد.', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
});
|
||||||
|
}); };
|
||||||
132
server/api/walletApi/bitcoin.ts
Executable file
132
server/api/walletApi/bitcoin.ts
Executable file
@@ -0,0 +1,132 @@
|
|||||||
|
const Client = require('bitcoin-core')
|
||||||
|
import myError from '../myError'
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
|
export const bitcoinTransferFromExchange = async(value, receiver) => {
|
||||||
|
const client = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host:"127.0.0.1",
|
||||||
|
port:8332
|
||||||
|
})
|
||||||
|
const query_options = {
|
||||||
|
"minimumAmount":value,
|
||||||
|
//"maximumAmount":value,
|
||||||
|
"maximumCount":1 ,
|
||||||
|
}
|
||||||
|
return client.listUnspent(0, 9999999, [], true, query_options)
|
||||||
|
.then((unspentTx) => {
|
||||||
|
if(unspentTx[0]) {
|
||||||
|
const txid = unspentTx[0].txid
|
||||||
|
const vout = unspentTx[0].vout
|
||||||
|
const txValue = unspentTx[0].amount
|
||||||
|
let txFee = value*(0.001)
|
||||||
|
const StxFee = txFee.toFixed(8)
|
||||||
|
const totalValue = Number(value) + Number(StxFee)
|
||||||
|
let change = txValue - totalValue
|
||||||
|
const Schange = change.toFixed(8)
|
||||||
|
const nodeAddress = unspentTx[0].address
|
||||||
|
const input = [{
|
||||||
|
"txid": txid,
|
||||||
|
"vout": vout,
|
||||||
|
}]
|
||||||
|
let output = []
|
||||||
|
let obj = {}
|
||||||
|
let obj_2 ={}
|
||||||
|
obj[receiver] = value
|
||||||
|
obj_2[nodeAddress] = Schange
|
||||||
|
output.push(obj,obj_2)
|
||||||
|
return client.createRawTransaction(input,output)
|
||||||
|
.then((txHex) => {
|
||||||
|
return client.signRawTransactionWithWallet(txHex)
|
||||||
|
.then((sinedHex) => {
|
||||||
|
return client.sendRawTransaction(sinedHex.hex)
|
||||||
|
.then((txHashOrId) => {
|
||||||
|
return txHashOrId
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("error in sendsigned",err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
console.log("error in sign ",err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err )=> {
|
||||||
|
console.log("error in create raw tx",err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'you do not have unspent trancaction',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'تراکنش خرج نشده پیدا نشد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("error in lisutxo",err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const bitcoinTransferToExchangeById = async(txId) => {
|
||||||
|
const btcAddress = ["tb1qfpf6lss60wmle9wanetjxjjt6lc6z65mapk50s"]
|
||||||
|
const client = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 8332
|
||||||
|
})
|
||||||
|
return client.getTransaction(txId)
|
||||||
|
.then((txInfo) => {
|
||||||
|
if(txInfo){
|
||||||
|
const tx = _.find(txInfo.details, (i) => { return i.category.toString() === "receive" && btcAddress.includes(i.address.toString())})
|
||||||
|
if(tx) {
|
||||||
|
let status
|
||||||
|
if(txInfo.confirmations>=6)
|
||||||
|
{
|
||||||
|
status = "Confirmed"
|
||||||
|
}else{
|
||||||
|
status = "pending"
|
||||||
|
}
|
||||||
|
const info = {
|
||||||
|
"txAddress":tx.address,
|
||||||
|
"txAmount":tx.amount,
|
||||||
|
"status":status
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'tx not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'تراکنش یافت نشد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'transaction not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'تراکنش مربوطه پیدا نشد.',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
201
server/api/walletApi/etheriuem.js
Executable file
201
server/api/walletApi/etheriuem.js
Executable file
@@ -0,0 +1,201 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.getAccounts = exports.receiveEtherFromClient = exports.sendEther = exports.getEtheriumNonce = exports.checkTransaction = exports.getBalance = exports.createPersonalAccount = exports.createAccount = void 0;
|
||||||
|
var ethereumjs_common_1 = require("ethereumjs-common");
|
||||||
|
var Web3 = require('web3');
|
||||||
|
var Tx = require('ethereumjs-tx').Transaction;
|
||||||
|
exports.createAccount = function () {
|
||||||
|
var web3 = new Web3("http://localhost:8545");
|
||||||
|
var data = web3.eth.accounts.create();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
exports.createPersonalAccount = function () {
|
||||||
|
var web3 = new Web3("http://localhost:8545");
|
||||||
|
return web3.eth.personal.newAccount("exchange")
|
||||||
|
.then(function (result) {
|
||||||
|
return result;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.getBalance = function (account) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var web3;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0: return [4 /*yield*/, new Web3("http://localhost:8545")];
|
||||||
|
case 1:
|
||||||
|
web3 = _a.sent();
|
||||||
|
return [2 /*return*/, web3.eth.getBalance(account.toString())
|
||||||
|
.then(function (balance) {
|
||||||
|
return balance;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
exports.checkTransaction = function (transactionId) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var web3;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0: return [4 /*yield*/, new Web3("http://localhost:8545")];
|
||||||
|
case 1:
|
||||||
|
web3 = _a.sent();
|
||||||
|
return [2 /*return*/, web3.eth.getTransactionReceipt(transactionId)
|
||||||
|
.then(function (txR) {
|
||||||
|
if (txR.blockNumber == undefined) {
|
||||||
|
throw "transaction receipt not found";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return web3.eth.getTransaction(transactionId)
|
||||||
|
.then(function (tx) {
|
||||||
|
if (tx.blockNumber == undefined || tx.value == undefined) {
|
||||||
|
throw "transaction receipt not found";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
exports.getEtheriumNonce = (function (address) {
|
||||||
|
var web3 = new Web3("http://localhost:8545");
|
||||||
|
return web3.eth.getTransactionCount(address, 'pending')
|
||||||
|
.then(function (nonce) {
|
||||||
|
//got nonce proceed with creating and signing transaction
|
||||||
|
return nonce;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
exports.sendEther = function (account, value) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var web3;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0: return [4 /*yield*/, new Web3("http://localhost:8545")];
|
||||||
|
case 1:
|
||||||
|
web3 = _a.sent();
|
||||||
|
//unlock it for a period of 15 secs
|
||||||
|
return [2 /*return*/, web3.eth.personal.unlockAccount("0x868453967f6806ef86de7cf5e57a32ab28b875b4", "exchange", 15000)
|
||||||
|
.then(function (unlocked) {
|
||||||
|
return web3.eth.sendTransaction({
|
||||||
|
//from: process.env.ADMIN_ETHERIUM_ACCOUNT_ADDRESS,
|
||||||
|
from: '0x868453967f6806ef86de7cf5e57a32ab28b875b4',
|
||||||
|
to: account.toString(),
|
||||||
|
value: web3.utils.toWei(value.toString())
|
||||||
|
})
|
||||||
|
.then(function (receipt) {
|
||||||
|
// then lock it
|
||||||
|
return web3.eth.personal.lockAccount("0x868453967f6806ef86de7cf5e57a32ab28b875b4")
|
||||||
|
.then(function () {
|
||||||
|
return receipt;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
return receipt;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
exports.receiveEtherFromClient = function (transactionHash) {
|
||||||
|
//receive transaction from the ui and send it
|
||||||
|
var web3 = new Web3("http://localhost:8545");
|
||||||
|
var rawTx = undefined;
|
||||||
|
var transaction = undefined;
|
||||||
|
//custom network
|
||||||
|
var customCommon = ethereumjs_common_1["default"].forCustomChain('mainnet', {
|
||||||
|
name: 'my-network',
|
||||||
|
networkId: 1981,
|
||||||
|
chainId: 1981
|
||||||
|
}, 'petersburg');
|
||||||
|
var preData = function () {
|
||||||
|
var privateKey = Buffer.from('64061456066baa81c5097c895b5176fb3e1452eaf6f6776e2d7bf07ddb9accfe', 'hex');
|
||||||
|
//parameters should be hex string starting with 0x
|
||||||
|
var txParams = {
|
||||||
|
nonce: '0x01',
|
||||||
|
gas: 50002,
|
||||||
|
gasPrice: Number(web3.utils.toWei('601', 'gwei')),
|
||||||
|
to: '0x868453967f6806ef86de7cf5e57a32ab28b875b4',
|
||||||
|
value: 10000003
|
||||||
|
};
|
||||||
|
// The second parameter is not necessary if these values are used
|
||||||
|
var tx = new Tx(txParams, { common: customCommon });
|
||||||
|
tx.sign(privateKey);
|
||||||
|
var serializedTx = tx.serialize();
|
||||||
|
return rawTx = '0x' + serializedTx.toString('hex');
|
||||||
|
};
|
||||||
|
return Promise.all([preData()])
|
||||||
|
.then(function () {
|
||||||
|
return web3.eth.sendSignedTransaction(rawTx)
|
||||||
|
.then(function (result) {
|
||||||
|
return result;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.getAccounts = function () { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var web3;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0: return [4 /*yield*/, new Web3("http://localhost:8545")];
|
||||||
|
case 1:
|
||||||
|
web3 = _a.sent();
|
||||||
|
return [2 /*return*/, web3.eth.getAccounts()
|
||||||
|
.then(function (result) {
|
||||||
|
console.log("all acounts is ", result);
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
157
server/api/walletApi/etheriuem.ts
Executable file
157
server/api/walletApi/etheriuem.ts
Executable file
@@ -0,0 +1,157 @@
|
|||||||
|
import Common from 'ethereumjs-common'
|
||||||
|
|
||||||
|
const Web3 = require('web3');
|
||||||
|
const Tx = require('ethereumjs-tx').Transaction;
|
||||||
|
|
||||||
|
export const createAccount = () => {
|
||||||
|
const web3 = new Web3( "http://localhost:8545");
|
||||||
|
const data = web3.eth.accounts.create()
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createPersonalAccount = () => {
|
||||||
|
const web3 = new Web3( "http://localhost:8545");
|
||||||
|
return web3.eth.personal.newAccount("exchange")
|
||||||
|
.then((result) => {
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getBalance = async (account) => {
|
||||||
|
const web3 = await new Web3( "http://localhost:8545");
|
||||||
|
return web3.eth.getBalance(account.toString())
|
||||||
|
.then((balance) => {
|
||||||
|
return balance
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const checkTransaction = async (transactionId) => {
|
||||||
|
const web3 = await new Web3( "http://localhost:8545");
|
||||||
|
return web3.eth.getTransactionReceipt(transactionId)
|
||||||
|
.then((txR) => {
|
||||||
|
if (txR.blockNumber == undefined) {
|
||||||
|
throw "transaction receipt not found";
|
||||||
|
} else {
|
||||||
|
return web3.eth.getTransaction(transactionId)
|
||||||
|
.then((tx) => {
|
||||||
|
if (tx.blockNumber == undefined|| tx.value == undefined) {
|
||||||
|
throw "transaction receipt not found";
|
||||||
|
} else {
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEtheriumNonce=((address) => {
|
||||||
|
const web3 = new Web3( "http://localhost:8545");
|
||||||
|
return web3.eth.getTransactionCount(address,'pending')
|
||||||
|
.then((nonce) => {
|
||||||
|
//got nonce proceed with creating and signing transaction
|
||||||
|
return nonce;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
export const sendEther = async (account,value) => {
|
||||||
|
const web3 = await new Web3( "http://localhost:8545");
|
||||||
|
//unlock it for a period of 15 secs
|
||||||
|
return web3.eth.personal.unlockAccount("0x868453967f6806ef86de7cf5e57a32ab28b875b4","exchange", 15000)
|
||||||
|
.then((unlocked) => {
|
||||||
|
return web3.eth.sendTransaction({
|
||||||
|
//from: process.env.ADMIN_ETHERIUM_ACCOUNT_ADDRESS,
|
||||||
|
from: '0x868453967f6806ef86de7cf5e57a32ab28b875b4',
|
||||||
|
to: account.toString(),
|
||||||
|
value: web3.utils.toWei (value.toString())
|
||||||
|
})
|
||||||
|
.then((receipt) => {
|
||||||
|
// then lock it
|
||||||
|
return web3.eth.personal.lockAccount("0x868453967f6806ef86de7cf5e57a32ab28b875b4")
|
||||||
|
.then(() => {
|
||||||
|
return receipt
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return receipt
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) =>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const receiveEtherFromClient = (transactionHash) => {
|
||||||
|
//receive transaction from the ui and send it
|
||||||
|
const web3 = new Web3( "http://localhost:8545");
|
||||||
|
let rawTx = undefined
|
||||||
|
let transaction = undefined
|
||||||
|
//custom network
|
||||||
|
const customCommon = Common.forCustomChain(
|
||||||
|
'mainnet',
|
||||||
|
{
|
||||||
|
name: 'my-network',
|
||||||
|
networkId: 1981,
|
||||||
|
chainId: 1981,
|
||||||
|
},
|
||||||
|
'petersburg',
|
||||||
|
)
|
||||||
|
const preData = () => {
|
||||||
|
const privateKey = Buffer.from(
|
||||||
|
'64061456066baa81c5097c895b5176fb3e1452eaf6f6776e2d7bf07ddb9accfe',
|
||||||
|
'hex'
|
||||||
|
)
|
||||||
|
//parameters should be hex string starting with 0x
|
||||||
|
const txParams = {
|
||||||
|
nonce: '0x01',
|
||||||
|
gas: 50002,
|
||||||
|
gasPrice: Number(web3.utils.toWei('601', 'gwei')),
|
||||||
|
to: '0x868453967f6806ef86de7cf5e57a32ab28b875b4',
|
||||||
|
value: 10000003
|
||||||
|
}
|
||||||
|
// The second parameter is not necessary if these values are used
|
||||||
|
const tx = new Tx(txParams,{common : customCommon})
|
||||||
|
tx.sign(privateKey)
|
||||||
|
const serializedTx = tx.serialize()
|
||||||
|
return rawTx = '0x' + serializedTx.toString('hex');
|
||||||
|
}
|
||||||
|
return Promise.all([preData()])
|
||||||
|
.then(()=>{
|
||||||
|
return web3.eth.sendSignedTransaction(rawTx)
|
||||||
|
.then((result) => {
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAccounts = async () => {
|
||||||
|
const web3 = await new Web3( "http://localhost:8545");
|
||||||
|
return web3.eth.getAccounts()
|
||||||
|
.then((result)=>{
|
||||||
|
console.log("all acounts is ", result)
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
220
server/api/walletApi/transferFromExchange.js
Executable file
220
server/api/walletApi/transferFromExchange.js
Executable file
@@ -0,0 +1,220 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.transferFromExchangeApi = void 0;
|
||||||
|
var myError_1 = require("../myError");
|
||||||
|
var currencies_1 = require("../../db/currencies");
|
||||||
|
var bitcoin = require("../walletApi/bitcoin");
|
||||||
|
var etheriuem = require("../walletApi/etheriuem");
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var user_1 = require("../../db/user");
|
||||||
|
var _ = require("lodash");
|
||||||
|
var pendingTransfers_1 = require("../../db/pendingTransfers");
|
||||||
|
exports.transferFromExchangeApi = function (currencyId, value, receiver, userId) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var info, resObj, checkStatus, session;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
checkStatus = function () {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return [4 /*yield*/, mongoose.startSession()];
|
||||||
|
case 1:
|
||||||
|
session = _a.sent();
|
||||||
|
return [2 /*return*/, session.withTransaction(function () { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
return [2 /*return*/, user_1.User.findOne({ _id: userId }).session(session)
|
||||||
|
.then(function (user) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var error;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
if (user) {
|
||||||
|
return [2 /*return*/, currencies_1.Currencies.findOne({ _id: currencyId })
|
||||||
|
.then(function (cur) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var CurAbName, curInWall_1, error, error, error;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
CurAbName = "";
|
||||||
|
if (cur) {
|
||||||
|
curInWall_1 = _.find(user.wallet, function (i) { return i.currency.toString() === currencyId.toString(); });
|
||||||
|
if (curInWall_1) {
|
||||||
|
if (curInWall_1.value >= Number(value)) {
|
||||||
|
CurAbName = cur.ab_name;
|
||||||
|
switch (CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
checkStatus = function () {
|
||||||
|
return bitcoin.bitcoinTransferFromExchange(value, receiver)
|
||||||
|
.then(function (txHash) {
|
||||||
|
info = {
|
||||||
|
status: "pending",
|
||||||
|
txHash: txHash
|
||||||
|
};
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
case "ETH":
|
||||||
|
return [2 /*return*/, etheriuem.sendEther(receiver.toString(), value)
|
||||||
|
.then(function (result) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var bodySuccessfulOffer, bodyTransaction;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
if (result && result.transactionHash) {
|
||||||
|
bodySuccessfulOffer = {
|
||||||
|
userId: user._id,
|
||||||
|
transactions: []
|
||||||
|
};
|
||||||
|
bodyTransaction = {
|
||||||
|
txId: result.transactionHash,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: Number(value),
|
||||||
|
type: 'send'
|
||||||
|
};
|
||||||
|
bodySuccessfulOffer.transactions.push(bodyTransaction);
|
||||||
|
}
|
||||||
|
else if (result) {
|
||||||
|
throw ("could not get any transaction " + result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw ("could not get result ");
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
case "TRX":
|
||||||
|
}
|
||||||
|
return [2 /*return*/, Promise.all([checkStatus()])
|
||||||
|
.then(function () {
|
||||||
|
return pendingTransfers_1.PendingTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(function (userPending) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var usrPending;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
if (!userPending) return [3 /*break*/, 2];
|
||||||
|
userPending.transactions.push({
|
||||||
|
txId: info.txHash,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: value,
|
||||||
|
type: "send"
|
||||||
|
});
|
||||||
|
return [4 /*yield*/, userPending.save()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
return [3 /*break*/, 4];
|
||||||
|
case 2:
|
||||||
|
usrPending = {
|
||||||
|
userId: userId,
|
||||||
|
transactions: [{
|
||||||
|
txId: info.txHash,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: value,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return [4 /*yield*/, pendingTransfers_1.PendingTransfers.create([usrPending], { session: session })];
|
||||||
|
case 3:
|
||||||
|
_a.sent();
|
||||||
|
_a.label = 4;
|
||||||
|
case 4:
|
||||||
|
curInWall_1.value -= value;
|
||||||
|
return [4 /*yield*/, user.save()];
|
||||||
|
case 5:
|
||||||
|
_a.sent();
|
||||||
|
resObj =
|
||||||
|
{
|
||||||
|
status: "success",
|
||||||
|
txValue: value,
|
||||||
|
txHash: info.txHash
|
||||||
|
};
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error = new myError_1["default"]('you do not have enough currency ', 400, 5, 'موجودی کافی نمی باشد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error = new myError_1["default"]('currency not found in user wallet', 400, 5, 'ارز در کیف پول پیدا نشد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error = new myError_1["default"]('currency not found', 400, 5, 'ارز پیدا نشد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error = new myError_1["default"]('user not found', 400, 5, 'کاربر پیدا نشد.', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
});
|
||||||
|
}); })
|
||||||
|
.then(function () {
|
||||||
|
return resObj;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("error in with Transaction", err);
|
||||||
|
throw ("error in with transaction");
|
||||||
|
})["finally"](function () {
|
||||||
|
session.endSession();
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
189
server/api/walletApi/transferFromExchange.ts
Executable file
189
server/api/walletApi/transferFromExchange.ts
Executable file
@@ -0,0 +1,189 @@
|
|||||||
|
import myError from '../myError'
|
||||||
|
import { Currencies } from '../../db/currencies'
|
||||||
|
import * as bitcoin from '../walletApi/bitcoin'
|
||||||
|
import * as etheriuem from '../walletApi/etheriuem'
|
||||||
|
import * as tron from '../walletApi/tron'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import { User } from '../../db/user'
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
import { PendingTransfers } from '../../db/pendingTransfers'
|
||||||
|
import { SuccessfulTransfers } from '../../db/successfulTransfers'
|
||||||
|
|
||||||
|
export const transferFromExchangeApi = async(currencyId, value, receiver, userId) => {
|
||||||
|
let info
|
||||||
|
let resObj
|
||||||
|
let checkStatus = () => {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const session = await mongoose.startSession()
|
||||||
|
return session.withTransaction(async() => {
|
||||||
|
return User.findOne({_id:userId}).session(session)
|
||||||
|
.then(async (user)=>{
|
||||||
|
if(user){
|
||||||
|
return Currencies.findOne({_id:currencyId})
|
||||||
|
.then(async(cur) => {
|
||||||
|
let CurAbName = ""
|
||||||
|
if(cur){
|
||||||
|
let curInWall = _.find(user.wallet, (i) => { return i.currency.toString() === currencyId.toString()})
|
||||||
|
if(curInWall) {
|
||||||
|
|
||||||
|
if(curInWall.value >= Number(value)){
|
||||||
|
CurAbName = cur.ab_name
|
||||||
|
switch(CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
checkStatus = () => {
|
||||||
|
return bitcoin.bitcoinTransferFromExchange(value,receiver)
|
||||||
|
.then((txHash) => {
|
||||||
|
info = {
|
||||||
|
status:"pending",
|
||||||
|
txHash:txHash
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "ETH":
|
||||||
|
return etheriuem.sendEther(receiver.toString(),value)
|
||||||
|
.then(async (result) => {
|
||||||
|
if(result&&result.transactionHash) {
|
||||||
|
const bodySuccessfulOffer = {
|
||||||
|
userId: user._id ,
|
||||||
|
transactions : []
|
||||||
|
}
|
||||||
|
const bodyTransaction = {
|
||||||
|
txId : result.transactionHash,
|
||||||
|
currencyId : currencyId,
|
||||||
|
currencyName : CurAbName,
|
||||||
|
value : Number(value),
|
||||||
|
type : 'send'
|
||||||
|
}
|
||||||
|
bodySuccessfulOffer.transactions.push(bodyTransaction)
|
||||||
|
} else if(result) {
|
||||||
|
throw ("could not get any transaction "+ result)
|
||||||
|
} else {
|
||||||
|
throw ("could not get result ")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
case "TRX":
|
||||||
|
}
|
||||||
|
return Promise.all([checkStatus()])
|
||||||
|
.then(() =>{
|
||||||
|
return PendingTransfers.findOne({ userId:userId }).session(session)
|
||||||
|
.then(async (userPending) => {
|
||||||
|
if(userPending){
|
||||||
|
userPending.transactions.push({
|
||||||
|
txId: info.txHash,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: value,
|
||||||
|
type: "send"
|
||||||
|
})
|
||||||
|
await userPending.save()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const usrPending = {
|
||||||
|
userId: userId,
|
||||||
|
transactions: [{
|
||||||
|
txId: info.txHash,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: value,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
await PendingTransfers.create([usrPending],{ session })
|
||||||
|
}
|
||||||
|
curInWall.value -= value
|
||||||
|
await user.save()
|
||||||
|
resObj =
|
||||||
|
{
|
||||||
|
status:"success",
|
||||||
|
txValue:value,
|
||||||
|
txHash:info.txHash
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'you do not have enough currency ',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'موجودی کافی نمی باشد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'currency not found in user wallet',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'ارز در کیف پول پیدا نشد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'currency not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'ارز پیدا نشد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'user not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'کاربر پیدا نشد.',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
|
||||||
|
return resObj
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("error in with Transaction",err)
|
||||||
|
throw("error in with transaction")
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
session.endSession()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
128
server/api/walletApi/transferInWithTxId.js
Executable file
128
server/api/walletApi/transferInWithTxId.js
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.transferInWithTxId = void 0;
|
||||||
|
var Client = require('bitcoin-core');
|
||||||
|
var _ = require("lodash");
|
||||||
|
exports.transferInWithTxId = function (currency, txId) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var client_1;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (currency) {
|
||||||
|
case "BTC":
|
||||||
|
client_1 = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 8332
|
||||||
|
});
|
||||||
|
client_1.listTransactions("*", 100, 0)
|
||||||
|
.theb(function (txs) {
|
||||||
|
var tx = _.find(txs, function (i) { return i.txid.toString() === txId.toString(); });
|
||||||
|
if (tx) {
|
||||||
|
if (tx.address === "node address") {
|
||||||
|
var amount_1 = tx.amount;
|
||||||
|
client_1.getBlockCount()
|
||||||
|
.then(function (blockCount) {
|
||||||
|
if (blockCount - Number(tx.blockindex) > 6) {
|
||||||
|
return amount_1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "ETH":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case "TRX":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); };
|
||||||
|
// fetch("connect to your bitcoin node",{
|
||||||
|
// method: "POST",
|
||||||
|
// body:{"jsonrpc": "1.0", "id":"curltest",
|
||||||
|
// "method": "listtransactions",
|
||||||
|
// "params": [txId]
|
||||||
|
// },
|
||||||
|
// headers:header
|
||||||
|
// })
|
||||||
|
// .then(res => res.json())
|
||||||
|
// .then((txs) => {
|
||||||
|
// const tx = _.find(txs, (i) => { return i.txid.toString()=== txId.toString()})
|
||||||
|
// if(tx){
|
||||||
|
// const blockIndex = Number(tx.blockindex)
|
||||||
|
// const txValue = Number(tx.vout)
|
||||||
|
// fetch("connect to your bitcoin node",{
|
||||||
|
// method: "POST",
|
||||||
|
// body:{"jsonrpc": "1.0", "id":"curltest",
|
||||||
|
// "method": "getblockcount",
|
||||||
|
// "params": []
|
||||||
|
// },
|
||||||
|
// headers:header
|
||||||
|
// })
|
||||||
|
// .then(res => res.json())
|
||||||
|
// .then((blockCount) => {
|
||||||
|
// if(Number(blockCount)-blockIndex>=6) {
|
||||||
|
// let cur = _.find(user.wallet, (i) => { return i.currency.toString()=== currencyId.toString() })
|
||||||
|
// cur.value += txValue
|
||||||
|
// } else {
|
||||||
|
// //wait for transaction confirmation
|
||||||
|
// }
|
||||||
|
// }).catch((err)=>{
|
||||||
|
// next(err)
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// //throw errrrrorrrrrr
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// next(err)
|
||||||
|
// })
|
||||||
114
server/api/walletApi/transferTo.js
Executable file
114
server/api/walletApi/transferTo.js
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.transferToApi = void 0;
|
||||||
|
var Client = require('bitcoin-core');
|
||||||
|
exports.transferToApi = function (currency, value, receiver) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var client_1, query_options;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (currency) {
|
||||||
|
case "BTC":
|
||||||
|
client_1 = new Client({
|
||||||
|
network: 'testnet',
|
||||||
|
username: 'polychain',
|
||||||
|
password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 8332
|
||||||
|
});
|
||||||
|
query_options = {
|
||||||
|
"minimumAmount": value
|
||||||
|
};
|
||||||
|
client_1.listUnspent(1, 1, [], true, query_options)
|
||||||
|
.then(function (unspentTx) {
|
||||||
|
if (unspentTx[0]) {
|
||||||
|
var txid = unspentTx[0].txid;
|
||||||
|
var txValue = Number(unspentTx[0].amount);
|
||||||
|
var change = txValue - value;
|
||||||
|
var nodeAddress_1 = unspentTx[0].address;
|
||||||
|
var input = [{
|
||||||
|
"txid": txid,
|
||||||
|
"vout": Number(txValue)
|
||||||
|
}];
|
||||||
|
var output = [
|
||||||
|
{
|
||||||
|
"receiver": txValue,
|
||||||
|
"nodeAddress": change
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": "Hi"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
client_1.createRawTransaction(input, output)
|
||||||
|
.then(function (txHex) {
|
||||||
|
client_1.dumpprivkey(nodeAddress_1)
|
||||||
|
.then(function (priKey) {
|
||||||
|
client_1.signRawTransactionWithKey(txHex, [priKey])
|
||||||
|
.then(function (sinedHex) {
|
||||||
|
client_1.sendRawTransaction(sinedHex)
|
||||||
|
.then(function (txHashOrId) {
|
||||||
|
return txHashOrId;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// throw err
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log('the error is', err);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "ETH":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case "TRX":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); };
|
||||||
100
server/api/walletApi/transferToExchange.js
Executable file
100
server/api/walletApi/transferToExchange.js
Executable file
@@ -0,0 +1,100 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.transferToExchangeApi = void 0;
|
||||||
|
var Client = require('bitcoin-core');
|
||||||
|
var myError_1 = require("../myError");
|
||||||
|
var currencies_1 = require("../../db/currencies");
|
||||||
|
exports.transferToExchangeApi = function (currencyId, signedRawTxHex, value) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
currencies_1.Currencies.findOne({ _id: currencyId })
|
||||||
|
.then(function (cur) {
|
||||||
|
var CurAbName = "";
|
||||||
|
if (cur) {
|
||||||
|
value = Number(value);
|
||||||
|
CurAbName = cur.ab_name;
|
||||||
|
switch (CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
// const client = new Client({
|
||||||
|
// network: 'testnet',
|
||||||
|
// username: 'polychain',
|
||||||
|
// password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
// host:"127.0.0.1",
|
||||||
|
// port:8332
|
||||||
|
// })
|
||||||
|
// client.decodeRawTransaction(signedRawTxHex)
|
||||||
|
// .then((tx) => {
|
||||||
|
// if(tx) {
|
||||||
|
// const txValue = Number(tx[0].vout[0].value)
|
||||||
|
// if(txValue===Number(value)) {
|
||||||
|
// client.sendRawTransaction(signedRawTxHex)
|
||||||
|
// .then((txHashOrId) => {
|
||||||
|
// return txHashOrId
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// throw(err)
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// //
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// //
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// throw err
|
||||||
|
// })
|
||||||
|
break;
|
||||||
|
case "ETH":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case "TRX":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('currency not found', 400, 5, 'ارز مربوطه پیدا نشد.', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
}); };
|
||||||
70
server/api/walletApi/transferToExchange.ts
Executable file
70
server/api/walletApi/transferToExchange.ts
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
const Client = require('bitcoin-core')
|
||||||
|
import { conformsTo } from 'lodash'
|
||||||
|
import myError from '../myError'
|
||||||
|
import { Currencies } from '../../db/currencies'
|
||||||
|
export const transferToExchangeApi = async(currencyId,signedRawTxHex,value) => {
|
||||||
|
Currencies.findOne({_id:currencyId})
|
||||||
|
.then((cur)=>{
|
||||||
|
let CurAbName = ""
|
||||||
|
if(cur){
|
||||||
|
value = Number(value)
|
||||||
|
CurAbName = cur.ab_name
|
||||||
|
switch(CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
// const client = new Client({
|
||||||
|
// network: 'testnet',
|
||||||
|
// username: 'polychain',
|
||||||
|
// password: '3QtnxrB7P5y4EpBdad1MkCeB2RHmArvcarw7udgXsAce',
|
||||||
|
// host:"127.0.0.1",
|
||||||
|
// port:8332
|
||||||
|
// })
|
||||||
|
// client.decodeRawTransaction(signedRawTxHex)
|
||||||
|
// .then((tx) => {
|
||||||
|
// if(tx) {
|
||||||
|
// const txValue = Number(tx[0].vout[0].value)
|
||||||
|
// if(txValue===Number(value)) {
|
||||||
|
// client.sendRawTransaction(signedRawTxHex)
|
||||||
|
// .then((txHashOrId) => {
|
||||||
|
// return txHashOrId
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// throw(err)
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// //
|
||||||
|
// }
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// //
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch((err) => {
|
||||||
|
// throw err
|
||||||
|
// })
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ETH":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "TRX":
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
const error = new myError(
|
||||||
|
'currency not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'ارز مربوطه پیدا نشد.',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
363
server/api/walletApi/transferToExchangeById.js
Executable file
363
server/api/walletApi/transferToExchangeById.js
Executable file
@@ -0,0 +1,363 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.transferToExchangeByIdApi = void 0;
|
||||||
|
var _ = require("lodash");
|
||||||
|
var myError_1 = require("../myError");
|
||||||
|
var currencies_1 = require("../../db/currencies");
|
||||||
|
var user_1 = require("../../db/user");
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var bitcoin = require("../walletApi/bitcoin");
|
||||||
|
var etherium = require("./etheriuem");
|
||||||
|
var tron = require("./tron");
|
||||||
|
var pendingTransfers_1 = require("../../db/pendingTransfers");
|
||||||
|
var successfulTransfers_1 = require("../../db/successfulTransfers");
|
||||||
|
exports.transferToExchangeByIdApi = function (currencyId, txId, userId) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var info, resObj, userHaveDoc, checkStatus, session;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
userHaveDoc = false;
|
||||||
|
checkStatus = function () {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
return [4 /*yield*/, mongoose.startSession()];
|
||||||
|
case 1:
|
||||||
|
session = _a.sent();
|
||||||
|
return [2 /*return*/, session.withTransaction(function () {
|
||||||
|
return user_1.User.findOne({ _id: userId }).session(session)
|
||||||
|
.then(function (user) {
|
||||||
|
if (user) {
|
||||||
|
return pendingTransfers_1.PendingTransfers.findOne({ userId: userId })
|
||||||
|
.then(function (userPending) {
|
||||||
|
if (userPending && userPending.userId.toString() === userId.toString()) {
|
||||||
|
userHaveDoc = true;
|
||||||
|
var pendingTx = _.find(userPending.transactions, function (i) { return i.txId.toString() === txId.toString(); });
|
||||||
|
if (pendingTx) {
|
||||||
|
var error = new myError_1["default"]('transaction already exsist', 400, 5, 'تراکنش قبلا وجود دارد', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currencies_1.Currencies.findOne({ _id: currencyId })
|
||||||
|
.then(function (cur) {
|
||||||
|
var CurAbName = "";
|
||||||
|
if (cur) {
|
||||||
|
CurAbName = cur.ab_name;
|
||||||
|
switch (CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
checkStatus = function () {
|
||||||
|
return bitcoin.bitcoinTransferToExchangeById(txId)
|
||||||
|
.then(function (result) {
|
||||||
|
info = result;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "ETH":
|
||||||
|
return etherium.checkTransaction(txId)
|
||||||
|
.then(function (transaction) {
|
||||||
|
if (transaction && transaction.hash.toString() === txId.toString()) {
|
||||||
|
var curInWall = _.find(user.wallet, function (i) { return i.currency.toString() === currencyId.toString(); });
|
||||||
|
if (curInWall) {
|
||||||
|
curInWall.value += Number(transaction.value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "transaction not valid";
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("api error: ", err);
|
||||||
|
});
|
||||||
|
//
|
||||||
|
case "TRX":
|
||||||
|
return tron.validateByTXId(txId)
|
||||||
|
.then(function (transaction) {
|
||||||
|
if (transaction.result) {
|
||||||
|
var resObj_1 = {
|
||||||
|
status: "successful",
|
||||||
|
txValue: transaction
|
||||||
|
};
|
||||||
|
return resObj_1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var resObj_2 = {
|
||||||
|
status: "pending",
|
||||||
|
txValue: transaction
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
// default
|
||||||
|
}
|
||||||
|
return Promise.all([checkStatus()])
|
||||||
|
.then(function () {
|
||||||
|
if (userHaveDoc) {
|
||||||
|
userPending.transactions.push({
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
});
|
||||||
|
userPending.save()
|
||||||
|
.then(function () {
|
||||||
|
if (info.status === 'Confirmed') {
|
||||||
|
return successfulTransfers_1.SuccessfulTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(function (userSuccess) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var usrSuccess;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
if (!(userSuccess && userSuccess.userId.toString() === userId.toString())) return [3 /*break*/, 2];
|
||||||
|
userSuccess.transactions.push({
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
});
|
||||||
|
return [4 /*yield*/, userSuccess.save()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
return [3 /*break*/, 4];
|
||||||
|
case 2:
|
||||||
|
usrSuccess = {
|
||||||
|
userId: userId,
|
||||||
|
transactions: [{
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return [4 /*yield*/, successfulTransfers_1.SuccessfulTransfers.create([usrSuccess], { session: session })];
|
||||||
|
case 3:
|
||||||
|
_a.sent();
|
||||||
|
_a.label = 4;
|
||||||
|
case 4: return [2 /*return*/, pendingTransfers_1.PendingTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(function (userPendinAfterSave) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var cur;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
userPendinAfterSave.transactions = _.filter(userPendinAfterSave.transactions, function (i) { return i.txId.toString() !== txId.toString(); });
|
||||||
|
return [4 /*yield*/, userPendinAfterSave.save()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
cur = _.find(user.wallet, function (i) { return i.currency.toString() === currencyId.toString(); });
|
||||||
|
if (!cur) return [3 /*break*/, 3];
|
||||||
|
cur.value += info.txAmount;
|
||||||
|
return [4 /*yield*/, user.save()];
|
||||||
|
case 2:
|
||||||
|
_a.sent();
|
||||||
|
return [3 /*break*/, 5];
|
||||||
|
case 3:
|
||||||
|
user.wallet.push({
|
||||||
|
currency: currencyId,
|
||||||
|
value: info.txAmount
|
||||||
|
});
|
||||||
|
return [4 /*yield*/, user.save()];
|
||||||
|
case 4:
|
||||||
|
_a.sent();
|
||||||
|
_a.label = 5;
|
||||||
|
case 5:
|
||||||
|
resObj = {
|
||||||
|
status: 'successful',
|
||||||
|
value: info.txAmount
|
||||||
|
};
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resObj = {
|
||||||
|
status: 'pending',
|
||||||
|
value: info.txAmount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var usrPending = {
|
||||||
|
userId: userId,
|
||||||
|
transactions: [{
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
pendingTransfers_1.PendingTransfers.create([usrPending])
|
||||||
|
.then(function () {
|
||||||
|
if (info.status === 'Confirmed') {
|
||||||
|
return successfulTransfers_1.SuccessfulTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(function (userSuccess) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var usrSuccess;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
if (!(userSuccess && userSuccess.userId.toString() === userId.toString())) return [3 /*break*/, 2];
|
||||||
|
userSuccess.transactions.push({
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
});
|
||||||
|
return [4 /*yield*/, userSuccess.save()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
return [3 /*break*/, 4];
|
||||||
|
case 2:
|
||||||
|
usrSuccess = {
|
||||||
|
userId: userId,
|
||||||
|
transactions: [{
|
||||||
|
txId: txId,
|
||||||
|
currencyId: currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
return [4 /*yield*/, successfulTransfers_1.SuccessfulTransfers.create([usrSuccess], { session: session })];
|
||||||
|
case 3:
|
||||||
|
_a.sent();
|
||||||
|
_a.label = 4;
|
||||||
|
case 4: return [2 /*return*/, pendingTransfers_1.PendingTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(function (userPendinAfterSave) { return __awaiter(void 0, void 0, void 0, function () {
|
||||||
|
var cur;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
switch (_a.label) {
|
||||||
|
case 0:
|
||||||
|
userPendinAfterSave.transactions = _.filter(userPendinAfterSave.transactions, function (i) { return i.txId.toString() !== txId.toString(); });
|
||||||
|
return [4 /*yield*/, userPendinAfterSave.save()];
|
||||||
|
case 1:
|
||||||
|
_a.sent();
|
||||||
|
cur = _.find(user.wallet, function (i) { return i.currency.toString() === currencyId.toString(); });
|
||||||
|
if (!cur) return [3 /*break*/, 3];
|
||||||
|
cur.value += info.txAmount;
|
||||||
|
return [4 /*yield*/, user.save()];
|
||||||
|
case 2:
|
||||||
|
_a.sent();
|
||||||
|
return [3 /*break*/, 5];
|
||||||
|
case 3:
|
||||||
|
user.wallet.push({
|
||||||
|
currency: currencyId,
|
||||||
|
value: info.txAmount
|
||||||
|
});
|
||||||
|
return [4 /*yield*/, user.save()];
|
||||||
|
case 4:
|
||||||
|
_a.sent();
|
||||||
|
_a.label = 5;
|
||||||
|
case 5:
|
||||||
|
resObj = {
|
||||||
|
status: 'successful',
|
||||||
|
value: info.txAmount
|
||||||
|
};
|
||||||
|
return [2 /*return*/];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); })["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resObj = {
|
||||||
|
status: 'pending',
|
||||||
|
value: info.txAmount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('currency not found', 400, 5, 'ارز مربوطه پیدا نشد.', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var error = new myError_1["default"]('user not found', 400, 5, 'کاربر پیدا نشد.', 'خطا رخ داد');
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return resObj;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
throw ("error in with Transaction" + ":" + err);
|
||||||
|
})["finally"](function () {
|
||||||
|
session.endSession();
|
||||||
|
})];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}); };
|
||||||
291
server/api/walletApi/transferToExchangeById.ts
Executable file
291
server/api/walletApi/transferToExchangeById.ts
Executable file
@@ -0,0 +1,291 @@
|
|||||||
|
import * as _ from 'lodash'
|
||||||
|
import myError from '../myError'
|
||||||
|
import { Currencies } from '../../db/currencies'
|
||||||
|
import { User } from '../../db/user'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bitcoin from '../walletApi/bitcoin'
|
||||||
|
import * as etherium from './etheriuem'
|
||||||
|
import * as tron from './tron'
|
||||||
|
import { PendingTransfers } from '../../db/pendingTransfers'
|
||||||
|
import { SuccessfulTransfers } from '../../db/successfulTransfers'
|
||||||
|
export const transferToExchangeByIdApi = async(currencyId, txId, userId) => {
|
||||||
|
let info
|
||||||
|
let resObj
|
||||||
|
let userHaveDoc = false
|
||||||
|
let checkStatus = () => {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const session = await mongoose.startSession()
|
||||||
|
return session.withTransaction(() => {
|
||||||
|
return User.findOne({ _id: userId }).session(session)
|
||||||
|
.then((user) => {
|
||||||
|
if(user) {
|
||||||
|
return PendingTransfers.findOne({ userId: userId })
|
||||||
|
.then((userPending) => {
|
||||||
|
if(userPending && userPending.userId.toString() === userId.toString()) {
|
||||||
|
userHaveDoc = true
|
||||||
|
let pendingTx = _.find(userPending.transactions, (i) => { return i.txId.toString() === txId.toString() })
|
||||||
|
if(pendingTx) {
|
||||||
|
const error = new myError(
|
||||||
|
'transaction already exsist',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'تراکنش قبلا وجود دارد',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Currencies.findOne({ _id: currencyId })
|
||||||
|
.then((cur) => {
|
||||||
|
let CurAbName = ""
|
||||||
|
if(cur) {
|
||||||
|
CurAbName = cur.ab_name
|
||||||
|
switch(CurAbName) {
|
||||||
|
case "BTC":
|
||||||
|
checkStatus = () => {
|
||||||
|
return bitcoin.bitcoinTransferToExchangeById(txId)
|
||||||
|
.then((result) => {
|
||||||
|
info = result
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "ETH":
|
||||||
|
return etherium.checkTransaction(txId)
|
||||||
|
.then((transaction) => {
|
||||||
|
if(transaction && transaction.hash.toString() === txId.toString()) {
|
||||||
|
let curInWall = _.find(user.wallet, (i) => { return i.currency.toString()=== currencyId.toString()})
|
||||||
|
if(curInWall) {
|
||||||
|
curInWall.value += Number(transaction.value)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
throw "transaction not valid"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
console.log("api error: ",err)
|
||||||
|
})
|
||||||
|
//
|
||||||
|
case "TRX":
|
||||||
|
return tron.validateByTXId(txId)
|
||||||
|
.then((transaction: any) => {
|
||||||
|
if(transaction.result) {
|
||||||
|
const resObj = {
|
||||||
|
status:"successful",
|
||||||
|
txValue : transaction
|
||||||
|
}
|
||||||
|
return resObj
|
||||||
|
} else {
|
||||||
|
const resObj = {
|
||||||
|
status:"pending",
|
||||||
|
txValue : transaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// default
|
||||||
|
}
|
||||||
|
return Promise.all([checkStatus()])
|
||||||
|
.then(() => {
|
||||||
|
if(userHaveDoc) {
|
||||||
|
userPending.transactions.push({
|
||||||
|
txId:txId,
|
||||||
|
currencyId:currencyId,
|
||||||
|
currencyName:CurAbName,
|
||||||
|
value:info.txAmount,
|
||||||
|
type:"id"
|
||||||
|
})
|
||||||
|
userPending.save()
|
||||||
|
.then(() => {
|
||||||
|
if(info.status === 'Confirmed') {
|
||||||
|
return SuccessfulTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(async (userSuccess) => {
|
||||||
|
if(userSuccess && userSuccess.userId.toString() === userId.toString()) {
|
||||||
|
userSuccess.transactions.push({
|
||||||
|
txId,
|
||||||
|
currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
})
|
||||||
|
await userSuccess.save()
|
||||||
|
} else {
|
||||||
|
const usrSuccess = {
|
||||||
|
userId:userId,
|
||||||
|
transactions: [{
|
||||||
|
txId,
|
||||||
|
currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
await SuccessfulTransfers.create([usrSuccess], { session })
|
||||||
|
}
|
||||||
|
return PendingTransfers.findOne({ userId:userId }).session(session)
|
||||||
|
.then(async (userPendinAfterSave) => {
|
||||||
|
userPendinAfterSave.transactions = _.filter(userPendinAfterSave.transactions, (i) => { return i.txId.toString() !== txId.toString() })
|
||||||
|
await userPendinAfterSave.save()
|
||||||
|
let cur = _.find(user.wallet, (i) => { return i.currency.toString() === currencyId.toString()})
|
||||||
|
if(cur) {
|
||||||
|
cur.value +=info.txAmount
|
||||||
|
await user.save()
|
||||||
|
} else {
|
||||||
|
user.wallet.push({
|
||||||
|
currency: currencyId,
|
||||||
|
value: info.txAmount
|
||||||
|
})
|
||||||
|
await user.save()
|
||||||
|
}
|
||||||
|
resObj = {
|
||||||
|
status: 'successful',
|
||||||
|
value: info.txAmount
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resObj = {
|
||||||
|
status: 'pending',
|
||||||
|
value: info.txAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const usrPending = {
|
||||||
|
userId:userId,
|
||||||
|
transactions: [{
|
||||||
|
txId,
|
||||||
|
currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
PendingTransfers.create([usrPending])
|
||||||
|
.then(() => {
|
||||||
|
if(info.status === 'Confirmed') {
|
||||||
|
return SuccessfulTransfers.findOne({ userId: userId }).session(session)
|
||||||
|
.then(async (userSuccess) => {
|
||||||
|
if(userSuccess && userSuccess.userId.toString() === userId.toString()) {
|
||||||
|
userSuccess.transactions.push({
|
||||||
|
txId,
|
||||||
|
currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
})
|
||||||
|
await userSuccess.save()
|
||||||
|
} else {
|
||||||
|
const usrSuccess = {
|
||||||
|
userId:userId,
|
||||||
|
transactions: [{
|
||||||
|
txId,
|
||||||
|
currencyId,
|
||||||
|
currencyName: CurAbName,
|
||||||
|
value: info.txAmount,
|
||||||
|
type: "id"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
await SuccessfulTransfers.create([usrSuccess], { session })
|
||||||
|
}
|
||||||
|
return PendingTransfers.findOne({ userId:userId }).session(session)
|
||||||
|
.then(async (userPendinAfterSave) => {
|
||||||
|
userPendinAfterSave.transactions = _.filter(userPendinAfterSave.transactions, (i) => { return i.txId.toString() !== txId.toString() })
|
||||||
|
await userPendinAfterSave.save()
|
||||||
|
let cur = _.find(user.wallet, (i) => { return i.currency.toString() === currencyId.toString()})
|
||||||
|
if(cur) {
|
||||||
|
cur.value +=info.txAmount
|
||||||
|
await user.save()
|
||||||
|
} else {
|
||||||
|
user.wallet.push({
|
||||||
|
currency: currencyId,
|
||||||
|
value: info.txAmount
|
||||||
|
})
|
||||||
|
await user.save()
|
||||||
|
}
|
||||||
|
resObj = {
|
||||||
|
status: 'successful',
|
||||||
|
value: info.txAmount
|
||||||
|
}
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}).catch((err)=>{
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resObj = {
|
||||||
|
status: 'pending',
|
||||||
|
value: info.txAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'currency not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'ارز مربوطه پیدا نشد.',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const error = new myError(
|
||||||
|
'user not found',
|
||||||
|
400,
|
||||||
|
5,
|
||||||
|
'کاربر پیدا نشد.',
|
||||||
|
'خطا رخ داد'
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return resObj
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw ("error in with Transaction"+ ":" + err)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
session.endSession()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
109
server/api/walletApi/tron.js
Executable file
109
server/api/walletApi/tron.js
Executable file
@@ -0,0 +1,109 @@
|
|||||||
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||||
|
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||||
|
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||||
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||||
|
function step(op) {
|
||||||
|
if (f) throw new TypeError("Generator is already executing.");
|
||||||
|
while (_) try {
|
||||||
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||||
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||||
|
switch (op[0]) {
|
||||||
|
case 0: case 1: t = op; break;
|
||||||
|
case 4: _.label++; return { value: op[1], done: false };
|
||||||
|
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||||
|
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||||
|
default:
|
||||||
|
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||||
|
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||||
|
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||||
|
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||||
|
if (t[2]) _.ops.pop();
|
||||||
|
_.trys.pop(); continue;
|
||||||
|
}
|
||||||
|
op = body.call(thisArg, _);
|
||||||
|
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||||
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.TRONTransferFrom = exports.validateByTXId = void 0;
|
||||||
|
var tronWeb = require("tronweb");
|
||||||
|
// export function TRONTransferTo(userId, systemAccount, userAccount, privateKey, amount){
|
||||||
|
// User.findOne({ _id : userId })
|
||||||
|
// .then((user) => {
|
||||||
|
// if(user && user._id.toString() === userId.toString()){
|
||||||
|
// const HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
// const fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const tw = new tronWeb(fullNode,solidityNode,eventServer,privateKey);
|
||||||
|
// const am = amount * 1000000
|
||||||
|
// tw.trx.getAccount(userAccount.toString()).then((usrAcc) =>{
|
||||||
|
// if(usrAcc){
|
||||||
|
// tw.trx.sendTransaction(systemAccount, am)
|
||||||
|
// }else{
|
||||||
|
// const error = "user Tron Account not fount"
|
||||||
|
// console.log("Error in TRONTransferTo : ", error)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch((err) => console.log(err))
|
||||||
|
// }else{
|
||||||
|
// const error = 'user not fount'
|
||||||
|
// console.log('Error in TRONTransferTo : ', error)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch((err) => console.log('Error in TRONTransferTo : ', err))
|
||||||
|
// }
|
||||||
|
function validateByTXId(hash) {
|
||||||
|
return __awaiter(this, void 0, void 0, function () {
|
||||||
|
var systemPrivateKey, HttpProvider, fullNode, solidityNode, eventServer, TronWeb;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
systemPrivateKey = '4a8f251556d19ab6625c0cc012a3c534bf978e6a099d0bb8f42d6539579a10c5';
|
||||||
|
HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
TronWeb = new tronWeb(fullNode, solidityNode, eventServer, systemPrivateKey);
|
||||||
|
console.log("here : ", TronWeb);
|
||||||
|
TronWeb.trx.getTransaction(hash.toString())
|
||||||
|
.then(function (transaction) {
|
||||||
|
return transaction;
|
||||||
|
})["catch"](function (err) { throw (err); });
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.validateByTXId = validateByTXId;
|
||||||
|
function TRONTransferFrom(destAccount, am) {
|
||||||
|
return __awaiter(this, void 0, void 0, function () {
|
||||||
|
var systemPrivateKey, amount, HttpProvider, fullNode, solidityNode, eventServer, TronWeb;
|
||||||
|
return __generator(this, function (_a) {
|
||||||
|
systemPrivateKey = '4a8f251556d19ab6625c0cc012a3c534bf978e6a099d0bb8f42d6539579a10c5';
|
||||||
|
amount = am * 1000000;
|
||||||
|
HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
TronWeb = new tronWeb(fullNode, solidityNode, eventServer, systemPrivateKey);
|
||||||
|
TronWeb.trx.sendTransaction(destAccount, amount)
|
||||||
|
.then(function (transaction) {
|
||||||
|
return transaction;
|
||||||
|
})["catch"](function (err) {
|
||||||
|
console.log("Error : ", err);
|
||||||
|
throw (err);
|
||||||
|
});
|
||||||
|
return [2 /*return*/];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.TRONTransferFrom = TRONTransferFrom;
|
||||||
80
server/api/walletApi/tron.ts
Executable file
80
server/api/walletApi/tron.ts
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
import * as tronWeb from 'tronweb'
|
||||||
|
// import { Currencies } from '../db/currencies';
|
||||||
|
// import { User } from '../db/user'
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
|
// export function TRONTransferTo(userId, systemAccount, userAccount, privateKey, amount){
|
||||||
|
|
||||||
|
// User.findOne({ _id : userId })
|
||||||
|
// .then((user) => {
|
||||||
|
|
||||||
|
// if(user && user._id.toString() === userId.toString()){
|
||||||
|
// const HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
// const fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
// const tw = new tronWeb(fullNode,solidityNode,eventServer,privateKey);
|
||||||
|
// const am = amount * 1000000
|
||||||
|
// tw.trx.getAccount(userAccount.toString()).then((usrAcc) =>{
|
||||||
|
// if(usrAcc){
|
||||||
|
// tw.trx.sendTransaction(systemAccount, am)
|
||||||
|
|
||||||
|
// }else{
|
||||||
|
// const error = "user Tron Account not fount"
|
||||||
|
// console.log("Error in TRONTransferTo : ", error)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .catch((err) => console.log(err))
|
||||||
|
|
||||||
|
|
||||||
|
// }else{
|
||||||
|
// const error = 'user not fount'
|
||||||
|
// console.log('Error in TRONTransferTo : ', error)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// })
|
||||||
|
// .catch((err) => console.log('Error in TRONTransferTo : ', err))
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function validateByTXId(hash){
|
||||||
|
|
||||||
|
const systemPrivateKey = '4a8f251556d19ab6625c0cc012a3c534bf978e6a099d0bb8f42d6539579a10c5'
|
||||||
|
|
||||||
|
const HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
const fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const TronWeb = new tronWeb(fullNode,solidityNode,eventServer,systemPrivateKey);
|
||||||
|
console.log("here : ", TronWeb)
|
||||||
|
TronWeb.trx.getTransaction(hash.toString())
|
||||||
|
.then((transaction) => {
|
||||||
|
return transaction
|
||||||
|
})
|
||||||
|
.catch((err) => {throw(err)})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function TRONTransferFrom(destAccount, am){
|
||||||
|
const systemPrivateKey = '4a8f251556d19ab6625c0cc012a3c534bf978e6a099d0bb8f42d6539579a10c5'
|
||||||
|
const amount = am * 1000000
|
||||||
|
|
||||||
|
|
||||||
|
const HttpProvider = tronWeb.providers.HttpProvider;
|
||||||
|
const fullNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const solidityNode = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const eventServer = new HttpProvider("https://api.shasta.trongrid.io");
|
||||||
|
const TronWeb = new tronWeb(fullNode,solidityNode,eventServer,systemPrivateKey);
|
||||||
|
TronWeb.trx.sendTransaction(destAccount, amount)
|
||||||
|
.then((transaction) => {
|
||||||
|
|
||||||
|
return transaction
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Error : ", err)
|
||||||
|
throw(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
103725
server/combined.log
Executable file
103725
server/combined.log
Executable file
File diff suppressed because it is too large
Load Diff
51
server/db/acceptedOffers.js
Executable file
51
server/db/acceptedOffers.js
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Accepted_Offers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var acceptedOffers = new mongoose.Schema({
|
||||||
|
buyOrderId: {
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
acceptor: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
creator: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offerId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
curGivenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offeredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expiredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.Accepted_Offers = mongoose.model('AcceptedOffers', acceptedOffers);
|
||||||
57
server/db/acceptedOffers.ts
Executable file
57
server/db/acceptedOffers.ts
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
const acceptedOffers = new mongoose.Schema({
|
||||||
|
|
||||||
|
buyOrderId:{
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
acceptor : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
creator: {
|
||||||
|
type:mongoose.ObjectId,
|
||||||
|
|
||||||
|
required:true,
|
||||||
|
},
|
||||||
|
offerId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
curGivenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offeredDate:{
|
||||||
|
type:Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
expiredDate:{
|
||||||
|
type:Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
}, schemaOptions )
|
||||||
|
|
||||||
|
|
||||||
|
export const Accepted_Offers = mongoose.model('AcceptedOffers', acceptedOffers)
|
||||||
|
|
||||||
|
|
||||||
46
server/db/activeOffers.js
Executable file
46
server/db/activeOffers.js
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Active_Offers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var activeOffers = new mongoose.Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offerId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
rank: {
|
||||||
|
type: Number,
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
curGivenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
"default": Date.now()
|
||||||
|
}
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.Active_Offers = mongoose.models.ActiveOffers || mongoose.model('ActiveOffers', activeOffers);
|
||||||
49
server/db/activeOffers.ts
Executable file
49
server/db/activeOffers.ts
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const activeOffers = new mongoose.Schema({
|
||||||
|
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offerId:{
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
rank: {
|
||||||
|
type: Number,
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
curGivenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expDate:{
|
||||||
|
type:Date,
|
||||||
|
required: true,
|
||||||
|
default: Date.now()
|
||||||
|
}
|
||||||
|
}, schemaOptions )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const Active_Offers = mongoose.models.ActiveOffers || mongoose.model('ActiveOffers', activeOffers)
|
||||||
108
server/db/admin.js
Executable file
108
server/db/admin.js
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Admin = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var bcrypt = require("bcrypt");
|
||||||
|
var adminSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
trim: true,
|
||||||
|
unique: 1
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minlength: 6,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['Admin', 'Manager', 'Supporter']
|
||||||
|
},
|
||||||
|
wallet: [
|
||||||
|
{
|
||||||
|
currency: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
adminActivities: [
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
device: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loginDeviceId: {},
|
||||||
|
ip: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
adminSchema.pre('save', function (next) {
|
||||||
|
var user = this;
|
||||||
|
if (user.isModified('password')) {
|
||||||
|
bcrypt.genSalt(Number(process.env.SALT_I))
|
||||||
|
.then(function (salt) {
|
||||||
|
bcrypt.hash(user.password, salt)
|
||||||
|
.then(function (hash) {
|
||||||
|
user.password = hash;
|
||||||
|
next();
|
||||||
|
})["catch"](function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
adminSchema.methods.comparePassword = function (candidatePassword, cb) {
|
||||||
|
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
|
||||||
|
if (err)
|
||||||
|
return cb(err);
|
||||||
|
cb(null, isMatch);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
adminSchema.methods.comparePasswordPromise = function (candidatePassword) {
|
||||||
|
var _this = this;
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
bcrypt.compare(candidatePassword, _this.password)
|
||||||
|
.then(function (isMatch) {
|
||||||
|
resolve(isMatch);
|
||||||
|
})["catch"](function (err) {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.Admin = mongoose.model('Admin', adminSchema);
|
||||||
111
server/db/admin.ts
Executable file
111
server/db/admin.ts
Executable file
@@ -0,0 +1,111 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
const adminSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
trim: true,
|
||||||
|
unique: 1
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minlength: 6,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: ['Admin', 'Manager', 'Supporter']
|
||||||
|
},
|
||||||
|
wallet: [
|
||||||
|
{
|
||||||
|
currency: {
|
||||||
|
type:mongoose.ObjectId,
|
||||||
|
required:true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type:Number,
|
||||||
|
required:true,
|
||||||
|
default:0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
adminActivities: [
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
device: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loginDeviceId: {},
|
||||||
|
ip: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
adminSchema.pre('save', function (next) {
|
||||||
|
var user = this
|
||||||
|
if (user.isModified('password')) {
|
||||||
|
bcrypt.genSalt(Number(process.env.SALT_I))
|
||||||
|
.then((salt) => {
|
||||||
|
bcrypt.hash(user.password, salt)
|
||||||
|
.then((hash) => {
|
||||||
|
user.password = hash
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
adminSchema.methods.comparePassword = function (candidatePassword, cb) {
|
||||||
|
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
cb(null, isMatch)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
adminSchema.methods.comparePasswordPromise = function (candidatePassword) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
bcrypt.compare(candidatePassword, this.password)
|
||||||
|
.then(function(isMatch) {
|
||||||
|
resolve(isMatch)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Admin = mongoose.model('Admin', adminSchema)
|
||||||
42
server/db/buyOrder.ts
Executable file
42
server/db/buyOrder.ts
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
const buyOrder = new mongoose.Schema({
|
||||||
|
currencyId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required : true,
|
||||||
|
}
|
||||||
|
,
|
||||||
|
id:{
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
transferredValue : {
|
||||||
|
type : Number,
|
||||||
|
required : true,
|
||||||
|
default : 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
userId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value : {
|
||||||
|
type : Number,
|
||||||
|
//required : true,
|
||||||
|
//default : 0,
|
||||||
|
},
|
||||||
|
shouldBuyValue : {
|
||||||
|
type: Number,
|
||||||
|
required : true,
|
||||||
|
default : 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},schemaOptions)
|
||||||
|
export const BuyOrder = mongoose.model('buyOrder', buyOrder)
|
||||||
|
|
||||||
24
server/db/continuesPriceStats.js
Executable file
24
server/db/continuesPriceStats.js
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.ContinuesPriceStat = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var continuesPriceStat = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
currencyPriceHistory: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
exports.ContinuesPriceStat = mongoose.model('continuesPriceStat', continuesPriceStat);
|
||||||
25
server/db/continuesPriceStats.ts
Executable file
25
server/db/continuesPriceStats.ts
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const continuesPriceStat = new mongoose.Schema({
|
||||||
|
name:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
currencyPriceHistory:[
|
||||||
|
{
|
||||||
|
currencyId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required:true,
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type : Number,
|
||||||
|
required:true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
export const ContinuesPriceStat = mongoose.model('continuesPriceStat', continuesPriceStat)
|
||||||
36
server/db/currencies.js
Executable file
36
server/db/currencies.js
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Currencies = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var currencies = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['RIAL', 'BITCOIN', 'TRON', 'ETHEREUM'],
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
per_name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['ریال', 'بیت کوین', 'ترون', 'اتریوم'],
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
ab_name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['IRR', 'BTC', 'TRX', 'ETH'],
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
type: Number,
|
||||||
|
//required: true,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
// value:{
|
||||||
|
// type:Number,
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
exports.Currencies = mongoose.model('currencies', currencies);
|
||||||
37
server/db/currencies.ts
Executable file
37
server/db/currencies.ts
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const currencies = new mongoose.Schema({
|
||||||
|
name:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum: ['RIAL', 'BITCOIN', 'TRON', 'ETHEREUM'],
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
per_name:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum:['ریال', 'بیت کوین','ترون','اتریوم'],
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
ab_name:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum: ['IRR', 'BTC', 'TRX', 'ETH'],
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
icon:{
|
||||||
|
type:String,
|
||||||
|
//required:true,
|
||||||
|
//unique: true,
|
||||||
|
},
|
||||||
|
quantity:{
|
||||||
|
type: Number,
|
||||||
|
//required: true,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
// value:{
|
||||||
|
// type:Number,
|
||||||
|
// },
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Currencies = mongoose.model('currencies', currencies)
|
||||||
28
server/db/dailyPriceStats.js
Executable file
28
server/db/dailyPriceStats.js
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.DailyPriceStat = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var dailyPriceStat = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
currencyPriceHistory: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
exports.DailyPriceStat = mongoose.model('dailyPriceStat', dailyPriceStat);
|
||||||
28
server/db/dailyPriceStats.ts
Executable file
28
server/db/dailyPriceStats.ts
Executable file
@@ -0,0 +1,28 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const dailyPriceStat = new mongoose.Schema({
|
||||||
|
name:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
currencyPriceHistory:[
|
||||||
|
{
|
||||||
|
currencyId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required:true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type : Number,
|
||||||
|
required:true
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
export const DailyPriceStat = mongoose.model('dailyPriceStat', dailyPriceStat)
|
||||||
41
server/db/failedTransfers.ts
Executable file
41
server/db/failedTransfers.ts
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
const failedTransfers = new mongoose.Schema({
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
transactions:[
|
||||||
|
{
|
||||||
|
txId:{
|
||||||
|
type : String,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
currencyId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
currencyName : {
|
||||||
|
type : String
|
||||||
|
},
|
||||||
|
value:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum: ['send','receive'],
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions )
|
||||||
|
export const FailedTransfers = mongoose.model('FailedTransfers', failedTransfers)
|
||||||
25
server/db/getPrice.js
Executable file
25
server/db/getPrice.js
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GetPrice = void 0;
|
||||||
|
var mongodb_1 = require("mongodb");
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var getPrice = new mongoose.Schema({
|
||||||
|
currency: {
|
||||||
|
type: mongodb_1.ObjectID,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
rialPricePerUnit: {
|
||||||
|
type: Number,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 20, "default": Date.now }
|
||||||
|
}, { timestamp: true });
|
||||||
|
exports.GetPrice = mongoose.model('getPrice', getPrice);
|
||||||
24
server/db/getPrice.ts
Executable file
24
server/db/getPrice.ts
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
import { ObjectID } from 'mongodb'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const getPrice = new mongoose.Schema({
|
||||||
|
currency: {
|
||||||
|
type:ObjectID,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
type:Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
rialPricePerUnit: {
|
||||||
|
type:Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 20, default: Date.now }
|
||||||
|
},{ timestamp: true })
|
||||||
|
|
||||||
|
export const GetPrice = mongoose.model('getPrice', getPrice)
|
||||||
26
server/db/globalDailyPrice.js
Executable file
26
server/db/globalDailyPrice.js
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GlobalDailyPrice = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var globalDailyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
price: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min: { type: Number },
|
||||||
|
max: { type: Number }
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
exports.GlobalDailyPrice = mongoose.model('GlobalDailyPrice', globalDailyPriceSchema);
|
||||||
33
server/db/globalDailyPrice.ts
Executable file
33
server/db/globalDailyPrice.ts
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const globalDailyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price:{
|
||||||
|
price : {
|
||||||
|
type: Number}
|
||||||
|
,min : { type : Number},
|
||||||
|
max : {type : Number},
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
volume : {
|
||||||
|
type : Number
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
|
||||||
|
export const GlobalDailyPrice = mongoose.model('GlobalDailyPrice', globalDailyPriceSchema)
|
||||||
30
server/db/globalHourlyPrice.js
Executable file
30
server/db/globalHourlyPrice.js
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GlobalHourlyPrice = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var globalHourlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
price: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
exports.GlobalHourlyPrice = mongoose.model('GlobalHourlyPrice', globalHourlyPriceSchema);
|
||||||
38
server/db/globalHourlyPrice.ts
Executable file
38
server/db/globalHourlyPrice.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const globalHourlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price:{
|
||||||
|
price :
|
||||||
|
{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min :{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
volume : {
|
||||||
|
type : Number
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
|
||||||
|
export const GlobalHourlyPrice = mongoose.model('GlobalHourlyPrice', globalHourlyPriceSchema)
|
||||||
30
server/db/globalMontlyPrice.js
Executable file
30
server/db/globalMontlyPrice.js
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GlobalMonthlyPrice = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var globalMonthlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
price: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
exports.GlobalMonthlyPrice = mongoose.model('GlobalMonthlyPrice', globalMonthlyPriceSchema);
|
||||||
38
server/db/globalMontlyPrice.ts
Executable file
38
server/db/globalMontlyPrice.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const globalMonthlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price:{
|
||||||
|
price :
|
||||||
|
{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min :{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
volume : {
|
||||||
|
type : Number
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
|
||||||
|
export const GlobalMonthlyPrice = mongoose.model('GlobalMonthlyPrice', globalMonthlyPriceSchema)
|
||||||
30
server/db/globalWeeklyPrice.js
Executable file
30
server/db/globalWeeklyPrice.js
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GlobalWeeklyPrice = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var globalWeeklyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
price: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
exports.GlobalWeeklyPrice = mongoose.model('GlobalWeeklyPrice', globalWeeklyPriceSchema);
|
||||||
38
server/db/globalWeeklyPrice.ts
Executable file
38
server/db/globalWeeklyPrice.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const globalWeeklyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price:{
|
||||||
|
price :
|
||||||
|
{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min :{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
volume : {
|
||||||
|
type : Number
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
|
||||||
|
export const GlobalWeeklyPrice = mongoose.model('GlobalWeeklyPrice', globalWeeklyPriceSchema)
|
||||||
30
server/db/globalYearlyPrice.js
Executable file
30
server/db/globalYearlyPrice.js
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.GlobalYearlyPrice = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var globalYearlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
price: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
exports.GlobalYearlyPrice = mongoose.model('GlobalYearlyPrice', globalYearlyPriceSchema);
|
||||||
38
server/db/globalYearlyPrice.ts
Executable file
38
server/db/globalYearlyPrice.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const globalYearlyPriceSchema = new mongoose.Schema({
|
||||||
|
timeStamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
price:{
|
||||||
|
price :
|
||||||
|
{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
min :{
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
volume : {
|
||||||
|
type : Number
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
|
||||||
|
export const GlobalYearlyPrice = mongoose.model('GlobalYearlyPrice', globalYearlyPriceSchema)
|
||||||
38
server/db/localDaily.js
Executable file
38
server/db/localDaily.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LocalDaily = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var localDaily = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencies: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.LocalDaily = mongoose.model('localDaily', localDaily);
|
||||||
45
server/db/localDaily.ts
Executable file
45
server/db/localDaily.ts
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
import { ObjectID } from 'mongodb'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const localDaily = new mongoose.Schema({
|
||||||
|
|
||||||
|
|
||||||
|
name:{
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
currencies:[
|
||||||
|
{
|
||||||
|
currencyId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
price:{
|
||||||
|
type:Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
min:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
max:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
export const LocalDaily = mongoose.model('localDaily', localDaily)
|
||||||
38
server/db/localHourly.js
Executable file
38
server/db/localHourly.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LocalHourly = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var localHourly = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencies: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.LocalHourly = mongoose.model('localHourly', localHourly);
|
||||||
42
server/db/localHourly.ts
Executable file
42
server/db/localHourly.ts
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const localHourly = new mongoose.Schema({
|
||||||
|
name:{
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
currencies:[
|
||||||
|
{
|
||||||
|
currencyId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
price:{
|
||||||
|
type:Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
min:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
max:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
export const LocalHourly = mongoose.model('localHourly', localHourly)
|
||||||
38
server/db/localMonthly.js
Executable file
38
server/db/localMonthly.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LocalMonthly = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var localMonthly = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencies: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.LocalMonthly = mongoose.model('localMonthly', localMonthly);
|
||||||
45
server/db/localMonthly.ts
Executable file
45
server/db/localMonthly.ts
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
import { ObjectID } from 'mongodb'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const localMonthly = new mongoose.Schema({
|
||||||
|
|
||||||
|
|
||||||
|
name:{
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
currencies:[
|
||||||
|
{
|
||||||
|
currencyId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
price:{
|
||||||
|
type:Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
min:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
max:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
export const LocalMonthly = mongoose.model('localMonthly', localMonthly)
|
||||||
38
server/db/localWeekly.js
Executable file
38
server/db/localWeekly.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LocalWeekly = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var localWeekly = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencies: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.LocalWeekly = mongoose.model('localWeekly', localWeekly);
|
||||||
45
server/db/localWeekly.ts
Executable file
45
server/db/localWeekly.ts
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
import { ObjectID } from 'mongodb'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const localWeekly = new mongoose.Schema({
|
||||||
|
|
||||||
|
|
||||||
|
name:{
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
currencies:[
|
||||||
|
{
|
||||||
|
currencyId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
price:{
|
||||||
|
type:Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
min:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
max:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
export const LocalWeekly = mongoose.model('localWeekly', localWeekly)
|
||||||
38
server/db/localYearly.js
Executable file
38
server/db/localYearly.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.LocalYearly = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var localYearly = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencies: [
|
||||||
|
{
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
volume: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.LocalYearly = mongoose.model('localYearly', localYearly);
|
||||||
45
server/db/localYearly.ts
Executable file
45
server/db/localYearly.ts
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
import { ObjectID } from 'mongodb'
|
||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const localYearly = new mongoose.Schema({
|
||||||
|
|
||||||
|
|
||||||
|
name:{
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
currencies:[
|
||||||
|
{
|
||||||
|
currencyId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
price:{
|
||||||
|
type:Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
volume:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
min:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
max:{
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
export const LocalYearly = mongoose.model('localYearly', localYearly)
|
||||||
38
server/db/pendingTransfers.js
Executable file
38
server/db/pendingTransfers.js
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.PendingTransfers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var pendingTransfers = new mongoose.Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
txId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencyName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['send', 'receive']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.PendingTransfers = mongoose.model('PendingTransfers', pendingTransfers);
|
||||||
38
server/db/pendingTransfers.ts
Executable file
38
server/db/pendingTransfers.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const pendingTransfers = new mongoose.Schema({
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
txId: {
|
||||||
|
type : String,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencyName: {
|
||||||
|
type : String
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum: ['send','receive'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions )
|
||||||
|
|
||||||
|
export const PendingTransfers = mongoose.model('PendingTransfers', pendingTransfers)
|
||||||
39
server/db/successfulTransfers.js
Executable file
39
server/db/successfulTransfers.js
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.SuccessfulTransfers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var successfulTransfers = new mongoose.Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
txId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencyId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currencyName: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
"enum": ['send', 'receive', 'id']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.SuccessfulTransfers = mongoose.model('SuccessfulTransfers', successfulTransfers);
|
||||||
38
server/db/successfulTransfers.ts
Executable file
38
server/db/successfulTransfers.ts
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
const successfulTransfers = new mongoose.Schema({
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
transactions:[
|
||||||
|
{
|
||||||
|
txId: {
|
||||||
|
type : String,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
currencyId : {
|
||||||
|
type : mongoose.ObjectId,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
currencyName : {
|
||||||
|
type : String,
|
||||||
|
required : true
|
||||||
|
},
|
||||||
|
value:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
type:{
|
||||||
|
type:String,
|
||||||
|
required:true,
|
||||||
|
enum: ['send','receive','id'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, schemaOptions )
|
||||||
|
|
||||||
|
export const SuccessfulTransfers = mongoose.model('SuccessfulTransfers', successfulTransfers)
|
||||||
245
server/db/user.js
Executable file
245
server/db/user.js
Executable file
@@ -0,0 +1,245 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.VerificationPhoneCode = exports.VerificationCode = exports.User = exports.verificationPhoneCodeSchema = exports.verificationCodeSchema = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var bcrypt = require("bcrypt");
|
||||||
|
exports.verificationCodeSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 60 * 60 * 2, "default": Date.now }
|
||||||
|
}, { timestamp: true });
|
||||||
|
exports.verificationPhoneCodeSchema = new mongoose.Schema({
|
||||||
|
phoneNumber: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: 11,
|
||||||
|
max: 11,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
sessionId: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 60 * 2, "default": Date.now }
|
||||||
|
}, { timestamp: true });
|
||||||
|
var userSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
address: {
|
||||||
|
type: String,
|
||||||
|
// required: true,
|
||||||
|
trim: true,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'email.address': { $type: "string" } }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
"default": false,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rank: {
|
||||||
|
type: Number,
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
phoneNumber: {
|
||||||
|
number: {
|
||||||
|
type: String,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'phoneNumber.number': { $type: "string" } }
|
||||||
|
},
|
||||||
|
min: 11,
|
||||||
|
max: 11
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
"default": false,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tempPhoneNumber: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
birthdate: {
|
||||||
|
year: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emailVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
resetPasswordVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minlength: 6,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
hasTicketAccount: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
userActivities: [
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
device: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loginDeviceId: {},
|
||||||
|
ip: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
address: [{
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
trim: 1
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
district: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
province: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
postalCode: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: [10, 'Postal Code is 10 Digits'],
|
||||||
|
max: [10, 'Postal Code is 10 Digits']
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
max: [130, 'Maximmum allowed string length is 130 ']
|
||||||
|
},
|
||||||
|
mobilePhone: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
phone: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
userType: {
|
||||||
|
type: String,
|
||||||
|
"enum": ['Normal', 'Builder', 'Vip'],
|
||||||
|
required: true,
|
||||||
|
"default": 'Normal'
|
||||||
|
},
|
||||||
|
wallet: [
|
||||||
|
{
|
||||||
|
currency: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
commitment: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
userSchema.pre('save', function (next) {
|
||||||
|
var user = this;
|
||||||
|
if (user.isModified('password')) {
|
||||||
|
bcrypt.genSalt(Number(process.env.SALT_I))
|
||||||
|
.then(function (salt) {
|
||||||
|
bcrypt.hash(user.password, salt)
|
||||||
|
.then(function (hash) {
|
||||||
|
user.password = hash;
|
||||||
|
next();
|
||||||
|
})["catch"](function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
})["catch"](function (err) {
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
userSchema.methods.comparePassword = function (candidatePassword, cb) {
|
||||||
|
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
|
||||||
|
if (err)
|
||||||
|
return cb(err);
|
||||||
|
cb(null, isMatch);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
userSchema.methods.comparePasswordPromise = function (candidatePassword) {
|
||||||
|
var _this = this;
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
bcrypt.compare(candidatePassword, _this.password)
|
||||||
|
.then(function (isMatch) {
|
||||||
|
resolve(isMatch);
|
||||||
|
})["catch"](function (err) {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.User = mongoose.model('User', userSchema);
|
||||||
|
exports.VerificationCode = mongoose.model('VerificationCode', exports.verificationCodeSchema);
|
||||||
|
exports.VerificationPhoneCode = mongoose.model('VerificationPhoneCode', exports.verificationPhoneCodeSchema);
|
||||||
253
server/db/user.ts
Executable file
253
server/db/user.ts
Executable file
@@ -0,0 +1,253 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
export const verificationCodeSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
email :{
|
||||||
|
type : String
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 60 * 60 * 2, default: Date.now }
|
||||||
|
}, { timestamp: true })
|
||||||
|
|
||||||
|
export const verificationPhoneCodeSchema = new mongoose.Schema({
|
||||||
|
phoneNumber: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: 11,
|
||||||
|
max: 11,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
sessionId: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 60 * 2, default: Date.now }
|
||||||
|
}, { timestamp: true })
|
||||||
|
|
||||||
|
|
||||||
|
const userSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
address :{
|
||||||
|
type: String,
|
||||||
|
// required: true,
|
||||||
|
trim: true,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'email.address': {$type: "string" } }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rank: {
|
||||||
|
type: Number,
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
phoneNumber: {
|
||||||
|
number: {
|
||||||
|
type: String,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'phoneNumber.number': {$type: "string" } }
|
||||||
|
},
|
||||||
|
min: 11,
|
||||||
|
max: 11
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tempPhoneNumber: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
birthdate: {
|
||||||
|
year: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emailVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
resetPasswordVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minlength: 6,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
hasTicketAccount : {
|
||||||
|
type : Boolean ,
|
||||||
|
required : true,
|
||||||
|
default : false
|
||||||
|
},
|
||||||
|
userActivities: [
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
device: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loginDeviceId: {},
|
||||||
|
ip: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
address: [{
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
trim: 1
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
district: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
province: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
postalCode: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: [10, 'Postal Code is 10 Digits'],
|
||||||
|
max: [10, 'Postal Code is 10 Digits']
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
max: [130, 'Maximmum allowed string length is 130 ']
|
||||||
|
},
|
||||||
|
|
||||||
|
mobilePhone: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
phone: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
userType: {
|
||||||
|
type: String,
|
||||||
|
enum: ['Normal', 'Builder', 'Vip'],
|
||||||
|
required: true,
|
||||||
|
default: 'Normal'
|
||||||
|
},
|
||||||
|
wallet: [
|
||||||
|
{
|
||||||
|
currency: {
|
||||||
|
type:mongoose.ObjectId,
|
||||||
|
required:true,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type:Number,
|
||||||
|
required:true,
|
||||||
|
default:0,
|
||||||
|
},
|
||||||
|
commitment:{
|
||||||
|
type: Number,
|
||||||
|
required:true,
|
||||||
|
default:0,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
userSchema.pre('save', function (next) {
|
||||||
|
var user = this
|
||||||
|
if (user.isModified('password')) {
|
||||||
|
bcrypt.genSalt(Number(process.env.SALT_I))
|
||||||
|
.then((salt) => {
|
||||||
|
bcrypt.hash(user.password, salt)
|
||||||
|
.then((hash) => {
|
||||||
|
user.password = hash
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
userSchema.methods.comparePassword = function (candidatePassword, cb) {
|
||||||
|
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
cb(null, isMatch)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
userSchema.methods.comparePasswordPromise = function (candidatePassword) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
bcrypt.compare(candidatePassword, this.password)
|
||||||
|
.then(function(isMatch) {
|
||||||
|
resolve(isMatch)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const User = mongoose.model('User', userSchema)
|
||||||
|
export const VerificationCode = mongoose.model('VerificationCode', verificationCodeSchema)
|
||||||
|
export const VerificationPhoneCode = mongoose.model('VerificationPhoneCode', verificationPhoneCodeSchema)
|
||||||
240
server/db/wallet.ts
Executable file
240
server/db/wallet.ts
Executable file
@@ -0,0 +1,240 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
import * as bcrypt from 'bcrypt'
|
||||||
|
|
||||||
|
export const verificationCodeSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
email :{
|
||||||
|
type : String
|
||||||
|
}
|
||||||
|
,
|
||||||
|
createdAt: { type: Date, expires: 60 * 60 * 2, default: Date.now }
|
||||||
|
}, { timestamp: true })
|
||||||
|
|
||||||
|
export const verificationPhoneCodeSchema = new mongoose.Schema({
|
||||||
|
phoneNumber: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: 11,
|
||||||
|
max: 11,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
sessionId: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
createdAt: { type: Date, expires: 60 * 2, default: Date.now }
|
||||||
|
}, { timestamp: true })
|
||||||
|
|
||||||
|
|
||||||
|
const userSchema = new mongoose.Schema({
|
||||||
|
name: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
lastName: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
address :{
|
||||||
|
type: String,
|
||||||
|
// required: true,
|
||||||
|
trim: true,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'email.address': {$type: "string" } }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
phoneNumber: {
|
||||||
|
number: {
|
||||||
|
type: String,
|
||||||
|
index: {
|
||||||
|
unique: true,
|
||||||
|
partialFilterExpression: { 'phoneNumber.number': {$type: "string" } }
|
||||||
|
},
|
||||||
|
min: 11,
|
||||||
|
max: 11
|
||||||
|
},
|
||||||
|
validated: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tempPhoneNumber: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
birthdate: {
|
||||||
|
year: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emailVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
resetPasswordVerificationString: {
|
||||||
|
type: mongoose.ObjectId
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
minlength: 6,
|
||||||
|
trim: true
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
userActivities: [
|
||||||
|
{
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
timestamp: {
|
||||||
|
type: Date
|
||||||
|
},
|
||||||
|
device: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
loginDeviceId: {},
|
||||||
|
ip: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
address: [{
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
trim: 1
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
district: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
province: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
postalCode: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
min: [10, 'Postal Code is 10 Digits'],
|
||||||
|
max: [10, 'Postal Code is 10 Digits']
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
max: [130, 'Maximmum allowed string length is 130 ']
|
||||||
|
},
|
||||||
|
|
||||||
|
mobilePhone: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
phone: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
userType: {
|
||||||
|
type: String,
|
||||||
|
enum: ['Normal', 'Builder', 'Vip'],
|
||||||
|
required: true,
|
||||||
|
default: 'Normal'
|
||||||
|
},
|
||||||
|
wallet:[
|
||||||
|
{
|
||||||
|
currency:{
|
||||||
|
type:mongoose.ObjectId,
|
||||||
|
required:true,
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
value:{
|
||||||
|
type:Number,
|
||||||
|
required:true,
|
||||||
|
default:0,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// This functions will execute if the password field is modified.
|
||||||
|
userSchema.pre('save', function (next) {
|
||||||
|
var user = this
|
||||||
|
if (user.isModified('password')) {
|
||||||
|
bcrypt.genSalt(Number(process.env.SALT_I))
|
||||||
|
.then((salt) => {
|
||||||
|
bcrypt.hash(user.password, salt)
|
||||||
|
.then((hash) => {
|
||||||
|
user.password = hash
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
next(err)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// This method compares the password which is stored in database and
|
||||||
|
// the password which the user entered. It is used in Login.
|
||||||
|
userSchema.methods.comparePassword = function (candidatePassword, cb) {
|
||||||
|
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
|
||||||
|
if (err) return cb(err)
|
||||||
|
cb(null, isMatch)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
userSchema.methods.comparePasswordPromise = function (candidatePassword) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
bcrypt.compare(candidatePassword, this.password)
|
||||||
|
.then(function(isMatch) {
|
||||||
|
resolve(isMatch)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const User = mongoose.model('User', userSchema)
|
||||||
|
export const VerificationCode = mongoose.model('VerificationCode', verificationCodeSchema)
|
||||||
|
export const VerificationPhoneCode = mongoose.model('VerificationPhoneCode', verificationPhoneCodeSchema)
|
||||||
45
server/db/withdrawOffers.js
Executable file
45
server/db/withdrawOffers.js
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Withdraw_Offers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' }
|
||||||
|
};
|
||||||
|
var withdrawnOffers = new mongoose.Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
offers: [{
|
||||||
|
offerId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
curGivenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offeredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expiredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}, schemaOptions);
|
||||||
|
exports.Withdraw_Offers = mongoose.model('WithdrawnOffers', withdrawnOffers);
|
||||||
73
server/db/withdrawOffers.ts
Executable file
73
server/db/withdrawOffers.ts
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
import * as mongoose from 'mongoose'
|
||||||
|
const schemaOptions = {
|
||||||
|
timestamps: { createdAt: 'created_at' },
|
||||||
|
};
|
||||||
|
const withdrawnOffers = new mongoose.Schema({
|
||||||
|
|
||||||
|
userId : {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
offers : [{
|
||||||
|
offerId:{
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
curGivenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId:{
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal:{
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offeredDate:{
|
||||||
|
type:Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
expiredDate:{
|
||||||
|
type:Date,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
//withdrawDate:{
|
||||||
|
// type: Date,
|
||||||
|
// required: true,
|
||||||
|
// default: Date.now,
|
||||||
|
//}
|
||||||
|
// bargains:[{
|
||||||
|
// userId:{
|
||||||
|
// type: mongoose.ObjectId,
|
||||||
|
// required: true,
|
||||||
|
// },
|
||||||
|
|
||||||
|
// value:{
|
||||||
|
// type: Number,
|
||||||
|
// required: true,
|
||||||
|
|
||||||
|
// },
|
||||||
|
|
||||||
|
// cur_id:{
|
||||||
|
// type: mongoose.ObjectId,
|
||||||
|
// required: true,
|
||||||
|
// },
|
||||||
|
// bar_date:{
|
||||||
|
// type:Date,
|
||||||
|
// required:true,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }]
|
||||||
|
}],
|
||||||
|
}, schemaOptions)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const Withdraw_Offers = mongoose.model('WithdrawnOffers', withdrawnOffers)
|
||||||
60
server/db/withdrawnOffers.js
Executable file
60
server/db/withdrawnOffers.js
Executable file
@@ -0,0 +1,60 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.Withdrawn_Offers = void 0;
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var withdrawnOffers = new mongoose.Schema({
|
||||||
|
userId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
offers: [{
|
||||||
|
curGivenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curGivenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenId: {
|
||||||
|
type: mongoose.ObjectId,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
curTakenVal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
offeredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
expiredDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
withdrawDate: {
|
||||||
|
type: Date,
|
||||||
|
required: true,
|
||||||
|
"default": Date.now
|
||||||
|
}
|
||||||
|
// bargains:[{
|
||||||
|
// userId:{
|
||||||
|
// type: mongoose.ObjectId,
|
||||||
|
// required: true,
|
||||||
|
// },
|
||||||
|
// value:{
|
||||||
|
// type: Number,
|
||||||
|
// required: true,
|
||||||
|
// },
|
||||||
|
// cur_id:{
|
||||||
|
// type: mongoose.ObjectId,
|
||||||
|
// required: true,
|
||||||
|
// },
|
||||||
|
// bar_date:{
|
||||||
|
// type:Date,
|
||||||
|
// required:true,
|
||||||
|
// }
|
||||||
|
// }]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
exports.Withdrawn_Offers = mongoose.model('WithdrawnOffers', withdrawnOffers);
|
||||||
BIN
server/dump/admin/system.version.bson
Executable file
BIN
server/dump/admin/system.version.bson
Executable file
Binary file not shown.
1
server/dump/admin/system.version.metadata.json
Executable file
1
server/dump/admin/system.version.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"daaa08c4bcf54161b9f06c5fc2d402d1","collectionName":"system.version"}
|
||||||
0
server/dump/exchange/acceptedoffers.bson
Executable file
0
server/dump/exchange/acceptedoffers.bson
Executable file
1
server/dump/exchange/acceptedoffers.metadata.json
Executable file
1
server/dump/exchange/acceptedoffers.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"},{"v":{"$numberInt":"2"},"unique":true,"key":{"offers.offerId":{"$numberInt":"1"}},"name":"offers.offerId_1","background":true},{"v":{"$numberInt":"2"},"unique":true,"key":{"offerId":{"$numberInt":"1"}},"name":"offerId_1","background":true}],"uuid":"8703dc2b5f5d4567a568d80817b56afa","collectionName":"acceptedoffers"}
|
||||||
BIN
server/dump/exchange/activeoffers.bson
Executable file
BIN
server/dump/exchange/activeoffers.bson
Executable file
Binary file not shown.
1
server/dump/exchange/activeoffers.metadata.json
Executable file
1
server/dump/exchange/activeoffers.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"},{"v":{"$numberInt":"2"},"unique":true,"key":{"userId":{"$numberInt":"1"}},"name":"userId_1","background":true},{"v":{"$numberInt":"2"},"unique":true,"key":{"offerId":{"$numberInt":"1"}},"name":"offerId_1","background":true}],"uuid":"fc4244e986a5438f87685af69e958898","collectionName":"activeoffers"}
|
||||||
BIN
server/dump/exchange/admins.bson
Executable file
BIN
server/dump/exchange/admins.bson
Executable file
Binary file not shown.
1
server/dump/exchange/admins.metadata.json
Executable file
1
server/dump/exchange/admins.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"},{"v":{"$numberInt":"2"},"unique":true,"key":{"email":{"$numberInt":"1"}},"name":"email_1","background":true}],"uuid":"19571896da2b47d98703ab79ffe3d1f5","collectionName":"admins"}
|
||||||
BIN
server/dump/exchange/currencies.bson
Executable file
BIN
server/dump/exchange/currencies.bson
Executable file
Binary file not shown.
1
server/dump/exchange/currencies.metadata.json
Executable file
1
server/dump/exchange/currencies.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"},{"v":{"$numberInt":"2"},"unique":true,"key":{"name":{"$numberInt":"1"}},"name":"name_1","background":true},{"v":{"$numberInt":"2"},"unique":true,"key":{"per_name":{"$numberInt":"1"}},"name":"per_name_1","background":true},{"v":{"$numberInt":"2"},"unique":true,"key":{"ab_name":{"$numberInt":"1"}},"name":"ab_name_1","background":true}],"uuid":"17d5a5198d0147478e485f1a6e60cfef","collectionName":"currencies"}
|
||||||
0
server/dump/exchange/getprices.bson
Executable file
0
server/dump/exchange/getprices.bson
Executable file
1
server/dump/exchange/getprices.metadata.json
Executable file
1
server/dump/exchange/getprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"},{"v":{"$numberInt":"2"},"key":{"createdAt":{"$numberInt":"1"}},"name":"createdAt_1","expireAfterSeconds":{"$numberInt":"20"},"background":true}],"uuid":"1b7d90c9468e4d4d8ae0d09010c118fd","collectionName":"getprices"}
|
||||||
BIN
server/dump/exchange/globaldailyprices.bson
Executable file
BIN
server/dump/exchange/globaldailyprices.bson
Executable file
Binary file not shown.
1
server/dump/exchange/globaldailyprices.metadata.json
Executable file
1
server/dump/exchange/globaldailyprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"1b7b7f5c1c474ab28210a6c0c16725a6","collectionName":"globaldailyprices"}
|
||||||
BIN
server/dump/exchange/globalhourlyprices.bson
Executable file
BIN
server/dump/exchange/globalhourlyprices.bson
Executable file
Binary file not shown.
1
server/dump/exchange/globalhourlyprices.metadata.json
Executable file
1
server/dump/exchange/globalhourlyprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"d36a7159cd864b2e8ce904964d7c91ff","collectionName":"globalhourlyprices"}
|
||||||
BIN
server/dump/exchange/globalmonthlyprices.bson
Executable file
BIN
server/dump/exchange/globalmonthlyprices.bson
Executable file
Binary file not shown.
1
server/dump/exchange/globalmonthlyprices.metadata.json
Executable file
1
server/dump/exchange/globalmonthlyprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"f804694693924d74bc73518bfffc61e8","collectionName":"globalmonthlyprices"}
|
||||||
BIN
server/dump/exchange/globalweeklyprices.bson
Executable file
BIN
server/dump/exchange/globalweeklyprices.bson
Executable file
Binary file not shown.
1
server/dump/exchange/globalweeklyprices.metadata.json
Executable file
1
server/dump/exchange/globalweeklyprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"beb258360afa44a39fca27c3ed669858","collectionName":"globalweeklyprices"}
|
||||||
BIN
server/dump/exchange/globalyearlyprices.bson
Executable file
BIN
server/dump/exchange/globalyearlyprices.bson
Executable file
Binary file not shown.
1
server/dump/exchange/globalyearlyprices.metadata.json
Executable file
1
server/dump/exchange/globalyearlyprices.metadata.json
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"indexes":[{"v":{"$numberInt":"2"},"key":{"_id":{"$numberInt":"1"}},"name":"_id_"}],"uuid":"f9f208ef081748199e70b442bf74143f","collectionName":"globalyearlyprices"}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user