multivendor-wallet 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/hooks/index.cjs +681 -0
- package/dist/hooks/index.cjs.map +1 -0
- package/dist/hooks/index.d.mts +7 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +678 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.cjs +2194 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +131 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +2173 -0
- package/dist/index.js.map +1 -0
- package/dist/store-BQ3whei-.d.mts +140 -0
- package/dist/store-BQ3whei-.d.ts +140 -0
- package/dist/typeorm/index.cjs +768 -0
- package/dist/typeorm/index.cjs.map +1 -0
- package/dist/typeorm/index.d.mts +79 -0
- package/dist/typeorm/index.d.ts +79 -0
- package/dist/typeorm/index.js +764 -0
- package/dist/typeorm/index.js.map +1 -0
- package/dist/types-CrJxUVwX.d.mts +224 -0
- package/dist/types-iNUEzUgo.d.ts +224 -0
- package/package.json +118 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2194 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var typeorm = require('typeorm');
|
|
4
|
+
require('reflect-metadata');
|
|
5
|
+
var routingControllers = require('routing-controllers');
|
|
6
|
+
var classValidator = require('class-validator');
|
|
7
|
+
var express = require('express');
|
|
8
|
+
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
12
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
13
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
14
|
+
}) : x)(function(x) {
|
|
15
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
16
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
17
|
+
});
|
|
18
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
19
|
+
|
|
20
|
+
// src/errors.ts
|
|
21
|
+
var _WalletError = class _WalletError extends Error {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "WalletError";
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
__name(_WalletError, "WalletError");
|
|
28
|
+
var WalletError = _WalletError;
|
|
29
|
+
var _WalletConfigError = class _WalletConfigError extends WalletError {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "WalletConfigError";
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
__name(_WalletConfigError, "WalletConfigError");
|
|
36
|
+
var WalletConfigError = _WalletConfigError;
|
|
37
|
+
var _InsufficientBalanceError = class _InsufficientBalanceError extends WalletError {
|
|
38
|
+
constructor(message = "Insufficient available balance") {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "InsufficientBalanceError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
__name(_InsufficientBalanceError, "InsufficientBalanceError");
|
|
44
|
+
var InsufficientBalanceError = _InsufficientBalanceError;
|
|
45
|
+
var _HoldNotFoundError = class _HoldNotFoundError extends WalletError {
|
|
46
|
+
constructor(message = "Active hold not found for reference") {
|
|
47
|
+
super(message);
|
|
48
|
+
this.name = "HoldNotFoundError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
__name(_HoldNotFoundError, "HoldNotFoundError");
|
|
52
|
+
var HoldNotFoundError = _HoldNotFoundError;
|
|
53
|
+
var _DuplicateOperationError = class _DuplicateOperationError extends WalletError {
|
|
54
|
+
constructor(message, existingEntry) {
|
|
55
|
+
super(message);
|
|
56
|
+
__publicField(this, "existingEntry");
|
|
57
|
+
this.name = "DuplicateOperationError";
|
|
58
|
+
this.existingEntry = existingEntry;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
__name(_DuplicateOperationError, "DuplicateOperationError");
|
|
62
|
+
var DuplicateOperationError = _DuplicateOperationError;
|
|
63
|
+
var _InvalidAmountError = class _InvalidAmountError extends WalletError {
|
|
64
|
+
constructor(message = "Amount must be a positive integer in minor units") {
|
|
65
|
+
super(message);
|
|
66
|
+
this.name = "InvalidAmountError";
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
__name(_InvalidAmountError, "InvalidAmountError");
|
|
70
|
+
var InvalidAmountError = _InvalidAmountError;
|
|
71
|
+
|
|
72
|
+
// src/types.ts
|
|
73
|
+
var WalletAccountType = /* @__PURE__ */ (function(WalletAccountType2) {
|
|
74
|
+
WalletAccountType2["CUSTOMER"] = "customer";
|
|
75
|
+
WalletAccountType2["VENDOR"] = "vendor";
|
|
76
|
+
WalletAccountType2["PLATFORM"] = "platform";
|
|
77
|
+
return WalletAccountType2;
|
|
78
|
+
})({});
|
|
79
|
+
var LedgerEntryType = /* @__PURE__ */ (function(LedgerEntryType2) {
|
|
80
|
+
LedgerEntryType2["CREDIT"] = "credit";
|
|
81
|
+
LedgerEntryType2["DEBIT"] = "debit";
|
|
82
|
+
LedgerEntryType2["HOLD"] = "hold";
|
|
83
|
+
LedgerEntryType2["RELEASE"] = "release";
|
|
84
|
+
LedgerEntryType2["CANCEL_HOLD"] = "cancel_hold";
|
|
85
|
+
LedgerEntryType2["TRANSFER"] = "transfer";
|
|
86
|
+
return LedgerEntryType2;
|
|
87
|
+
})({});
|
|
88
|
+
var HoldStatus = /* @__PURE__ */ (function(HoldStatus2) {
|
|
89
|
+
HoldStatus2["ACTIVE"] = "active";
|
|
90
|
+
HoldStatus2["RELEASED"] = "released";
|
|
91
|
+
HoldStatus2["CANCELLED"] = "cancelled";
|
|
92
|
+
return HoldStatus2;
|
|
93
|
+
})({});
|
|
94
|
+
|
|
95
|
+
// src/client.ts
|
|
96
|
+
var _WalletLedgerClient = class _WalletLedgerClient {
|
|
97
|
+
constructor(store, config = {}) {
|
|
98
|
+
__publicField(this, "store");
|
|
99
|
+
__publicField(this, "config");
|
|
100
|
+
this.store = store;
|
|
101
|
+
this.config = config;
|
|
102
|
+
}
|
|
103
|
+
async getOrCreateAccount(type, ownerId, currency, ctx) {
|
|
104
|
+
return this.store.runInTransaction((tx) => tx.getOrCreateAccount(type, ownerId, currency ?? this.config.defaultCurrency ?? "INR"), ctx);
|
|
105
|
+
}
|
|
106
|
+
async getBalance(accountId, ctx) {
|
|
107
|
+
return this.store.runInTransaction(async (tx) => {
|
|
108
|
+
const account = await tx.getAccountById(accountId);
|
|
109
|
+
if (!account) {
|
|
110
|
+
throw new Error(`Wallet account ${accountId} not found`);
|
|
111
|
+
}
|
|
112
|
+
return this.toBalance(account);
|
|
113
|
+
}, ctx);
|
|
114
|
+
}
|
|
115
|
+
async credit(params, ctx) {
|
|
116
|
+
this.assertPositiveAmount(params.amount);
|
|
117
|
+
return this.store.runInTransaction((tx) => this.creditInTx(tx, params), ctx);
|
|
118
|
+
}
|
|
119
|
+
async debit(params, ctx) {
|
|
120
|
+
this.assertPositiveAmount(params.amount);
|
|
121
|
+
return this.store.runInTransaction((tx) => this.debitInTx(tx, params), ctx);
|
|
122
|
+
}
|
|
123
|
+
async hold(params, ctx) {
|
|
124
|
+
this.assertPositiveAmount(params.amount);
|
|
125
|
+
return this.store.runInTransaction((tx) => this.holdInTx(tx, params), ctx);
|
|
126
|
+
}
|
|
127
|
+
async release(params, ctx) {
|
|
128
|
+
return this.store.runInTransaction((tx) => this.releaseInTx(tx, params), ctx);
|
|
129
|
+
}
|
|
130
|
+
async cancelHold(params, ctx) {
|
|
131
|
+
return this.store.runInTransaction((tx) => this.cancelHoldInTx(tx, params), ctx);
|
|
132
|
+
}
|
|
133
|
+
async transfer(params, ctx) {
|
|
134
|
+
this.assertPositiveAmount(params.amount);
|
|
135
|
+
return this.store.runInTransaction(async (tx) => {
|
|
136
|
+
const debit = await this.debitInTx(tx, {
|
|
137
|
+
accountId: params.fromAccountId,
|
|
138
|
+
amount: params.amount,
|
|
139
|
+
idempotencyKey: `${params.idempotencyKey}:debit`,
|
|
140
|
+
reference: params.reference,
|
|
141
|
+
metadata: params.metadata
|
|
142
|
+
});
|
|
143
|
+
const credit = await this.creditInTx(tx, {
|
|
144
|
+
accountId: params.toAccountId,
|
|
145
|
+
amount: params.amount,
|
|
146
|
+
idempotencyKey: `${params.idempotencyKey}:credit`,
|
|
147
|
+
reference: params.reference,
|
|
148
|
+
metadata: params.metadata
|
|
149
|
+
});
|
|
150
|
+
return {
|
|
151
|
+
debit,
|
|
152
|
+
credit
|
|
153
|
+
};
|
|
154
|
+
}, ctx);
|
|
155
|
+
}
|
|
156
|
+
async getTransactions(params, ctx) {
|
|
157
|
+
const limit = params.limit ?? 50;
|
|
158
|
+
const offset = params.offset ?? 0;
|
|
159
|
+
return this.store.runInTransaction((tx) => tx.listLedgerEntries(params.accountId, limit, offset), ctx);
|
|
160
|
+
}
|
|
161
|
+
async creditInTx(tx, params) {
|
|
162
|
+
const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
|
|
163
|
+
if (existing) {
|
|
164
|
+
const account = await tx.getAccountById(existing.accountId);
|
|
165
|
+
if (!account) {
|
|
166
|
+
throw new Error(`Wallet account ${existing.accountId} not found`);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
entry: existing,
|
|
170
|
+
account
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
await tx.lockAccount(params.accountId);
|
|
174
|
+
const updated = await tx.updateBalances(params.accountId, {
|
|
175
|
+
availableDelta: params.amount
|
|
176
|
+
});
|
|
177
|
+
const entry = await tx.appendLedgerEntry({
|
|
178
|
+
accountId: params.accountId,
|
|
179
|
+
entryType: LedgerEntryType.CREDIT,
|
|
180
|
+
amount: params.amount,
|
|
181
|
+
balanceAfterAvailable: updated.availableBalance,
|
|
182
|
+
balanceAfterHeld: updated.heldBalance,
|
|
183
|
+
idempotencyKey: params.idempotencyKey,
|
|
184
|
+
referenceType: params.reference?.referenceType,
|
|
185
|
+
referenceId: params.reference?.referenceId,
|
|
186
|
+
metadata: params.metadata
|
|
187
|
+
});
|
|
188
|
+
return {
|
|
189
|
+
entry,
|
|
190
|
+
account: updated
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
async debitInTx(tx, params) {
|
|
194
|
+
const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
|
|
195
|
+
if (existing) {
|
|
196
|
+
const account = await tx.getAccountById(existing.accountId);
|
|
197
|
+
if (!account) {
|
|
198
|
+
throw new Error(`Wallet account ${existing.accountId} not found`);
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
entry: existing,
|
|
202
|
+
account
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const locked = await tx.lockAccount(params.accountId);
|
|
206
|
+
if (locked.availableBalance < params.amount) {
|
|
207
|
+
throw new InsufficientBalanceError();
|
|
208
|
+
}
|
|
209
|
+
const updated = await tx.updateBalances(params.accountId, {
|
|
210
|
+
availableDelta: -params.amount
|
|
211
|
+
});
|
|
212
|
+
const entry = await tx.appendLedgerEntry({
|
|
213
|
+
accountId: params.accountId,
|
|
214
|
+
entryType: LedgerEntryType.DEBIT,
|
|
215
|
+
amount: params.amount,
|
|
216
|
+
balanceAfterAvailable: updated.availableBalance,
|
|
217
|
+
balanceAfterHeld: updated.heldBalance,
|
|
218
|
+
idempotencyKey: params.idempotencyKey,
|
|
219
|
+
referenceType: params.reference?.referenceType,
|
|
220
|
+
referenceId: params.reference?.referenceId,
|
|
221
|
+
metadata: params.metadata
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
entry,
|
|
225
|
+
account: updated
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async holdInTx(tx, params) {
|
|
229
|
+
const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
|
|
230
|
+
if (existing) {
|
|
231
|
+
const account = await tx.getAccountById(existing.accountId);
|
|
232
|
+
const hold2 = await tx.findHoldByReference(params.reference);
|
|
233
|
+
if (!account) {
|
|
234
|
+
throw new Error(`Wallet account ${existing.accountId} not found`);
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
entry: existing,
|
|
238
|
+
account,
|
|
239
|
+
hold: hold2 ?? void 0
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const existingHold = await tx.findHoldByReference(params.reference);
|
|
243
|
+
if (existingHold?.status === HoldStatus.ACTIVE) {
|
|
244
|
+
throw new DuplicateOperationError("Hold already exists for reference", existingHold);
|
|
245
|
+
}
|
|
246
|
+
const source = await tx.lockAccount(params.sourceAccountId);
|
|
247
|
+
if (source.availableBalance < params.amount) {
|
|
248
|
+
throw new InsufficientBalanceError("Insufficient platform balance for hold");
|
|
249
|
+
}
|
|
250
|
+
await tx.updateBalances(params.sourceAccountId, {
|
|
251
|
+
availableDelta: -params.amount
|
|
252
|
+
});
|
|
253
|
+
const targetUpdated = await tx.updateBalances(params.targetAccountId, {
|
|
254
|
+
heldDelta: params.amount
|
|
255
|
+
});
|
|
256
|
+
const hold = await tx.upsertHold({
|
|
257
|
+
sourceAccountId: params.sourceAccountId,
|
|
258
|
+
targetAccountId: params.targetAccountId,
|
|
259
|
+
amount: params.amount,
|
|
260
|
+
status: HoldStatus.ACTIVE,
|
|
261
|
+
referenceType: params.reference.referenceType,
|
|
262
|
+
referenceId: params.reference.referenceId,
|
|
263
|
+
idempotencyKey: params.idempotencyKey
|
|
264
|
+
});
|
|
265
|
+
const sourceAfterHold = await tx.getAccountById(params.sourceAccountId);
|
|
266
|
+
if (!sourceAfterHold) {
|
|
267
|
+
throw new Error(`Wallet account ${params.sourceAccountId} not found`);
|
|
268
|
+
}
|
|
269
|
+
await tx.appendLedgerEntry({
|
|
270
|
+
accountId: params.sourceAccountId,
|
|
271
|
+
entryType: LedgerEntryType.HOLD,
|
|
272
|
+
amount: params.amount,
|
|
273
|
+
balanceAfterAvailable: sourceAfterHold.availableBalance,
|
|
274
|
+
balanceAfterHeld: sourceAfterHold.heldBalance,
|
|
275
|
+
idempotencyKey: `${params.idempotencyKey}:source`,
|
|
276
|
+
referenceType: params.reference.referenceType,
|
|
277
|
+
referenceId: params.reference.referenceId,
|
|
278
|
+
metadata: params.metadata
|
|
279
|
+
});
|
|
280
|
+
const entry = await tx.appendLedgerEntry({
|
|
281
|
+
accountId: params.targetAccountId,
|
|
282
|
+
entryType: LedgerEntryType.HOLD,
|
|
283
|
+
amount: params.amount,
|
|
284
|
+
balanceAfterAvailable: targetUpdated.availableBalance,
|
|
285
|
+
balanceAfterHeld: targetUpdated.heldBalance,
|
|
286
|
+
idempotencyKey: params.idempotencyKey,
|
|
287
|
+
referenceType: params.reference.referenceType,
|
|
288
|
+
referenceId: params.reference.referenceId,
|
|
289
|
+
metadata: params.metadata
|
|
290
|
+
});
|
|
291
|
+
return {
|
|
292
|
+
entry,
|
|
293
|
+
account: targetUpdated,
|
|
294
|
+
hold
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
async releaseInTx(tx, params) {
|
|
298
|
+
const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
|
|
299
|
+
if (existing) {
|
|
300
|
+
const account = await tx.getAccountById(existing.accountId);
|
|
301
|
+
const hold2 = await tx.findHoldByReference(params.reference);
|
|
302
|
+
if (!account) {
|
|
303
|
+
throw new Error(`Wallet account ${existing.accountId} not found`);
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
entry: existing,
|
|
307
|
+
account,
|
|
308
|
+
hold: hold2 ?? void 0
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const hold = await this.requireActiveHold(tx, params.reference);
|
|
312
|
+
await tx.lockAccount(hold.targetAccountId);
|
|
313
|
+
const targetUpdated = await tx.updateBalances(hold.targetAccountId, {
|
|
314
|
+
heldDelta: -hold.amount,
|
|
315
|
+
availableDelta: hold.amount
|
|
316
|
+
});
|
|
317
|
+
const releasedHold = await tx.upsertHold({
|
|
318
|
+
...hold,
|
|
319
|
+
status: HoldStatus.RELEASED
|
|
320
|
+
});
|
|
321
|
+
const entry = await tx.appendLedgerEntry({
|
|
322
|
+
accountId: hold.targetAccountId,
|
|
323
|
+
entryType: LedgerEntryType.RELEASE,
|
|
324
|
+
amount: hold.amount,
|
|
325
|
+
balanceAfterAvailable: targetUpdated.availableBalance,
|
|
326
|
+
balanceAfterHeld: targetUpdated.heldBalance,
|
|
327
|
+
idempotencyKey: params.idempotencyKey,
|
|
328
|
+
referenceType: params.reference.referenceType,
|
|
329
|
+
referenceId: params.reference.referenceId,
|
|
330
|
+
metadata: params.metadata
|
|
331
|
+
});
|
|
332
|
+
return {
|
|
333
|
+
entry,
|
|
334
|
+
account: targetUpdated,
|
|
335
|
+
hold: releasedHold
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async cancelHoldInTx(tx, params) {
|
|
339
|
+
const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
|
|
340
|
+
if (existing) {
|
|
341
|
+
const account = await tx.getAccountById(existing.accountId);
|
|
342
|
+
const hold2 = await tx.findHoldByReference(params.reference);
|
|
343
|
+
if (!account) {
|
|
344
|
+
throw new Error(`Wallet account ${existing.accountId} not found`);
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
entry: existing,
|
|
348
|
+
account,
|
|
349
|
+
hold: hold2 ?? void 0
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const hold = await this.requireActiveHold(tx, params.reference);
|
|
353
|
+
await tx.lockAccount(hold.sourceAccountId);
|
|
354
|
+
await tx.lockAccount(hold.targetAccountId);
|
|
355
|
+
const sourceUpdated = await tx.updateBalances(hold.sourceAccountId, {
|
|
356
|
+
availableDelta: hold.amount
|
|
357
|
+
});
|
|
358
|
+
const targetUpdated = await tx.updateBalances(hold.targetAccountId, {
|
|
359
|
+
heldDelta: -hold.amount
|
|
360
|
+
});
|
|
361
|
+
const cancelledHold = await tx.upsertHold({
|
|
362
|
+
...hold,
|
|
363
|
+
status: HoldStatus.CANCELLED
|
|
364
|
+
});
|
|
365
|
+
await tx.appendLedgerEntry({
|
|
366
|
+
accountId: hold.sourceAccountId,
|
|
367
|
+
entryType: LedgerEntryType.CANCEL_HOLD,
|
|
368
|
+
amount: hold.amount,
|
|
369
|
+
balanceAfterAvailable: sourceUpdated.availableBalance,
|
|
370
|
+
balanceAfterHeld: sourceUpdated.heldBalance,
|
|
371
|
+
idempotencyKey: `${params.idempotencyKey}:source`,
|
|
372
|
+
referenceType: params.reference.referenceType,
|
|
373
|
+
referenceId: params.reference.referenceId,
|
|
374
|
+
metadata: params.metadata
|
|
375
|
+
});
|
|
376
|
+
const entry = await tx.appendLedgerEntry({
|
|
377
|
+
accountId: hold.targetAccountId,
|
|
378
|
+
entryType: LedgerEntryType.CANCEL_HOLD,
|
|
379
|
+
amount: hold.amount,
|
|
380
|
+
balanceAfterAvailable: targetUpdated.availableBalance,
|
|
381
|
+
balanceAfterHeld: targetUpdated.heldBalance,
|
|
382
|
+
idempotencyKey: params.idempotencyKey,
|
|
383
|
+
referenceType: params.reference.referenceType,
|
|
384
|
+
referenceId: params.reference.referenceId,
|
|
385
|
+
metadata: params.metadata
|
|
386
|
+
});
|
|
387
|
+
return {
|
|
388
|
+
entry,
|
|
389
|
+
account: targetUpdated,
|
|
390
|
+
hold: cancelledHold
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
toBalance(account) {
|
|
394
|
+
return {
|
|
395
|
+
available: account.availableBalance,
|
|
396
|
+
held: account.heldBalance,
|
|
397
|
+
total: account.availableBalance + account.heldBalance
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
assertPositiveAmount(amount) {
|
|
401
|
+
if (!Number.isInteger(amount) || amount <= 0) {
|
|
402
|
+
throw new InvalidAmountError();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
async requireActiveHold(tx, reference) {
|
|
406
|
+
const hold = await tx.findHoldByReference(reference);
|
|
407
|
+
if (!hold || hold.status !== HoldStatus.ACTIVE) {
|
|
408
|
+
throw new HoldNotFoundError();
|
|
409
|
+
}
|
|
410
|
+
return hold;
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
__name(_WalletLedgerClient, "WalletLedgerClient");
|
|
414
|
+
var WalletLedgerClient = _WalletLedgerClient;
|
|
415
|
+
|
|
416
|
+
// src/currency.ts
|
|
417
|
+
function toMinorUnit(amount) {
|
|
418
|
+
return Math.round(amount * 100);
|
|
419
|
+
}
|
|
420
|
+
__name(toMinorUnit, "toMinorUnit");
|
|
421
|
+
function fromMinorUnit(amount) {
|
|
422
|
+
return amount / 100;
|
|
423
|
+
}
|
|
424
|
+
__name(fromMinorUnit, "fromMinorUnit");
|
|
425
|
+
|
|
426
|
+
// src/hooks/order.ts
|
|
427
|
+
function isWalletOnlyPayment(paymentMethod) {
|
|
428
|
+
return String(paymentMethod ?? "").trim().toLowerCase() === "wallet";
|
|
429
|
+
}
|
|
430
|
+
__name(isWalletOnlyPayment, "isWalletOnlyPayment");
|
|
431
|
+
function createOrderHooks(runtime) {
|
|
432
|
+
const { client, platformOwnerId, flags } = runtime;
|
|
433
|
+
return {
|
|
434
|
+
async onOrderPaid(ctx) {
|
|
435
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const txCtx = {
|
|
439
|
+
nativeTx: ctx.nativeTx
|
|
440
|
+
};
|
|
441
|
+
const platform = await client.getOrCreateAccount(WalletAccountType.PLATFORM, platformOwnerId, ctx.currency, txCtx);
|
|
442
|
+
const orderTotalPaise = toMinorUnit(ctx.orderTotalRupees);
|
|
443
|
+
const shouldDebitCustomer = isWalletOnlyPayment(ctx.paymentMethod) && ctx.customerId && !ctx.skipCustomerDebit;
|
|
444
|
+
if (shouldDebitCustomer) {
|
|
445
|
+
const debitRupees = ctx.walletAmountRupees ?? ctx.orderTotalRupees;
|
|
446
|
+
const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency, txCtx);
|
|
447
|
+
await client.debit({
|
|
448
|
+
accountId: customer.id,
|
|
449
|
+
amount: toMinorUnit(debitRupees),
|
|
450
|
+
idempotencyKey: `wallet:payment:${ctx.paymentNumber}`,
|
|
451
|
+
reference: {
|
|
452
|
+
referenceType: "order",
|
|
453
|
+
referenceId: String(ctx.orderId)
|
|
454
|
+
}
|
|
455
|
+
}, txCtx);
|
|
456
|
+
}
|
|
457
|
+
await client.credit({
|
|
458
|
+
accountId: platform.id,
|
|
459
|
+
amount: orderTotalPaise,
|
|
460
|
+
idempotencyKey: `payment:${ctx.paymentNumber}`,
|
|
461
|
+
reference: {
|
|
462
|
+
referenceType: "order",
|
|
463
|
+
referenceId: String(ctx.orderId)
|
|
464
|
+
}
|
|
465
|
+
}, txCtx);
|
|
466
|
+
for (const line of ctx.lines) {
|
|
467
|
+
const vendorNetRupees = line.commissionBaseRupees - line.commissionRupees;
|
|
468
|
+
if (vendorNetRupees <= 0) {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const vendor = await client.getOrCreateAccount(WalletAccountType.VENDOR, line.vendorId, ctx.currency, txCtx);
|
|
472
|
+
await client.hold({
|
|
473
|
+
sourceAccountId: platform.id,
|
|
474
|
+
targetAccountId: vendor.id,
|
|
475
|
+
amount: toMinorUnit(vendorNetRupees),
|
|
476
|
+
idempotencyKey: `order:${ctx.orderId}:hold:vendorOrder:${line.vendorOrderId}`,
|
|
477
|
+
reference: {
|
|
478
|
+
referenceType: "vendor_order",
|
|
479
|
+
referenceId: String(line.vendorOrderId)
|
|
480
|
+
}
|
|
481
|
+
}, txCtx);
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
async onLineDelivered(ctx) {
|
|
485
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
await client.release({
|
|
489
|
+
reference: {
|
|
490
|
+
referenceType: "vendor_order",
|
|
491
|
+
referenceId: String(ctx.vendorOrderId)
|
|
492
|
+
},
|
|
493
|
+
idempotencyKey: `vendorOrder:${ctx.vendorOrderId}:release`
|
|
494
|
+
}, ctx.nativeTx != null ? {
|
|
495
|
+
nativeTx: ctx.nativeTx
|
|
496
|
+
} : void 0);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
__name(createOrderHooks, "createOrderHooks");
|
|
501
|
+
|
|
502
|
+
// src/hooks/refund.ts
|
|
503
|
+
function isWalletPayment(paymentMethod) {
|
|
504
|
+
return String(paymentMethod ?? "").trim().toLowerCase() === "wallet";
|
|
505
|
+
}
|
|
506
|
+
__name(isWalletPayment, "isWalletPayment");
|
|
507
|
+
function walletCreditRupees(ctx) {
|
|
508
|
+
if (ctx.walletRefundRupees != null && ctx.walletRefundRupees > 0) {
|
|
509
|
+
return ctx.walletRefundRupees;
|
|
510
|
+
}
|
|
511
|
+
return isWalletPayment(ctx.paymentMethod) ? ctx.lineTotalRupees : 0;
|
|
512
|
+
}
|
|
513
|
+
__name(walletCreditRupees, "walletCreditRupees");
|
|
514
|
+
function idempotencyPrefix(ctx) {
|
|
515
|
+
const scope = ctx.idempotencyScope ?? String(ctx.orderProductId);
|
|
516
|
+
return ctx.refundReason === "return" ? `return:${scope}` : `refund:${ctx.orderProductId}`;
|
|
517
|
+
}
|
|
518
|
+
__name(idempotencyPrefix, "idempotencyPrefix");
|
|
519
|
+
function createRefundHooks(runtime) {
|
|
520
|
+
const { client, platformOwnerId, flags } = runtime;
|
|
521
|
+
return {
|
|
522
|
+
async onRefund(ctx) {
|
|
523
|
+
if (!flags.enabled || !flags.ledgerWrites) {
|
|
524
|
+
await ctx.processExternalRefund();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
const keyPrefix = idempotencyPrefix(ctx);
|
|
528
|
+
if (!ctx.skipEscrow) {
|
|
529
|
+
await client.cancelHold({
|
|
530
|
+
reference: {
|
|
531
|
+
referenceType: "vendor_order",
|
|
532
|
+
referenceId: String(ctx.vendorOrderId)
|
|
533
|
+
},
|
|
534
|
+
idempotencyKey: `${keyPrefix}:cancel_hold`
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
const refundPaise = toMinorUnit(ctx.lineTotalRupees);
|
|
538
|
+
if (refundPaise > 0) {
|
|
539
|
+
const platform = await client.getOrCreateAccount(WalletAccountType.PLATFORM, platformOwnerId, ctx.currency);
|
|
540
|
+
const balance = await client.getBalance(platform.id);
|
|
541
|
+
if (balance.available >= refundPaise) {
|
|
542
|
+
await client.debit({
|
|
543
|
+
accountId: platform.id,
|
|
544
|
+
amount: refundPaise,
|
|
545
|
+
idempotencyKey: `${keyPrefix}:platform_debit`,
|
|
546
|
+
reference: {
|
|
547
|
+
referenceType: "order_product",
|
|
548
|
+
referenceId: String(ctx.orderProductId)
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
const creditRupees = walletCreditRupees(ctx);
|
|
553
|
+
if (creditRupees > 0 && ctx.customerId) {
|
|
554
|
+
const customer = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, ctx.customerId, ctx.currency);
|
|
555
|
+
await client.credit({
|
|
556
|
+
accountId: customer.id,
|
|
557
|
+
amount: toMinorUnit(creditRupees),
|
|
558
|
+
idempotencyKey: `${keyPrefix}:customer_credit`,
|
|
559
|
+
reference: {
|
|
560
|
+
referenceType: "order",
|
|
561
|
+
referenceId: String(ctx.orderId ?? ctx.orderProductId)
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
await ctx.processExternalRefund();
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
__name(createRefundHooks, "createRefundHooks");
|
|
571
|
+
|
|
572
|
+
// src/hooks/settlement.ts
|
|
573
|
+
function createSettlementHooks(runtime) {
|
|
574
|
+
const { client, flags } = runtime;
|
|
575
|
+
return {
|
|
576
|
+
async onSettlementDebit(ctx) {
|
|
577
|
+
if (!flags.enabled || !flags.settlementDebit) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
const txCtx = {
|
|
581
|
+
nativeTx: ctx.nativeTx
|
|
582
|
+
};
|
|
583
|
+
const amountPaise = toMinorUnit(ctx.amountRupees);
|
|
584
|
+
const vendorAccount = await client.getOrCreateAccount(WalletAccountType.VENDOR, ctx.vendorId, ctx.currency, txCtx);
|
|
585
|
+
const balance = await client.getBalance(vendorAccount.id, txCtx);
|
|
586
|
+
if (balance.available < amountPaise) {
|
|
587
|
+
throw new Error(`Insufficient vendor wallet balance for settlement (vendor ${ctx.vendorId})`);
|
|
588
|
+
}
|
|
589
|
+
await client.debit({
|
|
590
|
+
accountId: vendorAccount.id,
|
|
591
|
+
amount: amountPaise,
|
|
592
|
+
idempotencyKey: `settlement:${ctx.settlementId}:debit:${ctx.vendorId}`,
|
|
593
|
+
reference: {
|
|
594
|
+
referenceType: "settlement",
|
|
595
|
+
referenceId: String(ctx.settlementId)
|
|
596
|
+
}
|
|
597
|
+
}, txCtx);
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
__name(createSettlementHooks, "createSettlementHooks");
|
|
602
|
+
|
|
603
|
+
// src/plugin-instance.ts
|
|
604
|
+
var activePlugin;
|
|
605
|
+
var activeConnection;
|
|
606
|
+
function bindWalletPlugin(plugin) {
|
|
607
|
+
activePlugin = plugin;
|
|
608
|
+
}
|
|
609
|
+
__name(bindWalletPlugin, "bindWalletPlugin");
|
|
610
|
+
function bindWalletConnection(connection) {
|
|
611
|
+
activeConnection = connection;
|
|
612
|
+
}
|
|
613
|
+
__name(bindWalletConnection, "bindWalletConnection");
|
|
614
|
+
function resolveWalletPlugin() {
|
|
615
|
+
if (!activePlugin) {
|
|
616
|
+
throw new Error("Wallet plugin is not registered. Call registerWalletPlugin() during app bootstrap.");
|
|
617
|
+
}
|
|
618
|
+
return activePlugin;
|
|
619
|
+
}
|
|
620
|
+
__name(resolveWalletPlugin, "resolveWalletPlugin");
|
|
621
|
+
function resolveWalletConnection() {
|
|
622
|
+
if (!activeConnection?.manager) {
|
|
623
|
+
throw new Error("Wallet database connection is not registered. Pass host TypeORM Connection as dataSource.");
|
|
624
|
+
}
|
|
625
|
+
return activeConnection;
|
|
626
|
+
}
|
|
627
|
+
__name(resolveWalletConnection, "resolveWalletConnection");
|
|
628
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
629
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
630
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
631
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
632
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
633
|
+
}
|
|
634
|
+
__name(_ts_decorate, "_ts_decorate");
|
|
635
|
+
function _ts_metadata(k, v) {
|
|
636
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
637
|
+
}
|
|
638
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
639
|
+
function nowTimestamp() {
|
|
640
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
|
|
641
|
+
}
|
|
642
|
+
__name(nowTimestamp, "nowTimestamp");
|
|
643
|
+
var _WalletAccountEntity = class _WalletAccountEntity {
|
|
644
|
+
constructor() {
|
|
645
|
+
__publicField(this, "id");
|
|
646
|
+
__publicField(this, "ownerType");
|
|
647
|
+
__publicField(this, "ownerId");
|
|
648
|
+
__publicField(this, "currency");
|
|
649
|
+
__publicField(this, "availableBalance");
|
|
650
|
+
__publicField(this, "heldBalance");
|
|
651
|
+
__publicField(this, "createdBy");
|
|
652
|
+
__publicField(this, "createdDate");
|
|
653
|
+
__publicField(this, "modifiedBy");
|
|
654
|
+
__publicField(this, "modifiedDate");
|
|
655
|
+
}
|
|
656
|
+
setCreated() {
|
|
657
|
+
this.createdDate = nowTimestamp();
|
|
658
|
+
this.modifiedDate = nowTimestamp();
|
|
659
|
+
}
|
|
660
|
+
setModified() {
|
|
661
|
+
this.modifiedDate = nowTimestamp();
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
__name(_WalletAccountEntity, "WalletAccountEntity");
|
|
665
|
+
exports.WalletAccountEntity = _WalletAccountEntity;
|
|
666
|
+
_ts_decorate([
|
|
667
|
+
typeorm.PrimaryGeneratedColumn({
|
|
668
|
+
name: "id"
|
|
669
|
+
}),
|
|
670
|
+
_ts_metadata("design:type", Number)
|
|
671
|
+
], exports.WalletAccountEntity.prototype, "id", void 0);
|
|
672
|
+
_ts_decorate([
|
|
673
|
+
typeorm.Column({
|
|
674
|
+
name: "owner_type",
|
|
675
|
+
length: 32
|
|
676
|
+
}),
|
|
677
|
+
_ts_metadata("design:type", String)
|
|
678
|
+
], exports.WalletAccountEntity.prototype, "ownerType", void 0);
|
|
679
|
+
_ts_decorate([
|
|
680
|
+
typeorm.Column({
|
|
681
|
+
name: "owner_id"
|
|
682
|
+
}),
|
|
683
|
+
_ts_metadata("design:type", Number)
|
|
684
|
+
], exports.WalletAccountEntity.prototype, "ownerId", void 0);
|
|
685
|
+
_ts_decorate([
|
|
686
|
+
typeorm.Column({
|
|
687
|
+
name: "currency",
|
|
688
|
+
length: 8,
|
|
689
|
+
default: "INR"
|
|
690
|
+
}),
|
|
691
|
+
_ts_metadata("design:type", String)
|
|
692
|
+
], exports.WalletAccountEntity.prototype, "currency", void 0);
|
|
693
|
+
_ts_decorate([
|
|
694
|
+
typeorm.Column({
|
|
695
|
+
name: "available_balance",
|
|
696
|
+
type: "bigint",
|
|
697
|
+
default: 0
|
|
698
|
+
}),
|
|
699
|
+
_ts_metadata("design:type", String)
|
|
700
|
+
], exports.WalletAccountEntity.prototype, "availableBalance", void 0);
|
|
701
|
+
_ts_decorate([
|
|
702
|
+
typeorm.Column({
|
|
703
|
+
name: "held_balance",
|
|
704
|
+
type: "bigint",
|
|
705
|
+
default: 0
|
|
706
|
+
}),
|
|
707
|
+
_ts_metadata("design:type", String)
|
|
708
|
+
], exports.WalletAccountEntity.prototype, "heldBalance", void 0);
|
|
709
|
+
_ts_decorate([
|
|
710
|
+
typeorm.Column({
|
|
711
|
+
name: "created_by",
|
|
712
|
+
nullable: true
|
|
713
|
+
}),
|
|
714
|
+
_ts_metadata("design:type", Number)
|
|
715
|
+
], exports.WalletAccountEntity.prototype, "createdBy", void 0);
|
|
716
|
+
_ts_decorate([
|
|
717
|
+
typeorm.Column({
|
|
718
|
+
name: "created_date",
|
|
719
|
+
nullable: true
|
|
720
|
+
}),
|
|
721
|
+
_ts_metadata("design:type", String)
|
|
722
|
+
], exports.WalletAccountEntity.prototype, "createdDate", void 0);
|
|
723
|
+
_ts_decorate([
|
|
724
|
+
typeorm.Column({
|
|
725
|
+
name: "modified_by",
|
|
726
|
+
nullable: true
|
|
727
|
+
}),
|
|
728
|
+
_ts_metadata("design:type", Number)
|
|
729
|
+
], exports.WalletAccountEntity.prototype, "modifiedBy", void 0);
|
|
730
|
+
_ts_decorate([
|
|
731
|
+
typeorm.Column({
|
|
732
|
+
name: "modified_date",
|
|
733
|
+
nullable: true
|
|
734
|
+
}),
|
|
735
|
+
_ts_metadata("design:type", String)
|
|
736
|
+
], exports.WalletAccountEntity.prototype, "modifiedDate", void 0);
|
|
737
|
+
_ts_decorate([
|
|
738
|
+
typeorm.BeforeInsert(),
|
|
739
|
+
_ts_metadata("design:type", Function),
|
|
740
|
+
_ts_metadata("design:paramtypes", []),
|
|
741
|
+
_ts_metadata("design:returntype", void 0)
|
|
742
|
+
], exports.WalletAccountEntity.prototype, "setCreated", null);
|
|
743
|
+
_ts_decorate([
|
|
744
|
+
typeorm.BeforeUpdate(),
|
|
745
|
+
_ts_metadata("design:type", Function),
|
|
746
|
+
_ts_metadata("design:paramtypes", []),
|
|
747
|
+
_ts_metadata("design:returntype", void 0)
|
|
748
|
+
], exports.WalletAccountEntity.prototype, "setModified", null);
|
|
749
|
+
exports.WalletAccountEntity = _ts_decorate([
|
|
750
|
+
typeorm.Entity("wallet_account")
|
|
751
|
+
], exports.WalletAccountEntity);
|
|
752
|
+
var _WalletLedgerEntryEntity = class _WalletLedgerEntryEntity {
|
|
753
|
+
constructor() {
|
|
754
|
+
__publicField(this, "id");
|
|
755
|
+
__publicField(this, "accountId");
|
|
756
|
+
__publicField(this, "entryType");
|
|
757
|
+
__publicField(this, "amount");
|
|
758
|
+
__publicField(this, "balanceAfterAvailable");
|
|
759
|
+
__publicField(this, "balanceAfterHeld");
|
|
760
|
+
__publicField(this, "idempotencyKey");
|
|
761
|
+
__publicField(this, "referenceType");
|
|
762
|
+
__publicField(this, "referenceId");
|
|
763
|
+
__publicField(this, "metadata");
|
|
764
|
+
__publicField(this, "createdBy");
|
|
765
|
+
__publicField(this, "createdDate");
|
|
766
|
+
__publicField(this, "modifiedBy");
|
|
767
|
+
__publicField(this, "modifiedDate");
|
|
768
|
+
}
|
|
769
|
+
setCreated() {
|
|
770
|
+
this.createdDate = nowTimestamp();
|
|
771
|
+
this.modifiedDate = nowTimestamp();
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
__name(_WalletLedgerEntryEntity, "WalletLedgerEntryEntity");
|
|
775
|
+
exports.WalletLedgerEntryEntity = _WalletLedgerEntryEntity;
|
|
776
|
+
_ts_decorate([
|
|
777
|
+
typeorm.PrimaryGeneratedColumn({
|
|
778
|
+
name: "id"
|
|
779
|
+
}),
|
|
780
|
+
_ts_metadata("design:type", Number)
|
|
781
|
+
], exports.WalletLedgerEntryEntity.prototype, "id", void 0);
|
|
782
|
+
_ts_decorate([
|
|
783
|
+
typeorm.Column({
|
|
784
|
+
name: "account_id"
|
|
785
|
+
}),
|
|
786
|
+
_ts_metadata("design:type", Number)
|
|
787
|
+
], exports.WalletLedgerEntryEntity.prototype, "accountId", void 0);
|
|
788
|
+
_ts_decorate([
|
|
789
|
+
typeorm.Column({
|
|
790
|
+
name: "entry_type",
|
|
791
|
+
length: 32
|
|
792
|
+
}),
|
|
793
|
+
_ts_metadata("design:type", String)
|
|
794
|
+
], exports.WalletLedgerEntryEntity.prototype, "entryType", void 0);
|
|
795
|
+
_ts_decorate([
|
|
796
|
+
typeorm.Column({
|
|
797
|
+
name: "amount",
|
|
798
|
+
type: "bigint"
|
|
799
|
+
}),
|
|
800
|
+
_ts_metadata("design:type", String)
|
|
801
|
+
], exports.WalletLedgerEntryEntity.prototype, "amount", void 0);
|
|
802
|
+
_ts_decorate([
|
|
803
|
+
typeorm.Column({
|
|
804
|
+
name: "balance_after_available",
|
|
805
|
+
type: "bigint"
|
|
806
|
+
}),
|
|
807
|
+
_ts_metadata("design:type", String)
|
|
808
|
+
], exports.WalletLedgerEntryEntity.prototype, "balanceAfterAvailable", void 0);
|
|
809
|
+
_ts_decorate([
|
|
810
|
+
typeorm.Column({
|
|
811
|
+
name: "balance_after_held",
|
|
812
|
+
type: "bigint"
|
|
813
|
+
}),
|
|
814
|
+
_ts_metadata("design:type", String)
|
|
815
|
+
], exports.WalletLedgerEntryEntity.prototype, "balanceAfterHeld", void 0);
|
|
816
|
+
_ts_decorate([
|
|
817
|
+
typeorm.Column({
|
|
818
|
+
name: "idempotency_key",
|
|
819
|
+
length: 255,
|
|
820
|
+
unique: true
|
|
821
|
+
}),
|
|
822
|
+
_ts_metadata("design:type", String)
|
|
823
|
+
], exports.WalletLedgerEntryEntity.prototype, "idempotencyKey", void 0);
|
|
824
|
+
_ts_decorate([
|
|
825
|
+
typeorm.Column({
|
|
826
|
+
name: "reference_type",
|
|
827
|
+
length: 64,
|
|
828
|
+
nullable: true
|
|
829
|
+
}),
|
|
830
|
+
_ts_metadata("design:type", String)
|
|
831
|
+
], exports.WalletLedgerEntryEntity.prototype, "referenceType", void 0);
|
|
832
|
+
_ts_decorate([
|
|
833
|
+
typeorm.Column({
|
|
834
|
+
name: "reference_id",
|
|
835
|
+
length: 128,
|
|
836
|
+
nullable: true
|
|
837
|
+
}),
|
|
838
|
+
_ts_metadata("design:type", String)
|
|
839
|
+
], exports.WalletLedgerEntryEntity.prototype, "referenceId", void 0);
|
|
840
|
+
_ts_decorate([
|
|
841
|
+
typeorm.Column({
|
|
842
|
+
name: "metadata",
|
|
843
|
+
type: "json",
|
|
844
|
+
nullable: true
|
|
845
|
+
}),
|
|
846
|
+
_ts_metadata("design:type", typeof Record === "undefined" ? Object : Record)
|
|
847
|
+
], exports.WalletLedgerEntryEntity.prototype, "metadata", void 0);
|
|
848
|
+
_ts_decorate([
|
|
849
|
+
typeorm.Column({
|
|
850
|
+
name: "created_by",
|
|
851
|
+
nullable: true
|
|
852
|
+
}),
|
|
853
|
+
_ts_metadata("design:type", Number)
|
|
854
|
+
], exports.WalletLedgerEntryEntity.prototype, "createdBy", void 0);
|
|
855
|
+
_ts_decorate([
|
|
856
|
+
typeorm.Column({
|
|
857
|
+
name: "created_date",
|
|
858
|
+
nullable: true
|
|
859
|
+
}),
|
|
860
|
+
_ts_metadata("design:type", String)
|
|
861
|
+
], exports.WalletLedgerEntryEntity.prototype, "createdDate", void 0);
|
|
862
|
+
_ts_decorate([
|
|
863
|
+
typeorm.Column({
|
|
864
|
+
name: "modified_by",
|
|
865
|
+
nullable: true
|
|
866
|
+
}),
|
|
867
|
+
_ts_metadata("design:type", Number)
|
|
868
|
+
], exports.WalletLedgerEntryEntity.prototype, "modifiedBy", void 0);
|
|
869
|
+
_ts_decorate([
|
|
870
|
+
typeorm.Column({
|
|
871
|
+
name: "modified_date",
|
|
872
|
+
nullable: true
|
|
873
|
+
}),
|
|
874
|
+
_ts_metadata("design:type", String)
|
|
875
|
+
], exports.WalletLedgerEntryEntity.prototype, "modifiedDate", void 0);
|
|
876
|
+
_ts_decorate([
|
|
877
|
+
typeorm.BeforeInsert(),
|
|
878
|
+
_ts_metadata("design:type", Function),
|
|
879
|
+
_ts_metadata("design:paramtypes", []),
|
|
880
|
+
_ts_metadata("design:returntype", void 0)
|
|
881
|
+
], exports.WalletLedgerEntryEntity.prototype, "setCreated", null);
|
|
882
|
+
exports.WalletLedgerEntryEntity = _ts_decorate([
|
|
883
|
+
typeorm.Entity("wallet_ledger_entry")
|
|
884
|
+
], exports.WalletLedgerEntryEntity);
|
|
885
|
+
var _WalletHoldEntity = class _WalletHoldEntity {
|
|
886
|
+
constructor() {
|
|
887
|
+
__publicField(this, "id");
|
|
888
|
+
__publicField(this, "sourceAccountId");
|
|
889
|
+
__publicField(this, "targetAccountId");
|
|
890
|
+
__publicField(this, "amount");
|
|
891
|
+
__publicField(this, "status");
|
|
892
|
+
__publicField(this, "referenceType");
|
|
893
|
+
__publicField(this, "referenceId");
|
|
894
|
+
__publicField(this, "idempotencyKey");
|
|
895
|
+
__publicField(this, "createdBy");
|
|
896
|
+
__publicField(this, "createdDate");
|
|
897
|
+
__publicField(this, "modifiedBy");
|
|
898
|
+
__publicField(this, "modifiedDate");
|
|
899
|
+
}
|
|
900
|
+
setCreated() {
|
|
901
|
+
this.createdDate = nowTimestamp();
|
|
902
|
+
this.modifiedDate = nowTimestamp();
|
|
903
|
+
}
|
|
904
|
+
setModified() {
|
|
905
|
+
this.modifiedDate = nowTimestamp();
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
__name(_WalletHoldEntity, "WalletHoldEntity");
|
|
909
|
+
exports.WalletHoldEntity = _WalletHoldEntity;
|
|
910
|
+
_ts_decorate([
|
|
911
|
+
typeorm.PrimaryGeneratedColumn({
|
|
912
|
+
name: "id"
|
|
913
|
+
}),
|
|
914
|
+
_ts_metadata("design:type", Number)
|
|
915
|
+
], exports.WalletHoldEntity.prototype, "id", void 0);
|
|
916
|
+
_ts_decorate([
|
|
917
|
+
typeorm.Column({
|
|
918
|
+
name: "source_account_id"
|
|
919
|
+
}),
|
|
920
|
+
_ts_metadata("design:type", Number)
|
|
921
|
+
], exports.WalletHoldEntity.prototype, "sourceAccountId", void 0);
|
|
922
|
+
_ts_decorate([
|
|
923
|
+
typeorm.Column({
|
|
924
|
+
name: "target_account_id"
|
|
925
|
+
}),
|
|
926
|
+
_ts_metadata("design:type", Number)
|
|
927
|
+
], exports.WalletHoldEntity.prototype, "targetAccountId", void 0);
|
|
928
|
+
_ts_decorate([
|
|
929
|
+
typeorm.Column({
|
|
930
|
+
name: "amount",
|
|
931
|
+
type: "bigint"
|
|
932
|
+
}),
|
|
933
|
+
_ts_metadata("design:type", String)
|
|
934
|
+
], exports.WalletHoldEntity.prototype, "amount", void 0);
|
|
935
|
+
_ts_decorate([
|
|
936
|
+
typeorm.Column({
|
|
937
|
+
name: "status",
|
|
938
|
+
length: 16,
|
|
939
|
+
default: "active"
|
|
940
|
+
}),
|
|
941
|
+
_ts_metadata("design:type", String)
|
|
942
|
+
], exports.WalletHoldEntity.prototype, "status", void 0);
|
|
943
|
+
_ts_decorate([
|
|
944
|
+
typeorm.Column({
|
|
945
|
+
name: "reference_type",
|
|
946
|
+
length: 64
|
|
947
|
+
}),
|
|
948
|
+
_ts_metadata("design:type", String)
|
|
949
|
+
], exports.WalletHoldEntity.prototype, "referenceType", void 0);
|
|
950
|
+
_ts_decorate([
|
|
951
|
+
typeorm.Column({
|
|
952
|
+
name: "reference_id",
|
|
953
|
+
length: 128
|
|
954
|
+
}),
|
|
955
|
+
_ts_metadata("design:type", String)
|
|
956
|
+
], exports.WalletHoldEntity.prototype, "referenceId", void 0);
|
|
957
|
+
_ts_decorate([
|
|
958
|
+
typeorm.Column({
|
|
959
|
+
name: "idempotency_key",
|
|
960
|
+
length: 255
|
|
961
|
+
}),
|
|
962
|
+
_ts_metadata("design:type", String)
|
|
963
|
+
], exports.WalletHoldEntity.prototype, "idempotencyKey", void 0);
|
|
964
|
+
_ts_decorate([
|
|
965
|
+
typeorm.Column({
|
|
966
|
+
name: "created_by",
|
|
967
|
+
nullable: true
|
|
968
|
+
}),
|
|
969
|
+
_ts_metadata("design:type", Number)
|
|
970
|
+
], exports.WalletHoldEntity.prototype, "createdBy", void 0);
|
|
971
|
+
_ts_decorate([
|
|
972
|
+
typeorm.Column({
|
|
973
|
+
name: "created_date",
|
|
974
|
+
nullable: true
|
|
975
|
+
}),
|
|
976
|
+
_ts_metadata("design:type", String)
|
|
977
|
+
], exports.WalletHoldEntity.prototype, "createdDate", void 0);
|
|
978
|
+
_ts_decorate([
|
|
979
|
+
typeorm.Column({
|
|
980
|
+
name: "modified_by",
|
|
981
|
+
nullable: true
|
|
982
|
+
}),
|
|
983
|
+
_ts_metadata("design:type", Number)
|
|
984
|
+
], exports.WalletHoldEntity.prototype, "modifiedBy", void 0);
|
|
985
|
+
_ts_decorate([
|
|
986
|
+
typeorm.Column({
|
|
987
|
+
name: "modified_date",
|
|
988
|
+
nullable: true
|
|
989
|
+
}),
|
|
990
|
+
_ts_metadata("design:type", String)
|
|
991
|
+
], exports.WalletHoldEntity.prototype, "modifiedDate", void 0);
|
|
992
|
+
_ts_decorate([
|
|
993
|
+
typeorm.BeforeInsert(),
|
|
994
|
+
_ts_metadata("design:type", Function),
|
|
995
|
+
_ts_metadata("design:paramtypes", []),
|
|
996
|
+
_ts_metadata("design:returntype", void 0)
|
|
997
|
+
], exports.WalletHoldEntity.prototype, "setCreated", null);
|
|
998
|
+
_ts_decorate([
|
|
999
|
+
typeorm.BeforeUpdate(),
|
|
1000
|
+
_ts_metadata("design:type", Function),
|
|
1001
|
+
_ts_metadata("design:paramtypes", []),
|
|
1002
|
+
_ts_metadata("design:returntype", void 0)
|
|
1003
|
+
], exports.WalletHoldEntity.prototype, "setModified", null);
|
|
1004
|
+
exports.WalletHoldEntity = _ts_decorate([
|
|
1005
|
+
typeorm.Entity("wallet_hold")
|
|
1006
|
+
], exports.WalletHoldEntity);
|
|
1007
|
+
|
|
1008
|
+
// src/hooks/reconciliation.ts
|
|
1009
|
+
async function runWalletReconciliation() {
|
|
1010
|
+
const parityDeltas = await findVendorPaymentHoldParityDeltas();
|
|
1011
|
+
const cacheMismatches = await findCacheLedgerMismatches();
|
|
1012
|
+
return {
|
|
1013
|
+
parityDeltas,
|
|
1014
|
+
cacheMismatches
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
__name(runWalletReconciliation, "runWalletReconciliation");
|
|
1018
|
+
async function findVendorPaymentHoldParityDeltas() {
|
|
1019
|
+
const rows = await resolveWalletConnection().query(`
|
|
1020
|
+
SELECT
|
|
1021
|
+
vo.order_id AS orderId,
|
|
1022
|
+
vp.vendor_order_id AS vendorOrderId,
|
|
1023
|
+
vp.amount AS vendorPaymentAmount,
|
|
1024
|
+
wh.amount AS holdAmount,
|
|
1025
|
+
wh.status AS holdStatus
|
|
1026
|
+
FROM vendor_payment vp
|
|
1027
|
+
INNER JOIN vendor_orders vo ON vo.vendor_order_id = vp.vendor_order_id
|
|
1028
|
+
LEFT JOIN wallet_hold wh
|
|
1029
|
+
ON wh.reference_type = 'vendor_order'
|
|
1030
|
+
AND wh.reference_id = CAST(vp.vendor_order_id AS CHAR)
|
|
1031
|
+
WHERE vp.vendor_order_id IS NOT NULL
|
|
1032
|
+
`);
|
|
1033
|
+
const deltas = [];
|
|
1034
|
+
for (const row of rows) {
|
|
1035
|
+
const vendorPaymentRupees = Number(row.vendorPaymentAmount) || 0;
|
|
1036
|
+
const holdPaise = row.holdAmount != null ? Number(row.holdAmount) : 0;
|
|
1037
|
+
const holdRupees = fromMinorUnit(holdPaise);
|
|
1038
|
+
const delta = Math.abs(vendorPaymentRupees - holdRupees);
|
|
1039
|
+
if (delta > 0.01 && row.holdStatus === "active") {
|
|
1040
|
+
deltas.push({
|
|
1041
|
+
orderId: Number(row.orderId),
|
|
1042
|
+
vendorOrderId: Number(row.vendorOrderId),
|
|
1043
|
+
vendorPaymentRupees,
|
|
1044
|
+
holdPaise,
|
|
1045
|
+
deltaRupees: delta
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return deltas;
|
|
1050
|
+
}
|
|
1051
|
+
__name(findVendorPaymentHoldParityDeltas, "findVendorPaymentHoldParityDeltas");
|
|
1052
|
+
async function findCacheLedgerMismatches() {
|
|
1053
|
+
const connection = resolveWalletConnection();
|
|
1054
|
+
const accounts = await connection.getRepository(exports.WalletAccountEntity).find();
|
|
1055
|
+
const mismatches = [];
|
|
1056
|
+
for (const account of accounts) {
|
|
1057
|
+
const lastEntry = await connection.getRepository(exports.WalletLedgerEntryEntity).findOne({
|
|
1058
|
+
where: {
|
|
1059
|
+
accountId: account.id
|
|
1060
|
+
},
|
|
1061
|
+
order: {
|
|
1062
|
+
id: "DESC"
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
if (!lastEntry) {
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
const cachedAvailable = Number(account.availableBalance);
|
|
1069
|
+
const cachedHeld = Number(account.heldBalance);
|
|
1070
|
+
const ledgerAvailable = Number(lastEntry.balanceAfterAvailable);
|
|
1071
|
+
const ledgerHeld = Number(lastEntry.balanceAfterHeld);
|
|
1072
|
+
if (cachedAvailable !== ledgerAvailable || cachedHeld !== ledgerHeld) {
|
|
1073
|
+
mismatches.push({
|
|
1074
|
+
accountId: account.id,
|
|
1075
|
+
cachedAvailable,
|
|
1076
|
+
cachedHeld,
|
|
1077
|
+
ledgerAvailable,
|
|
1078
|
+
ledgerHeld
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
return mismatches;
|
|
1083
|
+
}
|
|
1084
|
+
__name(findCacheLedgerMismatches, "findCacheLedgerMismatches");
|
|
1085
|
+
|
|
1086
|
+
// src/hooks/index.ts
|
|
1087
|
+
function createLifecycleHooks(runtime) {
|
|
1088
|
+
return {
|
|
1089
|
+
...createOrderHooks(runtime),
|
|
1090
|
+
...createSettlementHooks(runtime),
|
|
1091
|
+
...createRefundHooks(runtime)
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
__name(createLifecycleHooks, "createLifecycleHooks");
|
|
1095
|
+
function _ts_decorate2(decorators, target, key, desc) {
|
|
1096
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1097
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1098
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1099
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1100
|
+
}
|
|
1101
|
+
__name(_ts_decorate2, "_ts_decorate");
|
|
1102
|
+
function _ts_metadata2(k, v) {
|
|
1103
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1104
|
+
}
|
|
1105
|
+
__name(_ts_metadata2, "_ts_metadata");
|
|
1106
|
+
function _ts_param(paramIndex, decorator) {
|
|
1107
|
+
return function(target, key) {
|
|
1108
|
+
decorator(target, key, paramIndex);
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
__name(_ts_param, "_ts_param");
|
|
1112
|
+
var _a;
|
|
1113
|
+
var WalletCreditDebitRequest = (_a = class {
|
|
1114
|
+
constructor() {
|
|
1115
|
+
__publicField(this, "ownerType");
|
|
1116
|
+
__publicField(this, "ownerId");
|
|
1117
|
+
__publicField(this, "amount");
|
|
1118
|
+
__publicField(this, "currency");
|
|
1119
|
+
__publicField(this, "reason");
|
|
1120
|
+
}
|
|
1121
|
+
}, __name(_a, "WalletCreditDebitRequest"), _a);
|
|
1122
|
+
_ts_decorate2([
|
|
1123
|
+
classValidator.IsString(),
|
|
1124
|
+
classValidator.IsNotEmpty(),
|
|
1125
|
+
_ts_metadata2("design:type", typeof WalletAccountType === "undefined" ? Object : WalletAccountType)
|
|
1126
|
+
], WalletCreditDebitRequest.prototype, "ownerType", void 0);
|
|
1127
|
+
_ts_decorate2([
|
|
1128
|
+
classValidator.IsInt(),
|
|
1129
|
+
classValidator.Min(0),
|
|
1130
|
+
_ts_metadata2("design:type", Number)
|
|
1131
|
+
], WalletCreditDebitRequest.prototype, "ownerId", void 0);
|
|
1132
|
+
_ts_decorate2([
|
|
1133
|
+
classValidator.IsNumber(),
|
|
1134
|
+
classValidator.Min(0.01),
|
|
1135
|
+
_ts_metadata2("design:type", Number)
|
|
1136
|
+
], WalletCreditDebitRequest.prototype, "amount", void 0);
|
|
1137
|
+
_ts_decorate2([
|
|
1138
|
+
classValidator.IsOptional(),
|
|
1139
|
+
classValidator.IsString(),
|
|
1140
|
+
_ts_metadata2("design:type", String)
|
|
1141
|
+
], WalletCreditDebitRequest.prototype, "currency", void 0);
|
|
1142
|
+
_ts_decorate2([
|
|
1143
|
+
classValidator.IsOptional(),
|
|
1144
|
+
classValidator.IsString(),
|
|
1145
|
+
_ts_metadata2("design:type", String)
|
|
1146
|
+
], WalletCreditDebitRequest.prototype, "reason", void 0);
|
|
1147
|
+
var _AdminWalletController = class _AdminWalletController {
|
|
1148
|
+
get plugin() {
|
|
1149
|
+
return resolveWalletPlugin();
|
|
1150
|
+
}
|
|
1151
|
+
assertEnabled(response) {
|
|
1152
|
+
if (!this.plugin.isEnabled()) {
|
|
1153
|
+
response.status(404).send({
|
|
1154
|
+
status: 0,
|
|
1155
|
+
message: "Wallet feature is disabled"
|
|
1156
|
+
});
|
|
1157
|
+
return false;
|
|
1158
|
+
}
|
|
1159
|
+
return true;
|
|
1160
|
+
}
|
|
1161
|
+
async listAccounts(limit = 50, offset = 0, response) {
|
|
1162
|
+
if (!this.assertEnabled(response)) {
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const rows = await resolveWalletConnection().getRepository(exports.WalletAccountEntity).find({
|
|
1166
|
+
take: limit,
|
|
1167
|
+
skip: offset,
|
|
1168
|
+
order: {
|
|
1169
|
+
id: "DESC"
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
response.status(200).send({
|
|
1173
|
+
status: 1,
|
|
1174
|
+
data: rows.map((row) => ({
|
|
1175
|
+
id: row.id,
|
|
1176
|
+
ownerType: row.ownerType,
|
|
1177
|
+
ownerId: row.ownerId,
|
|
1178
|
+
currency: row.currency,
|
|
1179
|
+
available: fromMinorUnit(Number(row.availableBalance)),
|
|
1180
|
+
held: fromMinorUnit(Number(row.heldBalance)),
|
|
1181
|
+
total: fromMinorUnit(Number(row.availableBalance) + Number(row.heldBalance))
|
|
1182
|
+
}))
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
async listTransactions(accountId, limit = 50, offset = 0, response) {
|
|
1186
|
+
if (!this.assertEnabled(response)) {
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
const entries = await this.plugin.client.getTransactions({
|
|
1190
|
+
accountId,
|
|
1191
|
+
limit,
|
|
1192
|
+
offset
|
|
1193
|
+
});
|
|
1194
|
+
response.status(200).send({
|
|
1195
|
+
status: 1,
|
|
1196
|
+
data: entries.map((e) => ({
|
|
1197
|
+
...e,
|
|
1198
|
+
amount: fromMinorUnit(e.amount),
|
|
1199
|
+
balanceAfterAvailable: fromMinorUnit(e.balanceAfterAvailable),
|
|
1200
|
+
balanceAfterHeld: fromMinorUnit(e.balanceAfterHeld)
|
|
1201
|
+
}))
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
async credit(body, request, response) {
|
|
1205
|
+
if (!this.assertEnabled(response)) {
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
const currency = body.currency || "INR";
|
|
1209
|
+
const account = await this.plugin.client.getOrCreateAccount(body.ownerType, body.ownerId, currency);
|
|
1210
|
+
const result = await this.plugin.client.credit({
|
|
1211
|
+
accountId: account.id,
|
|
1212
|
+
amount: toMinorUnit(body.amount),
|
|
1213
|
+
idempotencyKey: `admin:credit:${body.ownerType}:${body.ownerId}:${Date.now()}`,
|
|
1214
|
+
reference: {
|
|
1215
|
+
referenceType: "admin_adjustment",
|
|
1216
|
+
referenceId: String(request.user?.userId || 0)
|
|
1217
|
+
},
|
|
1218
|
+
metadata: {
|
|
1219
|
+
reason: body.reason
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
await this.emitAdminMutation({
|
|
1223
|
+
event: "wallet_admin_credit",
|
|
1224
|
+
actorId: request.user?.userId,
|
|
1225
|
+
actorRole: "admin",
|
|
1226
|
+
amount: body.amount,
|
|
1227
|
+
after: {
|
|
1228
|
+
accountId: account.id,
|
|
1229
|
+
entryId: result.entry.id
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
response.status(200).send({
|
|
1233
|
+
status: 1,
|
|
1234
|
+
message: "Wallet credited successfully",
|
|
1235
|
+
data: {
|
|
1236
|
+
accountId: account.id,
|
|
1237
|
+
available: fromMinorUnit(result.account.availableBalance)
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
async debit(body, request, response) {
|
|
1242
|
+
if (!this.assertEnabled(response)) {
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
const currency = body.currency || "INR";
|
|
1246
|
+
const account = await this.plugin.client.getOrCreateAccount(body.ownerType, body.ownerId, currency);
|
|
1247
|
+
const result = await this.plugin.client.debit({
|
|
1248
|
+
accountId: account.id,
|
|
1249
|
+
amount: toMinorUnit(body.amount),
|
|
1250
|
+
idempotencyKey: `admin:debit:${body.ownerType}:${body.ownerId}:${Date.now()}`,
|
|
1251
|
+
reference: {
|
|
1252
|
+
referenceType: "admin_adjustment",
|
|
1253
|
+
referenceId: String(request.user?.userId || 0)
|
|
1254
|
+
},
|
|
1255
|
+
metadata: {
|
|
1256
|
+
reason: body.reason
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
await this.emitAdminMutation({
|
|
1260
|
+
event: "wallet_admin_debit",
|
|
1261
|
+
actorId: request.user?.userId,
|
|
1262
|
+
actorRole: "admin",
|
|
1263
|
+
amount: body.amount,
|
|
1264
|
+
after: {
|
|
1265
|
+
accountId: account.id,
|
|
1266
|
+
entryId: result.entry.id
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
response.status(200).send({
|
|
1270
|
+
status: 1,
|
|
1271
|
+
message: "Wallet debited successfully",
|
|
1272
|
+
data: {
|
|
1273
|
+
accountId: account.id,
|
|
1274
|
+
available: fromMinorUnit(result.account.availableBalance)
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
async emitAdminMutation(event) {
|
|
1279
|
+
const handler = this.plugin.onAdminMutation;
|
|
1280
|
+
if (handler) {
|
|
1281
|
+
await handler(event);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
__name(_AdminWalletController, "AdminWalletController");
|
|
1286
|
+
exports.AdminWalletController = _AdminWalletController;
|
|
1287
|
+
_ts_decorate2([
|
|
1288
|
+
routingControllers.Get("/accounts"),
|
|
1289
|
+
routingControllers.Authorized([
|
|
1290
|
+
"admin"
|
|
1291
|
+
]),
|
|
1292
|
+
_ts_param(0, routingControllers.QueryParam("limit")),
|
|
1293
|
+
_ts_param(1, routingControllers.QueryParam("offset")),
|
|
1294
|
+
_ts_param(2, routingControllers.Res()),
|
|
1295
|
+
_ts_metadata2("design:type", Function),
|
|
1296
|
+
_ts_metadata2("design:paramtypes", [
|
|
1297
|
+
Number,
|
|
1298
|
+
Number,
|
|
1299
|
+
Object
|
|
1300
|
+
]),
|
|
1301
|
+
_ts_metadata2("design:returntype", Promise)
|
|
1302
|
+
], exports.AdminWalletController.prototype, "listAccounts", null);
|
|
1303
|
+
_ts_decorate2([
|
|
1304
|
+
routingControllers.Get("/transactions/:accountId"),
|
|
1305
|
+
routingControllers.Authorized([
|
|
1306
|
+
"admin"
|
|
1307
|
+
]),
|
|
1308
|
+
_ts_param(0, routingControllers.Param("accountId")),
|
|
1309
|
+
_ts_param(1, routingControllers.QueryParam("limit")),
|
|
1310
|
+
_ts_param(2, routingControllers.QueryParam("offset")),
|
|
1311
|
+
_ts_param(3, routingControllers.Res()),
|
|
1312
|
+
_ts_metadata2("design:type", Function),
|
|
1313
|
+
_ts_metadata2("design:paramtypes", [
|
|
1314
|
+
Number,
|
|
1315
|
+
Number,
|
|
1316
|
+
Number,
|
|
1317
|
+
Object
|
|
1318
|
+
]),
|
|
1319
|
+
_ts_metadata2("design:returntype", Promise)
|
|
1320
|
+
], exports.AdminWalletController.prototype, "listTransactions", null);
|
|
1321
|
+
_ts_decorate2([
|
|
1322
|
+
routingControllers.Post("/credit"),
|
|
1323
|
+
routingControllers.Authorized([
|
|
1324
|
+
"admin"
|
|
1325
|
+
]),
|
|
1326
|
+
_ts_param(0, routingControllers.Body({
|
|
1327
|
+
validate: true
|
|
1328
|
+
})),
|
|
1329
|
+
_ts_param(1, routingControllers.Req()),
|
|
1330
|
+
_ts_param(2, routingControllers.Res()),
|
|
1331
|
+
_ts_metadata2("design:type", Function),
|
|
1332
|
+
_ts_metadata2("design:paramtypes", [
|
|
1333
|
+
typeof WalletCreditDebitRequest === "undefined" ? Object : WalletCreditDebitRequest,
|
|
1334
|
+
Object,
|
|
1335
|
+
Object
|
|
1336
|
+
]),
|
|
1337
|
+
_ts_metadata2("design:returntype", Promise)
|
|
1338
|
+
], exports.AdminWalletController.prototype, "credit", null);
|
|
1339
|
+
_ts_decorate2([
|
|
1340
|
+
routingControllers.Post("/debit"),
|
|
1341
|
+
routingControllers.Authorized([
|
|
1342
|
+
"admin"
|
|
1343
|
+
]),
|
|
1344
|
+
_ts_param(0, routingControllers.Body({
|
|
1345
|
+
validate: true
|
|
1346
|
+
})),
|
|
1347
|
+
_ts_param(1, routingControllers.Req()),
|
|
1348
|
+
_ts_param(2, routingControllers.Res()),
|
|
1349
|
+
_ts_metadata2("design:type", Function),
|
|
1350
|
+
_ts_metadata2("design:paramtypes", [
|
|
1351
|
+
typeof WalletCreditDebitRequest === "undefined" ? Object : WalletCreditDebitRequest,
|
|
1352
|
+
Object,
|
|
1353
|
+
Object
|
|
1354
|
+
]),
|
|
1355
|
+
_ts_metadata2("design:returntype", Promise)
|
|
1356
|
+
], exports.AdminWalletController.prototype, "debit", null);
|
|
1357
|
+
exports.AdminWalletController = _ts_decorate2([
|
|
1358
|
+
routingControllers.JsonController("/admin/wallet")
|
|
1359
|
+
], exports.AdminWalletController);
|
|
1360
|
+
function _ts_decorate3(decorators, target, key, desc) {
|
|
1361
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1362
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1363
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1364
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1365
|
+
}
|
|
1366
|
+
__name(_ts_decorate3, "_ts_decorate");
|
|
1367
|
+
function _ts_metadata3(k, v) {
|
|
1368
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1369
|
+
}
|
|
1370
|
+
__name(_ts_metadata3, "_ts_metadata");
|
|
1371
|
+
function _ts_param2(paramIndex, decorator) {
|
|
1372
|
+
return function(target, key) {
|
|
1373
|
+
decorator(target, key, paramIndex);
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
__name(_ts_param2, "_ts_param");
|
|
1377
|
+
var _CustomerWalletController = class _CustomerWalletController {
|
|
1378
|
+
get plugin() {
|
|
1379
|
+
return resolveWalletPlugin();
|
|
1380
|
+
}
|
|
1381
|
+
assertEnabled(response) {
|
|
1382
|
+
if (!this.plugin.isEnabled()) {
|
|
1383
|
+
response.status(404).send({
|
|
1384
|
+
status: 0,
|
|
1385
|
+
message: "Wallet feature is disabled"
|
|
1386
|
+
});
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1389
|
+
return true;
|
|
1390
|
+
}
|
|
1391
|
+
async getBalance(request, response) {
|
|
1392
|
+
if (!this.assertEnabled(response)) {
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
const customerId = request.user?.id ?? 0;
|
|
1396
|
+
const account = await this.plugin.client.getOrCreateAccount(WalletAccountType.CUSTOMER, customerId, "INR");
|
|
1397
|
+
const balance = await this.plugin.client.getBalance(account.id);
|
|
1398
|
+
response.status(200).send({
|
|
1399
|
+
status: 1,
|
|
1400
|
+
data: {
|
|
1401
|
+
available: fromMinorUnit(balance.available),
|
|
1402
|
+
held: fromMinorUnit(balance.held),
|
|
1403
|
+
total: fromMinorUnit(balance.total),
|
|
1404
|
+
currency: account.currency
|
|
1405
|
+
}
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
async getTransactions(request, limit = 50, offset = 0, response) {
|
|
1409
|
+
if (!this.assertEnabled(response)) {
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
const customerId = request.user?.id ?? 0;
|
|
1413
|
+
const account = await this.plugin.client.getOrCreateAccount(WalletAccountType.CUSTOMER, customerId, "INR");
|
|
1414
|
+
const entries = await this.plugin.client.getTransactions({
|
|
1415
|
+
accountId: account.id,
|
|
1416
|
+
limit,
|
|
1417
|
+
offset
|
|
1418
|
+
});
|
|
1419
|
+
response.status(200).send({
|
|
1420
|
+
status: 1,
|
|
1421
|
+
data: entries.map((e) => ({
|
|
1422
|
+
id: e.id,
|
|
1423
|
+
entryType: e.entryType,
|
|
1424
|
+
amount: fromMinorUnit(e.amount),
|
|
1425
|
+
referenceType: e.referenceType,
|
|
1426
|
+
referenceId: e.referenceId,
|
|
1427
|
+
createdAt: e.createdAt
|
|
1428
|
+
}))
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
__name(_CustomerWalletController, "CustomerWalletController");
|
|
1433
|
+
exports.CustomerWalletController = _CustomerWalletController;
|
|
1434
|
+
_ts_decorate3([
|
|
1435
|
+
routingControllers.Get("/balance"),
|
|
1436
|
+
routingControllers.Authorized("customer"),
|
|
1437
|
+
_ts_param2(0, routingControllers.Req()),
|
|
1438
|
+
_ts_param2(1, routingControllers.Res()),
|
|
1439
|
+
_ts_metadata3("design:type", Function),
|
|
1440
|
+
_ts_metadata3("design:paramtypes", [
|
|
1441
|
+
Object,
|
|
1442
|
+
Object
|
|
1443
|
+
]),
|
|
1444
|
+
_ts_metadata3("design:returntype", Promise)
|
|
1445
|
+
], exports.CustomerWalletController.prototype, "getBalance", null);
|
|
1446
|
+
_ts_decorate3([
|
|
1447
|
+
routingControllers.Get("/transactions"),
|
|
1448
|
+
routingControllers.Authorized("customer"),
|
|
1449
|
+
_ts_param2(0, routingControllers.Req()),
|
|
1450
|
+
_ts_param2(1, routingControllers.QueryParam("limit")),
|
|
1451
|
+
_ts_param2(2, routingControllers.QueryParam("offset")),
|
|
1452
|
+
_ts_param2(3, routingControllers.Res()),
|
|
1453
|
+
_ts_metadata3("design:type", Function),
|
|
1454
|
+
_ts_metadata3("design:paramtypes", [
|
|
1455
|
+
Object,
|
|
1456
|
+
Number,
|
|
1457
|
+
Number,
|
|
1458
|
+
Object
|
|
1459
|
+
]),
|
|
1460
|
+
_ts_metadata3("design:returntype", Promise)
|
|
1461
|
+
], exports.CustomerWalletController.prototype, "getTransactions", null);
|
|
1462
|
+
exports.CustomerWalletController = _ts_decorate3([
|
|
1463
|
+
routingControllers.JsonController("/customer/wallet")
|
|
1464
|
+
], exports.CustomerWalletController);
|
|
1465
|
+
function _ts_decorate4(decorators, target, key, desc) {
|
|
1466
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1467
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1468
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1469
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1470
|
+
}
|
|
1471
|
+
__name(_ts_decorate4, "_ts_decorate");
|
|
1472
|
+
function _ts_metadata4(k, v) {
|
|
1473
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
1474
|
+
}
|
|
1475
|
+
__name(_ts_metadata4, "_ts_metadata");
|
|
1476
|
+
function _ts_param3(paramIndex, decorator) {
|
|
1477
|
+
return function(target, key) {
|
|
1478
|
+
decorator(target, key, paramIndex);
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
__name(_ts_param3, "_ts_param");
|
|
1482
|
+
var _VendorWalletController = class _VendorWalletController {
|
|
1483
|
+
get plugin() {
|
|
1484
|
+
return resolveWalletPlugin();
|
|
1485
|
+
}
|
|
1486
|
+
assertEnabled(response) {
|
|
1487
|
+
if (!this.plugin.isEnabled()) {
|
|
1488
|
+
response.status(404).send({
|
|
1489
|
+
status: 0,
|
|
1490
|
+
message: "Wallet feature is disabled"
|
|
1491
|
+
});
|
|
1492
|
+
return false;
|
|
1493
|
+
}
|
|
1494
|
+
return true;
|
|
1495
|
+
}
|
|
1496
|
+
async getBalance(request, response) {
|
|
1497
|
+
if (!this.assertEnabled(response)) {
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
const vendorId = request.user?.vendorId ?? 0;
|
|
1501
|
+
const account = await this.plugin.client.getOrCreateAccount(WalletAccountType.VENDOR, vendorId, "INR");
|
|
1502
|
+
const balance = await this.plugin.client.getBalance(account.id);
|
|
1503
|
+
response.status(200).send({
|
|
1504
|
+
status: 1,
|
|
1505
|
+
data: {
|
|
1506
|
+
available: fromMinorUnit(balance.available),
|
|
1507
|
+
held: fromMinorUnit(balance.held),
|
|
1508
|
+
total: fromMinorUnit(balance.total),
|
|
1509
|
+
currency: account.currency
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
async getTransactions(request, limit = 50, offset = 0, response) {
|
|
1514
|
+
if (!this.assertEnabled(response)) {
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
const vendorId = request.user?.vendorId ?? 0;
|
|
1518
|
+
const account = await this.plugin.client.getOrCreateAccount(WalletAccountType.VENDOR, vendorId, "INR");
|
|
1519
|
+
const entries = await this.plugin.client.getTransactions({
|
|
1520
|
+
accountId: account.id,
|
|
1521
|
+
limit,
|
|
1522
|
+
offset
|
|
1523
|
+
});
|
|
1524
|
+
response.status(200).send({
|
|
1525
|
+
status: 1,
|
|
1526
|
+
data: entries.map((e) => ({
|
|
1527
|
+
id: e.id,
|
|
1528
|
+
entryType: e.entryType,
|
|
1529
|
+
amount: fromMinorUnit(e.amount),
|
|
1530
|
+
referenceType: e.referenceType,
|
|
1531
|
+
referenceId: e.referenceId,
|
|
1532
|
+
createdAt: e.createdAt
|
|
1533
|
+
}))
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
__name(_VendorWalletController, "VendorWalletController");
|
|
1538
|
+
exports.VendorWalletController = _VendorWalletController;
|
|
1539
|
+
_ts_decorate4([
|
|
1540
|
+
routingControllers.Get("/balance"),
|
|
1541
|
+
routingControllers.Authorized("vendor"),
|
|
1542
|
+
_ts_param3(0, routingControllers.Req()),
|
|
1543
|
+
_ts_param3(1, routingControllers.Res()),
|
|
1544
|
+
_ts_metadata4("design:type", Function),
|
|
1545
|
+
_ts_metadata4("design:paramtypes", [
|
|
1546
|
+
Object,
|
|
1547
|
+
Object
|
|
1548
|
+
]),
|
|
1549
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1550
|
+
], exports.VendorWalletController.prototype, "getBalance", null);
|
|
1551
|
+
_ts_decorate4([
|
|
1552
|
+
routingControllers.Get("/transactions"),
|
|
1553
|
+
routingControllers.Authorized("vendor"),
|
|
1554
|
+
_ts_param3(0, routingControllers.Req()),
|
|
1555
|
+
_ts_param3(1, routingControllers.QueryParam("limit")),
|
|
1556
|
+
_ts_param3(2, routingControllers.QueryParam("offset")),
|
|
1557
|
+
_ts_param3(3, routingControllers.Res()),
|
|
1558
|
+
_ts_metadata4("design:type", Function),
|
|
1559
|
+
_ts_metadata4("design:paramtypes", [
|
|
1560
|
+
Object,
|
|
1561
|
+
Number,
|
|
1562
|
+
Number,
|
|
1563
|
+
Object
|
|
1564
|
+
]),
|
|
1565
|
+
_ts_metadata4("design:returntype", Promise)
|
|
1566
|
+
], exports.VendorWalletController.prototype, "getTransactions", null);
|
|
1567
|
+
exports.VendorWalletController = _ts_decorate4([
|
|
1568
|
+
routingControllers.JsonController("/vendor/wallet")
|
|
1569
|
+
], exports.VendorWalletController);
|
|
1570
|
+
function createExpressWalletRouter(plugin, _basePath = "/api") {
|
|
1571
|
+
const router = express.Router();
|
|
1572
|
+
const disabled = /* @__PURE__ */ __name((_req, res) => {
|
|
1573
|
+
res.status(404).json({
|
|
1574
|
+
status: 0,
|
|
1575
|
+
message: "Wallet feature is disabled"
|
|
1576
|
+
});
|
|
1577
|
+
}, "disabled");
|
|
1578
|
+
const guard = /* @__PURE__ */ __name((req, res, next) => {
|
|
1579
|
+
if (!plugin.isEnabled()) {
|
|
1580
|
+
disabled(req, res);
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
next();
|
|
1584
|
+
}, "guard");
|
|
1585
|
+
router.use(guard);
|
|
1586
|
+
router.get("/customer/wallet/balance", async (req, res) => {
|
|
1587
|
+
try {
|
|
1588
|
+
const customerId = Number(req.user?.id ?? 0);
|
|
1589
|
+
const account = await plugin.client.getOrCreateAccount(WalletAccountType.CUSTOMER, customerId, "INR");
|
|
1590
|
+
const balance = await plugin.client.getBalance(account.id);
|
|
1591
|
+
res.json({
|
|
1592
|
+
status: 1,
|
|
1593
|
+
data: {
|
|
1594
|
+
available: fromMinorUnit(balance.available),
|
|
1595
|
+
held: fromMinorUnit(balance.held),
|
|
1596
|
+
total: fromMinorUnit(balance.total),
|
|
1597
|
+
currency: account.currency
|
|
1598
|
+
}
|
|
1599
|
+
});
|
|
1600
|
+
} catch (e) {
|
|
1601
|
+
res.status(500).json({
|
|
1602
|
+
status: 0,
|
|
1603
|
+
message: e.message
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
router.get("/vendor/wallet/balance", async (req, res) => {
|
|
1608
|
+
try {
|
|
1609
|
+
const vendorId = Number(req.user?.vendorId ?? 0);
|
|
1610
|
+
const account = await plugin.client.getOrCreateAccount(WalletAccountType.VENDOR, vendorId, "INR");
|
|
1611
|
+
const balance = await plugin.client.getBalance(account.id);
|
|
1612
|
+
res.json({
|
|
1613
|
+
status: 1,
|
|
1614
|
+
data: {
|
|
1615
|
+
available: fromMinorUnit(balance.available),
|
|
1616
|
+
held: fromMinorUnit(balance.held),
|
|
1617
|
+
total: fromMinorUnit(balance.total),
|
|
1618
|
+
currency: account.currency
|
|
1619
|
+
}
|
|
1620
|
+
});
|
|
1621
|
+
} catch (e) {
|
|
1622
|
+
res.status(500).json({
|
|
1623
|
+
status: 0,
|
|
1624
|
+
message: e.message
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
return router;
|
|
1629
|
+
}
|
|
1630
|
+
__name(createExpressWalletRouter, "createExpressWalletRouter");
|
|
1631
|
+
|
|
1632
|
+
// src/http/plugin-http.ts
|
|
1633
|
+
function buildWalletHttp(plugin, config) {
|
|
1634
|
+
if (!config || config.mode === "none" || !plugin.isEnabled()) {
|
|
1635
|
+
return {};
|
|
1636
|
+
}
|
|
1637
|
+
if (config.mode === "routing-controllers") {
|
|
1638
|
+
return {
|
|
1639
|
+
controllers: [
|
|
1640
|
+
exports.AdminWalletController,
|
|
1641
|
+
exports.CustomerWalletController,
|
|
1642
|
+
exports.VendorWalletController
|
|
1643
|
+
]
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
if (config.mode === "express-router") {
|
|
1647
|
+
const router = createExpressWalletRouter(plugin, config.basePath ?? "/api");
|
|
1648
|
+
if (config.app) {
|
|
1649
|
+
config.app.use(config.basePath ?? "/api", router);
|
|
1650
|
+
}
|
|
1651
|
+
return {
|
|
1652
|
+
expressRouter: router
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
return {};
|
|
1656
|
+
}
|
|
1657
|
+
__name(buildWalletHttp, "buildWalletHttp");
|
|
1658
|
+
|
|
1659
|
+
// src/payment/types.ts
|
|
1660
|
+
var PaymentProviderWallet = "wallet";
|
|
1661
|
+
|
|
1662
|
+
// src/payment/WalletPaymentAdapter.ts
|
|
1663
|
+
function createWalletPaymentAdapter(plugin) {
|
|
1664
|
+
return {
|
|
1665
|
+
provider: PaymentProviderWallet,
|
|
1666
|
+
getPublicCredential() {
|
|
1667
|
+
return plugin.isCheckoutEnabled() ? "wallet" : null;
|
|
1668
|
+
},
|
|
1669
|
+
async createPayment(input) {
|
|
1670
|
+
if (!plugin.isCheckoutEnabled()) {
|
|
1671
|
+
throw new Error("Wallet checkout is not enabled");
|
|
1672
|
+
}
|
|
1673
|
+
const resolveCustomer = plugin.resolveOrderCustomerId;
|
|
1674
|
+
if (!resolveCustomer) {
|
|
1675
|
+
throw new Error("resolveOrderCustomerId is not configured on wallet plugin");
|
|
1676
|
+
}
|
|
1677
|
+
const customerId = await resolveCustomer(input.orderId);
|
|
1678
|
+
if (!customerId) {
|
|
1679
|
+
throw new Error("Order customer not found for wallet payment");
|
|
1680
|
+
}
|
|
1681
|
+
const client = plugin.client;
|
|
1682
|
+
const customerAccount = await client.getOrCreateAccount(WalletAccountType.CUSTOMER, customerId, input.currency);
|
|
1683
|
+
const balance = await client.getBalance(customerAccount.id);
|
|
1684
|
+
const amountPaise = toMinorUnit(input.amount);
|
|
1685
|
+
if (balance.available < amountPaise) {
|
|
1686
|
+
throw new Error("Insufficient wallet balance");
|
|
1687
|
+
}
|
|
1688
|
+
return {
|
|
1689
|
+
providerPaymentId: `wallet-order-${input.orderId}`,
|
|
1690
|
+
provider: PaymentProviderWallet,
|
|
1691
|
+
raw: {
|
|
1692
|
+
customerAccountId: customerAccount.id,
|
|
1693
|
+
amountPaise
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
},
|
|
1697
|
+
async verifyPayment(providerPaymentId) {
|
|
1698
|
+
return {
|
|
1699
|
+
providerPaymentId,
|
|
1700
|
+
status: "succeeded",
|
|
1701
|
+
amount: 0,
|
|
1702
|
+
currency: "INR",
|
|
1703
|
+
provider: PaymentProviderWallet,
|
|
1704
|
+
raw: {}
|
|
1705
|
+
};
|
|
1706
|
+
},
|
|
1707
|
+
async fetchPaymentStatus(providerPaymentId) {
|
|
1708
|
+
return this.verifyPayment(providerPaymentId);
|
|
1709
|
+
},
|
|
1710
|
+
async resolveProviderPaymentId(orderId) {
|
|
1711
|
+
return `wallet-order-${orderId}`;
|
|
1712
|
+
},
|
|
1713
|
+
async createRefund(_input) {
|
|
1714
|
+
throw new Error("Wallet refunds are handled via wallet hooks.onRefund");
|
|
1715
|
+
},
|
|
1716
|
+
verifyWebhook(_payload, _signature) {
|
|
1717
|
+
return {
|
|
1718
|
+
isValid: false
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
}
|
|
1723
|
+
__name(createWalletPaymentAdapter, "createWalletPaymentAdapter");
|
|
1724
|
+
|
|
1725
|
+
// src/typeorm/store.ts
|
|
1726
|
+
function toNumber(value) {
|
|
1727
|
+
if (value == null) {
|
|
1728
|
+
return 0;
|
|
1729
|
+
}
|
|
1730
|
+
return Number(value);
|
|
1731
|
+
}
|
|
1732
|
+
__name(toNumber, "toNumber");
|
|
1733
|
+
function toLedgerAccount(row) {
|
|
1734
|
+
return {
|
|
1735
|
+
id: row.id,
|
|
1736
|
+
ownerType: row.ownerType,
|
|
1737
|
+
ownerId: row.ownerId,
|
|
1738
|
+
currency: row.currency,
|
|
1739
|
+
availableBalance: toNumber(row.availableBalance),
|
|
1740
|
+
heldBalance: toNumber(row.heldBalance)
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
__name(toLedgerAccount, "toLedgerAccount");
|
|
1744
|
+
function toLedgerHold(row) {
|
|
1745
|
+
return {
|
|
1746
|
+
id: row.id,
|
|
1747
|
+
sourceAccountId: row.sourceAccountId,
|
|
1748
|
+
targetAccountId: row.targetAccountId,
|
|
1749
|
+
amount: toNumber(row.amount),
|
|
1750
|
+
status: row.status,
|
|
1751
|
+
referenceType: row.referenceType,
|
|
1752
|
+
referenceId: row.referenceId,
|
|
1753
|
+
idempotencyKey: row.idempotencyKey,
|
|
1754
|
+
createdAt: new Date(row.createdDate)
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
__name(toLedgerHold, "toLedgerHold");
|
|
1758
|
+
function toLedgerEntry(row) {
|
|
1759
|
+
return {
|
|
1760
|
+
id: row.id,
|
|
1761
|
+
accountId: row.accountId,
|
|
1762
|
+
entryType: row.entryType,
|
|
1763
|
+
amount: toNumber(row.amount),
|
|
1764
|
+
balanceAfterAvailable: toNumber(row.balanceAfterAvailable),
|
|
1765
|
+
balanceAfterHeld: toNumber(row.balanceAfterHeld),
|
|
1766
|
+
idempotencyKey: row.idempotencyKey,
|
|
1767
|
+
referenceType: row.referenceType,
|
|
1768
|
+
referenceId: row.referenceId,
|
|
1769
|
+
metadata: row.metadata,
|
|
1770
|
+
createdAt: new Date(row.createdDate)
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
__name(toLedgerEntry, "toLedgerEntry");
|
|
1774
|
+
function isEntityManager(value) {
|
|
1775
|
+
return value != null && typeof value === "object" && typeof value.getRepository === "function";
|
|
1776
|
+
}
|
|
1777
|
+
__name(isEntityManager, "isEntityManager");
|
|
1778
|
+
var _a2;
|
|
1779
|
+
var TypeOrmWalletStoreTx = (_a2 = class {
|
|
1780
|
+
constructor(em) {
|
|
1781
|
+
__publicField(this, "em");
|
|
1782
|
+
this.em = em;
|
|
1783
|
+
}
|
|
1784
|
+
async getOrCreateAccount(type, ownerId, currency) {
|
|
1785
|
+
const repo = this.em.getRepository(exports.WalletAccountEntity);
|
|
1786
|
+
let row = await repo.findOne({
|
|
1787
|
+
where: {
|
|
1788
|
+
ownerType: type,
|
|
1789
|
+
ownerId,
|
|
1790
|
+
currency
|
|
1791
|
+
}
|
|
1792
|
+
});
|
|
1793
|
+
if (!row) {
|
|
1794
|
+
row = repo.create({
|
|
1795
|
+
ownerType: type,
|
|
1796
|
+
ownerId,
|
|
1797
|
+
currency,
|
|
1798
|
+
availableBalance: "0",
|
|
1799
|
+
heldBalance: "0"
|
|
1800
|
+
});
|
|
1801
|
+
row = await repo.save(row);
|
|
1802
|
+
}
|
|
1803
|
+
return toLedgerAccount(row);
|
|
1804
|
+
}
|
|
1805
|
+
async lockAccount(accountId) {
|
|
1806
|
+
const row = await this.em.getRepository(exports.WalletAccountEntity).createQueryBuilder("wa").setLock("pessimistic_write").where("wa.id = :id", {
|
|
1807
|
+
id: accountId
|
|
1808
|
+
}).getOne();
|
|
1809
|
+
if (!row) {
|
|
1810
|
+
throw new Error(`Wallet account ${accountId} not found`);
|
|
1811
|
+
}
|
|
1812
|
+
return toLedgerAccount(row);
|
|
1813
|
+
}
|
|
1814
|
+
async getAccountById(accountId) {
|
|
1815
|
+
const row = await this.em.getRepository(exports.WalletAccountEntity).findOne({
|
|
1816
|
+
where: {
|
|
1817
|
+
id: accountId
|
|
1818
|
+
}
|
|
1819
|
+
});
|
|
1820
|
+
return row ? toLedgerAccount(row) : null;
|
|
1821
|
+
}
|
|
1822
|
+
async appendLedgerEntry(entry) {
|
|
1823
|
+
const existing = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);
|
|
1824
|
+
if (existing) {
|
|
1825
|
+
return existing;
|
|
1826
|
+
}
|
|
1827
|
+
const repo = this.em.getRepository(exports.WalletLedgerEntryEntity);
|
|
1828
|
+
try {
|
|
1829
|
+
const row = await repo.save(repo.create({
|
|
1830
|
+
accountId: entry.accountId,
|
|
1831
|
+
entryType: entry.entryType,
|
|
1832
|
+
amount: String(entry.amount),
|
|
1833
|
+
balanceAfterAvailable: String(entry.balanceAfterAvailable),
|
|
1834
|
+
balanceAfterHeld: String(entry.balanceAfterHeld),
|
|
1835
|
+
idempotencyKey: entry.idempotencyKey,
|
|
1836
|
+
referenceType: entry.referenceType,
|
|
1837
|
+
referenceId: entry.referenceId,
|
|
1838
|
+
metadata: entry.metadata
|
|
1839
|
+
}));
|
|
1840
|
+
return toLedgerEntry(row);
|
|
1841
|
+
} catch (error) {
|
|
1842
|
+
const err = error;
|
|
1843
|
+
const code = err?.code || err?.errno;
|
|
1844
|
+
if (code === "ER_DUP_ENTRY" || code === 1062) {
|
|
1845
|
+
const dup = await this.findLedgerByIdempotencyKey(entry.idempotencyKey);
|
|
1846
|
+
if (dup) {
|
|
1847
|
+
return dup;
|
|
1848
|
+
}
|
|
1849
|
+
throw new DuplicateOperationError("Duplicate idempotency key", null);
|
|
1850
|
+
}
|
|
1851
|
+
throw error;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
async updateBalances(accountId, deltas) {
|
|
1855
|
+
const row = await this.em.getRepository(exports.WalletAccountEntity).createQueryBuilder("wa").setLock("pessimistic_write").where("wa.id = :id", {
|
|
1856
|
+
id: accountId
|
|
1857
|
+
}).getOne();
|
|
1858
|
+
if (!row) {
|
|
1859
|
+
throw new Error(`Wallet account ${accountId} not found`);
|
|
1860
|
+
}
|
|
1861
|
+
const available = toNumber(row.availableBalance) + (deltas.availableDelta ?? 0);
|
|
1862
|
+
const held = toNumber(row.heldBalance) + (deltas.heldDelta ?? 0);
|
|
1863
|
+
if (available < 0 || held < 0) {
|
|
1864
|
+
throw new Error("Balance cannot be negative");
|
|
1865
|
+
}
|
|
1866
|
+
row.availableBalance = String(available);
|
|
1867
|
+
row.heldBalance = String(held);
|
|
1868
|
+
const saved = await this.em.getRepository(exports.WalletAccountEntity).save(row);
|
|
1869
|
+
return toLedgerAccount(saved);
|
|
1870
|
+
}
|
|
1871
|
+
async findHoldByReference(ref) {
|
|
1872
|
+
const row = await this.em.getRepository(exports.WalletHoldEntity).findOne({
|
|
1873
|
+
where: {
|
|
1874
|
+
referenceType: ref.referenceType,
|
|
1875
|
+
referenceId: ref.referenceId
|
|
1876
|
+
},
|
|
1877
|
+
order: {
|
|
1878
|
+
id: "DESC"
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
return row ? toLedgerHold(row) : null;
|
|
1882
|
+
}
|
|
1883
|
+
async upsertHold(hold) {
|
|
1884
|
+
const repo = this.em.getRepository(exports.WalletHoldEntity);
|
|
1885
|
+
let row;
|
|
1886
|
+
if (hold.id != null) {
|
|
1887
|
+
row = await repo.findOne({
|
|
1888
|
+
where: {
|
|
1889
|
+
id: hold.id
|
|
1890
|
+
}
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
if (!row) {
|
|
1894
|
+
row = await repo.findOne({
|
|
1895
|
+
where: {
|
|
1896
|
+
referenceType: hold.referenceType,
|
|
1897
|
+
referenceId: hold.referenceId
|
|
1898
|
+
}
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
if (!row) {
|
|
1902
|
+
row = repo.create({
|
|
1903
|
+
sourceAccountId: hold.sourceAccountId,
|
|
1904
|
+
targetAccountId: hold.targetAccountId,
|
|
1905
|
+
amount: String(hold.amount),
|
|
1906
|
+
status: hold.status,
|
|
1907
|
+
referenceType: hold.referenceType,
|
|
1908
|
+
referenceId: hold.referenceId,
|
|
1909
|
+
idempotencyKey: hold.idempotencyKey
|
|
1910
|
+
});
|
|
1911
|
+
} else {
|
|
1912
|
+
row.sourceAccountId = hold.sourceAccountId;
|
|
1913
|
+
row.targetAccountId = hold.targetAccountId;
|
|
1914
|
+
row.amount = String(hold.amount);
|
|
1915
|
+
row.status = hold.status;
|
|
1916
|
+
row.idempotencyKey = hold.idempotencyKey;
|
|
1917
|
+
}
|
|
1918
|
+
const saved = await repo.save(row);
|
|
1919
|
+
return toLedgerHold(saved);
|
|
1920
|
+
}
|
|
1921
|
+
async findLedgerByIdempotencyKey(key) {
|
|
1922
|
+
const row = await this.em.getRepository(exports.WalletLedgerEntryEntity).findOne({
|
|
1923
|
+
where: {
|
|
1924
|
+
idempotencyKey: key
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
return row ? toLedgerEntry(row) : null;
|
|
1928
|
+
}
|
|
1929
|
+
async listLedgerEntries(accountId, limit, offset) {
|
|
1930
|
+
const rows = await this.em.getRepository(exports.WalletLedgerEntryEntity).find({
|
|
1931
|
+
where: {
|
|
1932
|
+
accountId
|
|
1933
|
+
},
|
|
1934
|
+
order: {
|
|
1935
|
+
id: "DESC"
|
|
1936
|
+
},
|
|
1937
|
+
take: limit,
|
|
1938
|
+
skip: offset
|
|
1939
|
+
});
|
|
1940
|
+
return rows.map(toLedgerEntry);
|
|
1941
|
+
}
|
|
1942
|
+
}, __name(_a2, "TypeOrmWalletStoreTx"), _a2);
|
|
1943
|
+
var _TypeOrmWalletStore = class _TypeOrmWalletStore {
|
|
1944
|
+
constructor(connection) {
|
|
1945
|
+
__publicField(this, "connection");
|
|
1946
|
+
this.connection = connection;
|
|
1947
|
+
}
|
|
1948
|
+
async runInTransaction(fn, ctx) {
|
|
1949
|
+
if (isEntityManager(ctx?.nativeTx)) {
|
|
1950
|
+
return fn(new TypeOrmWalletStoreTx(ctx.nativeTx));
|
|
1951
|
+
}
|
|
1952
|
+
return this.connection.manager.transaction(async (em) => fn(new TypeOrmWalletStoreTx(em)));
|
|
1953
|
+
}
|
|
1954
|
+
};
|
|
1955
|
+
__name(_TypeOrmWalletStore, "TypeOrmWalletStore");
|
|
1956
|
+
var TypeOrmWalletStore = _TypeOrmWalletStore;
|
|
1957
|
+
|
|
1958
|
+
// src/typeorm/migrations/CreateWalletTables.ts
|
|
1959
|
+
async function indexExists(queryRunner, tableName, indexName) {
|
|
1960
|
+
const rows = await queryRunner.query(`SELECT COUNT(1) AS c
|
|
1961
|
+
FROM information_schema.statistics
|
|
1962
|
+
WHERE table_schema = DATABASE()
|
|
1963
|
+
AND table_name = ?
|
|
1964
|
+
AND index_name = ?`, [
|
|
1965
|
+
tableName,
|
|
1966
|
+
indexName
|
|
1967
|
+
]);
|
|
1968
|
+
return Number(rows[0]?.c ?? 0) > 0;
|
|
1969
|
+
}
|
|
1970
|
+
__name(indexExists, "indexExists");
|
|
1971
|
+
var _CreateWalletTables1790000000000 = class _CreateWalletTables1790000000000 {
|
|
1972
|
+
async up(queryRunner) {
|
|
1973
|
+
if (!await queryRunner.hasTable("wallet_account")) {
|
|
1974
|
+
await queryRunner.query(`
|
|
1975
|
+
CREATE TABLE \`wallet_account\` (
|
|
1976
|
+
\`id\` int NOT NULL AUTO_INCREMENT,
|
|
1977
|
+
\`owner_type\` varchar(32) NOT NULL,
|
|
1978
|
+
\`owner_id\` int NOT NULL,
|
|
1979
|
+
\`currency\` varchar(8) NOT NULL DEFAULT 'INR',
|
|
1980
|
+
\`available_balance\` bigint NOT NULL DEFAULT 0,
|
|
1981
|
+
\`held_balance\` bigint NOT NULL DEFAULT 0,
|
|
1982
|
+
\`created_by\` int NULL,
|
|
1983
|
+
\`created_date\` datetime NULL,
|
|
1984
|
+
\`modified_by\` int NULL,
|
|
1985
|
+
\`modified_date\` datetime NULL,
|
|
1986
|
+
PRIMARY KEY (\`id\`)
|
|
1987
|
+
) ENGINE=InnoDB
|
|
1988
|
+
`);
|
|
1989
|
+
}
|
|
1990
|
+
if (!await indexExists(queryRunner, "wallet_account", "IDX_wallet_account_owner_currency")) {
|
|
1991
|
+
await queryRunner.query(`
|
|
1992
|
+
CREATE UNIQUE INDEX \`IDX_wallet_account_owner_currency\`
|
|
1993
|
+
ON \`wallet_account\` (\`owner_type\`, \`owner_id\`, \`currency\`)
|
|
1994
|
+
`);
|
|
1995
|
+
}
|
|
1996
|
+
if (!await queryRunner.hasTable("wallet_ledger_entry")) {
|
|
1997
|
+
await queryRunner.query(`
|
|
1998
|
+
CREATE TABLE \`wallet_ledger_entry\` (
|
|
1999
|
+
\`id\` int NOT NULL AUTO_INCREMENT,
|
|
2000
|
+
\`account_id\` int NOT NULL,
|
|
2001
|
+
\`entry_type\` varchar(32) NOT NULL,
|
|
2002
|
+
\`amount\` bigint NOT NULL,
|
|
2003
|
+
\`balance_after_available\` bigint NOT NULL,
|
|
2004
|
+
\`balance_after_held\` bigint NOT NULL,
|
|
2005
|
+
\`idempotency_key\` varchar(255) NOT NULL,
|
|
2006
|
+
\`reference_type\` varchar(64) NULL,
|
|
2007
|
+
\`reference_id\` varchar(128) NULL,
|
|
2008
|
+
\`metadata\` json NULL,
|
|
2009
|
+
\`created_by\` int NULL,
|
|
2010
|
+
\`created_date\` datetime NULL,
|
|
2011
|
+
\`modified_by\` int NULL,
|
|
2012
|
+
\`modified_date\` datetime NULL,
|
|
2013
|
+
PRIMARY KEY (\`id\`),
|
|
2014
|
+
UNIQUE INDEX \`UQ_wallet_ledger_idempotency_key\` (\`idempotency_key\`)
|
|
2015
|
+
) ENGINE=InnoDB
|
|
2016
|
+
`);
|
|
2017
|
+
}
|
|
2018
|
+
if (!await indexExists(queryRunner, "wallet_ledger_entry", "IDX_wallet_ledger_account_id")) {
|
|
2019
|
+
await queryRunner.query(`
|
|
2020
|
+
CREATE INDEX \`IDX_wallet_ledger_account_id\`
|
|
2021
|
+
ON \`wallet_ledger_entry\` (\`account_id\`)
|
|
2022
|
+
`);
|
|
2023
|
+
}
|
|
2024
|
+
if (!await queryRunner.hasTable("wallet_hold")) {
|
|
2025
|
+
await queryRunner.query(`
|
|
2026
|
+
CREATE TABLE \`wallet_hold\` (
|
|
2027
|
+
\`id\` int NOT NULL AUTO_INCREMENT,
|
|
2028
|
+
\`source_account_id\` int NOT NULL,
|
|
2029
|
+
\`target_account_id\` int NOT NULL,
|
|
2030
|
+
\`amount\` bigint NOT NULL,
|
|
2031
|
+
\`status\` varchar(16) NOT NULL DEFAULT 'active',
|
|
2032
|
+
\`reference_type\` varchar(64) NOT NULL,
|
|
2033
|
+
\`reference_id\` varchar(128) NOT NULL,
|
|
2034
|
+
\`idempotency_key\` varchar(255) NOT NULL,
|
|
2035
|
+
\`created_by\` int NULL,
|
|
2036
|
+
\`created_date\` datetime NULL,
|
|
2037
|
+
\`modified_by\` int NULL,
|
|
2038
|
+
\`modified_date\` datetime NULL,
|
|
2039
|
+
PRIMARY KEY (\`id\`)
|
|
2040
|
+
) ENGINE=InnoDB
|
|
2041
|
+
`);
|
|
2042
|
+
}
|
|
2043
|
+
if (!await indexExists(queryRunner, "wallet_hold", "IDX_wallet_hold_reference")) {
|
|
2044
|
+
await queryRunner.query(`
|
|
2045
|
+
CREATE INDEX \`IDX_wallet_hold_reference\`
|
|
2046
|
+
ON \`wallet_hold\` (\`reference_type\`, \`reference_id\`)
|
|
2047
|
+
`);
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
async down(queryRunner) {
|
|
2051
|
+
if (await queryRunner.hasTable("wallet_hold")) {
|
|
2052
|
+
await queryRunner.query("DROP TABLE `wallet_hold`");
|
|
2053
|
+
}
|
|
2054
|
+
if (await queryRunner.hasTable("wallet_ledger_entry")) {
|
|
2055
|
+
await queryRunner.query("DROP TABLE `wallet_ledger_entry`");
|
|
2056
|
+
}
|
|
2057
|
+
if (await queryRunner.hasTable("wallet_account")) {
|
|
2058
|
+
await queryRunner.query("DROP TABLE `wallet_account`");
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
__name(_CreateWalletTables1790000000000, "CreateWalletTables1790000000000");
|
|
2063
|
+
var CreateWalletTables1790000000000 = _CreateWalletTables1790000000000;
|
|
2064
|
+
|
|
2065
|
+
// src/typeorm/metadata.ts
|
|
2066
|
+
function getWalletOrmMetadata() {
|
|
2067
|
+
return {
|
|
2068
|
+
entities: [
|
|
2069
|
+
exports.WalletAccountEntity,
|
|
2070
|
+
exports.WalletLedgerEntryEntity,
|
|
2071
|
+
exports.WalletHoldEntity
|
|
2072
|
+
],
|
|
2073
|
+
migrations: [
|
|
2074
|
+
CreateWalletTables1790000000000
|
|
2075
|
+
]
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
__name(getWalletOrmMetadata, "getWalletOrmMetadata");
|
|
2079
|
+
|
|
2080
|
+
// src/plugin-types.ts
|
|
2081
|
+
var WALLET_PLUGIN_TOKEN = "multivendor-wallet.plugin";
|
|
2082
|
+
|
|
2083
|
+
// src/plugin.ts
|
|
2084
|
+
function scheduleReconciliation(config, onRun) {
|
|
2085
|
+
if (!config.reconciliation?.enabled || !config.flags.enabled) {
|
|
2086
|
+
return void 0;
|
|
2087
|
+
}
|
|
2088
|
+
const cronExpr = config.reconciliation.cron ?? "0 2 * * *";
|
|
2089
|
+
let intervalId;
|
|
2090
|
+
try {
|
|
2091
|
+
const cron = __require("node-cron");
|
|
2092
|
+
return cron.schedule(cronExpr, () => {
|
|
2093
|
+
void onRun();
|
|
2094
|
+
});
|
|
2095
|
+
} catch {
|
|
2096
|
+
intervalId = setInterval(() => {
|
|
2097
|
+
void onRun();
|
|
2098
|
+
}, 24 * 60 * 60 * 1e3);
|
|
2099
|
+
return {
|
|
2100
|
+
stop: /* @__PURE__ */ __name(() => clearInterval(intervalId), "stop")
|
|
2101
|
+
};
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
__name(scheduleReconciliation, "scheduleReconciliation");
|
|
2105
|
+
var _a3;
|
|
2106
|
+
var WalletPluginImpl = (_a3 = class {
|
|
2107
|
+
constructor(config, store) {
|
|
2108
|
+
__publicField(this, "client");
|
|
2109
|
+
__publicField(this, "hooks");
|
|
2110
|
+
__publicField(this, "flags");
|
|
2111
|
+
__publicField(this, "http");
|
|
2112
|
+
__publicField(this, "payment");
|
|
2113
|
+
__publicField(this, "onAdminMutation");
|
|
2114
|
+
__publicField(this, "resolveOrderCustomerId");
|
|
2115
|
+
__publicField(this, "cronTask");
|
|
2116
|
+
this.flags = config.flags;
|
|
2117
|
+
this.onAdminMutation = config.onAdminMutation;
|
|
2118
|
+
this.resolveOrderCustomerId = config.resolveOrderCustomerId;
|
|
2119
|
+
this.client = new WalletLedgerClient(store, {
|
|
2120
|
+
defaultCurrency: config.defaultCurrency ?? "INR",
|
|
2121
|
+
platformOwnerId: config.platformOwnerId
|
|
2122
|
+
});
|
|
2123
|
+
this.hooks = createLifecycleHooks({
|
|
2124
|
+
client: this.client,
|
|
2125
|
+
platformOwnerId: config.platformOwnerId,
|
|
2126
|
+
defaultCurrency: config.defaultCurrency ?? "INR",
|
|
2127
|
+
flags: config.flags
|
|
2128
|
+
});
|
|
2129
|
+
this.http = buildWalletHttp(this, config.http);
|
|
2130
|
+
this.payment = {
|
|
2131
|
+
createWalletPaymentAdapter: /* @__PURE__ */ __name(() => createWalletPaymentAdapter(this), "createWalletPaymentAdapter")
|
|
2132
|
+
};
|
|
2133
|
+
if (config.reconciliation?.enabled && config.flags.enabled) {
|
|
2134
|
+
this.cronTask = scheduleReconciliation(config, async () => {
|
|
2135
|
+
const report = await runWalletReconciliation();
|
|
2136
|
+
if (report.parityDeltas.length > 0 || report.cacheMismatches.length > 0) {
|
|
2137
|
+
config.reconciliation?.onMismatch?.(report);
|
|
2138
|
+
config.reconciliation?.onLog?.("warn", "wallet reconciliation mismatch", report);
|
|
2139
|
+
} else {
|
|
2140
|
+
config.reconciliation?.onLog?.("info", "wallet reconciliation ok");
|
|
2141
|
+
}
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
isEnabled() {
|
|
2146
|
+
return this.flags.enabled;
|
|
2147
|
+
}
|
|
2148
|
+
isLedgerWritesEnabled() {
|
|
2149
|
+
return this.flags.enabled && this.flags.ledgerWrites;
|
|
2150
|
+
}
|
|
2151
|
+
isSettlementDebitEnabled() {
|
|
2152
|
+
return this.flags.enabled && this.flags.settlementDebit;
|
|
2153
|
+
}
|
|
2154
|
+
isCheckoutEnabled() {
|
|
2155
|
+
return this.flags.enabled && this.flags.checkout;
|
|
2156
|
+
}
|
|
2157
|
+
async shutdown() {
|
|
2158
|
+
this.cronTask?.stop();
|
|
2159
|
+
}
|
|
2160
|
+
}, __name(_a3, "WalletPluginImpl"), _a3);
|
|
2161
|
+
function registerWalletPlugin(config) {
|
|
2162
|
+
if (config.dataSource == null) {
|
|
2163
|
+
throw new Error("WalletPluginConfig.dataSource is required (host TypeORM Connection).");
|
|
2164
|
+
}
|
|
2165
|
+
bindWalletConnection(config.dataSource);
|
|
2166
|
+
const store = new TypeOrmWalletStore(config.dataSource);
|
|
2167
|
+
const plugin = new WalletPluginImpl(config, store);
|
|
2168
|
+
bindWalletPlugin(plugin);
|
|
2169
|
+
return plugin;
|
|
2170
|
+
}
|
|
2171
|
+
__name(registerWalletPlugin, "registerWalletPlugin");
|
|
2172
|
+
|
|
2173
|
+
exports.CreateWalletTables1790000000000 = CreateWalletTables1790000000000;
|
|
2174
|
+
exports.DuplicateOperationError = DuplicateOperationError;
|
|
2175
|
+
exports.HoldNotFoundError = HoldNotFoundError;
|
|
2176
|
+
exports.HoldStatus = HoldStatus;
|
|
2177
|
+
exports.InsufficientBalanceError = InsufficientBalanceError;
|
|
2178
|
+
exports.InvalidAmountError = InvalidAmountError;
|
|
2179
|
+
exports.LedgerEntryType = LedgerEntryType;
|
|
2180
|
+
exports.PaymentProviderWallet = PaymentProviderWallet;
|
|
2181
|
+
exports.TypeOrmWalletStore = TypeOrmWalletStore;
|
|
2182
|
+
exports.WALLET_PLUGIN_TOKEN = WALLET_PLUGIN_TOKEN;
|
|
2183
|
+
exports.WalletAccountType = WalletAccountType;
|
|
2184
|
+
exports.WalletConfigError = WalletConfigError;
|
|
2185
|
+
exports.WalletError = WalletError;
|
|
2186
|
+
exports.WalletLedgerClient = WalletLedgerClient;
|
|
2187
|
+
exports.createExpressWalletRouter = createExpressWalletRouter;
|
|
2188
|
+
exports.createWalletPaymentAdapter = createWalletPaymentAdapter;
|
|
2189
|
+
exports.fromMinorUnit = fromMinorUnit;
|
|
2190
|
+
exports.getWalletOrmMetadata = getWalletOrmMetadata;
|
|
2191
|
+
exports.registerWalletPlugin = registerWalletPlugin;
|
|
2192
|
+
exports.toMinorUnit = toMinorUnit;
|
|
2193
|
+
//# sourceMappingURL=index.cjs.map
|
|
2194
|
+
//# sourceMappingURL=index.cjs.map
|