forked from tigerbeetle/tigerbeetle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMOJALOOP_BUSINESS_LOGIC.txt
129 lines (108 loc) · 10 KB
/
MOJALOOP_BUSINESS_LOGIC.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
PREPARE-POSITION
prepare duplicate check:
1587309924652 "insert into `transferDuplicateCheck` (`hash`, `transferId`) values (?, ?)"
validateFspiopSourceMatchesPayer(payload, headers) // asserts headers['fspiop-source'] matches payload.payerFsp
validateParticipantByName(payload.payerFsp) // asserts payer participant exists by doing a lookup by name (discards result of lookup work)
validatePositionAccountByNameAndCurrency(payload.payerFsp, payload.amount.currency) // asserts account exists for name-currency tuple (discards result of lookup work)
validateParticipantByName(payload.payeeFsp) // asserts payee participant exists by doing a lookup by name (discards result of lookup work)
validatePositionAccountByNameAndCurrency(payload.payeeFsp, payload.amount.currency) // asserts account exists for name-currency tuple (discards result of lookup work)
validateAmount(payload.amount) // TODO: validates allowed scale of decimal places and allowed precision
validateConditionAndExpiration(payload) // TODO: validates condition and expiration
assert(payload.condition)
assert(FiveBellsCondition.validateCondition('ni:///sha-256;' + payload.condition + '?fpt=preimage-sha-256&cost=0'))
assert(payload.expiration)
assert(Date.parse(payload.expiration) >= Date.parse(new Date().toDateString()))
validateDifferentDfsp(payload) // asserts lowercase string comparison of payload.payerFsp and payload.payeeFsp is different
write the transfer to the DB...AND attempt payer dfsp position adjustment at the same time:
saveTransferPreparedChangePosition()
1587309924656 "insert into `transfer` (`amount`, `currencyId`, `expirationDate`, `ilpCondition`, `transferId`) values (?, ?, ?, ?, ?)"
1587309924656 "insert into `transferParticipant` (`amount`, `ledgerEntryTypeId`, `participantCurrencyId`, `transferId`, `transferParticipantRoleTypeId`) values (?, ?, ?, ?, ?)"
1587309924656 "insert into `transferParticipant` (`amount`, `ledgerEntryTypeId`, `participantCurrencyId`, `transferId`, `transferParticipantRoleTypeId`) values (?, ?, ?, ?, ?)"
1587309924656 "insert into `ilpPacket` (`transferId`, `value`) values (?, ?)"
1587309924658 "insert into `transferStateChange` (`createdDate`, `reason`, `transferId`, `transferStateId`) values (?, ?, ?, ?)"
1587309924660 "UPDATE participantPosition SET value = (value + 100), changedDate = '2020-04-19 15:25:24.655' WHERE participantPositionId = 3 AND (value + 100) < (SELECT value FROM participantLimit WHERE participantLimitId = 1)"
1587309924661 "INSERT INTO participantPositionChange (participantPositionId, transferStateChangeId, value, reservedValue, createdDate) SELECT 3, 1253, value, reservedValue, '2020-04-19 15:25:24.655' FROM participantPosition WHERE participantPositionId = 3"
const names = [payload.payeeFsp, payload.payerFsp]
const participants = [] // filled out by doing lookups for both participants in names array
const insert_transfer = {
amount: payload.amount.amount,
currencyId: payload.amount.currency,
expirationDate: Time.getUTCString(new Date(payload.expiration)),
ilpCondition: payload.condition,
transferId: payload.transferId
}
const payerTransferParticipantRecord = {
amount: payload.amount.amount,
ledgerEntryTypeId: Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE,
participantCurrencyId: participantCurrencyIds[payload.payerFsp],
transferId: payload.transferId,
transferParticipantRoleTypeId: Enum.Accounts.TransferParticipantRoleType.PAYER_DFSP
}
const payeeTransferParticipantRecord = {
amount: -payload.amount.amount,
ledgerEntryTypeId: Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE,
participantCurrencyId: participantCurrencyIds[payload.payeeFsp],
transferId: payload.transferId,
transferParticipantRoleTypeId: Enum.Accounts.TransferParticipantRoleType.PAYEE_DFSP
}
const insert_ilpPacket = {
transferId: payload.transferId,
value: payload.ilpPacket
}
const transferStateChangeRecord = {
createdDate: Time.getUTCString(now),
reason: stateReason = null,
transferId: payload.transferId,
transferStateId: Enum.Transfers.TransferInternalState.RESERVED
}
send notification to payee dfsp
---
FULFIL-POSITION
1587309924755 "select `transfer`.*, `transfer`.`currencyId` as `currency`, `pc1`.`participantCurrencyId` as `payerParticipantCurrencyId`, `tp1`.`amount` as `payerAmount`, `da`.`participantId` as `payerParticipantId`, `da`.`name` as `payerFsp`, `pc2`.`participantCurrencyId` as `payeeParticipantCurrencyId`, `tp2`.`amount` as `payeeAmount`, `ca`.`participantId` as `payeeParticipantId`, `ca`.`name` as `payeeFsp`, `tsc`.`transferStateChangeId`, `tsc`.`transferStateId` as `transferState`, `tsc`.`reason` as `reason`, `tsc`.`createdDate` as `completedTimestamp`, `ts`.`enumeration` as `transferStateEnumeration`, `ts`.`description` as `transferStateDescription`, `ilpp`.`value` as `ilpPacket`, `transfer`.`ilpCondition` as `condition`, `tf`.`ilpFulfilment` as `fulfilment`, `te`.`errorCode`, `te`.`errorDescription` from `transfer` inner join `transferParticipant` as `tp1` on `tp1`.`transferId` = `transfer`.`transferId` inner join `transferParticipantRoleType` as `tprt1` on `tprt1`.`transferParticipantRoleTypeId` = `tp1`.`transferParticipantRoleTypeId` inner join `participantCurrency` as `pc1` on `pc1`.`participantCurrencyId` = `tp1`.`participantCurrencyId` inner join `participant` as `da` on `da`.`participantId` = `pc1`.`participantId` inner join `transferParticipant` as `tp2` on `tp2`.`transferId` = `transfer`.`transferId` inner join `transferParticipantRoleType` as `tprt2` on `tprt2`.`transferParticipantRoleTypeId` = `tp2`.`transferParticipantRoleTypeId` inner join `participantCurrency` as `pc2` on `pc2`.`participantCurrencyId` = `tp2`.`participantCurrencyId` inner join `participant` as `ca` on `ca`.`participantId` = `pc2`.`participantId` inner join `ilpPacket` as `ilpp` on `ilpp`.`transferId` = `transfer`.`transferId` left join `transferStateChange` as `tsc` on `tsc`.`transferId` = `transfer`.`transferId` left join `transferState` as `ts` on `ts`.`transferStateId` = `tsc`.`transferStateId` left join `transferFulfilment` as `tf` on `tf`.`transferId` = `transfer`.`transferId` left join `transferError` as `te` on `te`.`transferId` = `transfer`.`transferId` where `transfer`.`transferId` = ? and `tprt1`.`name` = ? and `tprt2`.`name` = ? and pc1.currencyId = transfer.currencyId and pc2.currencyId = transfer.currencyId order by `tsc`.`transferStateChangeId` desc limit ?"
1587309924757 "select * from `transferExtension` where `transferId` = ? and `isFulfilment` = ? and `isError` = ?"
1587309924759 "insert into `transferFulfilmentDuplicateCheck` (`hash`, `transferId`) values (?, ?)"
1587309924768 "select `transferParticipant`.*, `tsc`.`transferStateId`, `tsc`.`reason` from `transferParticipant` inner join `transferStateChange` as `tsc` on `tsc`.`transferId` = `transferParticipant`.`transferId` where `transferParticipant`.`transferId` = ? and `transferParticipant`.`transferParticipantRoleTypeId` = ? and `transferParticipant`.`ledgerEntryTypeId` = ? order by `tsc`.`transferStateChangeId` desc limit ?"
1587309924770 "select `settlementWindow`.`settlementWindowId`, `swsc`.`settlementWindowStateId` as `state`, `swsc`.`reason` as `reason`, `settlementWindow`.`createdDate` as `createdDate`, `swsc`.`createdDate` as `changedDate` from `settlementWindow` left join `settlementWindowStateChange` as `swsc` on `swsc`.`settlementWindowStateChangeId` = `settlementWindow`.`currentStateChangeId` where `swsc`.`settlementWindowStateId` = ? order by `changedDate` desc"
1587309924771 "insert into `transferFulfilment` (`completedDate`, `createdDate`, `ilpFulfilment`, `isValid`, `settlementWindowId`, `transferId`) values (?, ?, ?, ?, ?, ?)"
1587309924774 "insert into `transferStateChange` (`createdDate`, `transferId`, `transferStateId`) values (?, ?, ?)"
1587309924775 "UPDATE participantPosition SET value = (value + -100), changedDate = '2020-04-19 15:25:24.769' WHERE participantPositionId = 5 "
1587309924775 "select * from `transferStateChange` where `transferId` = ? order by `transferStateChangeId` desc limit ? for update"
1587309924776 "INSERT INTO participantPositionChange (participantPositionId, transferStateChangeId, value, reservedValue, createdDate) SELECT 5, 1254, value, reservedValue, '2020-04-19 15:25:24.769' FROM participantPosition WHERE participantPositionId = 5"
if (payload.fulfilment && !Validator.validateFulfilCondition(payload.fulfilment, transfer.condition))
if (transfer.transferState !== TransferState.RESERVED)
if (transfer.expirationDate <= new Date(Util.Time.getUTCString(new Date())))
await TransferService.handleResponseAdjustPosition(transferId, payload, action)
await TransferFacade.fulfilPosition
const transferStateChangePosition = {
transferId: transferId,
transferStateId: Enum.Transfers.TransferState.COMMITTED
}
const { participantCurrencyId, amount } = await getTransferInfoToChangePosition(transferId, Enum.Accounts.TransferParticipantRoleType.PAYEE_DFSP, Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE)
const transferFulfilmentRecord = {
transferId,
ilpFulfilment: payload.fulfilment || null,
completedDate: completedTimestamp,
isValid: !fspiopError,
settlementWindowId: null,
createdDate: transactionTimestamp
}
await calculateFulfilPositionRawQuery(participantCurrencyId, amount, transactionTimestamp, insertedTransferStateChange, payload, trx)
const participantPosition = await knex('participantPosition').transacting(trx).where({ participantCurrencyId }).forUpdate().select('*').first()
let latestPosition
if (isReversal) {
latestPosition = new MLNumber(participantPosition.value).subtract(amount)
} else {
latestPosition = new MLNumber(participantPosition.value).add(amount)
}
latestPosition = latestPosition.toFixed(Config.AMOUNT.SCALE)
await knex('participantPosition').transacting(trx).where({ participantCurrencyId }).update({
value: latestPosition,
changedDate: transactionTimestamp
})
const participantPositionChange = {
participantPositionId: participantPosition.participantPositionId,
transferStateChangeId: insertedTransferStateChange.transferStateChangeId,
value: latestPosition,
reservedValue: participantPosition.reservedValue,
createdDate: transactionTimestamp
}