@mojaloop/central-ledger 9.2.2 → 15.1.3-snapshot.2

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 (256) hide show
  1. package/.circleci/config.yml +625 -204
  2. package/.env +3 -2
  3. package/.ncurc.yaml +9 -0
  4. package/.nvmrc +1 -1
  5. package/.versionrc +15 -0
  6. package/CHANGELOG.md +353 -0
  7. package/CODEOWNERS +31 -0
  8. package/Dockerfile +20 -14
  9. package/LICENSE.md +4 -4
  10. package/Onboarding.md +0 -7
  11. package/README.md +99 -22
  12. package/audit-resolve.json +136 -1
  13. package/config/default.json +82 -27
  14. package/docker/central-ledger/default.json +68 -21
  15. package/docker/ml-api-adapter/default.json +10 -1
  16. package/docker/wait-for/wait-for-objstore.sh +1 -6
  17. package/docker/wait-for/wait-for.env +1 -1
  18. package/docker-compose.integration.yml +8 -5
  19. package/docker-compose.yml +73 -16
  20. package/migrations/310203_transferParticipant-indexes.js +38 -0
  21. package/migrations/310503_participantLimit-indexes-composite.js +38 -0
  22. package/migrations/{400401_settlementWindowStateChange-indexes.js → 400401_settlmentWindowStateChange-indexes.js} +0 -0
  23. package/migrations/401301_settlementModel-indexes.js +2 -0
  24. package/migrations/500401_quote-hotfix-2719.js +58 -0
  25. package/migrations/500501_feature-fixSubIdRef.js +53 -0
  26. package/migrations/500601_party-2480.js +63 -0
  27. package/migrations/501001_quoteExtension-quote-service-174.js +46 -0
  28. package/migrations/501002_quoteExtension-2522.js +61 -0
  29. package/migrations/800101_feature-fixSubIdRef.js +90 -0
  30. package/migrations/910102_hotfix954.js +4 -1
  31. package/migrations/940100_quotePartyIdInfoExtension.js +52 -0
  32. package/migrations/940101_quotePartyIdInfoExtension-2522.js +64 -0
  33. package/migrations/950100_settlementContentAggregation-decimal184.js +40 -0
  34. package/migrations/950101_transferParticipantStateChange.js +46 -0
  35. package/migrations/950102_settlementModel-adjustPosition.js +42 -0
  36. package/migrations/950103_dropTransferParticipantStateChange.js +47 -0
  37. package/migrations/950104_settlementModel-settlementAccountTypeId.js +79 -0
  38. package/migrations/950106_unique_settlement_model_ledger_account_currency.js +38 -0
  39. package/migrations/950107_settlementWindowContent_foreign_settlementModel.js +60 -0
  40. package/package.json +99 -81
  41. package/scripts/_wait4_all.js +146 -0
  42. package/seeds/amountType.js +4 -6
  43. package/seeds/balanceOfPayments.js +4 -6
  44. package/seeds/bulkProcessingState.js +4 -6
  45. package/seeds/bulkTransferState.js +4 -6
  46. package/seeds/currency.js +4 -6
  47. package/seeds/endpointType.js +128 -7
  48. package/seeds/ledgerAccountType.js +11 -10
  49. package/seeds/ledgerEntryType.js +5 -7
  50. package/seeds/participant.js +4 -6
  51. package/seeds/participantLimitType.js +4 -6
  52. package/seeds/partyIdentifierType.js +4 -6
  53. package/seeds/partyType.js +4 -6
  54. package/seeds/settlementDelay.js +4 -6
  55. package/seeds/settlementGranularity.js +4 -6
  56. package/seeds/settlementInterchange.js +4 -6
  57. package/seeds/settlementState.js +4 -6
  58. package/seeds/settlementWindow1State.js +4 -6
  59. package/seeds/transactionInitiator.js +4 -6
  60. package/seeds/transactionInitiatorType.js +4 -6
  61. package/seeds/transactionScenario.js +4 -6
  62. package/seeds/transferParticipantRoleType.js +4 -6
  63. package/seeds/transferState.js +9 -6
  64. package/src/api/interface/swagger.json +728 -948
  65. package/src/api/ledgerAccountTypes/handler.js +55 -0
  66. package/src/api/ledgerAccountTypes/routes.js +63 -0
  67. package/src/api/metrics/handler.js +2 -2
  68. package/src/api/metrics/routes.js +1 -1
  69. package/src/api/participants/handler.js +43 -35
  70. package/src/api/participants/routes.js +13 -13
  71. package/src/api/root/routes.js +2 -2
  72. package/src/api/settlementModels/handler.js +9 -26
  73. package/src/api/settlementModels/routes.js +4 -4
  74. package/src/api/transactions/handler.js +46 -0
  75. package/src/api/transactions/routes.js +45 -0
  76. package/src/domain/bulkTransfer/index.js +6 -5
  77. package/src/domain/ledgerAccountTypes/index.js +58 -0
  78. package/src/domain/participant/index.js +55 -4
  79. package/src/domain/position/index.js +18 -2
  80. package/src/domain/settlement/index.js +39 -6
  81. package/src/domain/transactions/index.js +61 -0
  82. package/src/domain/transfer/index.js +22 -2
  83. package/src/domain/transfer/transform.js +3 -3
  84. package/src/handlers/admin/handler.js +24 -32
  85. package/src/handlers/bulk/fulfil/handler.js +89 -56
  86. package/src/handlers/bulk/get/handler.js +203 -0
  87. package/src/handlers/bulk/index.js +4 -1
  88. package/src/handlers/bulk/prepare/handler.js +30 -29
  89. package/src/handlers/bulk/processing/handler.js +61 -32
  90. package/src/handlers/bulk/shared/validator.js +13 -1
  91. package/src/handlers/index.js +18 -9
  92. package/src/handlers/positions/handler.js +67 -46
  93. package/src/handlers/register.js +7 -7
  94. package/src/handlers/timeouts/handler.js +9 -4
  95. package/src/handlers/transfers/handler.js +408 -182
  96. package/src/handlers/transfers/validator.js +41 -11
  97. package/src/lib/cache.js +8 -34
  98. package/src/lib/config.js +5 -7
  99. package/src/lib/enum.js +22 -22
  100. package/src/lib/enumCached.js +76 -0
  101. package/src/lib/healthCheck/subServiceHealth.js +2 -2
  102. package/src/lib/requestLogger.js +9 -9
  103. package/src/lib/urlParser.js +1 -1
  104. package/src/models/bulkTransfer/bulkTransfer.js +6 -6
  105. package/src/models/bulkTransfer/bulkTransferAssociation.js +3 -3
  106. package/src/models/bulkTransfer/bulkTransferDuplicateCheck.js +4 -4
  107. package/src/models/bulkTransfer/bulkTransferExtension.js +2 -2
  108. package/src/models/bulkTransfer/bulkTransferFulfilmentDuplicateCheck.js +4 -4
  109. package/src/models/bulkTransfer/bulkTransferStateChange.js +7 -7
  110. package/src/models/bulkTransfer/facade.js +54 -3
  111. package/src/models/bulkTransfer/individualTransfer.js +2 -2
  112. package/src/models/ilpPackets/ilpPacket.js +36 -0
  113. package/src/models/ledgerAccountType/ledgerAccountType.js +139 -3
  114. package/src/models/misc/migrationLock.js +1 -1
  115. package/src/models/misc/segment.js +1 -1
  116. package/src/models/participant/facade.js +226 -76
  117. package/src/models/participant/participant.js +6 -5
  118. package/src/models/participant/participantCached.js +8 -0
  119. package/src/models/participant/participantCurrency.js +7 -7
  120. package/src/models/participant/participantCurrencyCached.js +11 -1
  121. package/src/models/participant/participantLimit.js +13 -13
  122. package/src/models/participant/participantLimitCached.js +124 -0
  123. package/src/models/participant/participantPosition.js +34 -5
  124. package/src/models/participant/participantPositionChange.js +10 -2
  125. package/src/models/position/facade.js +112 -18
  126. package/src/models/position/participantPosition.js +6 -6
  127. package/src/models/settlement/settlementModel.js +92 -17
  128. package/src/models/settlement/settlementModelCached.js +139 -0
  129. package/src/models/transfer/facade.js +97 -32
  130. package/src/models/transfer/ilpPacket.js +4 -4
  131. package/src/models/transfer/transfer.js +7 -7
  132. package/src/models/transfer/transferDuplicateCheck.js +21 -5
  133. package/src/models/transfer/transferError.js +5 -5
  134. package/src/models/transfer/transferErrorDuplicateCheck.js +4 -4
  135. package/src/models/transfer/transferExtension.js +4 -4
  136. package/src/models/transfer/transferFulfilment.js +5 -5
  137. package/src/models/transfer/transferFulfilmentDuplicateCheck.js +4 -4
  138. package/src/models/transfer/transferParticipant.js +3 -3
  139. package/src/models/transfer/transferStateChange.js +11 -11
  140. package/src/models/transfer/transferTimeout.js +5 -5
  141. package/src/schema/bulkTransfer.js +4 -4
  142. package/src/shared/plugins.js +10 -9
  143. package/src/shared/setup.js +69 -46
  144. package/test/integration/domain/participant/index.test.js +2 -0
  145. package/test/integration/handlers/handlers.test.js +605 -166
  146. package/test/integration/handlers/root.test.js +1 -1
  147. package/test/integration/helpers/hubAccounts.js +62 -0
  148. package/test/integration/helpers/ilpPacket.js +1 -1
  149. package/test/integration/helpers/participantFundsInOut.js +80 -0
  150. package/test/integration/helpers/participantLimit.js +6 -1
  151. package/test/integration/helpers/settlementModels.js +88 -0
  152. package/test/integration/helpers/testConsumer.js +163 -0
  153. package/test/integration/helpers/testProducer.js +0 -1
  154. package/test/integration/helpers/transferDuplicateCheck.js +1 -1
  155. package/test/integration/helpers/transferStateChange.js +1 -1
  156. package/test/integration/helpers/transferTestHelper.js +3 -5
  157. package/test/integration/models/transfer/transferStateChange.test.js +6 -0
  158. package/test/unit/api/ledgerAccountTypes/handler.test.js +126 -0
  159. package/test/unit/api/ledgerAccountTypes/routes.test.js +52 -0
  160. package/test/unit/api/participants/handler.test.js +75 -33
  161. package/test/unit/api/root/handler.test.js +1 -1
  162. package/test/unit/api/root/routes.test.js +2 -2
  163. package/test/unit/api/settlementModels/handler.test.js +21 -57
  164. package/test/unit/api/transactions/handler.test.js +108 -0
  165. package/test/unit/api/transactions/routes.test.js +38 -0
  166. package/test/unit/domain/ledgerAccountTypes/index.test.js +197 -0
  167. package/test/unit/domain/participant/index.test.js +115 -2
  168. package/test/unit/domain/settlement/index.test.js +199 -29
  169. package/test/unit/domain/transactions/index.test.js +128 -0
  170. package/test/unit/domain/transfer/index.test.js +1 -0
  171. package/test/unit/domain/transfer/transform.test.js +2 -0
  172. package/test/unit/handlers/admin/handler.test.js +5 -5
  173. package/test/unit/handlers/bulk/get/handler.test.js +401 -0
  174. package/test/unit/handlers/index.test.js +6 -0
  175. package/test/unit/handlers/positions/handler.test.js +26 -0
  176. package/test/unit/handlers/register.test.js +2 -0
  177. package/test/unit/handlers/transfers/handler.test.js +491 -36
  178. package/test/unit/handlers/transfers/validator.test.js +31 -31
  179. package/test/unit/lib/cache.test.js +0 -64
  180. package/test/unit/lib/cachingOfEnums.test.js +121 -0
  181. package/test/unit/lib/config.test.js +34 -0
  182. package/test/unit/lib/enum.test.js +6 -1
  183. package/test/unit/lib/enumCached.test.js +82 -0
  184. package/test/unit/lib/healthCheck/subServiceHealth.test.js +2 -0
  185. package/test/unit/lib/requestLogger.test.js +14 -12
  186. package/test/unit/models/ilpPackets/ilpPacket.test.js +89 -0
  187. package/test/unit/models/ledgerAccountType/ledgerAccountType.test.js +255 -6
  188. package/test/unit/models/misc/migrationLock.test.js +4 -0
  189. package/test/unit/models/misc/segment.test.js +5 -0
  190. package/test/unit/models/participant/facade.test.js +493 -54
  191. package/test/unit/models/participant/participant.test.js +4 -0
  192. package/test/unit/models/participant/participantCurrency.test.js +22 -9
  193. package/test/unit/models/participant/participantCurrencyCached.test.js +1 -1
  194. package/test/unit/models/participant/participantLimit.test.js +97 -0
  195. package/test/unit/models/participant/participantLimitCached.test.js +232 -0
  196. package/test/unit/models/participant/participantPosition.test.js +217 -0
  197. package/test/unit/models/participant/participantPositionChange.test.js +3 -0
  198. package/test/unit/models/position/facade.test.js +318 -29
  199. package/test/unit/models/position/participantPosition.test.js +22 -7
  200. package/test/unit/models/settlement/settlementModel.test.js +18 -37
  201. package/test/unit/models/settlement/settlementModelCached.test.js +171 -0
  202. package/test/unit/models/transfer/facade.test.js +115 -0
  203. package/test/unit/models/transfer/ilpPacket.test.js +28 -11
  204. package/test/unit/models/transfer/transfer.test.js +13 -4
  205. package/test/unit/models/transfer/transferDuplicateCheck.test.js +4 -0
  206. package/test/unit/models/transfer/transferError.test.js +5 -1
  207. package/test/unit/models/transfer/transferErrorDuplicateCheck.test.js +4 -0
  208. package/test/unit/models/transfer/transferExtension.test.js +26 -9
  209. package/test/unit/models/transfer/transferFulfilment.test.js +14 -5
  210. package/test/unit/models/transfer/transferFulfilmentDuplicateCheck.test.js +4 -0
  211. package/test/unit/models/transfer/transferParticipant.test.js +14 -5
  212. package/test/unit/models/transfer/transferStateChange.test.js +3 -0
  213. package/test/unit/models/transfer/transferTimeout.test.js +6 -0
  214. package/test/unit/seeds/amountType.test.js +6 -22
  215. package/test/unit/seeds/balanceOfPayments.test.js +6 -22
  216. package/test/unit/seeds/bulkProcessingState.test.js +84 -0
  217. package/test/unit/{lib/sidecar/nullClient.test.js → seeds/bulkTransferState.test.js} +36 -39
  218. package/test/unit/seeds/currency.test.js +6 -22
  219. package/test/unit/seeds/endpointType.test.js +6 -22
  220. package/test/unit/seeds/ledgerAccountType.test.js +5 -22
  221. package/test/unit/seeds/ledgerEntryType.test.js +6 -22
  222. package/test/unit/seeds/participant.test.js +5 -22
  223. package/test/unit/seeds/participantLimitType.test.js +6 -22
  224. package/test/unit/seeds/partyIdentifierType.test.js +6 -22
  225. package/test/unit/seeds/partyType.test.js +6 -22
  226. package/test/unit/seeds/settlementState.test.js +5 -22
  227. package/test/unit/seeds/settlementWindow1State.test.js +5 -22
  228. package/test/unit/seeds/transactionInitiator.test.js +6 -22
  229. package/test/unit/seeds/transactionInitiatorType.test.js +6 -22
  230. package/test/unit/seeds/transactionScenario.test.js +6 -22
  231. package/test/unit/seeds/transferParticipantRoleType.test.js +6 -22
  232. package/test/unit/seeds/transferState.test.js +6 -22
  233. package/test/unit/shared/plugins.test.js +31 -1
  234. package/test/unit/shared/setup.test.js +25 -36
  235. package/test/util/helpers.js +37 -2
  236. package/test/util/randomTransfers.js +1 -1
  237. package/test/util/scripts/env.sh +6 -5
  238. package/test/util/scripts/populateTestData.sh +204 -181
  239. package/test/util/scripts/populateTestDataForLegacySimulator.sh +261 -0
  240. package/test/util/scripts/restartObjStore.sh +1 -1
  241. package/test-integration.Dockerfile +15 -15
  242. package/test.Dockerfile +12 -12
  243. package/.circleci/_set_up_deploy_envs.sh +0 -47
  244. package/.dockerignore +0 -17
  245. package/.ncurc.json +0 -3
  246. package/server.sh +0 -4
  247. package/sonar-project.properties +0 -17
  248. package/src/lib/sidecar/index.js +0 -47
  249. package/src/lib/sidecar/nullClient.js +0 -18
  250. package/test/.env +0 -8
  251. package/test/integration-config.json +0 -367
  252. package/test/integration-runner.env +0 -31
  253. package/test/integration-runner.sh +0 -264
  254. package/test/spec-runner.sh +0 -132
  255. package/test/unit/lib/sidecar/index.test.js +0 -148
  256. package/test/unit/models/position/participantLimit.test.js +0 -135
@@ -27,21 +27,34 @@
27
27
 
28
28
  'use strict'
29
29
 
30
- const Test = require('tape')
30
+ const Test = require('tapes')(require('tape'))
31
31
  const Sinon = require('sinon')
32
32
  const Db = require('../../../../src/lib/db')
33
33
  const Logger = require('@mojaloop/central-services-logger')
34
34
  const Model = require('../../../../src/models/participant/participantCurrency')
35
35
 
36
36
  Test('Participant Currency model', async (participantCurrencyTest) => {
37
- const sandbox = Sinon.createSandbox()
38
- Db.participantCurrency = {
39
- insert: sandbox.stub(),
40
- findOne: sandbox.stub(),
41
- find: sandbox.stub(),
42
- destroy: sandbox.stub(),
43
- update: sandbox.stub()
44
- }
37
+ let sandbox
38
+
39
+ participantCurrencyTest.beforeEach(t => {
40
+ sandbox = Sinon.createSandbox()
41
+ Db.participantCurrency = {
42
+ insert: sandbox.stub(),
43
+ findOne: sandbox.stub(),
44
+ find: sandbox.stub(),
45
+ destroy: sandbox.stub(),
46
+ update: sandbox.stub()
47
+ }
48
+ Db.from = (table) => {
49
+ return Db[table]
50
+ }
51
+ t.end()
52
+ })
53
+
54
+ participantCurrencyTest.afterEach(t => {
55
+ sandbox.restore()
56
+ t.end()
57
+ })
45
58
 
46
59
  await participantCurrencyTest.test('create currency for fake participant', async (assert) => {
47
60
  Db.participantCurrency.insert.withArgs({ participantId: 3, currencyId: 'FAKE', createdBy: 'unknown' }).throws(new Error('message'))
@@ -190,7 +190,7 @@ Test('ParticipantCurrency cached model', async (participantCurrencyCachedTest) =
190
190
  Cache.registerCacheClient.returns(cacheClient)
191
191
  await Model.initialize()
192
192
 
193
- // test same things for 4 different functions
193
+ // test same things for 3 different functions
194
194
  const functionsToTest = ['create', 'update', 'destroyByParticipantId']
195
195
  for (const functionToTestIdx in functionsToTest) {
196
196
  const functionName = functionsToTest[functionToTestIdx]
@@ -34,18 +34,34 @@ const Db = require('../../../../src/lib/db')
34
34
  const Logger = require('@mojaloop/central-services-logger')
35
35
  const ParticipantCurrencyModel = require('../../../../src/models/participant/participantCurrencyCached')
36
36
  const Model = require('../../../../src/models/participant/participantLimit')
37
+ const Enum = require('@mojaloop/central-services-shared').Enum
37
38
 
38
39
  Test('Participant Limit model', async (participantLimitTest) => {
39
40
  let sandbox
40
41
 
42
+ const participantLimit1 = {
43
+ participantCurrencyId: 1,
44
+ participantLimitTypeId: Enum.Accounts.ParticipantLimitType.NET_DEBIT_CAP,
45
+ value: 1000,
46
+ thresholdAlarmPercentage: 10,
47
+ startAfterParticipantPositionChangeId: null,
48
+ isActive: true,
49
+ createDate: new Date(),
50
+ createdBy: 'unit-testing'
51
+ }
52
+
41
53
  participantLimitTest.beforeEach(t => {
42
54
  sandbox = Sinon.createSandbox()
43
55
  Db.participantLimit = {
44
56
  insert: sandbox.stub(),
57
+ update: sandbox.stub(),
45
58
  findOne: sandbox.stub(),
46
59
  find: sandbox.stub(),
47
60
  destroy: sandbox.stub()
48
61
  }
62
+ Db.from = (table) => {
63
+ return Db[table]
64
+ }
49
65
  t.end()
50
66
  })
51
67
 
@@ -54,6 +70,87 @@ Test('Participant Limit model', async (participantLimitTest) => {
54
70
  t.end()
55
71
  })
56
72
 
73
+ await participantLimitTest.test('insert participant limit', async (assert) => {
74
+ try {
75
+ Db.participantLimit.insert.withArgs(participantLimit1).returns(1)
76
+ const result = await Model.insert(participantLimit1)
77
+ assert.equal(result, 1, `returns ${result}`)
78
+ assert.end()
79
+ } catch (err) {
80
+ Logger.error(`insert participant limit failed with error - ${err}`)
81
+ assert.fail()
82
+ assert.end()
83
+ }
84
+ })
85
+
86
+ await participantLimitTest.test('insert participant limit should throw an error', async (assert) => {
87
+ try {
88
+ Db.participantLimit.insert.withArgs(participantLimit1).throws(new Error('message'))
89
+ await Model.insert(participantLimit1)
90
+ assert.fail('Error not thrown!')
91
+ assert.end()
92
+ } catch (err) {
93
+ Logger.error(`insert participant limit failed with error - ${err}`)
94
+ assert.assert(err instanceof Error, 'instance of Error')
95
+ assert.pass('Error thrown')
96
+ assert.end()
97
+ }
98
+ })
99
+
100
+ await participantLimitTest.test('update participant limit', async (assert) => {
101
+ try {
102
+ Db.participantLimit.update.withArgs({ participantCurrencyId: participantLimit1.participantCurrencyId }, { value: participantLimit1.value, isActive: participantLimit1.isActive }).returns(1)
103
+ const result = await Model.update(participantLimit1)
104
+ assert.equal(result, 1, `returns ${result}`)
105
+ assert.end()
106
+ } catch (err) {
107
+ Logger.error(`update participant limit failed with error - ${err}`)
108
+ assert.fail()
109
+ assert.end()
110
+ }
111
+ })
112
+
113
+ await participantLimitTest.test('update participant limit should throw an error', async (assert) => {
114
+ try {
115
+ Db.participantLimit.update.withArgs({ participantCurrencyId: participantLimit1.participantCurrencyId }, { value: participantLimit1.value, isActive: participantLimit1.isActive }).throws(new Error('message'))
116
+ await Model.update(participantLimit1)
117
+ assert.fail('Error not thrown!')
118
+ assert.end()
119
+ } catch (err) {
120
+ Logger.error(`update participant limit failed with error - ${err}`)
121
+ assert.assert(err instanceof Error, 'instance of Error')
122
+ assert.pass('Error thrown')
123
+ assert.end()
124
+ }
125
+ })
126
+
127
+ await participantLimitTest.test('getAll participants limit', async (assert) => {
128
+ try {
129
+ Db.participantLimit.find.withArgs({}).returns(1)
130
+ const result = await Model.getAll()
131
+ assert.equal(result, 1, `returns ${result}`)
132
+ assert.end()
133
+ } catch (err) {
134
+ Logger.error(`getAll participant limit failed with error - ${err}`)
135
+ assert.fail()
136
+ assert.end()
137
+ }
138
+ })
139
+
140
+ await participantLimitTest.test('getAll participant limit should throw an error', async (assert) => {
141
+ try {
142
+ Db.participantLimit.find.withArgs({}).throws(new Error('message'))
143
+ await Model.getAll()
144
+ assert.fail('Error not thrown!')
145
+ assert.end()
146
+ } catch (err) {
147
+ Logger.error(`getAll participant limit failed with error - ${err}`)
148
+ assert.assert(err instanceof Error, 'instance of Error')
149
+ assert.pass('Error thrown')
150
+ assert.end()
151
+ }
152
+ })
153
+
57
154
  await participantLimitTest.test('getByParticipantCurrencyId', async (assert) => {
58
155
  try {
59
156
  Db.participantLimit.findOne.withArgs({ participantCurrencyId: 1, isActive: 1 }).returns({
@@ -0,0 +1,232 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * Roman Pietrzak <roman.pietrzak@modusbox.com>
22
+ --------------
23
+ ******/
24
+
25
+ 'use strict'
26
+
27
+ const Test = require('tapes')(require('tape'))
28
+ const Sinon = require('sinon')
29
+ const ParticipantLimitUncached = require('../../../../src/models/participant/participantLimit')
30
+ const Cache = require('../../../../src/lib/cache')
31
+ const Model = require('../../../../src/models/participant/participantLimitCached')
32
+
33
+ Test('Participant Limit cached model', async (participantLimitCachedTest) => {
34
+ let sandbox
35
+
36
+ const participantLimitFixtures = [
37
+ {
38
+ participantLimitId: 1,
39
+ participantCurrencyId: 3,
40
+ participantLimitTypeId: 1,
41
+ value: 1000000,
42
+ thresholdAlarmPercentage: 10,
43
+ startAfterParticipantPositionChangeId: null,
44
+ isActive: 1,
45
+ createdDate: new Date(),
46
+ createdBy: 'theCreator'
47
+ },
48
+ {
49
+ participantLimitId: 2,
50
+ participantCurrencyId: 5,
51
+ participantLimitTypeId: 1,
52
+ value: 1000000,
53
+ thresholdAlarmPercentage: 10,
54
+ startAfterParticipantPositionChangeId: null,
55
+ isActive: 1,
56
+ createdDate: new Date(),
57
+ createdBy: 'theCreator'
58
+ },
59
+ {
60
+ participantLimitId: 3,
61
+ participantCurrencyId: 7,
62
+ participantLimitTypeId: 1,
63
+ value: 1000000,
64
+ thresholdAlarmPercentage: 10,
65
+ startAfterParticipantPositionChangeId: null,
66
+ isActive: 1,
67
+ createdDate: new Date(),
68
+ createdBy: 'theCreator'
69
+ }
70
+ ]
71
+
72
+ participantLimitCachedTest.beforeEach(t => {
73
+ sandbox = Sinon.createSandbox()
74
+ sandbox.stub(Cache)
75
+ sandbox.stub(ParticipantLimitUncached)
76
+ ParticipantLimitUncached.getAll.returns(participantLimitFixtures)
77
+ t.end()
78
+ })
79
+
80
+ participantLimitCachedTest.afterEach(t => {
81
+ sandbox.restore()
82
+ t.end()
83
+ })
84
+
85
+ await participantLimitCachedTest.test('initializes cache correctly', async (test) => {
86
+ const cacheClient = {
87
+ createKey: sandbox.stub().returns({})
88
+ }
89
+ Cache.registerCacheClient.returns(cacheClient)
90
+
91
+ // initialize calls registerCacheClient and createKey
92
+ test.notOk(Cache.registerCacheClient.calledOnce)
93
+ test.notOk(cacheClient.createKey.calledOnce)
94
+ await Model.initialize()
95
+ test.ok(Cache.registerCacheClient.calledOnce)
96
+ test.ok(cacheClient.createKey.calledOnce)
97
+
98
+ test.end()
99
+ })
100
+
101
+ await participantLimitCachedTest.test('calls drop() for invalidateParticipantLimitCache', async (test) => {
102
+ // initialize
103
+ const cacheClient = {
104
+ createKey: sandbox.stub().returns({}),
105
+ drop: sandbox.stub()
106
+ }
107
+ Cache.registerCacheClient.returns(cacheClient)
108
+ await Model.initialize()
109
+
110
+ // check
111
+ test.notOk(cacheClient.drop.calledOnce)
112
+ await Model.invalidateParticipantLimitCache()
113
+ test.ok(cacheClient.drop.calledOnce)
114
+
115
+ test.end()
116
+ })
117
+
118
+ await participantLimitCachedTest.test('getByParticipantCurrencyId() works and manages cache correctly', async (test) => {
119
+ let cache = null
120
+ let cacheGetCallsCnt = 0
121
+ let cacheSetCallsCnt = 0
122
+ const cacheClient = {
123
+ createKey: sandbox.stub().returns({}),
124
+ get: () => {
125
+ cacheGetCallsCnt++
126
+ return cache
127
+ },
128
+ set: (key, x) => {
129
+ cache = { item: x } // the cache retuns {item: <data>} structure
130
+ cacheSetCallsCnt++
131
+ }
132
+ }
133
+ Cache.registerCacheClient.returns(cacheClient)
134
+ await Model.initialize()
135
+
136
+ // make sure get/set wasn't called during inits
137
+ test.equal(cacheGetCallsCnt, 0, 'no cache.get() called')
138
+ test.equal(cacheSetCallsCnt, 0, 'no cache.set() called')
139
+
140
+ // check getById()
141
+ let participantByParticipantId = await Model.getByParticipantCurrencyId(participantLimitFixtures[1].participantCurrencyId)
142
+ test.equal(JSON.stringify(participantByParticipantId), JSON.stringify(participantLimitFixtures[1]), 'getByParticipantId(<arg>) works')
143
+
144
+ // check that get/set was called once when getByParticipantCurrencyId() for the 1st time
145
+ test.equal(cacheGetCallsCnt, 1, 'cache.get() called once')
146
+ test.equal(cacheSetCallsCnt, 1, 'cache.set() called once')
147
+
148
+ // check getById()
149
+ participantByParticipantId = await Model.getByParticipantCurrencyId(participantLimitFixtures[1].participantCurrencyId)
150
+ test.equal(JSON.stringify(participantByParticipantId), JSON.stringify(participantLimitFixtures[1]), 'getByParticipantId(<arg>) works')
151
+
152
+ // check that get called again, but set wasn't
153
+ test.equal(cacheGetCallsCnt, 2, 'cache.get() called twice')
154
+ test.equal(cacheSetCallsCnt, 1, 'cache.set() called once')
155
+
156
+ test.end()
157
+ })
158
+
159
+ await participantLimitCachedTest.test('insert(), update(), destroyByParticipantCurrencyId() and destroyByParticipantId() call the participant-limit model and cache invalidation', async (test) => {
160
+ const cacheClient = {
161
+ createKey: sandbox.stub().returns({}),
162
+ get: () => null
163
+ }
164
+ sandbox.stub(Model, 'invalidateParticipantLimitCache')
165
+
166
+ Cache.registerCacheClient.returns(cacheClient)
167
+ await Model.initialize()
168
+
169
+ // test same things for 4 different functions
170
+ const functionsToTest = ['insert', 'update', 'destroyByParticipantCurrencyId', 'destroyByParticipantId']
171
+ for (const functionToTestIdx in functionsToTest) {
172
+ const functionName = functionsToTest[functionToTestIdx]
173
+
174
+ // make sure nothing was called before
175
+ test.ok(Model.invalidateParticipantLimitCache.notCalled, 'invalidateParticipantLimitCache() not yet called')
176
+ test.ok(ParticipantLimitUncached[functionName].notCalled, `ParticipantLimitUncached.${functionName}() not yet called`)
177
+
178
+ // call the function
179
+ await Model[functionName]({})
180
+
181
+ // check invalidateParticipantLimitCache and function under test was called once
182
+ test.ok(Model.invalidateParticipantLimitCache.calledOnce, 'invalidateParticipantLimitCache() called once')
183
+ test.ok(ParticipantLimitUncached[functionName].calledOnce, `ParticipantLimitUncached.${functionName}() called once`)
184
+
185
+ // cleanup
186
+ Model.invalidateParticipantLimitCache.resetHistory()
187
+ }
188
+
189
+ test.end()
190
+ })
191
+
192
+ await participantLimitCachedTest.test('insert(), update(), destroyByParticipantCurrencyId() and destroyByParticipantId() fail when error thrown', async (test) => {
193
+ const cacheClient = {
194
+ createKey: sandbox.stub().returns({}),
195
+ get: () => null
196
+ }
197
+ sandbox.stub(Model, 'invalidateParticipantLimitCache')
198
+
199
+ Cache.registerCacheClient.returns(cacheClient)
200
+ await Model.initialize()
201
+
202
+ // test same things for 4 different functions
203
+ const functionsToTest = ['insert', 'update', 'destroyByParticipantCurrencyId', 'destroyByParticipantId']
204
+ for (const functionToTestIdx in functionsToTest) {
205
+ const functionName = functionsToTest[functionToTestIdx]
206
+
207
+ ParticipantLimitUncached[functionName].throws(new Error())
208
+
209
+ // make sure nothing was called before
210
+ test.ok(Model.invalidateParticipantLimitCache.notCalled, 'invalidateParticipantLimitCache() not yet called')
211
+ test.ok(ParticipantLimitUncached[functionName].notCalled, `ParticipantLimitUncached.${functionName}() not yet called`)
212
+
213
+ // call the function
214
+ try {
215
+ await Model[functionName]({})
216
+ test.fail(`Error not thrown for ${functionName}`)
217
+ } catch (err) {
218
+ test.pass(`Error thrown for ${functionName}`)
219
+ }
220
+
221
+ // check invalidateParticipantLimitCache and function under test was called once
222
+ test.ok(Model.invalidateParticipantLimitCache.notCalled, 'invalidateParticipantLimitCache() not called, as the error was thrown')
223
+
224
+ // cleanup
225
+ Model.invalidateParticipantLimitCache.resetHistory()
226
+ }
227
+
228
+ test.end()
229
+ })
230
+
231
+ await participantLimitCachedTest.end()
232
+ })
@@ -46,6 +46,9 @@ Test('Participant Position model', async (participantPositionTest) => {
46
46
  find: sandbox.stub(),
47
47
  destroy: sandbox.stub()
48
48
  }
49
+ Db.from = (table) => {
50
+ return Db[table]
51
+ }
49
52
  t.end()
50
53
  })
51
54
 
@@ -154,5 +157,219 @@ Test('Participant Position model', async (participantPositionTest) => {
154
157
  }
155
158
  })
156
159
 
160
+ await participantPositionTest.test('createParticipantPositionRecords should', async (test) => {
161
+ try {
162
+ sandbox.stub(Db, 'getKnex')
163
+ const knexStub = sandbox.stub()
164
+ const trxStub = sandbox.stub()
165
+ trxStub.commit = sandbox.stub()
166
+ knexStub.transaction = sandbox.stub().callsArgWith(0, trxStub)
167
+ Db.getKnex.returns(knexStub)
168
+ const transactingStub = sandbox.stub()
169
+ const batchInsertStub = sandbox.stub()
170
+ transactingStub.resolves()
171
+ knexStub.batchInsert = batchInsertStub.returns({ transacting: transactingStub })
172
+ const participantPositions = [
173
+ {
174
+ participantPositionId: 1,
175
+ participantCurrencyId: 1,
176
+ value: 0.000,
177
+ reservedValue: 0.000
178
+ },
179
+ {
180
+ participantPositionId: 1,
181
+ participantCurrencyId: 2,
182
+ value: 0.000,
183
+ reservedValue: 0.000
184
+ }
185
+ ]
186
+ await Model.createParticipantPositionRecords(participantPositions, trxStub)
187
+ test.equal(batchInsertStub.callCount, 1, 'call batch insert')
188
+ test.equal(batchInsertStub.lastCall.args[0], 'participantPosition', 'write to the participantPosition table')
189
+ test.deepEqual(batchInsertStub.lastCall.args[1], participantPositions, 'all records should be inserted')
190
+ test.equal(transactingStub.callCount, 1, 'make the database calls as transaction')
191
+ test.equal(transactingStub.lastCall.args[0], trxStub, 'run as transaction')
192
+ test.equal(trxStub.commit.callCount, 0, 'not commit the transaction if transaction is passed')
193
+ test.end()
194
+ } catch (err) {
195
+ Logger.error(`createParticipantPositionRecords failed with error - ${err}`)
196
+ test.fail('Error thrown')
197
+ test.end()
198
+ }
199
+ })
200
+
201
+ await participantPositionTest.test('createParticipantPositionRecords should', async (test) => {
202
+ try {
203
+ sandbox.stub(Db, 'getKnex')
204
+ const knexStub = sandbox.stub()
205
+ const trxStub = {
206
+ get commit () {
207
+
208
+ },
209
+ get rollback () {
210
+
211
+ }
212
+ }
213
+ const trxSpyCommit = sandbox.spy(trxStub, 'commit', ['get'])
214
+
215
+ knexStub.transaction = sandbox.stub().callsArgWith(0, trxStub)
216
+ Db.getKnex.returns(knexStub)
217
+ const transactingStub = sandbox.stub()
218
+ const batchInsertStub = sandbox.stub()
219
+ transactingStub.resolves()
220
+ knexStub.batchInsert = batchInsertStub.returns({ transacting: transactingStub })
221
+ const participantPositions = [
222
+ {
223
+ participantPositionId: 1,
224
+ participantCurrencyId: 1,
225
+ value: 0.000,
226
+ reservedValue: 0.000
227
+ },
228
+ {
229
+ participantPositionId: 1,
230
+ participantCurrencyId: 2,
231
+ value: 0.000,
232
+ reservedValue: 0.000
233
+ }
234
+ ]
235
+ await Model.createParticipantPositionRecords(participantPositions)
236
+ test.equal(batchInsertStub.callCount, 1, 'call batch insert')
237
+ test.equal(batchInsertStub.lastCall.args[0], 'participantPosition', 'write to the participantPosition table')
238
+ test.deepEqual(batchInsertStub.lastCall.args[1], participantPositions, 'all records should be inserted')
239
+ test.equal(transactingStub.callCount, 1, 'make the database calls as transaction')
240
+ test.equal(transactingStub.lastCall.args[0], trxStub, 'run as transaction')
241
+ test.equal(trxSpyCommit.get.calledOnce, true, 'commit the transaction if no transaction is passed')
242
+
243
+ test.end()
244
+ } catch (err) {
245
+ Logger.error(`createParticipantPositionRecords failed with error - ${err}`)
246
+ test.fail('Error thrown')
247
+ test.end()
248
+ }
249
+ })
250
+
251
+ await participantPositionTest.test('createParticipantPositionRecords should', async (test) => {
252
+ let trxStub
253
+ let trxSpyRollBack
254
+
255
+ try {
256
+ sandbox.stub(Db, 'getKnex')
257
+ const knexStub = sandbox.stub()
258
+ trxStub = {
259
+ get commit () {
260
+
261
+ },
262
+ get rollback () {
263
+
264
+ }
265
+ }
266
+ trxSpyRollBack = sandbox.spy(trxStub, 'rollback', ['get'])
267
+
268
+ knexStub.transaction = sandbox.stub().callsArgWith(0, trxStub)
269
+ Db.getKnex.returns(knexStub)
270
+ const transactingStub = sandbox.stub()
271
+ const batchInsertStub = sandbox.stub()
272
+ transactingStub.rejects(new Error())
273
+ knexStub.batchInsert = batchInsertStub.returns({ transacting: transactingStub })
274
+
275
+ const participantPositions = [
276
+ {
277
+ participantPositionId: 1,
278
+ participantCurrencyId: 1,
279
+ value: 0.000,
280
+ reservedValue: 0.000
281
+ },
282
+ {
283
+ participantPositionId: 1,
284
+ participantCurrencyId: 2,
285
+ value: 0.000,
286
+ reservedValue: 0.000
287
+ }
288
+ ]
289
+ await Model.createParticipantPositionRecords(participantPositions)
290
+ test.fail('have thrown an error')
291
+ test.end()
292
+ } catch (err) {
293
+ test.pass('throw an error')
294
+ test.equal(trxSpyRollBack.get.calledOnce, true, 'rollback the transaction if no transaction is passed')
295
+ test.end()
296
+ }
297
+ })
298
+
299
+ await participantPositionTest.test('createParticipantCurrencyRecords should', async (test) => {
300
+ let trxStub
301
+ let trxSpyRollBack
302
+
303
+ try {
304
+ sandbox.stub(Db, 'getKnex')
305
+ const knexStub = sandbox.stub()
306
+ trxStub = {
307
+ get commit () {
308
+
309
+ },
310
+ get rollback () {
311
+
312
+ }
313
+ }
314
+ trxSpyRollBack = sandbox.spy(trxStub, 'rollback', ['get'])
315
+
316
+ knexStub.transaction = sandbox.stub().callsArgWith(0, [trxStub, true])
317
+ Db.getKnex.returns(knexStub)
318
+ const transactingStub = sandbox.stub()
319
+ const batchInsertStub = sandbox.stub()
320
+ transactingStub.rejects(new Error())
321
+ knexStub.batchInsert = batchInsertStub.returns({ transacting: transactingStub })
322
+
323
+ const participantPositions = [
324
+ {
325
+ participantPositionId: 1,
326
+ participantCurrencyId: 1,
327
+ value: 0.000,
328
+ reservedValue: 0.000
329
+ },
330
+ {
331
+ participantPositionId: 1,
332
+ participantCurrencyId: 2,
333
+ value: 0.000,
334
+ reservedValue: 0.000
335
+ }
336
+ ]
337
+ await Model.createParticipantPositionRecords(participantPositions)
338
+ test.fail('have thrown an error')
339
+ test.end()
340
+ } catch (err) {
341
+ test.pass('throw an error')
342
+ test.equal(trxSpyRollBack.get.calledOnce, false, 'not rollback the transaction if transaction is passed')
343
+ test.end()
344
+ }
345
+ })
346
+
347
+ await participantPositionTest.test('createParticipantCurrencyRecords should', async (test) => {
348
+ try {
349
+ const participantPositions = [
350
+ {
351
+ participantPositionId: 1,
352
+ participantCurrencyId: 1,
353
+ value: 0.000,
354
+ reservedValue: 0.000
355
+ },
356
+ {
357
+ participantPositionId: 1,
358
+ participantCurrencyId: 2,
359
+ value: 0.000,
360
+ reservedValue: 0.000
361
+ }
362
+ ]
363
+ sandbox.stub(Db, 'getKnex')
364
+ Db.getKnex.throws(new Error())
365
+ await Model.createParticipantPositionRecords(participantPositions)
366
+ test.fail('have thrown an error')
367
+ test.end()
368
+ } catch (err) {
369
+ test.pass('throw an error')
370
+ test.end()
371
+ }
372
+ })
373
+
157
374
  participantPositionTest.end()
158
375
  })
@@ -42,6 +42,9 @@ Test('Participant Position model', async (participantPositionChangeTest) => {
42
42
  destroy: sandbox.stub(),
43
43
  query: sandbox.stub()
44
44
  }
45
+ Db.from = (table) => {
46
+ return Db[table]
47
+ }
45
48
  t.end()
46
49
  })
47
50