-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.js
More file actions
118 lines (103 loc) · 3.41 KB
/
handler.js
File metadata and controls
118 lines (103 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'use strict';
const AWS = require('aws-sdk');
const ccxt = require('ccxt');
const axios = require('axios');
function publishSNS(result) {
const topicArn = process.env.NOTIFY_TOPIC_ARN || 'arn:aws:sns:ap-southeast-1:156969275739:NOTIFY_CLIENT_APP';
const sns = new AWS.SNS();
const snsParams = {
Message: JSON.stringify(result),
Subject: "SNS from Transaction Lambda",
TopicArn: topicArn
};
sns.publish(snsParams, context.done);
}
module.exports.transaction = async (event, context) => {
const actionSNS = event.Records[0].Sns.TopicArn;
// SNS has single record only https://stackoverflow.com/questions/33690231/when-lambda-is-invoked-by-sns-will-there-always-be-just-1-record
// requires jobId in Message
const jobId = event.Records[0].Sns.Message;
const serviceBase = process.env.KEY_SERVICE_BASE_URL || 'http://pair.service.thinblock.io/';
const jobBase = process.env.JOBS_SERVICE_BASE_URL || 'http://jobs.service.thinblock.io/';
const result = {
jobId,
event: '',
data: ''
}
const jobURL = `${jobBase}jobs/${jobId}?look_up=_id`;
const { data: { actions } } = await axios.get(jobURL);
// find appropriate action in job
let actionIndex = -1;
actions.forEach((element, index) => {
if (element.action.sns_topic_arn === actionSNS) {
actionIndex = index;
}
});
if (actionIndex = -1) {
// Couldn't find appropriate action in job
result.event = null;
result.data = {
status: 'failed',
error_message: 'transaction_failed: action not found in job'
}
publishSNS(result);
return;
}
const { params, action } = actions[actionIndex];
result.event = action.name;
if (params.user_id === undefined || params.exchange === undefined ||
params.symbol === undefined || params.side === undefined ||
params.amount === undefined || params.price === undefined) {
result.data = {
status: 'failed',
error_message: 'transaction_failed: Requires user_id, exchange, symbol, side, amount, price'
}
publishSNS(result);
return;
}
const user = params.user_id;
const exchangeName = params.exchange;
let { symbol, side, amount, price } = params;
let order = null;
try {
const serviceURL = `${serviceBase}pairs?user_id=${user}&exchange=${exchangeName}`;
const { key, secret } = (await axios.get(serviceURL)).data;
const exchangeId = exchangeName
, exchangeClass = ccxt[exchangeId]
, exchange = new exchangeClass ({
'apiKey': key,
'secret': secret,
'timeout': 30000,
'enableRateLimit': true,
});
await exchange.loadMarkets();
amount = exchange.amountToPrecision(symbol, amount);
price = exchange.priceToPrecision(symbol, price);
if (side === 'buy') {
order = await exchange.createLimitBuyOrder(symbol, amount, price, { test: true });
} else if (side === 'sell') {
order = await exchange.createLimitSellOrder(symbol, amount, price, { test: true });
} else {
result.data = {
status: 'failed',
error_message: 'transaction_failed: side should be "buy" or "sell"'
}
publishSNS(result);
return;
}
result.data = {
status: 'success',
message: 'transaction_completed: success - please verify order',
data: {
order: order
}
}
publishSNS(result);
return;
} catch (e) {
console.log(e);
result.data = 'transaction_failed: Error';
publishSNS(result);
return;
}
};