@unchainedshop/plugins 1.2.40 → 2.0.0-beta2
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/lib/files/gridfs/gridfs-webhook.js +1 -1
- package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
- package/lib/files/minio/minio-webhook.js +1 -1
- package/lib/files/minio/minio-webhook.js.map +1 -1
- package/lib/payment/apple-iap/adapter.js +1 -1
- package/lib/payment/apple-iap/adapter.js.map +1 -1
- package/lib/payment/bity/adapter.js +2 -2
- package/lib/payment/bity/adapter.js.map +1 -1
- package/lib/payment/cryptopay/db/CryptopayTransactions.d.ts +13 -0
- package/lib/payment/cryptopay/db/CryptopayTransactions.js +4 -0
- package/lib/payment/cryptopay/db/CryptopayTransactions.js.map +1 -0
- package/lib/payment/cryptopay/index.d.ts +5 -0
- package/lib/payment/cryptopay/index.js +6 -0
- package/lib/payment/cryptopay/index.js.map +1 -0
- package/lib/payment/{cryptopay.d.ts → cryptopay/middleware.d.ts} +0 -0
- package/lib/payment/cryptopay/middleware.js +79 -0
- package/lib/payment/cryptopay/middleware.js.map +1 -0
- package/lib/payment/cryptopay/module/configureCryptopayModule.d.ts +25 -0
- package/lib/payment/cryptopay/module/configureCryptopayModule.js +75 -0
- package/lib/payment/cryptopay/module/configureCryptopayModule.js.map +1 -0
- package/lib/payment/cryptopay/plugin.d.ts +3 -0
- package/lib/payment/cryptopay/plugin.js +201 -0
- package/lib/payment/cryptopay/plugin.js.map +1 -0
- package/lib/payment/datatrans-v2/middleware.js +1 -1
- package/lib/payment/datatrans-v2/middleware.js.map +1 -1
- package/lib/payment/postfinance-checkout/middleware.js +1 -1
- package/lib/payment/postfinance-checkout/middleware.js.map +1 -1
- package/lib/pricing/product-catalog-price.js.map +1 -1
- package/lib/pricing/product-price-rateconversion.js +23 -17
- package/lib/pricing/product-price-rateconversion.js.map +1 -1
- package/lib/pricing/product-price-round.js +3 -4
- package/lib/pricing/product-price-round.js.map +1 -1
- package/lib/pricing/utils/cache.d.ts +2 -1
- package/lib/warehousing/google-sheets.js +3 -2
- package/lib/warehousing/google-sheets.js.map +1 -1
- package/lib/{pricing/product-price-ECB-interbank-exchange.d.ts → warehousing/infinite-minter.d.ts} +0 -0
- package/lib/warehousing/infinite-minter.js +50 -0
- package/lib/warehousing/infinite-minter.js.map +1 -0
- package/lib/warehousing/store.js +2 -1
- package/lib/warehousing/store.js.map +1 -1
- package/lib/worker/BulkImportWorker.js +2 -3
- package/lib/worker/BulkImportWorker.js.map +1 -1
- package/lib/worker/ZombieKillerWorker.js +2 -3
- package/lib/worker/ZombieKillerWorker.js.map +1 -1
- package/lib/worker/email.js.map +1 -1
- package/lib/worker/export-token.d.ts +5 -0
- package/lib/worker/export-token.js +26 -0
- package/lib/worker/export-token.js.map +1 -0
- package/lib/worker/external.js +1 -0
- package/lib/worker/external.js.map +1 -1
- package/lib/{pricing/product-price-coinbase-exchange.d.ts → worker/update-coinbase-rates.d.ts} +0 -0
- package/lib/worker/update-coinbase-rates.js +69 -0
- package/lib/worker/update-coinbase-rates.js.map +1 -0
- package/lib/worker/update-ecb-rates.d.ts +1 -0
- package/lib/worker/update-ecb-rates.js +79 -0
- package/lib/worker/update-ecb-rates.js.map +1 -0
- package/lib/worker/update-token-ownership.d.ts +6 -0
- package/lib/worker/update-token-ownership.js +66 -0
- package/lib/worker/update-token-ownership.js.map +1 -0
- package/package.json +22 -19
- package/src/files/gridfs/gridfs-webhook.ts +1 -1
- package/src/files/minio/minio-webhook.js +1 -1
- package/src/payment/apple-iap/adapter.ts +1 -1
- package/src/payment/bity/adapter.ts +2 -2
- package/src/payment/cryptopay/db/CryptopayTransactions.ts +17 -0
- package/src/payment/cryptopay/index.ts +8 -0
- package/src/payment/cryptopay/middleware.ts +95 -0
- package/src/payment/cryptopay/module/configureCryptopayModule.ts +133 -0
- package/src/payment/cryptopay/plugin.ts +289 -0
- package/src/payment/cryptopay/readme.md +1 -0
- package/src/payment/datatrans-v2/middleware.ts +1 -1
- package/src/payment/postfinance-checkout/middleware.ts +1 -1
- package/src/pricing/product-catalog-price.ts +1 -0
- package/src/pricing/product-price-rateconversion.ts +25 -28
- package/src/pricing/product-price-round.ts +4 -5
- package/src/warehousing/google-sheets.ts +4 -2
- package/src/warehousing/infinite-minter.ts +66 -0
- package/src/warehousing/store.ts +3 -1
- package/src/worker/BulkImportWorker.ts +2 -3
- package/src/worker/ZombieKillerWorker.ts +2 -3
- package/src/worker/email.ts +0 -1
- package/src/worker/export-token.ts +33 -0
- package/src/worker/external.ts +1 -0
- package/src/worker/update-coinbase-rates.ts +91 -0
- package/src/worker/update-ecb-rates.ts +97 -0
- package/src/worker/update-token-ownership.ts +85 -0
- package/lib/payment/cryptopay.js +0 -161
- package/lib/payment/cryptopay.js.map +0 -1
- package/lib/pricing/product-price-ECB-interbank-exchange.js +0 -90
- package/lib/pricing/product-price-ECB-interbank-exchange.js.map +0 -1
- package/lib/pricing/product-price-coinbase-exchange.js +0 -60
- package/lib/pricing/product-price-coinbase-exchange.js.map +0 -1
- package/lib/pricing/product-price-cryptopay.d.ts +0 -2
- package/lib/pricing/product-price-cryptopay.js +0 -23
- package/lib/pricing/product-price-cryptopay.js.map +0 -1
- package/src/payment/cryptopay.ts +0 -197
- package/src/pricing/product-price-ECB-interbank-exchange.ts +0 -108
- package/src/pricing/product-price-coinbase-exchange.ts +0 -82
- package/src/pricing/product-price-cryptopay.ts +0 -27
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { WorkerAdapter, WorkerDirector } from '@unchainedshop/core-worker';
|
|
2
|
+
import later from '@breejs/later';
|
|
3
|
+
import xmlJs from 'xml-js';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
const getExchangeRates = async () => {
|
|
6
|
+
return fetch(`https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml`, {
|
|
7
|
+
method: 'GET',
|
|
8
|
+
})
|
|
9
|
+
.then((res) => res.text())
|
|
10
|
+
.then((text) => JSON.parse(xmlJs.xml2json(text)))
|
|
11
|
+
.then((json) => json.elements?.[0]?.elements
|
|
12
|
+
.filter((e) => e.name.toLowerCase() === 'cube')[0]
|
|
13
|
+
?.elements[0]?.elements.map((element) => element.attributes));
|
|
14
|
+
};
|
|
15
|
+
// https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html
|
|
16
|
+
// CET = UTC + 1
|
|
17
|
+
const everyDayAtFour = later.parse.cron('0 15 * * *');
|
|
18
|
+
const baseCurrency = 'EUR';
|
|
19
|
+
const UpdateECBRates = {
|
|
20
|
+
...WorkerAdapter,
|
|
21
|
+
key: 'shop.unchained.worker.update-ecb-rates',
|
|
22
|
+
label: 'Update ECB Rates',
|
|
23
|
+
version: '1.0',
|
|
24
|
+
type: 'UPDATE_ECB_RATES',
|
|
25
|
+
doWork: async (input, requestContext) => {
|
|
26
|
+
const { modules } = requestContext;
|
|
27
|
+
try {
|
|
28
|
+
const data = await getExchangeRates();
|
|
29
|
+
const timestamp = new Date();
|
|
30
|
+
const expiresAt = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
|
|
31
|
+
const currencies = await modules.currencies.findCurrencies({ includeInactive: true });
|
|
32
|
+
const currencyCodes = currencies.map((currency) => currency.isoCode);
|
|
33
|
+
if (!currencyCodes.includes(baseCurrency))
|
|
34
|
+
return {
|
|
35
|
+
success: true,
|
|
36
|
+
result: {
|
|
37
|
+
ratesUpdated: 0,
|
|
38
|
+
info: 'EUR not enabled',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const rates = data
|
|
42
|
+
.map((d) => {
|
|
43
|
+
return {
|
|
44
|
+
baseCurrency,
|
|
45
|
+
quoteCurrency: d.currency,
|
|
46
|
+
rate: parseFloat(d.rate),
|
|
47
|
+
timestamp,
|
|
48
|
+
expiresAt,
|
|
49
|
+
};
|
|
50
|
+
})
|
|
51
|
+
.filter((rate) => currencyCodes.includes(rate.quoteCurrency) && rate.quoteCurrency !== rate.baseCurrency);
|
|
52
|
+
const success = await modules.products.prices.rates.updateRates(rates);
|
|
53
|
+
return {
|
|
54
|
+
success,
|
|
55
|
+
result: {
|
|
56
|
+
ratesUpdated: rates.length,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: {
|
|
64
|
+
name: 'UPDATE_ECB_RATES_FAILED',
|
|
65
|
+
message: 'Updating ECB Rates failed',
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
WorkerDirector.registerAdapter(UpdateECBRates);
|
|
72
|
+
WorkerDirector.configureAutoscheduling(UpdateECBRates, {
|
|
73
|
+
schedule: everyDayAtFour,
|
|
74
|
+
retries: 5,
|
|
75
|
+
input: () => {
|
|
76
|
+
/* */
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=update-ecb-rates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-ecb-rates.js","sourceRoot":"","sources":["../../src/worker/update-ecb-rates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IWorkerAdapter } from '@unchainedshop/types/worker';
|
|
2
|
+
import { UnchainedCore } from '@unchainedshop/types/core';
|
|
3
|
+
export declare const UpdateTokenOwnership: IWorkerAdapter<void, void>;
|
|
4
|
+
export declare const RefreshTokens: IWorkerAdapter<void, any>;
|
|
5
|
+
export declare const configureUpdateTokenOwnership: (unchainedApi: UnchainedCore) => void;
|
|
6
|
+
export default configureUpdateTokenOwnership;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { WorkerDirector, WorkerAdapter, WorkerEventTypes } from '@unchainedshop/core-worker';
|
|
2
|
+
import later from '@breejs/later';
|
|
3
|
+
const everyMinute = later.parse.cron('* * * * *');
|
|
4
|
+
export const UpdateTokenOwnership = {
|
|
5
|
+
...WorkerAdapter,
|
|
6
|
+
key: 'shop.unchained.worker-plugin.update-token-ownership',
|
|
7
|
+
label: 'External worker to update ownership of provided tokens',
|
|
8
|
+
version: '1.0',
|
|
9
|
+
type: 'UPDATE_TOKEN_OWNERSHIP',
|
|
10
|
+
external: true,
|
|
11
|
+
async doWork() {
|
|
12
|
+
throw new Error('Cannot do work for external workers');
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
export const RefreshTokens = {
|
|
16
|
+
...WorkerAdapter,
|
|
17
|
+
key: 'shop.unchained.worker-plugin.refresh-tokens',
|
|
18
|
+
label: 'Worker to refresh tokens for accounts',
|
|
19
|
+
version: '1.0',
|
|
20
|
+
type: 'REFRESH_TOKENS',
|
|
21
|
+
external: false,
|
|
22
|
+
async doWork(input, requestContext) {
|
|
23
|
+
const { modules } = requestContext;
|
|
24
|
+
const tokens = await modules.warehousing.findTokens({});
|
|
25
|
+
const users = await modules.users.findUsers({ includeGuests: true });
|
|
26
|
+
const accounts = users.flatMap((user) => {
|
|
27
|
+
return user?.services?.web3?.flatMap((service) => {
|
|
28
|
+
if (service.verified)
|
|
29
|
+
return [service.address];
|
|
30
|
+
return [];
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
tokens.forEach((token) => {
|
|
34
|
+
accounts.push(token.walletAddress);
|
|
35
|
+
});
|
|
36
|
+
const forked = await modules.worker.addWork({
|
|
37
|
+
type: 'UPDATE_TOKEN_OWNERSHIP',
|
|
38
|
+
retries: 0,
|
|
39
|
+
input: {
|
|
40
|
+
filter: {
|
|
41
|
+
tokens,
|
|
42
|
+
accounts: [...new Set(accounts)],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}, null);
|
|
46
|
+
return { success: true, result: { forked } };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
export const configureUpdateTokenOwnership = (unchainedApi) => {
|
|
50
|
+
WorkerDirector.events.on(WorkerEventTypes.FINISHED, async ({ work }) => {
|
|
51
|
+
if (work.type === 'UPDATE_TOKEN_OWNERSHIP' && work.success) {
|
|
52
|
+
await Promise.all((work.result?.tokens || []).map(unchainedApi.modules.warehousing.updateTokenOwnership));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export default configureUpdateTokenOwnership;
|
|
57
|
+
WorkerDirector.registerAdapter(RefreshTokens);
|
|
58
|
+
WorkerDirector.registerAdapter(UpdateTokenOwnership);
|
|
59
|
+
WorkerDirector.configureAutoscheduling(RefreshTokens, {
|
|
60
|
+
schedule: everyMinute,
|
|
61
|
+
retries: 5,
|
|
62
|
+
input: () => {
|
|
63
|
+
/* */
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=update-token-ownership.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-token-ownership.js","sourceRoot":"","sources":["../../src/worker/update-token-ownership.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/plugins",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta2",
|
|
4
4
|
"main": "lib/plugins-index.js",
|
|
5
5
|
"types": "lib/plugins-index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -64,28 +64,28 @@
|
|
|
64
64
|
},
|
|
65
65
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@types/node": "^16.11.
|
|
68
|
-
"@unchainedshop/api": "^
|
|
67
|
+
"@types/node": "^16.11.68",
|
|
68
|
+
"@unchainedshop/api": "^2.0.0-beta2",
|
|
69
69
|
"@unchainedshop/client-oauth2": "^4.3.3",
|
|
70
|
-
"@unchainedshop/core-delivery": "^
|
|
71
|
-
"@unchainedshop/core-enrollments": "^
|
|
72
|
-
"@unchainedshop/core-filters": "^
|
|
73
|
-
"@unchainedshop/core-messaging": "^
|
|
74
|
-
"@unchainedshop/core-orders": "^
|
|
75
|
-
"@unchainedshop/core-payment": "^
|
|
76
|
-
"@unchainedshop/core-products": "^
|
|
77
|
-
"@unchainedshop/core-quotations": "^
|
|
78
|
-
"@unchainedshop/core-warehousing": "^
|
|
79
|
-
"@unchainedshop/core-worker": "^
|
|
80
|
-
"@unchainedshop/events": "^
|
|
81
|
-
"@unchainedshop/file-upload": "^
|
|
82
|
-
"@unchainedshop/logger": "^
|
|
83
|
-
"@unchainedshop/types": "^
|
|
84
|
-
"@unchainedshop/utils": "^
|
|
70
|
+
"@unchainedshop/core-delivery": "^2.0.0-beta2",
|
|
71
|
+
"@unchainedshop/core-enrollments": "^2.0.0-beta2",
|
|
72
|
+
"@unchainedshop/core-filters": "^2.0.0-beta2",
|
|
73
|
+
"@unchainedshop/core-messaging": "^2.0.0-beta2",
|
|
74
|
+
"@unchainedshop/core-orders": "^2.0.0-beta2",
|
|
75
|
+
"@unchainedshop/core-payment": "^2.0.0-beta2",
|
|
76
|
+
"@unchainedshop/core-products": "^2.0.0-beta2",
|
|
77
|
+
"@unchainedshop/core-quotations": "^2.0.0-beta2",
|
|
78
|
+
"@unchainedshop/core-warehousing": "^2.0.0-beta2",
|
|
79
|
+
"@unchainedshop/core-worker": "^2.0.0-beta2",
|
|
80
|
+
"@unchainedshop/events": "^2.0.0-beta2",
|
|
81
|
+
"@unchainedshop/file-upload": "^2.0.0-beta2",
|
|
82
|
+
"@unchainedshop/logger": "^2.0.0-beta2",
|
|
83
|
+
"@unchainedshop/types": "^2.0.0-beta2",
|
|
84
|
+
"@unchainedshop/utils": "^2.0.0-beta2",
|
|
85
85
|
"bluebird": "^3.7.2",
|
|
86
86
|
"body-parser": "^1.20.0",
|
|
87
87
|
"event-iterator": "^2.0.0",
|
|
88
|
-
"jest": "^29.2.
|
|
88
|
+
"jest": "^29.2.1",
|
|
89
89
|
"JSONStream": "^1.3.5",
|
|
90
90
|
"minio": "^7.0.32",
|
|
91
91
|
"mongodb": "^4.10.0",
|
|
@@ -98,5 +98,8 @@
|
|
|
98
98
|
"typescript": "^4.8.4",
|
|
99
99
|
"xml-js": "^1.6.11",
|
|
100
100
|
"xml2js": "0.4.23"
|
|
101
|
+
},
|
|
102
|
+
"peerDependencies": {
|
|
103
|
+
"node-fetch": "^2.6.7"
|
|
101
104
|
}
|
|
102
105
|
}
|
|
@@ -219,7 +219,7 @@ export default (app) => {
|
|
|
219
219
|
} catch (e) {
|
|
220
220
|
logger.warn(`Apple IAP Webhook: ${e.message}`, e);
|
|
221
221
|
res.writeHead(503);
|
|
222
|
-
res.end(JSON.stringify(e));
|
|
222
|
+
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
225
|
}
|
|
@@ -205,7 +205,7 @@ export default (app) => {
|
|
|
205
205
|
} catch (e) {
|
|
206
206
|
logger.warn(`Bity Webhook: Failed with ${e.message}`);
|
|
207
207
|
res.writeHead(503);
|
|
208
|
-
res.end(JSON.stringify(e));
|
|
208
|
+
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
209
209
|
return;
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -231,7 +231,7 @@ export default (app) => {
|
|
|
231
231
|
} catch (e) {
|
|
232
232
|
logger.warn(`Bity Webhook: Failed with ${e.message}`);
|
|
233
233
|
res.writeHead(503);
|
|
234
|
-
res.end(JSON.stringify(e));
|
|
234
|
+
res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
237
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Db, TimestampFields, _ID } from '@unchainedshop/types/common';
|
|
2
|
+
import { Decimal128 } from 'mongodb';
|
|
3
|
+
|
|
4
|
+
export type CryptopayTransaction = {
|
|
5
|
+
_id?: _ID;
|
|
6
|
+
blockHeight: number;
|
|
7
|
+
mostRecentBlockHeight: number;
|
|
8
|
+
amount: Decimal128;
|
|
9
|
+
currency: string;
|
|
10
|
+
decimals: number;
|
|
11
|
+
contract: string;
|
|
12
|
+
orderPaymentId?: string;
|
|
13
|
+
} & TimestampFields;
|
|
14
|
+
|
|
15
|
+
export const CryptopayTransactionsCollection = (db: Db) => {
|
|
16
|
+
return db.collection<CryptopayTransaction>('cryptopay_transactions');
|
|
17
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { useMiddlewareWithCurrentContext } from '@unchainedshop/api';
|
|
2
|
+
import bodyParser from 'body-parser';
|
|
3
|
+
import { createLogger } from '@unchainedshop/logger';
|
|
4
|
+
import { Context } from '@unchainedshop/types/api';
|
|
5
|
+
|
|
6
|
+
import { UnchainedCore } from '@unchainedshop/types/core';
|
|
7
|
+
import { OrderStatus } from '@unchainedshop/core-orders';
|
|
8
|
+
import { ProductPriceRate } from '@unchainedshop/types/products.pricing';
|
|
9
|
+
import { CryptopayModule } from './module/configureCryptopayModule';
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
CRYPTOPAY_WEBHOOK_PATH = '/payment/cryptopay',
|
|
13
|
+
CRYPTOPAY_SECRET,
|
|
14
|
+
CRYPTOPAY_MAX_RATE_AGE,
|
|
15
|
+
} = process.env;
|
|
16
|
+
|
|
17
|
+
const logger = createLogger('unchained:core-payment:cryptopay');
|
|
18
|
+
|
|
19
|
+
export default (app: any) => {
|
|
20
|
+
useMiddlewareWithCurrentContext(app, CRYPTOPAY_WEBHOOK_PATH, bodyParser.json());
|
|
21
|
+
useMiddlewareWithCurrentContext(app, CRYPTOPAY_WEBHOOK_PATH, async (req, res) => {
|
|
22
|
+
const resolvedContext = req.unchainedContext as Context;
|
|
23
|
+
const modules = resolvedContext.modules as UnchainedCore['modules'] & { cryptopay: CryptopayModule };
|
|
24
|
+
if (req.method === 'POST') {
|
|
25
|
+
try {
|
|
26
|
+
const { secret, price, wallet, ping } = req.body;
|
|
27
|
+
if (secret !== CRYPTOPAY_SECRET) {
|
|
28
|
+
logger.warn(`Cryptopay Plugin: Invalid Cryptopay Secret provided`);
|
|
29
|
+
throw new Error('Secret invalid');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (wallet) {
|
|
33
|
+
const { address, blockHeight, amount, contract, decimals, currency } = wallet;
|
|
34
|
+
const { orderPaymentId } = await modules.cryptopay.updateWalletAddress({
|
|
35
|
+
addressId: address,
|
|
36
|
+
blockHeight,
|
|
37
|
+
amount,
|
|
38
|
+
contract,
|
|
39
|
+
decimals,
|
|
40
|
+
currency,
|
|
41
|
+
});
|
|
42
|
+
const orderPayment =
|
|
43
|
+
orderPaymentId &&
|
|
44
|
+
(await modules.orders.payments.findOrderPayment({
|
|
45
|
+
orderPaymentId,
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
if (orderPayment) {
|
|
49
|
+
// Try to process order to next status
|
|
50
|
+
const order = await modules.orders.findOrder({ orderId: orderPayment.orderId });
|
|
51
|
+
if (order.status === null) {
|
|
52
|
+
await modules.orders.checkout(order._id, {}, resolvedContext);
|
|
53
|
+
} else if (order.status === OrderStatus.PENDING) {
|
|
54
|
+
await modules.orders.processOrder(order, {}, resolvedContext);
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error('Already processed');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (price) {
|
|
62
|
+
const { baseCurrency, token, rate, timestamp } = price;
|
|
63
|
+
|
|
64
|
+
const timestampDate = new Date(timestamp);
|
|
65
|
+
const expiresAt = new Date(new Date().getTime() + parseInt(CRYPTOPAY_MAX_RATE_AGE, 10) * 1000);
|
|
66
|
+
|
|
67
|
+
const rateData: ProductPriceRate = {
|
|
68
|
+
baseCurrency,
|
|
69
|
+
quoteCurrency: token,
|
|
70
|
+
rate,
|
|
71
|
+
expiresAt,
|
|
72
|
+
timestamp: timestampDate,
|
|
73
|
+
};
|
|
74
|
+
console.log('update rate', price, rateData);
|
|
75
|
+
await resolvedContext.modules.products.prices.rates.updateRates([rateData]);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (ping) {
|
|
79
|
+
const { blockHeight, currency } = ping;
|
|
80
|
+
await modules.cryptopay.updateMostRecentBlock(currency, blockHeight);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
res.writeHead(200);
|
|
84
|
+
res.end(JSON.stringify({ success: true }));
|
|
85
|
+
return;
|
|
86
|
+
} catch (e) {
|
|
87
|
+
res.writeHead(500);
|
|
88
|
+
res.end(JSON.stringify({ success: false, error: e.message }));
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
res.writeHead(404);
|
|
93
|
+
res.end(JSON.stringify({ success: false }));
|
|
94
|
+
});
|
|
95
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Db } from '@unchainedshop/types/common';
|
|
2
|
+
import { Decimal128 } from 'mongodb';
|
|
3
|
+
import { CryptopayTransaction, CryptopayTransactionsCollection } from '../db/CryptopayTransactions';
|
|
4
|
+
|
|
5
|
+
export interface CryptopayModule {
|
|
6
|
+
getWalletAddress: (addressId: string) => Promise<CryptopayTransaction>;
|
|
7
|
+
getWalletAddressesByOrderPaymentId: (orderPaymentId: string) => Promise<CryptopayTransaction[]>;
|
|
8
|
+
updateMostRecentBlock: (currency: string, blockHeight: number) => Promise<void>;
|
|
9
|
+
updateWalletAddress: (walletData: {
|
|
10
|
+
addressId: string;
|
|
11
|
+
blockHeight: number;
|
|
12
|
+
amount: string;
|
|
13
|
+
contract: string;
|
|
14
|
+
currency: string;
|
|
15
|
+
decimals: number;
|
|
16
|
+
}) => Promise<CryptopayTransaction>;
|
|
17
|
+
mapOrderPaymentToWalletAddress: (walletData: {
|
|
18
|
+
addressId: string;
|
|
19
|
+
contract: string;
|
|
20
|
+
currency: string;
|
|
21
|
+
orderPaymentId: string;
|
|
22
|
+
}) => Promise<CryptopayTransaction>;
|
|
23
|
+
getNextDerivationNumber: (currency: string) => Promise<number>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const configureCryptopayModule = ({ db }: { db: Db }): CryptopayModule => {
|
|
27
|
+
const CryptoTransactions = CryptopayTransactionsCollection(db);
|
|
28
|
+
|
|
29
|
+
const getWalletAddress: CryptopayModule['getWalletAddress'] = async (addressId) => {
|
|
30
|
+
return CryptoTransactions.findOne({ _id: addressId });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const updateMostRecentBlock: CryptopayModule['updateMostRecentBlock'] = async (
|
|
34
|
+
currency,
|
|
35
|
+
blockHeight,
|
|
36
|
+
) => {
|
|
37
|
+
await CryptoTransactions.updateMany(
|
|
38
|
+
{
|
|
39
|
+
currency,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
$set: {
|
|
43
|
+
mostRecentBlockHeight: blockHeight,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const mapOrderPaymentToWalletAddress: CryptopayModule['mapOrderPaymentToWalletAddress'] = async ({
|
|
50
|
+
addressId,
|
|
51
|
+
contract,
|
|
52
|
+
currency,
|
|
53
|
+
orderPaymentId,
|
|
54
|
+
}) => {
|
|
55
|
+
await CryptoTransactions.updateOne(
|
|
56
|
+
{
|
|
57
|
+
_id: addressId,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
$setOnInsert: {
|
|
61
|
+
_id: addressId,
|
|
62
|
+
contract,
|
|
63
|
+
currency,
|
|
64
|
+
decimals: null,
|
|
65
|
+
mostRecentBlockHeight: 0,
|
|
66
|
+
blockHeight: 0,
|
|
67
|
+
amount: Decimal128.fromString('0'),
|
|
68
|
+
created: new Date(),
|
|
69
|
+
},
|
|
70
|
+
$set: {
|
|
71
|
+
orderPaymentId,
|
|
72
|
+
updated: new Date(),
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{ upsert: true },
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return CryptoTransactions.findOne({ _id: addressId });
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const getNextDerivationNumber: CryptopayModule['getNextDerivationNumber'] = async (currency) => {
|
|
82
|
+
return (await CryptoTransactions.countDocuments({ currency })) + 1;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const getWalletAddressesByOrderPaymentId: CryptopayModule['getWalletAddressesByOrderPaymentId'] =
|
|
86
|
+
async (orderPaymentId) => {
|
|
87
|
+
return CryptoTransactions.find({
|
|
88
|
+
orderPaymentId,
|
|
89
|
+
}).toArray();
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const updateWalletAddress: CryptopayModule['updateWalletAddress'] = async ({
|
|
93
|
+
addressId,
|
|
94
|
+
blockHeight,
|
|
95
|
+
amount,
|
|
96
|
+
contract,
|
|
97
|
+
currency,
|
|
98
|
+
decimals,
|
|
99
|
+
}) => {
|
|
100
|
+
await CryptoTransactions.updateOne(
|
|
101
|
+
{
|
|
102
|
+
_id: addressId,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
$setOnInsert: {
|
|
106
|
+
_id: addressId,
|
|
107
|
+
currency,
|
|
108
|
+
contract,
|
|
109
|
+
created: new Date(),
|
|
110
|
+
},
|
|
111
|
+
$set: {
|
|
112
|
+
decimals,
|
|
113
|
+
blockHeight,
|
|
114
|
+
mostRecentBlockHeight: blockHeight,
|
|
115
|
+
amount: Decimal128.fromString(amount),
|
|
116
|
+
updated: new Date(),
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{ upsert: true },
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return CryptoTransactions.findOne({ _id: addressId });
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
getWalletAddress,
|
|
127
|
+
updateMostRecentBlock,
|
|
128
|
+
updateWalletAddress,
|
|
129
|
+
mapOrderPaymentToWalletAddress,
|
|
130
|
+
getNextDerivationNumber,
|
|
131
|
+
getWalletAddressesByOrderPaymentId,
|
|
132
|
+
};
|
|
133
|
+
};
|