Skip to content

Commit d4e0867

Browse files
authored
Merge pull request #3366 from DFXswiss/develop
Release: develop -> main
2 parents ebe2ec9 + 5b17bc8 commit d4e0867

6 files changed

Lines changed: 105 additions & 11 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/**
2+
* @typedef {import('typeorm').MigrationInterface} MigrationInterface
3+
* @typedef {import('typeorm').QueryRunner} QueryRunner
4+
*/
5+
6+
/**
7+
* Recalibrate financeLogPairIds for toScrypt EUR (second recalibration).
8+
*
9+
* The receiver side (eurReceiverScryptExchangeTx) includes ALL Scrypt EUR deposits,
10+
* while the sender side (eurSenderScryptBankTx) is filtered by eurBankIbans (Olkypay +
11+
* Yapeal only). Former MaerkiBaumann transfers (bank_tx 191068: 363k, 191069: 42k)
12+
* created exchange_tx deposits but are excluded from the bank_tx sender list, causing
13+
* a 281k EUR mismatch and a negative toScryptUnfiltered.
14+
*
15+
* Fix: Move the pair IDs forward to the latest settled pair:
16+
* bankTxId 191523 (30k EUR, Olkypay, Mar 4)
17+
* exchangeTxId 126558 (30k EUR, Scrypt DEPOSIT, Mar 4)
18+
*
19+
* This excludes orphan exchange_tx and MaerkiBaumann bank_tx from the window,
20+
* correctly showing only the pending 30k EUR transfer.
21+
*
22+
* @class
23+
* @implements {MigrationInterface}
24+
*/
25+
module.exports = class RecalibrateScryptEurPairIds1772600000000 {
26+
name = 'RecalibrateScryptEurPairIds1772600000000';
27+
28+
/**
29+
* @param {QueryRunner} queryRunner
30+
*/
31+
async up(queryRunner) {
32+
console.log('=== Recalibrate financeLogPairIds toScrypt EUR (2nd) ===\n');
33+
34+
const rows = await queryRunner.query(
35+
`SELECT id, value FROM dbo.setting WHERE [key] = 'financeLogPairIds'`,
36+
);
37+
38+
if (rows.length === 0) {
39+
console.log('ERROR: financeLogPairIds setting not found. Aborting.');
40+
return;
41+
}
42+
43+
const setting = rows[0];
44+
const pairIds = JSON.parse(setting.value);
45+
46+
console.log('Current toScrypt.eur:', JSON.stringify(pairIds.toScrypt.eur));
47+
48+
pairIds.toScrypt.eur.bankTxId = 191523;
49+
pairIds.toScrypt.eur.exchangeTxId = 126558;
50+
51+
console.log('New toScrypt.eur:', JSON.stringify(pairIds.toScrypt.eur));
52+
53+
const newValue = JSON.stringify(pairIds);
54+
55+
await queryRunner.query(
56+
`UPDATE dbo.setting SET value = '${newValue}' WHERE id = ${setting.id}`,
57+
);
58+
59+
// Verify
60+
const verify = await queryRunner.query(
61+
`SELECT value FROM dbo.setting WHERE id = ${setting.id}`,
62+
);
63+
const verified = JSON.parse(verify[0].value);
64+
console.log('\nVerified toScrypt.eur:', JSON.stringify(verified.toScrypt.eur));
65+
console.log('\n=== Migration Complete ===');
66+
}
67+
68+
/**
69+
* @param {QueryRunner} queryRunner
70+
*/
71+
async down(queryRunner) {
72+
const rows = await queryRunner.query(
73+
`SELECT id, value FROM dbo.setting WHERE [key] = 'financeLogPairIds'`,
74+
);
75+
76+
if (rows.length === 0) return;
77+
78+
const setting = rows[0];
79+
const pairIds = JSON.parse(setting.value);
80+
81+
pairIds.toScrypt.eur.bankTxId = 190029;
82+
pairIds.toScrypt.eur.exchangeTxId = 123655;
83+
84+
await queryRunner.query(
85+
`UPDATE dbo.setting SET value = '${JSON.stringify(pairIds)}' WHERE id = ${setting.id}`,
86+
);
87+
}
88+
};

src/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export class Configuration {
4747
kycVersion: Version = '2';
4848
defaultVersionString = `v${this.defaultVersion}`;
4949
defaultRef = '000-000';
50+
defaultWalletId = 1;
5051
transactionRefundExpirySeconds = 300; // 5 minutes - enough time to fill out the refund form
5152
refRewardManualCheckLimit = 3000; // EUR
5253
txRequestWaitingExpiryDays = 7;

src/subdomains/core/custody/services/custody.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export class CustodyService {
5454
const custodyWallet = EvmUtil.createWallet(Config.blockchain.evm.custodyAccount(addressIndex));
5555
const signature = await custodyWallet.signMessage(Config.auth.signMessageGeneral + custodyWallet.address);
5656

57-
const account = await this.userDataService.getUserData(accountId);
57+
const account = await this.userDataService.getUserData(accountId, { users: true });
5858
if (!account) throw new NotFoundException('User not found');
5959

6060
const custodyUser = await this.userService.createUser(

src/subdomains/generic/user/models/user-data/user-data.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ export class UserDataService {
11661166
// optional master updates
11671167
if (master.status === UserDataStatus.KYC_ONLY && slave.users.length && slave.wallet) master.wallet = slave.wallet;
11681168
if ([UserDataStatus.KYC_ONLY, UserDataStatus.DEACTIVATED].includes(master.status)) master.status = slave.status;
1169+
if ((!master.wallet || master.wallet.id === Config.defaultWalletId) && slave.wallet) master.wallet = slave.wallet;
11691170
if (!master.amlListAddedDate && slave.amlListAddedDate) {
11701171
master.amlListAddedDate = slave.amlListAddedDate;
11711172
master.amlListExpiredDate = slave.amlListExpiredDate;

src/subdomains/generic/user/models/user/user.service.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,14 @@ export class UserService {
240240
addressType: CryptoService.getAddressType(data.address),
241241
});
242242
const userIsActive = data.userData?.status === UserDataStatus.ACTIVE;
243+
const lastExistingUsedRef = data.userData?.users
244+
? Util.sort(data.userData.users, 'id', 'DESC').find((u) => u.usedRef !== Config.defaultRef)?.usedRef
245+
: undefined;
243246

244247
user.ip = data.ip;
245248
user.ipCountry = this.geoLocationService.getCountry(data.ip);
246249
user.wallet = data.wallet ?? (await this.walletService.getDefault());
247-
user.usedRef = await this.checkRef(user, data.usedRef);
250+
user.usedRef = await this.checkRef(user, data.usedRef, lastExistingUsedRef);
248251
user.origin = data.origin;
249252
user.custodyProvider = data.custodyProvider;
250253
if (userIsActive) user.status = UserStatus.ACTIVE;
@@ -597,14 +600,14 @@ export class UserService {
597600
await this.userDataRepo.activateUserData(userData);
598601
}
599602

600-
private async checkRef(user: User, usedRef: string): Promise<string> {
601-
const refUser = await this.getRefUser(usedRef);
602-
return usedRef === null ||
603-
usedRef === user.ref ||
604-
(usedRef && !refUser) ||
605-
user?.userData?.id === refUser?.userData?.id
606-
? Config.defaultRef
607-
: usedRef;
603+
private async checkRef(user: User, usedRef?: string, existingUsedRef?: string): Promise<string> {
604+
if (usedRef) {
605+
const refUser = await this.getRefUser(usedRef);
606+
const isValidRef = usedRef !== user.ref && refUser && user?.userData?.id !== refUser?.userData?.id;
607+
if (isValidRef) return usedRef;
608+
}
609+
610+
return existingUsedRef ?? Config.defaultRef;
608611
}
609612

610613
public async getTotalRefRewards(): Promise<number> {

src/subdomains/generic/user/models/wallet/wallet.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Injectable, NotFoundException } from '@nestjs/common';
2+
import { Config } from 'src/config/config';
23
import { WalletRepository } from 'src/subdomains/generic/user/models/wallet/wallet.repository';
34
import { FindOptionsRelations } from 'typeorm';
45
import { WalletDto } from './dto/wallet.dto';
@@ -40,6 +41,6 @@ export class WalletService {
4041
}
4142

4243
async getDefault(): Promise<Wallet> {
43-
return this.repo.findOneCachedBy('default', { id: 1 });
44+
return this.repo.findOneCachedBy('default', { id: Config.defaultWalletId });
4445
}
4546
}

0 commit comments

Comments
 (0)