b5-api-client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nvmrc +1 -0
- package/README.md +99 -0
- package/dist/APITester.d.ts +1 -0
- package/dist/APITester.js +142 -0
- package/dist/BolsilloArgentoAPIClient.d.ts +19 -0
- package/dist/BolsilloArgentoAPIClient.js +200 -0
- package/dist/P2PMarketplaceAPIClient.d.ts +19 -0
- package/dist/P2PMarketplaceAPIClient.js +200 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.js +2 -0
- package/package.json +26 -0
- package/src/APITester.ts +132 -0
- package/src/P2PMarketplaceAPIClient.ts +184 -0
- package/src/index.ts +2 -0
- package/src/types.ts +140 -0
- package/tsconfig.json +14 -0
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
18
|
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# P2P stablecoin marketplace
|
|
2
|
+
|
|
3
|
+
Peer 2 Peer stablecoin marketplace
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
You can install the package via npm:
|
|
8
|
+
|
|
9
|
+
`npm install b5-api-client@0.0.1 `
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
First, import and initialize the `P2PMarketplaceAPIClient`:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { P2PMarketplaceAPIClient } from "b5-api-client";
|
|
17
|
+
const BASE_URL = "https://bolsillo-argento-586dfd80364d.herokuapp.com";
|
|
18
|
+
const client = new P2PMarketplaceAPIClient(BASE_URL);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## API
|
|
22
|
+
|
|
23
|
+
### `getOrders(status?: OrderStatus, headers?: Record<string, string>): Promise<OrderResponse>`
|
|
24
|
+
|
|
25
|
+
Fetches a list of orders with an optional status filter.
|
|
26
|
+
|
|
27
|
+
**Parameters:**
|
|
28
|
+
|
|
29
|
+
- `status` (optional): The status of the orders to fetch.
|
|
30
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
31
|
+
|
|
32
|
+
**Returns:**
|
|
33
|
+
|
|
34
|
+
- A promise that resolves to an `OrderResponse` object.
|
|
35
|
+
|
|
36
|
+
### `getOrderById(id: string, headers?: Record<string, string>): Promise<OrderResponse>`
|
|
37
|
+
|
|
38
|
+
Fetches an order by its ID.
|
|
39
|
+
|
|
40
|
+
**Parameters:**
|
|
41
|
+
|
|
42
|
+
- `id`: The ID of the order to fetch.
|
|
43
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
44
|
+
|
|
45
|
+
**Returns:**
|
|
46
|
+
|
|
47
|
+
- A promise that resolves to an `OrderResponse` object.
|
|
48
|
+
|
|
49
|
+
### `createOrder(order: CreateOrderRequest, headers?: Record<string, string>): Promise<OrderResponse>`
|
|
50
|
+
|
|
51
|
+
Creates a new order.
|
|
52
|
+
|
|
53
|
+
**Parameters:**
|
|
54
|
+
|
|
55
|
+
- `order`: The order details.
|
|
56
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
57
|
+
|
|
58
|
+
**Returns:**
|
|
59
|
+
|
|
60
|
+
- A promise that resolves to the created `OrderResponse` object.
|
|
61
|
+
|
|
62
|
+
### `takeOrder(order: TakeOrderRequest, headers?: Record<string, string>): Promise<Order>`
|
|
63
|
+
|
|
64
|
+
Takes an order.
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
|
|
68
|
+
- `order`: The order details, which can be either `TakeSellOrderRequest` or `TakeBuyOrderRequest`.
|
|
69
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
70
|
+
|
|
71
|
+
**Returns:**
|
|
72
|
+
|
|
73
|
+
- A promise that resolves to the taken `Order` object.
|
|
74
|
+
|
|
75
|
+
### `createUser(user: CreateUserRequest, headers?: Record<string, string>): Promise<Order>`
|
|
76
|
+
|
|
77
|
+
Creates a new user.
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
|
|
81
|
+
- `user`: The user details.
|
|
82
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
83
|
+
|
|
84
|
+
**Returns:**
|
|
85
|
+
|
|
86
|
+
- A promise that resolves to the created `Order` object.
|
|
87
|
+
|
|
88
|
+
### `updateOrder(updateRequest: UpdateOrderRequest, headers?: Record<string, string>): Promise<Order>`
|
|
89
|
+
|
|
90
|
+
Updates an order's status.
|
|
91
|
+
|
|
92
|
+
**Parameters:**
|
|
93
|
+
|
|
94
|
+
- `updateRequest`: The update request details.
|
|
95
|
+
- `headers` (optional): Additional headers to include in the request.
|
|
96
|
+
|
|
97
|
+
**Returns:**
|
|
98
|
+
|
|
99
|
+
- A promise that resolves to the updated `Order` object.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const P2PMarketplaceAPIClient_1 = __importDefault(require("./P2PMarketplaceAPIClient"));
|
|
17
|
+
const BASE_URL = 'https://bolsillo-argento-586dfd80364d.herokuapp.com'; // Replace with your actual base URL
|
|
18
|
+
// const BASE_URL = 'http://localhost:8080'; // Replace with your actual base URL
|
|
19
|
+
const client = new P2PMarketplaceAPIClient_1.default(BASE_URL);
|
|
20
|
+
function runTest(testFunction) {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
try {
|
|
23
|
+
yield testFunction();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
27
|
+
console.error('Error message:', error.message);
|
|
28
|
+
if (error.response) {
|
|
29
|
+
console.error('Response status:', error.response.status);
|
|
30
|
+
console.error('Response data:', error.response.data);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.error('Unexpected error:', error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function testHealthCheck() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const response = yield client.get('/api/health_check');
|
|
42
|
+
console.log('Status:', response);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function testGetOrders() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const response = yield client.getOrders({ status: ['PENDING'] });
|
|
48
|
+
console.log('Orders:', response);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function testGetOrderById() {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
const orderId = '168434dc-546c-497b-a125-0fb15f364511'; // Replace with a valid order ID
|
|
54
|
+
const response = yield client.getOrderById(orderId, {
|
|
55
|
+
'x-api-secret': 'test',
|
|
56
|
+
'x-blockchain': 'rsk_testnet'
|
|
57
|
+
});
|
|
58
|
+
console.log('Order:', response);
|
|
59
|
+
// console.log('Data:', response.data);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function testCreateOrder() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const order = {
|
|
65
|
+
type: 'SELL',
|
|
66
|
+
description: 'Test full flow ts',
|
|
67
|
+
amount: '0.023',
|
|
68
|
+
tokenCode: 'RBTC',
|
|
69
|
+
fiatAmount: '232323',
|
|
70
|
+
status: "PENDING",
|
|
71
|
+
fiatCode: 'ARS',
|
|
72
|
+
paymentMethods: [
|
|
73
|
+
{
|
|
74
|
+
type: 'MERCADO_PAGO',
|
|
75
|
+
username: 'blas'
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
creatorId: '7b74abef-f1b2-4431-aa95-ce565893d47c'
|
|
79
|
+
};
|
|
80
|
+
const response = yield client.createOrder(order, {
|
|
81
|
+
'x-api-secret': 'test',
|
|
82
|
+
'x-blockchain': 'rsk_testnet'
|
|
83
|
+
});
|
|
84
|
+
console.log('Data:', response);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function testTakeOrder() {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
const takeOrderRequest = {
|
|
90
|
+
type: "SELL",
|
|
91
|
+
orderId: 'f18ffa7c-83bb-4b0c-a96c-e64c8f536c51',
|
|
92
|
+
userId: 'd41724af-aa3d-4184-8fa2-479db5f00660',
|
|
93
|
+
buyerAddress: '0x25DFBA06A227a6AAf5d29ED48437A23405F9FbFf',
|
|
94
|
+
fiatAmount: "60000"
|
|
95
|
+
};
|
|
96
|
+
const response = yield client.takeOrder(takeOrderRequest, {
|
|
97
|
+
'x-api-secret': 'test',
|
|
98
|
+
'x-blockchain': 'rsk_testnet'
|
|
99
|
+
});
|
|
100
|
+
console.log('Order Taken:', response);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function testCreateUser() {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
const user = {
|
|
106
|
+
username: "username_test"
|
|
107
|
+
};
|
|
108
|
+
const response = yield client.createUser(user);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function testUpdateOrder() {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
const updateOrderRequest = {
|
|
114
|
+
status: 'FIAT_SENT',
|
|
115
|
+
orderId: '643eac58-8dd4-44e5-99d4-fe779a581b58' // Replace with a valid order ID
|
|
116
|
+
};
|
|
117
|
+
const response = yield client.updateOrder(updateOrderRequest, {
|
|
118
|
+
'x-api-secret': 'test',
|
|
119
|
+
'x-blockchain': 'rsk_testnet'
|
|
120
|
+
});
|
|
121
|
+
console.log('Order Updated:', response);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function runTests() {
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
// console.log('Testing Health Check...');
|
|
127
|
+
// await runTest(testHealthCheck);
|
|
128
|
+
// console.log('Testing Get Orders...');
|
|
129
|
+
// await runTest(testGetOrders);
|
|
130
|
+
// console.log('Testing Create Order...');
|
|
131
|
+
// await runTest(testCreateOrder);
|
|
132
|
+
// console.log('Testing Get Order By ID...');
|
|
133
|
+
// await runTest(testGetOrderById);
|
|
134
|
+
// console.log('Testing Take Order...');
|
|
135
|
+
// await runTest(testTakeOrder);
|
|
136
|
+
// console.log('Testing Create User...');
|
|
137
|
+
// await runTest(testCreateUser);
|
|
138
|
+
// console.log('Testing Update Order...');
|
|
139
|
+
// await runTest(testUpdateOrder);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// runTests();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CreateOrderRequest, CreateUserRequest, GetOrdersParams, Order, OrderResponse, TakeOrderRequest, TestEventParams, UpdateOrderRequest } from './types';
|
|
2
|
+
declare class BolsilloArgentoAPIClient {
|
|
3
|
+
private readonly client;
|
|
4
|
+
private readonly defaultHeaders;
|
|
5
|
+
constructor(baseURL: string, timeout?: number);
|
|
6
|
+
private mergeHeaders;
|
|
7
|
+
private createConfig;
|
|
8
|
+
get<T>(url: string, headers?: Record<string, string>): Promise<T>;
|
|
9
|
+
post<T>(url: string, data: any, headers?: Record<string, string>): Promise<T>;
|
|
10
|
+
getOrders(props: GetOrdersParams, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
11
|
+
getOrderById(id: string, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
12
|
+
createOrder(order: CreateOrderRequest, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
13
|
+
takeOrder(order: TakeOrderRequest, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
14
|
+
createUser(user: CreateUserRequest, headers?: Record<string, string>): Promise<Order>;
|
|
15
|
+
updateOrder(updateRequest: UpdateOrderRequest, headers?: Record<string, string>): Promise<Order>;
|
|
16
|
+
testLockFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
17
|
+
testReleaseFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export default BolsilloArgentoAPIClient;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const lodash_1 = require("lodash");
|
|
17
|
+
class BolsilloArgentoAPIClient {
|
|
18
|
+
constructor(baseURL, timeout = 30000) {
|
|
19
|
+
this.client = axios_1.default.create({
|
|
20
|
+
baseURL,
|
|
21
|
+
timeout,
|
|
22
|
+
});
|
|
23
|
+
this.defaultHeaders = {
|
|
24
|
+
'x-api-secret': 'test',
|
|
25
|
+
'x-blockchain': 'rsk_testnet'
|
|
26
|
+
};
|
|
27
|
+
// Add a request interceptor to transform request data to snake_case
|
|
28
|
+
this.client.interceptors.request.use((config) => {
|
|
29
|
+
if (config.data) {
|
|
30
|
+
config.data = toSnakeCase(config.data);
|
|
31
|
+
}
|
|
32
|
+
return config;
|
|
33
|
+
}, (error) => {
|
|
34
|
+
return Promise.reject(error);
|
|
35
|
+
});
|
|
36
|
+
// Add a response interceptor to transform response data to camelCase
|
|
37
|
+
this.client.interceptors.response.use((response) => {
|
|
38
|
+
if (response.data) {
|
|
39
|
+
response.data = toCamelCase(response.data);
|
|
40
|
+
}
|
|
41
|
+
return response;
|
|
42
|
+
}, (error) => {
|
|
43
|
+
return Promise.reject(error);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
mergeHeaders(customHeaders) {
|
|
47
|
+
return Object.assign(Object.assign({}, this.defaultHeaders), customHeaders);
|
|
48
|
+
}
|
|
49
|
+
createConfig(headers) {
|
|
50
|
+
return {
|
|
51
|
+
headers: this.mergeHeaders(headers)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
get(url, headers) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const config = this.createConfig(headers);
|
|
57
|
+
try {
|
|
58
|
+
const response = yield this.client.get(url, config);
|
|
59
|
+
return response.data;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error(`GET request to ${url} failed:`, error);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
post(url, data, headers) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const config = this.createConfig(headers);
|
|
70
|
+
try {
|
|
71
|
+
const response = yield this.client.post(url, data, config);
|
|
72
|
+
return response.data;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(`POST request to ${url} failed:`, error);
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
getOrders(props, headers) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
const { status, user, buyer } = props;
|
|
83
|
+
const params = new URLSearchParams();
|
|
84
|
+
if (status)
|
|
85
|
+
params.append('status', status.join(','));
|
|
86
|
+
if (user)
|
|
87
|
+
params.append('user', user);
|
|
88
|
+
if (buyer)
|
|
89
|
+
params.append('buyer', buyer);
|
|
90
|
+
const url = `/api/orders?${params.toString()}`;
|
|
91
|
+
return this.get(url, headers);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
getOrderById(id, headers) {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const url = `/api/orders/${id}`;
|
|
97
|
+
return this.get(url, headers);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
createOrder(order, headers) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
const url = '/api/orders';
|
|
103
|
+
return this.post(url, order, headers);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
takeOrder(order, headers) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
const url = '/api/orders/take';
|
|
109
|
+
return this.post(url, order, headers);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
createUser(user, headers) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const url = '/api/users';
|
|
115
|
+
return this.post(url, user, headers);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
updateOrder(updateRequest, headers) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const url = '/api/orders/update';
|
|
121
|
+
return this.post(url, updateRequest, headers);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
testLockFunds(order, testParams, headers) {
|
|
125
|
+
var _a, _b, _c, _d;
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const orderEvent = {
|
|
128
|
+
type: "LOCKED",
|
|
129
|
+
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
130
|
+
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
131
|
+
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
132
|
+
transaction: {
|
|
133
|
+
hash: "0x976d8c61b958e286d907a2e1c5ffde8c9316800ab4de1396a54927a39dc533a2",
|
|
134
|
+
},
|
|
135
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
136
|
+
buyerHash: "02809d5cc2ec09a7503ef77358654a5bfc958e08c04ecb33f412884c0933be68",
|
|
137
|
+
sellerAddress: "0x2A4E89D18C2742FEDC65444d339cC5fAF3dE4dF1",
|
|
138
|
+
sellerHash: "4b3560738b8e3cb8a0a30ac664b12de2ace977c62ade94bc08a37fe5b93bf34b",
|
|
139
|
+
fee: "30000000000000000",
|
|
140
|
+
timestamp: new Date().toISOString(),
|
|
141
|
+
};
|
|
142
|
+
const url = "api/events/simulate/lock";
|
|
143
|
+
try {
|
|
144
|
+
yield this.post(url, orderEvent, headers);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error("Error locking funds:", error);
|
|
148
|
+
throw new Error("Failed to lock funds");
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
testReleaseFunds(order, testParams, headers) {
|
|
153
|
+
var _a, _b, _c, _d;
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
const releaseOrderEvent = {
|
|
156
|
+
type: "RELEASED",
|
|
157
|
+
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
158
|
+
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
159
|
+
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
160
|
+
transaction: {
|
|
161
|
+
hash: "0xeab4797bf0e13dff0bda481503a544698127c5f97dd826c465ebdb41bcfec3f5",
|
|
162
|
+
},
|
|
163
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
164
|
+
adminAction: true,
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
};
|
|
167
|
+
const url = "api/events/simulate/release";
|
|
168
|
+
try {
|
|
169
|
+
yield this.post(url, releaseOrderEvent, headers);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error("Error releasing funds:", error);
|
|
173
|
+
throw new Error("Failed to release funds");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function toSnakeCase(obj) {
|
|
179
|
+
if (Array.isArray(obj)) {
|
|
180
|
+
return obj.map(toSnakeCase);
|
|
181
|
+
}
|
|
182
|
+
else if ((0, lodash_1.isPlainObject)(obj)) {
|
|
183
|
+
return (0, lodash_1.transform)(obj, (result, value, key) => {
|
|
184
|
+
result[(0, lodash_1.snakeCase)(key)] = toSnakeCase(value);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return obj;
|
|
188
|
+
}
|
|
189
|
+
function toCamelCase(obj) {
|
|
190
|
+
if (Array.isArray(obj)) {
|
|
191
|
+
return obj.map(toCamelCase);
|
|
192
|
+
}
|
|
193
|
+
else if ((0, lodash_1.isPlainObject)(obj)) {
|
|
194
|
+
return (0, lodash_1.transform)(obj, (result, value, key) => {
|
|
195
|
+
result[(0, lodash_1.camelCase)(key)] = toCamelCase(value);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return obj;
|
|
199
|
+
}
|
|
200
|
+
exports.default = BolsilloArgentoAPIClient;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CreateOrderRequest, CreateUserRequest, GetOrdersParams, Order, OrderResponse, TakeOrderRequest, TestEventParams, UpdateOrderRequest } from './types';
|
|
2
|
+
declare class P2PMarketplaceAPIClient {
|
|
3
|
+
private readonly client;
|
|
4
|
+
private readonly defaultHeaders;
|
|
5
|
+
constructor(baseURL: string, timeout?: number);
|
|
6
|
+
private mergeHeaders;
|
|
7
|
+
private createConfig;
|
|
8
|
+
get<T>(url: string, headers?: Record<string, string>): Promise<T>;
|
|
9
|
+
post<T>(url: string, data: any, headers?: Record<string, string>): Promise<T>;
|
|
10
|
+
getOrders(props: GetOrdersParams, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
11
|
+
getOrderById(id: string, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
12
|
+
createOrder(order: CreateOrderRequest, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
13
|
+
takeOrder(order: TakeOrderRequest, headers?: Record<string, string>): Promise<OrderResponse>;
|
|
14
|
+
createUser(user: CreateUserRequest, headers?: Record<string, string>): Promise<Order>;
|
|
15
|
+
updateOrder(updateRequest: UpdateOrderRequest, headers?: Record<string, string>): Promise<Order>;
|
|
16
|
+
testLockFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
17
|
+
testReleaseFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export default P2PMarketplaceAPIClient;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const lodash_1 = require("lodash");
|
|
17
|
+
class P2PMarketplaceAPIClient {
|
|
18
|
+
constructor(baseURL, timeout = 30000) {
|
|
19
|
+
this.client = axios_1.default.create({
|
|
20
|
+
baseURL,
|
|
21
|
+
timeout,
|
|
22
|
+
});
|
|
23
|
+
this.defaultHeaders = {
|
|
24
|
+
'x-api-secret': 'test',
|
|
25
|
+
'x-blockchain': 'rsk_testnet'
|
|
26
|
+
};
|
|
27
|
+
// Add a request interceptor to transform request data to snake_case
|
|
28
|
+
this.client.interceptors.request.use((config) => {
|
|
29
|
+
if (config.data) {
|
|
30
|
+
config.data = toSnakeCase(config.data);
|
|
31
|
+
}
|
|
32
|
+
return config;
|
|
33
|
+
}, (error) => {
|
|
34
|
+
return Promise.reject(error);
|
|
35
|
+
});
|
|
36
|
+
// Add a response interceptor to transform response data to camelCase
|
|
37
|
+
this.client.interceptors.response.use((response) => {
|
|
38
|
+
if (response.data) {
|
|
39
|
+
response.data = toCamelCase(response.data);
|
|
40
|
+
}
|
|
41
|
+
return response;
|
|
42
|
+
}, (error) => {
|
|
43
|
+
return Promise.reject(error);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
mergeHeaders(customHeaders) {
|
|
47
|
+
return Object.assign(Object.assign({}, this.defaultHeaders), customHeaders);
|
|
48
|
+
}
|
|
49
|
+
createConfig(headers) {
|
|
50
|
+
return {
|
|
51
|
+
headers: this.mergeHeaders(headers)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
get(url, headers) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const config = this.createConfig(headers);
|
|
57
|
+
try {
|
|
58
|
+
const response = yield this.client.get(url, config);
|
|
59
|
+
return response.data;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error(`GET request to ${url} failed:`, error);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
post(url, data, headers) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const config = this.createConfig(headers);
|
|
70
|
+
try {
|
|
71
|
+
const response = yield this.client.post(url, data, config);
|
|
72
|
+
return response.data;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error(`POST request to ${url} failed:`, error);
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
getOrders(props, headers) {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
const { status, user, buyer } = props;
|
|
83
|
+
const params = new URLSearchParams();
|
|
84
|
+
if (status)
|
|
85
|
+
params.append('status', status.join(','));
|
|
86
|
+
if (user)
|
|
87
|
+
params.append('user', user);
|
|
88
|
+
if (buyer)
|
|
89
|
+
params.append('buyer', buyer);
|
|
90
|
+
const url = `/api/orders?${params.toString()}`;
|
|
91
|
+
return this.get(url, headers);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
getOrderById(id, headers) {
|
|
95
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const url = `/api/orders/${id}`;
|
|
97
|
+
return this.get(url, headers);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
createOrder(order, headers) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
const url = '/api/orders';
|
|
103
|
+
return this.post(url, order, headers);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
takeOrder(order, headers) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
const url = '/api/orders/take';
|
|
109
|
+
return this.post(url, order, headers);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
createUser(user, headers) {
|
|
113
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
const url = '/api/users';
|
|
115
|
+
return this.post(url, user, headers);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
updateOrder(updateRequest, headers) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const url = '/api/orders/update';
|
|
121
|
+
return this.post(url, updateRequest, headers);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
testLockFunds(order, testParams, headers) {
|
|
125
|
+
var _a, _b, _c, _d;
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const orderEvent = {
|
|
128
|
+
type: "LOCKED",
|
|
129
|
+
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
130
|
+
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
131
|
+
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
132
|
+
transaction: {
|
|
133
|
+
hash: "0x976d8c61b958e286d907a2e1c5ffde8c9316800ab4de1396a54927a39dc533a2",
|
|
134
|
+
},
|
|
135
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
136
|
+
buyerHash: "02809d5cc2ec09a7503ef77358654a5bfc958e08c04ecb33f412884c0933be68",
|
|
137
|
+
sellerAddress: "0x2A4E89D18C2742FEDC65444d339cC5fAF3dE4dF1",
|
|
138
|
+
sellerHash: "4b3560738b8e3cb8a0a30ac664b12de2ace977c62ade94bc08a37fe5b93bf34b",
|
|
139
|
+
fee: "30000000000000000",
|
|
140
|
+
timestamp: new Date().toISOString(),
|
|
141
|
+
};
|
|
142
|
+
const url = "api/events/simulate/lock";
|
|
143
|
+
try {
|
|
144
|
+
yield this.post(url, orderEvent, headers);
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
console.error("Error locking funds:", error);
|
|
148
|
+
throw new Error("Failed to lock funds");
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
testReleaseFunds(order, testParams, headers) {
|
|
153
|
+
var _a, _b, _c, _d;
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
const releaseOrderEvent = {
|
|
156
|
+
type: "RELEASED",
|
|
157
|
+
orderId: (_a = order.id) !== null && _a !== void 0 ? _a : "",
|
|
158
|
+
buyerAddress: (_b = order.buyerAddress) !== null && _b !== void 0 ? _b : "",
|
|
159
|
+
amount: (_d = (_c = order.amount) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : "0",
|
|
160
|
+
transaction: {
|
|
161
|
+
hash: "0xeab4797bf0e13dff0bda481503a544698127c5f97dd826c465ebdb41bcfec3f5",
|
|
162
|
+
},
|
|
163
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
164
|
+
adminAction: true,
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
};
|
|
167
|
+
const url = "api/events/simulate/release";
|
|
168
|
+
try {
|
|
169
|
+
yield this.post(url, releaseOrderEvent, headers);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error("Error releasing funds:", error);
|
|
173
|
+
throw new Error("Failed to release funds");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function toSnakeCase(obj) {
|
|
179
|
+
if (Array.isArray(obj)) {
|
|
180
|
+
return obj.map(toSnakeCase);
|
|
181
|
+
}
|
|
182
|
+
else if ((0, lodash_1.isPlainObject)(obj)) {
|
|
183
|
+
return (0, lodash_1.transform)(obj, (result, value, key) => {
|
|
184
|
+
result[(0, lodash_1.snakeCase)(key)] = toSnakeCase(value);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return obj;
|
|
188
|
+
}
|
|
189
|
+
function toCamelCase(obj) {
|
|
190
|
+
if (Array.isArray(obj)) {
|
|
191
|
+
return obj.map(toCamelCase);
|
|
192
|
+
}
|
|
193
|
+
else if ((0, lodash_1.isPlainObject)(obj)) {
|
|
194
|
+
return (0, lodash_1.transform)(obj, (result, value, key) => {
|
|
195
|
+
result[(0, lodash_1.camelCase)(key)] = toCamelCase(value);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return obj;
|
|
199
|
+
}
|
|
200
|
+
exports.default = P2PMarketplaceAPIClient;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.P2PMarketplaceAPIClient = void 0;
|
|
21
|
+
var P2PMarketplaceAPIClient_1 = require("./P2PMarketplaceAPIClient");
|
|
22
|
+
Object.defineProperty(exports, "P2PMarketplaceAPIClient", { enumerable: true, get: function () { return __importDefault(P2PMarketplaceAPIClient_1).default; } });
|
|
23
|
+
__exportStar(require("./types"), exports);
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export type OrderType = 'SELL' | 'BUY';
|
|
2
|
+
export type OrderStatus = 'WAITING_DEPOSIT' | 'WAITING_BUYER_ADDRESS' | 'PENDING' | 'ACTIVE' | 'FIAT_SENT' | 'RELEASED' | 'CLOSED' | 'DISPUTE' | 'CANCELED' | 'SUCCESS' | 'PAID_HOLD_INVOICE' | 'CANCELED_BY_ADMIN' | 'EXPIRED' | 'COMPLETED_BY_ADMIN';
|
|
3
|
+
export interface PaymentMethod {
|
|
4
|
+
type: string;
|
|
5
|
+
username: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Order {
|
|
8
|
+
type: OrderType;
|
|
9
|
+
id?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
amount?: string;
|
|
12
|
+
fee?: string;
|
|
13
|
+
maxFiatAmount?: string;
|
|
14
|
+
minFiatAmount?: string;
|
|
15
|
+
creatorId?: string;
|
|
16
|
+
sellerId?: string;
|
|
17
|
+
sellerUsername?: string;
|
|
18
|
+
buyerId?: string;
|
|
19
|
+
buyerUsername?: string;
|
|
20
|
+
buyerAddress?: string;
|
|
21
|
+
status?: OrderStatus;
|
|
22
|
+
tokenCode?: string;
|
|
23
|
+
fiatAmount?: string;
|
|
24
|
+
fiatCode: string;
|
|
25
|
+
paymentMethod?: PaymentMethod[];
|
|
26
|
+
createdAt?: string;
|
|
27
|
+
transaction?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface OrderResponse {
|
|
30
|
+
orders: Order[];
|
|
31
|
+
}
|
|
32
|
+
export interface PaymentMethod {
|
|
33
|
+
type: string;
|
|
34
|
+
username: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CreateOrderRequest {
|
|
37
|
+
type: OrderType;
|
|
38
|
+
description: string;
|
|
39
|
+
amount: string;
|
|
40
|
+
tokenCode: string;
|
|
41
|
+
fiatAmount?: string;
|
|
42
|
+
minFiatAmount?: string;
|
|
43
|
+
maxFiatAmount?: string;
|
|
44
|
+
fiatCode: string;
|
|
45
|
+
paymentMethods?: PaymentMethod[];
|
|
46
|
+
status?: OrderStatus;
|
|
47
|
+
priceMargin?: number;
|
|
48
|
+
walletAddress?: string;
|
|
49
|
+
creatorId?: string;
|
|
50
|
+
creatorUsername?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface GetOrdersParams {
|
|
53
|
+
status?: OrderStatus[];
|
|
54
|
+
user?: string;
|
|
55
|
+
buyer?: string;
|
|
56
|
+
}
|
|
57
|
+
export type TakeOrderRequest = TakeSellOrderRequest | TakeBuyOrderRequest;
|
|
58
|
+
export interface TakeSellOrderRequest {
|
|
59
|
+
type: string;
|
|
60
|
+
orderId: string;
|
|
61
|
+
userId: string;
|
|
62
|
+
buyerAddress?: string;
|
|
63
|
+
fiatAmount?: string;
|
|
64
|
+
username?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface TakeBuyOrderRequest {
|
|
67
|
+
type: string;
|
|
68
|
+
orderId: string;
|
|
69
|
+
userId: string;
|
|
70
|
+
amount: string;
|
|
71
|
+
username?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CreateUserRequest {
|
|
74
|
+
username: string;
|
|
75
|
+
}
|
|
76
|
+
export interface UpdateOrderRequest {
|
|
77
|
+
status: string;
|
|
78
|
+
orderId: string;
|
|
79
|
+
}
|
|
80
|
+
export interface OrderLockedEvent {
|
|
81
|
+
type: string;
|
|
82
|
+
orderId: string;
|
|
83
|
+
buyerAddress: string;
|
|
84
|
+
amount?: string;
|
|
85
|
+
transaction?: {
|
|
86
|
+
hash: string;
|
|
87
|
+
};
|
|
88
|
+
tokenContractAddress: string;
|
|
89
|
+
buyerHash: string;
|
|
90
|
+
sellerAddress: string;
|
|
91
|
+
sellerHash: string;
|
|
92
|
+
fee: string;
|
|
93
|
+
timestamp: string;
|
|
94
|
+
}
|
|
95
|
+
export interface ReleaseOrderEvent {
|
|
96
|
+
type: string;
|
|
97
|
+
orderId: string;
|
|
98
|
+
buyerAddress: string;
|
|
99
|
+
amount: string;
|
|
100
|
+
transaction: {
|
|
101
|
+
hash: string;
|
|
102
|
+
};
|
|
103
|
+
tokenContractAddress: string;
|
|
104
|
+
adminAction: boolean;
|
|
105
|
+
timestamp: string;
|
|
106
|
+
}
|
|
107
|
+
export interface TestEventParams {
|
|
108
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "b5-api-client",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Escrow Backend API client",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test:api": "ts-node ./src/APITester.ts"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"axios": "^0.21.4",
|
|
13
|
+
"https-proxy-agent": "^7.0.5",
|
|
14
|
+
"lodash": "^4.17.21"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/axios": "^0.14.0",
|
|
18
|
+
"@types/lodash": "^4.17.7",
|
|
19
|
+
"@types/node": "^14.14.10",
|
|
20
|
+
"ts-node": "^10.9.2",
|
|
21
|
+
"typescript": "^4.1.3"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/APITester.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import P2PMarketplaceAPIClient from './P2PMarketplaceAPIClient';
|
|
3
|
+
import { CreateOrderRequest, CreateUserRequest, OrderStatus, TakeSellOrderRequest, UpdateOrderRequest } from './types';
|
|
4
|
+
|
|
5
|
+
const BASE_URL = 'https://bolsillo-argento-586dfd80364d.herokuapp.com'; // Replace with your actual base URL
|
|
6
|
+
// const BASE_URL = 'http://localhost:8080'; // Replace with your actual base URL
|
|
7
|
+
const client = new P2PMarketplaceAPIClient(BASE_URL);
|
|
8
|
+
|
|
9
|
+
async function runTest(testFunction: () => Promise<void>) {
|
|
10
|
+
try {
|
|
11
|
+
await testFunction();
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (axios.isAxiosError(error)) {
|
|
14
|
+
console.error('Error message:', error.message);
|
|
15
|
+
if (error.response) {
|
|
16
|
+
console.error('Response status:', error.response.status);
|
|
17
|
+
console.error('Response data:', error.response.data);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
console.error('Unexpected error:', error);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function testHealthCheck() {
|
|
26
|
+
const response = await client.get<{ status: string }>('/api/health_check');
|
|
27
|
+
console.log('Status:', response);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function testGetOrders() {
|
|
31
|
+
const response = await client.getOrders({ status: ['PENDING'] });
|
|
32
|
+
console.log('Orders:', response)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function testGetOrderById() {
|
|
36
|
+
const orderId = '168434dc-546c-497b-a125-0fb15f364511'; // Replace with a valid order ID
|
|
37
|
+
const response = await client.getOrderById(orderId, {
|
|
38
|
+
'x-api-secret': 'test',
|
|
39
|
+
'x-blockchain': 'rsk_testnet'
|
|
40
|
+
});
|
|
41
|
+
console.log('Order:', response);
|
|
42
|
+
// console.log('Data:', response.data);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function testCreateOrder() {
|
|
46
|
+
const order: CreateOrderRequest = {
|
|
47
|
+
type: 'SELL',
|
|
48
|
+
description: 'Test full flow ts',
|
|
49
|
+
amount: '0.023',
|
|
50
|
+
tokenCode: 'RBTC',
|
|
51
|
+
fiatAmount: '232323',
|
|
52
|
+
status: "PENDING",
|
|
53
|
+
fiatCode: 'ARS',
|
|
54
|
+
paymentMethods: [
|
|
55
|
+
{
|
|
56
|
+
type: 'MERCADO_PAGO',
|
|
57
|
+
username: 'blas'
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
creatorId: '7b74abef-f1b2-4431-aa95-ce565893d47c'
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const response = await client.createOrder(order, {
|
|
64
|
+
'x-api-secret': 'test',
|
|
65
|
+
'x-blockchain': 'rsk_testnet'
|
|
66
|
+
});
|
|
67
|
+
console.log('Data:', response);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function testTakeOrder() {
|
|
71
|
+
const takeOrderRequest: TakeSellOrderRequest = {
|
|
72
|
+
type: "SELL",
|
|
73
|
+
orderId: 'f18ffa7c-83bb-4b0c-a96c-e64c8f536c51', // Replace with a valid order ID
|
|
74
|
+
userId: 'd41724af-aa3d-4184-8fa2-479db5f00660', // Replace with a valid user ID
|
|
75
|
+
buyerAddress: '0x25DFBA06A227a6AAf5d29ED48437A23405F9FbFf',
|
|
76
|
+
fiatAmount: "60000"
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const response = await client.takeOrder(takeOrderRequest, {
|
|
80
|
+
'x-api-secret': 'test',
|
|
81
|
+
'x-blockchain': 'rsk_testnet'
|
|
82
|
+
});
|
|
83
|
+
console.log('Order Taken:', response);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function testCreateUser() {
|
|
87
|
+
const user: CreateUserRequest = {
|
|
88
|
+
username: "username_test"
|
|
89
|
+
}
|
|
90
|
+
const response = await client.createUser(user);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function testUpdateOrder() {
|
|
94
|
+
const updateOrderRequest: UpdateOrderRequest = {
|
|
95
|
+
status: 'FIAT_SENT',
|
|
96
|
+
orderId: '643eac58-8dd4-44e5-99d4-fe779a581b58' // Replace with a valid order ID
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const response = await client.updateOrder(updateOrderRequest, {
|
|
100
|
+
'x-api-secret': 'test',
|
|
101
|
+
'x-blockchain': 'rsk_testnet'
|
|
102
|
+
});
|
|
103
|
+
console.log('Order Updated:', response);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async function runTests() {
|
|
108
|
+
|
|
109
|
+
// console.log('Testing Health Check...');
|
|
110
|
+
// await runTest(testHealthCheck);
|
|
111
|
+
|
|
112
|
+
// console.log('Testing Get Orders...');
|
|
113
|
+
// await runTest(testGetOrders);
|
|
114
|
+
|
|
115
|
+
// console.log('Testing Create Order...');
|
|
116
|
+
// await runTest(testCreateOrder);
|
|
117
|
+
|
|
118
|
+
// console.log('Testing Get Order By ID...');
|
|
119
|
+
// await runTest(testGetOrderById);
|
|
120
|
+
|
|
121
|
+
// console.log('Testing Take Order...');
|
|
122
|
+
// await runTest(testTakeOrder);
|
|
123
|
+
|
|
124
|
+
// console.log('Testing Create User...');
|
|
125
|
+
// await runTest(testCreateUser);
|
|
126
|
+
|
|
127
|
+
// console.log('Testing Update Order...');
|
|
128
|
+
// await runTest(testUpdateOrder);
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// runTests();
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
|
+
import { CreateOrderRequest, CreateUserRequest, GetOrdersParams, Order, OrderLockedEvent, OrderResponse, ReleaseOrderEvent as OrderReleasedEvent, TakeOrderRequest, TestEventParams, UpdateOrderRequest } from './types';
|
|
3
|
+
import { isPlainObject, camelCase, snakeCase, transform } from 'lodash';
|
|
4
|
+
|
|
5
|
+
class P2PMarketplaceAPIClient {
|
|
6
|
+
private readonly client: AxiosInstance;
|
|
7
|
+
private readonly defaultHeaders: Record<string, string>;
|
|
8
|
+
|
|
9
|
+
constructor(baseURL: string, timeout: number = 30000) {
|
|
10
|
+
this.client = axios.create({
|
|
11
|
+
baseURL,
|
|
12
|
+
timeout,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
this.defaultHeaders = {
|
|
16
|
+
'x-api-secret': 'test',
|
|
17
|
+
'x-blockchain': 'rsk_testnet'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Add a request interceptor to transform request data to snake_case
|
|
21
|
+
this.client.interceptors.request.use((config) => {
|
|
22
|
+
if (config.data) {
|
|
23
|
+
config.data = toSnakeCase(config.data);
|
|
24
|
+
}
|
|
25
|
+
return config;
|
|
26
|
+
}, (error) => {
|
|
27
|
+
return Promise.reject(error);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Add a response interceptor to transform response data to camelCase
|
|
31
|
+
this.client.interceptors.response.use((response) => {
|
|
32
|
+
if (response.data) {
|
|
33
|
+
response.data = toCamelCase(response.data);
|
|
34
|
+
}
|
|
35
|
+
return response;
|
|
36
|
+
}, (error) => {
|
|
37
|
+
return Promise.reject(error);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private mergeHeaders(customHeaders?: Record<string, string>): Record<string, string> {
|
|
42
|
+
return { ...this.defaultHeaders, ...customHeaders };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private createConfig(headers?: Record<string, string>): AxiosRequestConfig {
|
|
46
|
+
return {
|
|
47
|
+
headers: this.mergeHeaders(headers)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async get<T>(url: string, headers?: Record<string, string>): Promise<T> {
|
|
52
|
+
const config = this.createConfig(headers);
|
|
53
|
+
try {
|
|
54
|
+
const response = await this.client.get<T>(url, config);
|
|
55
|
+
return response.data;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(`GET request to ${url} failed:`, error);
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async post<T>(url: string, data: any, headers?: Record<string, string>): Promise<T> {
|
|
63
|
+
const config = this.createConfig(headers);
|
|
64
|
+
try {
|
|
65
|
+
const response = await this.client.post<T>(url, data, config);
|
|
66
|
+
return response.data;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`POST request to ${url} failed:`, error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async getOrders(props: GetOrdersParams, headers?: Record<string, string>): Promise<OrderResponse> {
|
|
74
|
+
const { status, user, buyer } = props;
|
|
75
|
+
const params = new URLSearchParams();
|
|
76
|
+
if (status) params.append('status', status.join(','));
|
|
77
|
+
if (user) params.append('user', user);
|
|
78
|
+
if (buyer) params.append('buyer', buyer);
|
|
79
|
+
|
|
80
|
+
const url = `/api/orders?${params.toString()}`;
|
|
81
|
+
return this.get<OrderResponse>(url, headers);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async getOrderById(id: string, headers?: Record<string, string>): Promise<OrderResponse> {
|
|
85
|
+
const url = `/api/orders/${id}`;
|
|
86
|
+
return this.get<OrderResponse>(url, headers);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public async createOrder(order: CreateOrderRequest, headers?: Record<string, string>): Promise<OrderResponse> {
|
|
90
|
+
const url = '/api/orders';
|
|
91
|
+
return this.post<OrderResponse>(url, order, headers);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public async takeOrder(order: TakeOrderRequest, headers?: Record<string, string>): Promise<OrderResponse> {
|
|
95
|
+
const url = '/api/orders/take';
|
|
96
|
+
return this.post<OrderResponse>(url, order, headers);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public async createUser(user: CreateUserRequest, headers?: Record<string, string>): Promise<Order> {
|
|
100
|
+
const url = '/api/users';
|
|
101
|
+
return this.post<Order>(url, user, headers);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public async updateOrder(updateRequest: UpdateOrderRequest, headers?: Record<string, string>): Promise<Order> {
|
|
105
|
+
const url = '/api/orders/update';
|
|
106
|
+
return this.post<Order>(url, updateRequest, headers);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public async testLockFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>) {
|
|
110
|
+
const orderEvent: OrderLockedEvent = {
|
|
111
|
+
type: "LOCKED",
|
|
112
|
+
orderId: order.id ?? "",
|
|
113
|
+
buyerAddress: order.buyerAddress ?? "",
|
|
114
|
+
amount: order.amount?.toString() ?? "0",
|
|
115
|
+
transaction: {
|
|
116
|
+
hash: "0x976d8c61b958e286d907a2e1c5ffde8c9316800ab4de1396a54927a39dc533a2",
|
|
117
|
+
},
|
|
118
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
119
|
+
buyerHash:
|
|
120
|
+
"02809d5cc2ec09a7503ef77358654a5bfc958e08c04ecb33f412884c0933be68",
|
|
121
|
+
sellerAddress: "0x2A4E89D18C2742FEDC65444d339cC5fAF3dE4dF1",
|
|
122
|
+
sellerHash:
|
|
123
|
+
"4b3560738b8e3cb8a0a30ac664b12de2ace977c62ade94bc08a37fe5b93bf34b",
|
|
124
|
+
fee: "30000000000000000",
|
|
125
|
+
timestamp: new Date().toISOString(),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const url = "api/events/simulate/lock"
|
|
129
|
+
try {
|
|
130
|
+
await this.post<undefined>(url, orderEvent, headers);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error("Error locking funds:", error);
|
|
133
|
+
throw new Error("Failed to lock funds");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public async testReleaseFunds(order: Order, testParams?: TestEventParams, headers?: Record<string, string>) {
|
|
138
|
+
const releaseOrderEvent: OrderReleasedEvent = {
|
|
139
|
+
type: "RELEASED",
|
|
140
|
+
orderId: order.id ?? "",
|
|
141
|
+
buyerAddress: order.buyerAddress ?? "",
|
|
142
|
+
amount: order.amount?.toString() ?? "0",
|
|
143
|
+
transaction: {
|
|
144
|
+
hash: "0xeab4797bf0e13dff0bda481503a544698127c5f97dd826c465ebdb41bcfec3f5",
|
|
145
|
+
},
|
|
146
|
+
tokenContractAddress: "0xee5e8291b551603a19ef41eea69ae49592ed14f8",
|
|
147
|
+
adminAction: true,
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const url = "api/events/simulate/release"
|
|
152
|
+
try {
|
|
153
|
+
await this.post<undefined>(url, releaseOrderEvent, headers);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error("Error releasing funds:", error);
|
|
156
|
+
throw new Error("Failed to release funds");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function toSnakeCase(obj: any): any {
|
|
163
|
+
if (Array.isArray(obj)) {
|
|
164
|
+
return obj.map(toSnakeCase);
|
|
165
|
+
} else if (isPlainObject(obj)) {
|
|
166
|
+
return transform(obj, (result, value, key) => {
|
|
167
|
+
result[snakeCase(key as string)] = toSnakeCase(value);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return obj;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function toCamelCase(obj: any): any {
|
|
174
|
+
if (Array.isArray(obj)) {
|
|
175
|
+
return obj.map(toCamelCase);
|
|
176
|
+
} else if (isPlainObject(obj)) {
|
|
177
|
+
return transform(obj, (result, value, key) => {
|
|
178
|
+
result[camelCase(key as string)] = toCamelCase(value);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return obj;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export default P2PMarketplaceAPIClient;
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export type OrderType = 'SELL' | 'BUY';
|
|
2
|
+
|
|
3
|
+
export type OrderStatus =
|
|
4
|
+
'WAITING_DEPOSIT' |
|
|
5
|
+
'WAITING_BUYER_ADDRESS' |
|
|
6
|
+
'PENDING' |
|
|
7
|
+
'ACTIVE' |
|
|
8
|
+
'FIAT_SENT' |
|
|
9
|
+
'RELEASED' |
|
|
10
|
+
'CLOSED' |
|
|
11
|
+
'DISPUTE' |
|
|
12
|
+
'CANCELED' |
|
|
13
|
+
'SUCCESS' |
|
|
14
|
+
'PAID_HOLD_INVOICE' |
|
|
15
|
+
'CANCELED_BY_ADMIN' |
|
|
16
|
+
'EXPIRED' |
|
|
17
|
+
'COMPLETED_BY_ADMIN';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export interface PaymentMethod {
|
|
21
|
+
type: string;
|
|
22
|
+
username: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Order {
|
|
26
|
+
type: OrderType;
|
|
27
|
+
id?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
amount?: string;
|
|
30
|
+
fee?: string;
|
|
31
|
+
maxFiatAmount?: string;
|
|
32
|
+
minFiatAmount?: string;
|
|
33
|
+
creatorId?: string;
|
|
34
|
+
sellerId?: string;
|
|
35
|
+
sellerUsername?: string;
|
|
36
|
+
buyerId?: string;
|
|
37
|
+
buyerUsername?: string;
|
|
38
|
+
buyerAddress?: string;
|
|
39
|
+
status?: OrderStatus;
|
|
40
|
+
tokenCode?: string;
|
|
41
|
+
fiatAmount?: string;
|
|
42
|
+
fiatCode: string;
|
|
43
|
+
paymentMethod?: PaymentMethod[];
|
|
44
|
+
createdAt?: string; // ISO 8601 string
|
|
45
|
+
transaction?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface OrderResponse {
|
|
49
|
+
orders: Order[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface PaymentMethod {
|
|
53
|
+
type: string;
|
|
54
|
+
username: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface CreateOrderRequest {
|
|
58
|
+
type: OrderType;
|
|
59
|
+
description: string;
|
|
60
|
+
amount: string;
|
|
61
|
+
tokenCode: string;
|
|
62
|
+
fiatAmount?: string;
|
|
63
|
+
minFiatAmount?: string;
|
|
64
|
+
maxFiatAmount?: string;
|
|
65
|
+
fiatCode: string;
|
|
66
|
+
paymentMethods?: PaymentMethod[];
|
|
67
|
+
status?: OrderStatus;
|
|
68
|
+
priceMargin?: number;
|
|
69
|
+
walletAddress?: string;
|
|
70
|
+
creatorId?: string;
|
|
71
|
+
creatorUsername?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface GetOrdersParams {
|
|
75
|
+
status?: OrderStatus[];
|
|
76
|
+
user?: string;
|
|
77
|
+
buyer?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type TakeOrderRequest = TakeSellOrderRequest | TakeBuyOrderRequest;
|
|
81
|
+
|
|
82
|
+
export interface TakeSellOrderRequest {
|
|
83
|
+
type: string;
|
|
84
|
+
orderId: string;
|
|
85
|
+
userId: string;
|
|
86
|
+
buyerAddress?: string;
|
|
87
|
+
fiatAmount?: string;
|
|
88
|
+
username?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface TakeBuyOrderRequest {
|
|
92
|
+
type: string;
|
|
93
|
+
orderId: string;
|
|
94
|
+
userId: string;
|
|
95
|
+
amount: string;
|
|
96
|
+
username?: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface CreateUserRequest {
|
|
100
|
+
username: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface UpdateOrderRequest {
|
|
104
|
+
status: string;
|
|
105
|
+
orderId: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface OrderLockedEvent {
|
|
109
|
+
type: string;
|
|
110
|
+
orderId: string;
|
|
111
|
+
buyerAddress: string;
|
|
112
|
+
amount?: string;
|
|
113
|
+
transaction?: {
|
|
114
|
+
hash: string;
|
|
115
|
+
};
|
|
116
|
+
tokenContractAddress: string;
|
|
117
|
+
buyerHash: string;
|
|
118
|
+
sellerAddress: string;
|
|
119
|
+
sellerHash: string;
|
|
120
|
+
fee: string;
|
|
121
|
+
timestamp: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
export interface ReleaseOrderEvent {
|
|
126
|
+
type: string;
|
|
127
|
+
orderId: string;
|
|
128
|
+
buyerAddress: string;
|
|
129
|
+
amount: string;
|
|
130
|
+
transaction: {
|
|
131
|
+
hash: string;
|
|
132
|
+
};
|
|
133
|
+
tokenContractAddress: string;
|
|
134
|
+
adminAction: boolean;
|
|
135
|
+
timestamp: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface TestEventParams {
|
|
139
|
+
|
|
140
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES6",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"declaration": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src"],
|
|
13
|
+
"exclude": ["dist"]
|
|
14
|
+
}
|