Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 212 additions & 4 deletions payments/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,216 @@ In order to run test successfully, you will need to have test wallet for which t
Safex payments module can be used as REST service and/or nodeJS module.
- node REST_service.js

# Current steps
- Write tests and be thorough
- Specify API with easy use on FE part
- Implement SSL/TLS on REST service.
Config json is main configuration file for SfxPaymentModule:

Field name | Description
------------ | -------------
nodeRPCPort | RPC Port for local node.
walletRPCPort | RPC port for local safex-wallet-rpc
scanningSpan | Number of blocks to be scanned from the end of blockchain.
listeningPeriod | Time period on which scan is performed
port | Listening port of REST Service

Every REST Service response has error and timestamp field by default. If error field is set to false, there will be result field with targeted data. Otherwise it will be error_msg indicating what was error which happened.
REST Service has next exposed endpoints

>@IMPORTANT: Confirmations are calculated from last block which contains tx linked with given paymentId!!!

### **POST** /getpaymentinfo

##### Description:
*Getting paymentinfo from internal book keeping of payment module. This is roughly around scanningSpan number of blocks.*

##### Request Data:
```json
{ "paymentId" : "a1b2c5d4e5e61236" }
```
##### Response:
```json
{
"error": false,
"result": {
"paymentId": "a1b2c5d4e5e61236",
"confirmations": 178,
"totalAmount": 1500000000000
},
"timestamp": "2018-11-17T22:27:49.000Z"
}
```

### **POST** /getpaymentinfowholebc

##### Description:
*Getting payment info connected to paymentId scaning entire blockchain. Its intended for dispute solving and debugging.*

##### Request Data:

```json{ "paymentId" : "a1b2c5d4e5e61236" }```

##### Response:

```json
{
"error": false,
"result": {
"paymentId": "a1b2c5d4e5e61236",
"confirmations": 179,
"totalAmount": 1500000000000
},
"timestamp": "2018-11-17T22:33:05.506Z"
}
```

### **POST** /getintegratedaddress

##### Description:
*Get integrated address based on given paymentId*

##### Request Data:

```json
{ "paymentId" : "a1b2c5d4e5e61236" }
```

##### Response:

```json
{
"error": false,
"result": {
"integrated_address": "SFXti9o1apCRhgUEU4FVJjBkNS9sarNpbexP6YfZgDYv3bcSVwCZtm9PWnpkoRiifC3uMQJS9ihFmNTbUXr2eWgY7LUMiRvnD3RfTJin1xguGC"
},
"timestamp": "2018-11-17T22:34:40.828Z"
}
```

### **POST** /splitintegratedaddress

##### Description:
*For given integrated address returns paymentId and payment address.*

##### Request Data:

```json
{ "integratedAddress" : "SFXti9o1apCRhgUEU4FVJjBkNS9sarNpbexP6YfZgDYv3bcSVwCZtm9PWnpkoRiifC3uMQJS9ihFmNTbUXr2eWgY7LUMiRvnD3RfTJin1xguGC"
}
```

##### Response:

```json
{
"error": false,
"result": {
"paymentId": "a1b2c5d4e5e61236",
"address": "SFXtzWd5wWCRhgUEU4FVJjBkNS9sarNpbexP6YfZgDYv3bcSVwCZtm9PWnpkoRiifC3uMQJS9ihFmNTbUXr2eWgY7LUMiPBHFgq"
},
"timestamp": "2018-11-17T22:44:41.770Z"
}
```

### **POST** /getpaymentaddress
##### Description:

##### Request Data:
```json {} ```

##### Response:

```json
{
"error": false,
"result": {
"payment_address": "SFXtzWd5wWCRhgUEU4FVJjBkNS9sarNpbexP6YfZgDYv3bcSVwCZtm9PWnpkoRiifC3uMQJS9ihFmNTbUXr2eWgY7LUMiPBHFgq"
},
"timestamp": "2018-11-17T22:35:22.061Z"
}
```


### **POST** /hardforkinfo

##### Description:
*Getting some relevant information regarding hard fork. For more info see https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#hard_fork_info*

##### Request Data:

```json
{}
```

##### Response:

```json
{
"error": false,
"result": {
"enabled": true,
"state": 2,
"status": "OK",
"version": 2
},
"timestamp": "2018-11-17T22:37:14.282Z"
}
```

### **POST** /nodeinfo

##### Description:
*Getting some relevant (filtered) information regarding node. https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_info*

##### Request Data:

```json
{}
```

##### Request Data:

```json
{
"error": false,
"result": {
"height": 45237,
"free_space": 15625752576,
"mainnet": false,
"stagenet": false,
"testnet": true,
"status": "OK",
"start_time": 1542493587
},
"timestamp": "2018-11-17T22:38:00.522Z"
}
```

### **POST** /openwallet

##### Description:
*Wallet file should be located in dir specified when starting walletRPC. Its intended for debugging purposes and for remote activating wallet file. Empty result means success.*

##### Request Data:

```json
{ "filename" : "test.bin", "password" : "cicko" }
```


##### Response:

```json
{
"error": false,
"result": {},
"timestamp": "2018-11-17T22:51:37.838Z"
}
```

### Error example:

```json
{
"error": true,
"error_msg": "API Error: Failed to open wallet",
"timestamp": "2018-11-17T22:56:34.735Z"
}
```
73 changes: 52 additions & 21 deletions payments/REST_service.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,41 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

var express = require("express");
var bodyParser = require('body-parser')
const colors = require('colors');
var router = express.Router()
var cookieParser = require('cookie-parser')
var errorHandler = require('errorhandler')
let express = require("express");
let bodyParser = require('body-parser');
let colors = require('colors');
let cookieParser = require('cookie-parser');
let errorHandler = require('errorhandler');

const https = require("https");
const fs = require("fs");
const helmet = require("helmet");

const config = require('./config');

const options = {
key: fs.readFileSync("./certs/host1.key"),
cert: fs.readFileSync("./certs/host1.cert")
key: fs.readFileSync("./certs/key.pem"),
cert: fs.readFileSync("./certs/cert.pem"),

passphrase : '1234',
requestCert: true,
rejectUnauthorized: true,

ca : [fs.readFileSync('./certs/client-cert.pem')]

};

const sfx_pay = require('./index');

let sfxPayment = new sfx_pay.SafexPayments(config.walletRPCPort, config.nodeRPCPort);
let sfxPayment = new sfx_pay.Payments();
sfxPayment.listenForPayments();

var app = express();
app.use(helmet());
app.use(bodyParser.json());
app.use(cookieParser());
app.use(errorHandler());

const port = 3000;

// Forming REST request.
let form_rest_response = function(result) {
return {
error: false,
Expand All @@ -75,8 +80,12 @@ let form_rest_error = function(err) {

app.post("/getpaymentinfo", function(req,res,next){
if(req.body.paymentId) {
sfxPayment.getPaymentStatusOne(req.body.paymentId).then((result) => {
res.json(form_rest_response(result));
sfxPayment.getPaymentInfo(req.body.paymentId).then((result) => {
res.json(form_rest_response({
paymentId : req.body.paymentId,
confirmations: sfxPayment.bcHeight - result.block_height,
totalAmount: result.total_amount
}));
}).catch((e) => {
res.json(form_rest_error(e));
});
Expand All @@ -90,10 +99,14 @@ app.post("/getpaymentinfo", function(req,res,next){
}
});

app.post("/getpaymentsinfo", function(req,res,next){
if(req.body.paymentIds && req.body.startBlockHeight) {
sfxPayment.getPaymentStatusBulk(req.body.paymentIds, req.body.startBlockHeight).then((result) => {
res.json(form_rest_response(result));
app.post("/getpaymentinfowholebc", function(req,res,next){
if(req.body.paymentId) {
sfxPayment.getPaymentInfoWholeBC(req.body.paymentId).then((result) => {
res.json(form_rest_response({
paymentId : req.body.paymentId,
confirmations: sfxPayment.bcHeight - result[0].block_height,
totalAmount: result[0].total_amount
}));
}).catch((e) => {
res.json(form_rest_error(e));
});
Expand All @@ -110,7 +123,24 @@ app.post("/getpaymentsinfo", function(req,res,next){
app.post("/getintegratedaddress", function(req,res,next){
if(req.body.paymentId) {
sfxPayment.getIntegratedAddress(req.body.paymentId).then((result) => {
res.json(form_rest_response({ integrated_address: result}));
res.json(form_rest_response(result));
}).catch((e) => {
res.json(form_rest_error(e));
});
}
else {
res.json({
error : true,
error_msg: 'Invalid request!',
timestamp: new Date()
})
}
});

app.post("/splitintegratedaddress", function(req,res,next){
if(req.body.integratedAddress) {
sfxPayment.splitIntegratedAddress(req.body.integratedAddress).then((result) => {
res.json(form_rest_response(result));
}).catch((e) => {
res.json(form_rest_error(e));
});
Expand All @@ -136,15 +166,15 @@ app.post("/getpaymentaddress", function(req, res, next){

app.post("/hardforkinfo", function(req, res, next){
sfxPayment.getHardForkInfo().then((result) => {
res.json(form_rest_response({ integrated_address: result}));
res.json(form_rest_response(result));
}).catch((e) => {
res.json(form_rest_error(e));
});
});

app.post("/nodeinfo", function(req, res, next){
sfxPayment.getInfo().then((result) => {
res.json(form_rest_response({ integrated_address: result}));
res.json(form_rest_response(result));
}).catch((e) => {
res.json(form_rest_error(e));
});
Expand Down Expand Up @@ -172,4 +202,5 @@ app.use(function(req, res){
res.json({ error: true, error_msg : 'Not found', timestamp: new Date() });
});

app.listen(port);
https.createServer(options, app).listen(port+1);
10 changes: 6 additions & 4 deletions payments/certs/generate_certs.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/bin/bash

# Sample script to create cert/key pair for SSL/TLS communication.
# Sample script to create cert/key pair for SSL-TLS

openssl genrsa 1024 > host.key
chmod 400 host.key
openssl req -new -x509 -nodes -sha1 -days 365 -key host.key -out host.cert
# Creating key.pem cert.pem
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365

# Client keys
openssl req -x509 -newkey rsa:2048 -keyout client-key.pem -out client-cert.pem -days 365
18 changes: 0 additions & 18 deletions payments/certs/host1.cert

This file was deleted.

Loading