@unchainedshop/plugins 1.2.36 → 2.0.0-beta1

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.
Files changed (94) hide show
  1. package/lib/files/gridfs/gridfs-webhook.js +1 -1
  2. package/lib/files/gridfs/gridfs-webhook.js.map +1 -1
  3. package/lib/files/minio/minio-webhook.js +1 -1
  4. package/lib/files/minio/minio-webhook.js.map +1 -1
  5. package/lib/payment/apple-iap/adapter.js +1 -1
  6. package/lib/payment/apple-iap/adapter.js.map +1 -1
  7. package/lib/payment/bity/adapter.js +2 -2
  8. package/lib/payment/bity/adapter.js.map +1 -1
  9. package/lib/payment/cryptopay/db/CryptopayTransactions.d.ts +13 -0
  10. package/lib/payment/cryptopay/db/CryptopayTransactions.js +4 -0
  11. package/lib/payment/cryptopay/db/CryptopayTransactions.js.map +1 -0
  12. package/lib/payment/cryptopay/index.d.ts +5 -0
  13. package/lib/payment/cryptopay/index.js +6 -0
  14. package/lib/payment/cryptopay/index.js.map +1 -0
  15. package/lib/payment/{cryptopay.d.ts → cryptopay/middleware.d.ts} +0 -0
  16. package/lib/payment/cryptopay/middleware.js +79 -0
  17. package/lib/payment/cryptopay/middleware.js.map +1 -0
  18. package/lib/payment/cryptopay/module/configureCryptopayModule.d.ts +25 -0
  19. package/lib/payment/cryptopay/module/configureCryptopayModule.js +75 -0
  20. package/lib/payment/cryptopay/module/configureCryptopayModule.js.map +1 -0
  21. package/lib/payment/cryptopay/plugin.d.ts +3 -0
  22. package/lib/payment/cryptopay/plugin.js +201 -0
  23. package/lib/payment/cryptopay/plugin.js.map +1 -0
  24. package/lib/payment/datatrans-v2/middleware.js +1 -1
  25. package/lib/payment/datatrans-v2/middleware.js.map +1 -1
  26. package/lib/payment/postfinance-checkout/middleware.js +1 -1
  27. package/lib/payment/postfinance-checkout/middleware.js.map +1 -1
  28. package/lib/pricing/product-catalog-price.js.map +1 -1
  29. package/lib/pricing/product-price-rateconversion.js +23 -17
  30. package/lib/pricing/product-price-rateconversion.js.map +1 -1
  31. package/lib/pricing/product-price-round.js +2 -1
  32. package/lib/pricing/product-price-round.js.map +1 -1
  33. package/lib/warehousing/google-sheets.js +3 -2
  34. package/lib/warehousing/google-sheets.js.map +1 -1
  35. package/lib/{pricing/product-price-ECB-interbank-exchange.d.ts → warehousing/infinite-minter.d.ts} +0 -0
  36. package/lib/warehousing/infinite-minter.js +50 -0
  37. package/lib/warehousing/infinite-minter.js.map +1 -0
  38. package/lib/warehousing/store.js +2 -1
  39. package/lib/warehousing/store.js.map +1 -1
  40. package/lib/worker/BulkImportWorker.js +2 -3
  41. package/lib/worker/BulkImportWorker.js.map +1 -1
  42. package/lib/worker/ZombieKillerWorker.js +2 -3
  43. package/lib/worker/ZombieKillerWorker.js.map +1 -1
  44. package/lib/worker/email.js.map +1 -1
  45. package/lib/worker/export-token.d.ts +4 -0
  46. package/lib/worker/export-token.js +25 -0
  47. package/lib/worker/export-token.js.map +1 -0
  48. package/lib/worker/external.js +1 -0
  49. package/lib/worker/external.js.map +1 -1
  50. package/lib/{pricing/product-price-coinbase-exchange.d.ts → worker/update-coinbase-rates.d.ts} +0 -0
  51. package/lib/worker/update-coinbase-rates.js +69 -0
  52. package/lib/worker/update-coinbase-rates.js.map +1 -0
  53. package/lib/worker/update-ecb-rates.d.ts +1 -0
  54. package/lib/worker/update-ecb-rates.js +79 -0
  55. package/lib/worker/update-ecb-rates.js.map +1 -0
  56. package/package.json +23 -20
  57. package/src/files/gridfs/gridfs-webhook.ts +1 -1
  58. package/src/files/minio/minio-webhook.js +1 -1
  59. package/src/payment/apple-iap/adapter.ts +1 -1
  60. package/src/payment/bity/adapter.ts +2 -2
  61. package/src/payment/cryptopay/db/CryptopayTransactions.ts +17 -0
  62. package/src/payment/cryptopay/index.ts +8 -0
  63. package/src/payment/cryptopay/middleware.ts +95 -0
  64. package/src/payment/cryptopay/module/configureCryptopayModule.ts +133 -0
  65. package/src/payment/cryptopay/plugin.ts +289 -0
  66. package/src/payment/cryptopay/readme.md +1 -0
  67. package/src/payment/datatrans-v2/middleware.ts +1 -1
  68. package/src/payment/postfinance-checkout/middleware.ts +1 -1
  69. package/src/pricing/product-catalog-price.ts +1 -0
  70. package/src/pricing/product-price-rateconversion.ts +25 -28
  71. package/src/pricing/product-price-round.ts +3 -1
  72. package/src/warehousing/google-sheets.ts +4 -2
  73. package/src/warehousing/infinite-minter.ts +66 -0
  74. package/src/warehousing/store.ts +3 -1
  75. package/src/worker/BulkImportWorker.ts +2 -3
  76. package/src/worker/ZombieKillerWorker.ts +2 -3
  77. package/src/worker/email.ts +0 -1
  78. package/src/worker/export-token.ts +31 -0
  79. package/src/worker/external.ts +1 -0
  80. package/src/worker/update-coinbase-rates.ts +91 -0
  81. package/src/worker/update-ecb-rates.ts +97 -0
  82. package/lib/payment/cryptopay.js +0 -161
  83. package/lib/payment/cryptopay.js.map +0 -1
  84. package/lib/pricing/product-price-ECB-interbank-exchange.js +0 -90
  85. package/lib/pricing/product-price-ECB-interbank-exchange.js.map +0 -1
  86. package/lib/pricing/product-price-coinbase-exchange.js +0 -60
  87. package/lib/pricing/product-price-coinbase-exchange.js.map +0 -1
  88. package/lib/pricing/product-price-cryptopay.d.ts +0 -2
  89. package/lib/pricing/product-price-cryptopay.js +0 -23
  90. package/lib/pricing/product-price-cryptopay.js.map +0 -1
  91. package/src/payment/cryptopay.ts +0 -197
  92. package/src/pricing/product-price-ECB-interbank-exchange.ts +0 -108
  93. package/src/pricing/product-price-coinbase-exchange.ts +0 -82
  94. 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/plugins",
3
- "version": "1.2.36",
3
+ "version": "2.0.0-beta1",
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.64",
68
- "@unchainedshop/api": "^1.2.32",
67
+ "@types/node": "^16.11.66",
68
+ "@unchainedshop/api": "^2.0.0-beta1",
69
69
  "@unchainedshop/client-oauth2": "^4.3.3",
70
- "@unchainedshop/core-delivery": "^1.2.31",
71
- "@unchainedshop/core-enrollments": "^1.2.31",
72
- "@unchainedshop/core-filters": "^1.2.31",
73
- "@unchainedshop/core-messaging": "^1.2.31",
74
- "@unchainedshop/core-orders": "^1.2.32",
75
- "@unchainedshop/core-payment": "^1.2.31",
76
- "@unchainedshop/core-products": "^1.2.31",
77
- "@unchainedshop/core-quotations": "^1.2.31",
78
- "@unchainedshop/core-warehousing": "^1.2.31",
79
- "@unchainedshop/core-worker": "^1.2.31",
80
- "@unchainedshop/events": "^1.2.31",
81
- "@unchainedshop/file-upload": "^1.2.31",
82
- "@unchainedshop/logger": "^1.2.31",
83
- "@unchainedshop/types": "^1.2.32",
84
- "@unchainedshop/utils": "^1.2.31",
70
+ "@unchainedshop/core-delivery": "^2.0.0-beta1",
71
+ "@unchainedshop/core-enrollments": "^2.0.0-beta1",
72
+ "@unchainedshop/core-filters": "^2.0.0-beta1",
73
+ "@unchainedshop/core-messaging": "^2.0.0-beta1",
74
+ "@unchainedshop/core-orders": "^2.0.0-beta1",
75
+ "@unchainedshop/core-payment": "^2.0.0-beta1",
76
+ "@unchainedshop/core-products": "^2.0.0-beta1",
77
+ "@unchainedshop/core-quotations": "^2.0.0-beta1",
78
+ "@unchainedshop/core-warehousing": "^2.0.0-beta1",
79
+ "@unchainedshop/core-worker": "^2.0.0-beta1",
80
+ "@unchainedshop/events": "^2.0.0-beta1",
81
+ "@unchainedshop/file-upload": "^2.0.0-beta1",
82
+ "@unchainedshop/logger": "^2.0.0-beta1",
83
+ "@unchainedshop/types": "^2.0.0-beta1",
84
+ "@unchainedshop/utils": "^2.0.0-beta1",
85
85
  "bluebird": "^3.7.2",
86
86
  "body-parser": "^1.20.0",
87
87
  "event-iterator": "^2.0.0",
88
- "jest": "^29.0.2",
88
+ "jest": "^29.2.1",
89
89
  "JSONStream": "^1.3.5",
90
90
  "minio": "^7.0.32",
91
91
  "mongodb": "^4.10.0",
@@ -94,9 +94,12 @@
94
94
  "open": "^8.4.0",
95
95
  "redis": "^4.3.1",
96
96
  "request": "^2.88.2",
97
- "ts-jest": "^28.0.8",
97
+ "ts-jest": "^29.0.3",
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
  }
@@ -61,6 +61,6 @@ export default (app) =>
61
61
  } catch (e) {
62
62
  log(e.message, { level: LogLevel.Error });
63
63
  res.writeHead(503);
64
- res.end(JSON.stringify(e));
64
+ res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
65
65
  }
66
66
  });
@@ -41,7 +41,7 @@ export default (app) => {
41
41
  } catch (e) {
42
42
  log(e.message, { level: LogLevel.Error });
43
43
  res.writeHead(503);
44
- res.end(JSON.stringify(e));
44
+ res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
45
45
  }
46
46
  });
47
47
  };
@@ -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,8 @@
1
+ import setupCryptopayWebhooks from './middleware';
2
+ import CryptopayPlugin from './plugin';
3
+
4
+ export { configureCryptopayModule } from './module/configureCryptopayModule';
5
+
6
+ export { setupCryptopayWebhooks };
7
+
8
+ export default CryptopayPlugin;
@@ -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
+ };