@nestjs-dash/wallet 0.1.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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +95 -0
- package/dist/cli.js.map +1 -0
- package/dist/entities/transaction.entity.d.ts +18 -0
- package/dist/entities/transaction.entity.d.ts.map +1 -0
- package/dist/entities/transaction.entity.js +68 -0
- package/dist/entities/transaction.entity.js.map +1 -0
- package/dist/entities/transfer.entity.d.ts +23 -0
- package/dist/entities/transfer.entity.d.ts.map +1 -0
- package/dist/entities/transfer.entity.js +97 -0
- package/dist/entities/transfer.entity.js.map +1 -0
- package/dist/entities/wallet.entity.d.ts +16 -0
- package/dist/entities/wallet.entity.d.ts.map +1 -0
- package/dist/entities/wallet.entity.js +67 -0
- package/dist/entities/wallet.entity.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/events/wallet-event.publisher.d.ts +12 -0
- package/dist/events/wallet-event.publisher.d.ts.map +1 -0
- package/dist/events/wallet-event.publisher.js +44 -0
- package/dist/events/wallet-event.publisher.js.map +1 -0
- package/dist/events/wallet.events.d.ts +22 -0
- package/dist/events/wallet.events.d.ts.map +1 -0
- package/dist/events/wallet.events.js +2 -0
- package/dist/events/wallet.events.js.map +1 -0
- package/dist/exchange.service.d.ts +17 -0
- package/dist/exchange.service.d.ts.map +1 -0
- package/dist/exchange.service.js +70 -0
- package/dist/exchange.service.js.map +1 -0
- package/dist/float-wallet.service.d.ts +11 -0
- package/dist/float-wallet.service.d.ts.map +1 -0
- package/dist/float-wallet.service.js +33 -0
- package/dist/float-wallet.service.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/lock/array-lock.service.d.ts +8 -0
- package/dist/lock/array-lock.service.d.ts.map +1 -0
- package/dist/lock/array-lock.service.js +60 -0
- package/dist/lock/array-lock.service.js.map +1 -0
- package/dist/lock/lock.service.d.ts +5 -0
- package/dist/lock/lock.service.d.ts.map +1 -0
- package/dist/lock/lock.service.js +4 -0
- package/dist/lock/lock.service.js.map +1 -0
- package/dist/lock/memcached-lock.service.d.ts +21 -0
- package/dist/lock/memcached-lock.service.d.ts.map +1 -0
- package/dist/lock/memcached-lock.service.js +45 -0
- package/dist/lock/memcached-lock.service.js.map +1 -0
- package/dist/lock/redis-lock.service.d.ts +13 -0
- package/dist/lock/redis-lock.service.d.ts.map +1 -0
- package/dist/lock/redis-lock.service.js +43 -0
- package/dist/lock/redis-lock.service.js.map +1 -0
- package/dist/migrations/generate.d.ts +22 -0
- package/dist/migrations/generate.d.ts.map +1 -0
- package/dist/migrations/generate.js +226 -0
- package/dist/migrations/generate.js.map +1 -0
- package/dist/tokens.d.ts +56 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +13 -0
- package/dist/tokens.js.map +1 -0
- package/dist/transfer.service.d.ts +29 -0
- package/dist/transfer.service.d.ts.map +1 -0
- package/dist/transfer.service.js +154 -0
- package/dist/transfer.service.js.map +1 -0
- package/dist/wallet.module.d.ts +12 -0
- package/dist/wallet.module.d.ts.map +1 -0
- package/dist/wallet.module.js +150 -0
- package/dist/wallet.module.js.map +1 -0
- package/dist/wallet.service.d.ts +39 -0
- package/dist/wallet.service.d.ts.map +1 -0
- package/dist/wallet.service.js +230 -0
- package/dist/wallet.service.js.map +1 -0
- package/dist/warmup.service.d.ts +13 -0
- package/dist/warmup.service.d.ts.map +1 -0
- package/dist/warmup.service.js +76 -0
- package/dist/warmup.service.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
14
|
+
import { ExchangeRateNotFoundError } from './errors.js';
|
|
15
|
+
import { WALLET_OPTIONS } from './tokens.js';
|
|
16
|
+
import { TransferService } from './transfer.service.js';
|
|
17
|
+
import { WalletService } from './wallet.service.js';
|
|
18
|
+
let ExchangeService = class ExchangeService {
|
|
19
|
+
constructor(transfers, wallets, options) {
|
|
20
|
+
this.transfers = transfers;
|
|
21
|
+
this.wallets = wallets;
|
|
22
|
+
this.rates = structuredClone(options.exchange?.rates ?? {});
|
|
23
|
+
}
|
|
24
|
+
setExchangeRate(fromCurrency, toCurrency, rate) {
|
|
25
|
+
if (!this.rates[fromCurrency])
|
|
26
|
+
this.rates[fromCurrency] = {};
|
|
27
|
+
this.rates[fromCurrency][toCurrency] = rate;
|
|
28
|
+
}
|
|
29
|
+
getExchangeRate(fromCurrency, toCurrency) {
|
|
30
|
+
if (fromCurrency === toCurrency)
|
|
31
|
+
return 1;
|
|
32
|
+
const rate = this.rates[fromCurrency]?.[toCurrency];
|
|
33
|
+
if (rate == null) {
|
|
34
|
+
throw new ExchangeRateNotFoundError(`No rate for ${fromCurrency} → ${toCurrency}`);
|
|
35
|
+
}
|
|
36
|
+
return rate;
|
|
37
|
+
}
|
|
38
|
+
currencyOf(wallet) {
|
|
39
|
+
const meta = wallet.meta ?? {};
|
|
40
|
+
const currency = meta.currency;
|
|
41
|
+
if (typeof currency !== 'string' || !currency) {
|
|
42
|
+
throw new ExchangeRateNotFoundError(`Wallet ${wallet.id} has no meta.currency`);
|
|
43
|
+
}
|
|
44
|
+
return currency;
|
|
45
|
+
}
|
|
46
|
+
async exchange(from, to, amount, explicitRate) {
|
|
47
|
+
const fromCurrency = this.currencyOf(from);
|
|
48
|
+
const toCurrency = this.currencyOf(to);
|
|
49
|
+
const rate = explicitRate ?? this.getExchangeRate(fromCurrency, toCurrency);
|
|
50
|
+
const withdrawAmount = this.wallets.normalizeAmount(amount);
|
|
51
|
+
const depositAmount = BigInt(Math.round(Number(withdrawAmount) * rate));
|
|
52
|
+
return this.transfers.transfer(from, to, withdrawAmount.toString(), {
|
|
53
|
+
depositAmount: depositAmount.toString(),
|
|
54
|
+
status: 'exchange',
|
|
55
|
+
extra: { rate, fromCurrency, toCurrency },
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async exchangeFloat(from, to, amount, explicitRate) {
|
|
59
|
+
const intAmount = this.wallets.floatToInt(amount, from.decimalPlaces);
|
|
60
|
+
return this.exchange(from, to, intAmount.toString(), explicitRate);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
ExchangeService = __decorate([
|
|
64
|
+
Injectable(),
|
|
65
|
+
__param(2, Inject(WALLET_OPTIONS)),
|
|
66
|
+
__metadata("design:paramtypes", [TransferService,
|
|
67
|
+
WalletService, Object])
|
|
68
|
+
], ExchangeService);
|
|
69
|
+
export { ExchangeService };
|
|
70
|
+
//# sourceMappingURL=exchange.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exchange.service.js","sourceRoot":"","sources":["../src/exchange.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TransactionEntity } from './entities/transaction.entity.js';
|
|
2
|
+
import type { WalletEntity } from './entities/wallet.entity.js';
|
|
3
|
+
import { WalletService } from './wallet.service.js';
|
|
4
|
+
export declare class FloatWalletService {
|
|
5
|
+
private readonly wallets;
|
|
6
|
+
constructor(wallets: WalletService);
|
|
7
|
+
balanceFloat(wallet: WalletEntity): number;
|
|
8
|
+
depositFloat(wallet: WalletEntity, amount: number, meta?: Record<string, unknown> | null): Promise<TransactionEntity>;
|
|
9
|
+
withdrawFloat(wallet: WalletEntity, amount: number, meta?: Record<string, unknown> | null): Promise<TransactionEntity>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=float-wallet.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"float-wallet.service.d.ts","sourceRoot":"","sources":["../src/float-wallet.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,qBACa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAEnD,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAIpC,YAAY,CAChB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAC1C,OAAO,CAAC,iBAAiB,CAAC;IAKvB,aAAa,CACjB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAC1C,OAAO,CAAC,iBAAiB,CAAC;CAI9B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Injectable } from '@nestjs/common';
|
|
11
|
+
import { WalletService } from './wallet.service.js';
|
|
12
|
+
let FloatWalletService = class FloatWalletService {
|
|
13
|
+
constructor(wallets) {
|
|
14
|
+
this.wallets = wallets;
|
|
15
|
+
}
|
|
16
|
+
balanceFloat(wallet) {
|
|
17
|
+
return this.wallets.intToFloat(wallet.balance, wallet.decimalPlaces);
|
|
18
|
+
}
|
|
19
|
+
async depositFloat(wallet, amount, meta = null) {
|
|
20
|
+
const intAmount = this.wallets.floatToInt(amount, wallet.decimalPlaces);
|
|
21
|
+
return this.wallets.deposit(wallet, intAmount.toString(), meta);
|
|
22
|
+
}
|
|
23
|
+
async withdrawFloat(wallet, amount, meta = null) {
|
|
24
|
+
const intAmount = this.wallets.floatToInt(amount, wallet.decimalPlaces);
|
|
25
|
+
return this.wallets.withdraw(wallet, intAmount.toString(), meta);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
FloatWalletService = __decorate([
|
|
29
|
+
Injectable(),
|
|
30
|
+
__metadata("design:paramtypes", [WalletService])
|
|
31
|
+
], FloatWalletService);
|
|
32
|
+
export { FloatWalletService };
|
|
33
|
+
//# sourceMappingURL=float-wallet.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"float-wallet.service.js","sourceRoot":"","sources":["../src/float-wallet.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG7C,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YAA6B,OAAsB;QAAtB,YAAO,GAAP,OAAO,CAAe;IAAG,CAAC;IAEvD,YAAY,CAAC,MAAoB;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,MAAoB,EACpB,MAAc,EACd,OAAuC,IAAI;QAE3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,MAAoB,EACpB,MAAc,EACd,OAAuC,IAAI;QAE3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;CACF,CAAA;AAxBY,kBAAkB;IAD9B,UAAU,EAAE;qCAE2B,aAAa;GADxC,kBAAkB,CAwB9B"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { WalletModule, type WalletModuleAsyncOptions } from './wallet.module.js';
|
|
2
|
+
export { WalletService, type CreateWalletInput } from './wallet.service.js';
|
|
3
|
+
export { FloatWalletService } from './float-wallet.service.js';
|
|
4
|
+
export { TransferService, type TransferOptions } from './transfer.service.js';
|
|
5
|
+
export { ExchangeService } from './exchange.service.js';
|
|
6
|
+
export { WarmupService } from './warmup.service.js';
|
|
7
|
+
export { WalletEntity } from './entities/wallet.entity.js';
|
|
8
|
+
export { TransactionEntity, type TransactionType } from './entities/transaction.entity.js';
|
|
9
|
+
export { TransferEntity, type TransferStatus } from './entities/transfer.entity.js';
|
|
10
|
+
export { WalletEventPublisher } from './events/wallet-event.publisher.js';
|
|
11
|
+
export type { WalletCreatedEventPayload, TransactionCreatedEventPayload, BalanceUpdatedEventPayload, } from './events/wallet.events.js';
|
|
12
|
+
export { ArrayLockService } from './lock/array-lock.service.js';
|
|
13
|
+
export { RedisLockService } from './lock/redis-lock.service.js';
|
|
14
|
+
export { MemcachedLockService } from './lock/memcached-lock.service.js';
|
|
15
|
+
export type { WalletLockService } from './lock/lock.service.js';
|
|
16
|
+
export { walletLockKey } from './lock/lock.service.js';
|
|
17
|
+
export { InsufficientFundsError, WalletNotFoundError, WalletLockTimeoutError, ExchangeRateNotFoundError, } from './errors.js';
|
|
18
|
+
export { WALLET_OPTIONS, WALLET_LOCK, WALLET_DATA_SOURCE, WALLET_EVENT, DEFAULT_WALLET_SLUG, DEFAULT_WALLET_NAME, DEFAULT_LOCK_TTL_MS, type WalletModuleOptions, type WalletDataSourceLike, type WalletTableNames, type WalletLockOptions, type HolderId, type HolderIdType, type LockDriver, } from './tokens.js';
|
|
19
|
+
export { generateMigrationFiles, listMigrationSpecs, resolveTables, DEFAULT_TABLES, type MigrationTableNames, } from './migrations/generate.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,YAAY,EACV,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { WalletModule } from './wallet.module.js';
|
|
2
|
+
export { WalletService } from './wallet.service.js';
|
|
3
|
+
export { FloatWalletService } from './float-wallet.service.js';
|
|
4
|
+
export { TransferService } from './transfer.service.js';
|
|
5
|
+
export { ExchangeService } from './exchange.service.js';
|
|
6
|
+
export { WarmupService } from './warmup.service.js';
|
|
7
|
+
export { WalletEntity } from './entities/wallet.entity.js';
|
|
8
|
+
export { TransactionEntity } from './entities/transaction.entity.js';
|
|
9
|
+
export { TransferEntity } from './entities/transfer.entity.js';
|
|
10
|
+
export { WalletEventPublisher } from './events/wallet-event.publisher.js';
|
|
11
|
+
export { ArrayLockService } from './lock/array-lock.service.js';
|
|
12
|
+
export { RedisLockService } from './lock/redis-lock.service.js';
|
|
13
|
+
export { MemcachedLockService } from './lock/memcached-lock.service.js';
|
|
14
|
+
export { walletLockKey } from './lock/lock.service.js';
|
|
15
|
+
export { InsufficientFundsError, WalletNotFoundError, WalletLockTimeoutError, ExchangeRateNotFoundError, } from './errors.js';
|
|
16
|
+
export { WALLET_OPTIONS, WALLET_LOCK, WALLET_DATA_SOURCE, WALLET_EVENT, DEFAULT_WALLET_SLUG, DEFAULT_WALLET_NAME, DEFAULT_LOCK_TTL_MS, } from './tokens.js';
|
|
17
|
+
export { generateMigrationFiles, listMigrationSpecs, resolveTables, DEFAULT_TABLES, } from './migrations/generate.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAiC,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,aAAa,EAA0B,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAwB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAwB,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAuB,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAM1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GAQpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,cAAc,GAEf,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WalletLockService } from './lock.service.js';
|
|
2
|
+
export declare class ArrayLockService implements WalletLockService {
|
|
3
|
+
private readonly locks;
|
|
4
|
+
lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
|
|
5
|
+
private acquire;
|
|
6
|
+
private release;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=array-lock.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/array-lock.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAM3D,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEnD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY3E,OAAO,CAAC,OAAO;IA+Bf,OAAO,CAAC,OAAO;CAUhB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { WalletLockTimeoutError } from '../errors.js';
|
|
2
|
+
export class ArrayLockService {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.locks = new Map();
|
|
5
|
+
}
|
|
6
|
+
async lock(key, ttlMs, fn) {
|
|
7
|
+
const acquired = await this.acquire(key, ttlMs);
|
|
8
|
+
if (!acquired) {
|
|
9
|
+
throw new WalletLockTimeoutError(`Timed out acquiring lock for ${key}`);
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return await fn();
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
this.release(key);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
acquire(key, ttlMs) {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const queue = this.locks.get(key);
|
|
21
|
+
if (!queue) {
|
|
22
|
+
this.locks.set(key, []);
|
|
23
|
+
resolve(true);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
const q = this.locks.get(key);
|
|
28
|
+
if (!q) {
|
|
29
|
+
resolve(false);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const idx = q.indexOf(entry);
|
|
33
|
+
if (idx >= 0)
|
|
34
|
+
q.splice(idx, 1);
|
|
35
|
+
if (q.length === 0)
|
|
36
|
+
this.locks.delete(key);
|
|
37
|
+
resolve(false);
|
|
38
|
+
}, ttlMs);
|
|
39
|
+
const entry = {
|
|
40
|
+
resolve: () => {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
resolve(true);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
queue.push(entry);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
release(key) {
|
|
49
|
+
const queue = this.locks.get(key);
|
|
50
|
+
if (!queue)
|
|
51
|
+
return;
|
|
52
|
+
const next = queue.shift();
|
|
53
|
+
if (next) {
|
|
54
|
+
next.resolve();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.locks.delete(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=array-lock.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-lock.service.js","sourceRoot":"","sources":["../../src/lock/array-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAOtD,MAAM,OAAO,gBAAgB;IAA7B;QACmB,UAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAuD3D,CAAC;IArDC,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,GAAW,EAAE,KAAa;QACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;oBACP,OAAO,CAAC,KAAK,CAAC,CAAC;oBACf,OAAO;gBACT,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,GAAG,IAAI,CAAC;oBAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC3C,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EAAE,KAAK,CAAC,CAAC;YAEV,MAAM,KAAK,GAAe;gBACxB,OAAO,EAAE,GAAG,EAAE;oBACZ,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;aACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,GAAW;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/lock.service.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.service.js","sourceRoot":"","sources":["../../src/lock/lock.service.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,aAAa,CAAC,QAAyB;IACrD,OAAO,eAAe,QAAQ,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WalletLockService } from './lock.service.js';
|
|
2
|
+
type MemjsClient = {
|
|
3
|
+
add(key: string, value: Buffer | string, options: {
|
|
4
|
+
expires: number;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
status?: string;
|
|
7
|
+
success?: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
delete(key: string): Promise<unknown>;
|
|
10
|
+
get(key: string): Promise<{
|
|
11
|
+
value: Buffer | null;
|
|
12
|
+
}>;
|
|
13
|
+
};
|
|
14
|
+
export declare class MemcachedLockService implements WalletLockService {
|
|
15
|
+
private readonly client;
|
|
16
|
+
constructor(client: MemjsClient);
|
|
17
|
+
static create(servers?: string[]): Promise<MemcachedLockService>;
|
|
18
|
+
lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=memcached-lock.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memcached-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/memcached-lock.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,KAAK,WAAW,GAAG;IACjB,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAC3B,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CACrD,CAAC;AAEF,qBAAa,oBAAqB,YAAW,iBAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;WAEnC,MAAM,CAAC,OAAO,GAAE,MAAM,EAAwB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IASrF,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAgC5E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { WalletLockTimeoutError } from '../errors.js';
|
|
3
|
+
export class MemcachedLockService {
|
|
4
|
+
constructor(client) {
|
|
5
|
+
this.client = client;
|
|
6
|
+
}
|
|
7
|
+
static async create(servers = ['127.0.0.1:11211']) {
|
|
8
|
+
// Optional peer — loaded dynamically; typed loosely to avoid requiring @types/memjs
|
|
9
|
+
const memjs = (await import('memjs'));
|
|
10
|
+
const client = memjs.Client.create(servers.join(','));
|
|
11
|
+
return new MemcachedLockService(client);
|
|
12
|
+
}
|
|
13
|
+
async lock(key, ttlMs, fn) {
|
|
14
|
+
const token = randomUUID();
|
|
15
|
+
const expires = Math.max(1, Math.ceil(ttlMs / 1000));
|
|
16
|
+
const deadline = Date.now() + ttlMs;
|
|
17
|
+
let acquired = false;
|
|
18
|
+
while (Date.now() < deadline) {
|
|
19
|
+
try {
|
|
20
|
+
const result = await this.client.add(key, token, { expires });
|
|
21
|
+
if (result.status === 'STORED' || result.success) {
|
|
22
|
+
acquired = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// retry until timeout
|
|
28
|
+
}
|
|
29
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
30
|
+
}
|
|
31
|
+
if (!acquired) {
|
|
32
|
+
throw new WalletLockTimeoutError(`Timed out acquiring memcached lock for ${key}`);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return await fn();
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
const current = await this.client.get(key);
|
|
39
|
+
if (current.value?.toString() === token) {
|
|
40
|
+
await this.client.delete(key);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=memcached-lock.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memcached-lock.service.js","sourceRoot":"","sources":["../../src/lock/memcached-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAatD,MAAM,OAAO,oBAAoB;IAC/B,YAA6B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAEpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAoB,CAAC,iBAAiB,CAAC;QACzD,oFAAoF;QACpF,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,OAAiB,CAAC,CAE7C,CAAC;QACF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjD,QAAQ,GAAG,IAAI,CAAC;oBAChB,MAAM;gBACR,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB;YACxB,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { WalletLockService } from './lock.service.js';
|
|
2
|
+
type RedisClient = {
|
|
3
|
+
set(key: string, value: string, ...args: Array<string | number>): Promise<string | null>;
|
|
4
|
+
eval(script: string, numKeys: number, ...args: string[]): Promise<unknown>;
|
|
5
|
+
};
|
|
6
|
+
export declare class RedisLockService implements WalletLockService {
|
|
7
|
+
private readonly redis;
|
|
8
|
+
constructor(redis: RedisClient);
|
|
9
|
+
static create(url?: string): Promise<RedisLockService>;
|
|
10
|
+
lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=redis-lock.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/redis-lock.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzF,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E,CAAC;AAUF,qBAAa,gBAAiB,YAAW,iBAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,WAAW;WAElC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAStD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAwB5E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { WalletLockTimeoutError } from '../errors.js';
|
|
3
|
+
const RELEASE_SCRIPT = `
|
|
4
|
+
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
5
|
+
return redis.call("del", KEYS[1])
|
|
6
|
+
else
|
|
7
|
+
return 0
|
|
8
|
+
end
|
|
9
|
+
`;
|
|
10
|
+
export class RedisLockService {
|
|
11
|
+
constructor(redis) {
|
|
12
|
+
this.redis = redis;
|
|
13
|
+
}
|
|
14
|
+
static async create(url) {
|
|
15
|
+
const mod = (await import('ioredis'));
|
|
16
|
+
const RedisCtor = mod.default;
|
|
17
|
+
const client = url ? new RedisCtor(url) : new RedisCtor();
|
|
18
|
+
return new RedisLockService(client);
|
|
19
|
+
}
|
|
20
|
+
async lock(key, ttlMs, fn) {
|
|
21
|
+
const token = randomUUID();
|
|
22
|
+
const deadline = Date.now() + ttlMs;
|
|
23
|
+
let acquired = false;
|
|
24
|
+
while (Date.now() < deadline) {
|
|
25
|
+
const result = await this.redis.set(key, token, 'PX', ttlMs, 'NX');
|
|
26
|
+
if (result === 'OK') {
|
|
27
|
+
acquired = true;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
31
|
+
}
|
|
32
|
+
if (!acquired) {
|
|
33
|
+
throw new WalletLockTimeoutError(`Timed out acquiring redis lock for ${key}`);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
return await fn();
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
await this.redis.eval(RELEASE_SCRIPT, 1, key, token);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=redis-lock.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-lock.service.js","sourceRoot":"","sources":["../../src/lock/redis-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAQtD,MAAM,cAAc,GAAG;;;;;;CAMtB,CAAC;AAEF,MAAM,OAAO,gBAAgB;IAC3B,YAA6B,KAAkB;QAAlB,UAAK,GAAL,KAAK,CAAa;IAAG,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAY;QAC9B,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAEnC,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC;QAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1D,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACnE,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface MigrationTableNames {
|
|
2
|
+
wallets: string;
|
|
3
|
+
transactions: string;
|
|
4
|
+
transfers: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const DEFAULT_TABLES: MigrationTableNames;
|
|
7
|
+
export interface PublishMigrationSpec {
|
|
8
|
+
key: string;
|
|
9
|
+
fileSuffix: string;
|
|
10
|
+
contents: (tables: MigrationTableNames, className: string) => string;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildMigrationClassName(suffix: string, stampValue: string): string;
|
|
13
|
+
export declare const MIGRATION_SPECS: PublishMigrationSpec[];
|
|
14
|
+
export declare const UUID_MIGRATION_SPEC: PublishMigrationSpec;
|
|
15
|
+
export declare function resolveTables(overrides?: Partial<MigrationTableNames>): MigrationTableNames;
|
|
16
|
+
export declare function listMigrationSpecs(withUuid?: boolean): PublishMigrationSpec[];
|
|
17
|
+
export declare function generateMigrationFiles(tables: MigrationTableNames, withUuid?: boolean, baseStamp?: number): Array<{
|
|
18
|
+
key: string;
|
|
19
|
+
fileName: string;
|
|
20
|
+
contents: string;
|
|
21
|
+
}>;
|
|
22
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/migrations/generate.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,mBAI5B,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtE;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED,eAAO,MAAM,eAAe,EAAE,oBAAoB,EA8KjD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBA6BjC,CAAC;AAEF,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAE3F;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,UAAQ,GAAG,oBAAoB,EAAE,CAE3E;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,UAAQ,EAChB,SAAS,SAAa,GACrB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAW5D"}
|