Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/shared/i18n/de/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "Wenn dir diese Nachricht nicht weiterhilft, kannst du einfach nochmal eine Nachricht hier schreiben und wirst automatisch an einen Support Mitarbeiter übergeben, der sich den Fall anschaut.",
"monero_not_displayed": "❓ Die Kryptolieferung wird in der Cake Wallet nicht angezeigt:\n\n⓵ Verbindung prüfen:\n▪️ Gehe zum Guthaben-Bildschirm in der Cake Wallet\n▪️ überprüfe, ob die Leiste oben eines der folgenden anzeigt\n🟢 „Synchronisiert“ („Synchronised“)\n🟠 „Connecting“ („Verbindung wird hergestellt“)\n🔴 „Blöcke verbleibend“ („blocks remaining“)\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Wallet synchronisieren, falls Blöcke verbleiben:\n▪️ Lass die App geöffnet\n▪️ bleibe auf dem Guthaben-Bildschirm\n▫️ bis die verbleibenden Blöcke auf 0 reduziert sind.\n\n⓷ Blockchain scannen (Neuscan ab Datum):\n▪️ Falls die Synchronisation das Problem nicht löst\n▪️ starte einen Scan der Blockchain-Blöcke\n👉 1–2 Tage vor der Kryptolieferung.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Überprüfen:\nDeine Kryptolieferung sollte nach diesen Schritten\nin der Wallet angezeigt werden.\n\n⓹ Cake Wallet Support kontaktieren\n(falls ⓵ – ⓸ nicht helfen)\nhttps://docs.cakewallet.com/support\n\n🫵 Du kannst auch die „Cake Wallet In-App Support“-Funktion nutzen,\num direkt über die App mit dem Support-Team zu chatten:\n📲 Öffne dazu das Menü und wähle:\nSupport ➔ Live-Support, um dort Kontakt aufzunehmen."
}
4 changes: 4 additions & 0 deletions src/shared/i18n/en/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "If this message does not help you, simply write another message here and you will be automatically transferred to a support employee who will look into the issue.",
"monero_not_displayed": "❓ The crypto delivery is not displayed in the Cake Wallet:\n\n⓵ Check Connection:\n▪️ Go to the balance screen in the Cake Wallet\n▪️ Check if the bar at the top shows one of the following\n🟢 „Synchronised“\n🟠 „Connecting“\n🔴 „blocks remaining“\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Synchronise the wallet if the bar shows blocks remaining:\nTo do this,\n▪️ Leave the app open\n▪️ and stay on the balance screen\n▫️ until the remaining blocks decrease to 0.\n\n⓷ Scan the blockchain (Rescan from date):\n▪️ If the synchronisation does not solve the problem\n▪️ start the scan of the blockchain blocks\n👉 1–2 days before the crypto delivery.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Check:\nYour crypto delivery should appear in the wallet after these steps.\n\n⓹ Contact Cake Wallet Support\n(if ⓵ – ⓸ does not work)\nhttps://docs.cakewallet.com/support\n\n🫵 You may also use the „Cake Wallet In-App Support“ function\nto chat with the support team directly through the app:\n📲 Open the menu and select:\nSupport ➔ Live Support to get in touch there. ☝️"
}
4 changes: 4 additions & 0 deletions src/shared/i18n/es/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "If this message does not help you, simply write another message here and you will be automatically transferred to a support employee who will look into the issue.",
"monero_not_displayed": "❓ The crypto delivery is not displayed in the Cake Wallet:\n\n⓵ Check Connection:\n▪️ Go to the balance screen in the Cake Wallet\n▪️ Check if the bar at the top shows one of the following\n🟢 „Synchronised“\n🟠 „Connecting“\n🔴 „blocks remaining“\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Synchronise the wallet if the bar shows blocks remaining:\nTo do this,\n▪️ Leave the app open\n▪️ and stay on the balance screen\n▫️ until the remaining blocks decrease to 0.\n\n⓷ Scan the blockchain (Rescan from date):\n▪️ If the synchronisation does not solve the problem\n▪️ start the scan of the blockchain blocks\n👉 1–2 days before the crypto delivery.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Check:\nYour crypto delivery should appear in the wallet after these steps.\n\n⓹ Contact Cake Wallet Support\n(if ⓵ – ⓸ does not work)\nhttps://docs.cakewallet.com/support\n\n🫵 You may also use the „Cake Wallet In-App Support“ function\nto chat with the support team directly through the app:\n📲 Open the menu and select:\nSupport ➔ Live Support to get in touch there. ☝️"
}
4 changes: 4 additions & 0 deletions src/shared/i18n/fr/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "If this message does not help you, simply write another message here and you will be automatically transferred to a support employee who will look into the issue.",
"monero_not_displayed": "❓ The crypto delivery is not displayed in the Cake Wallet:\n\n⓵ Check Connection:\n▪️ Go to the balance screen in the Cake Wallet\n▪️ Check if the bar at the top shows one of the following\n🟢 „Synchronised“\n🟠 „Connecting“\n🔴 „blocks remaining“\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Synchronise the wallet if the bar shows blocks remaining:\nTo do this,\n▪️ Leave the app open\n▪️ and stay on the balance screen\n▫️ until the remaining blocks decrease to 0.\n\n⓷ Scan the blockchain (Rescan from date):\n▪️ If the synchronisation does not solve the problem\n▪️ start the scan of the blockchain blocks\n👉 1–2 days before the crypto delivery.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Check:\nYour crypto delivery should appear in the wallet after these steps.\n\n⓹ Contact Cake Wallet Support\n(if ⓵ – ⓸ does not work)\nhttps://docs.cakewallet.com/support\n\n🫵 You may also use the „Cake Wallet In-App Support“ function\nto chat with the support team directly through the app:\n📲 Open the menu and select:\nSupport ➔ Live Support to get in touch there. ☝️"
}
4 changes: 4 additions & 0 deletions src/shared/i18n/it/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "If this message does not help you, simply write another message here and you will be automatically transferred to a support employee who will look into the issue.",
"monero_not_displayed": "❓ The crypto delivery is not displayed in the Cake Wallet:\n\n⓵ Check Connection:\n▪️ Go to the balance screen in the Cake Wallet\n▪️ Check if the bar at the top shows one of the following\n🟢 „Synchronised“\n🟠 „Connecting“\n🔴 „blocks remaining“\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Synchronise the wallet if the bar shows blocks remaining:\nTo do this,\n▪️ Leave the app open\n▪️ and stay on the balance screen\n▫️ until the remaining blocks decrease to 0.\n\n⓷ Scan the blockchain (Rescan from date):\n▪️ If the synchronisation does not solve the problem\n▪️ start the scan of the blockchain blocks\n👉 1–2 days before the crypto delivery.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Check:\nYour crypto delivery should appear in the wallet after these steps.\n\n⓹ Contact Cake Wallet Support\n(if ⓵ – ⓸ does not work)\nhttps://docs.cakewallet.com/support\n\n🫵 You may also use the „Cake Wallet In-App Support“ function\nto chat with the support team directly through the app:\n📲 Open the menu and select:\nSupport ➔ Live Support to get in touch there. ☝️"
}
4 changes: 4 additions & 0 deletions src/shared/i18n/pt/support-issue.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"bot_hint": "If this message does not help you, simply write another message here and you will be automatically transferred to a support employee who will look into the issue.",
"monero_not_displayed": "❓ The crypto delivery is not displayed in the Cake Wallet:\n\n⓵ Check Connection:\n▪️ Go to the balance screen in the Cake Wallet\n▪️ Check if the bar at the top shows one of the following\n🟢 „Synchronised“\n🟠 „Connecting“\n🔴 „blocks remaining“\nhttps://docs.cakewallet.com/faq/funds-not-appearing\n\n⓶ Synchronise the wallet if the bar shows blocks remaining:\nTo do this,\n▪️ Leave the app open\n▪️ and stay on the balance screen\n▫️ until the remaining blocks decrease to 0.\n\n⓷ Scan the blockchain (Rescan from date):\n▪️ If the synchronisation does not solve the problem\n▪️ start the scan of the blockchain blocks\n👉 1–2 days before the crypto delivery.\nhttps://docs.cakewallet.com/features/advanced/rescan-wallet\n\n⓸ Check:\nYour crypto delivery should appear in the wallet after these steps.\n\n⓹ Contact Cake Wallet Support\n(if ⓵ – ⓸ does not work)\nhttps://docs.cakewallet.com/support\n\n🫵 You may also use the „Cake Wallet In-App Support“ function\nto chat with the support team directly through the app:\n📲 Open the menu and select:\nSupport ➔ Live Support to get in touch there. ☝️"
}
1 change: 1 addition & 0 deletions src/shared/services/process.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export enum Process {
AML_RECHECK_MAIL_RESET = 'AmlRecheckMailReset',
ZANO_ASSET_WHITELIST = 'ZanoAssetWhitelist',
TRADE_APPROVAL_DATE = 'TradeApprovalDate',
SUPPORT_BOT = 'SupportBot',
}

const safetyProcesses: Process[] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { CronExpression } from '@nestjs/schedule';
import { Config } from 'src/config/config';
import { EvmUtil } from 'src/integration/blockchain/shared/evm/evm.util';
import { EvmCoinHistoryEntry, EvmTokenHistoryEntry } from 'src/integration/blockchain/shared/evm/interfaces';
import { Asset, AssetType } from 'src/shared/models/asset/asset.entity';
import { BlockchainAddress } from 'src/shared/models/blockchain-address';
import { DfxLogger } from 'src/shared/services/dfx-logger';
import { Process } from 'src/shared/services/process.service';
import { DfxCron } from 'src/shared/utils/cron';
import { Util } from 'src/shared/utils/util';
import { TransactionRequestService } from 'src/subdomains/supporting/payment/services/transaction-request.service';
import { PayInType } from '../../../../entities/crypto-input.entity';
import { PayInEntry } from '../../../../interfaces';
import { RegisterStrategy } from './register.strategy';

export interface PayInCitreaServiceInterface {
getHistory(address: string, fromBlock: number): Promise<[EvmCoinHistoryEntry[], EvmTokenHistoryEntry[]]>;
}

export abstract class CitreaBaseStrategy extends RegisterStrategy {
protected readonly logger = new DfxLogger(CitreaBaseStrategy);

private readonly paymentDepositAddress: string;

protected abstract getOwnAddresses(): string[];

constructor(
protected readonly payInCitreaService: PayInCitreaServiceInterface,
protected readonly transactionRequestService: TransactionRequestService,
) {
super();
this.paymentDepositAddress = EvmUtil.createWallet({ seed: Config.payment.evmSeed, index: 0 }).address;
}

// --- JOBS --- //
@DfxCron(CronExpression.EVERY_MINUTE, { process: Process.PAY_IN, timeout: 7200 })
async checkPayInEntries(): Promise<void> {
const activeDepositAddresses = await this.transactionRequestService.getActiveDepositAddresses(
Util.hoursBefore(1),
this.blockchain,
);

await this.processNewPayInEntries(activeDepositAddresses.map((a) => BlockchainAddress.create(a, this.blockchain)));
}

async pollAddress(depositAddress: BlockchainAddress): Promise<void> {
if (depositAddress.blockchain !== this.blockchain)
throw new Error(`Invalid blockchain: ${depositAddress.blockchain}`);

return this.processNewPayInEntries([depositAddress]);
}

private async processNewPayInEntries(depositAddresses: BlockchainAddress[]): Promise<void> {
const log = this.createNewLogObject();

const newEntries: PayInEntry[] = [];

for (const depositAddress of depositAddresses) {
const lastCheckedBlockHeight = await this.getLastCheckedBlockHeight(depositAddress);

newEntries.push(...(await this.getNewEntries(depositAddress, lastCheckedBlockHeight)));
}

if (newEntries?.length) {
await this.createPayInsAndSave(newEntries, log);
}

this.printInputLog(log, 'omitted', this.blockchain);
}

private async getLastCheckedBlockHeight(depositAddress: BlockchainAddress): Promise<number> {
return this.payInRepository
.findOne({
select: ['id', 'blockHeight'],
where: { address: depositAddress },
order: { blockHeight: 'DESC' },
loadEagerRelations: false,
})
.then((input) => input?.blockHeight ?? 0);
}

private async getNewEntries(
depositAddress: BlockchainAddress,
lastCheckedBlockHeight: number,
): Promise<PayInEntry[]> {
const fromBlock = lastCheckedBlockHeight + 1;
const [coinTransactions, tokenTransactions] = await this.payInCitreaService.getHistory(
depositAddress.address,
fromBlock,
);

const supportedAssets = await this.assetService.getAllBlockchainAssets([this.blockchain]);

const coinEntries = this.mapCoinTransactionsToEntries(coinTransactions, depositAddress, supportedAssets);
const tokenEntries = this.mapTokenTransactionsToEntries(tokenTransactions, depositAddress, supportedAssets);

return [...coinEntries, ...tokenEntries];
}

private mapCoinTransactionsToEntries(
transactions: EvmCoinHistoryEntry[],
depositAddress: BlockchainAddress,
supportedAssets: Asset[],
): PayInEntry[] {
const ownAddresses = this.getOwnAddresses();
const relevantTransactions = transactions.filter(
(t) =>
t.to.toLowerCase() === depositAddress.address.toLowerCase() && !Util.includesIgnoreCase(ownAddresses, t.from),
);

const coinAsset = supportedAssets.find((a) => a.type === AssetType.COIN);

return relevantTransactions.map((tx) => ({
senderAddresses: tx.from,
receiverAddress: depositAddress,
txId: tx.hash,
txType: this.getTxType(depositAddress.address),
txSequence: 0,
blockHeight: parseInt(tx.blockNumber),
amount: Util.floorByPrecision(EvmUtil.fromWeiAmount(tx.value), 15),
asset: coinAsset,
}));
}

private mapTokenTransactionsToEntries(
transactions: EvmTokenHistoryEntry[],
depositAddress: BlockchainAddress,
supportedAssets: Asset[],
): PayInEntry[] {
const ownAddresses = this.getOwnAddresses();
const relevantTransactions = transactions.filter(
(t) =>
t.to.toLowerCase() === depositAddress.address.toLowerCase() && !Util.includesIgnoreCase(ownAddresses, t.from),
);

const entries: PayInEntry[] = [];
const txGroups = Util.groupBy(relevantTransactions, 'hash');

for (const txGroup of txGroups.values()) {
for (let i = 0; i < txGroup.length; i++) {
const tx = txGroup[i];

const asset = this.assetService.getByChainIdSync(supportedAssets, this.blockchain, tx.contractAddress);
const decimals = tx.tokenDecimal ? parseInt(tx.tokenDecimal) : asset?.decimals;

entries.push({
senderAddresses: tx.from,
receiverAddress: depositAddress,
txId: tx.hash,
txType: this.getTxType(depositAddress.address),
txSequence: i,
blockHeight: parseInt(tx.blockNumber),
amount: Util.floorByPrecision(EvmUtil.fromWeiAmount(tx.value, decimals), 15),
asset,
});
}
}

return entries;
}

private getTxType(depositAddress: string): PayInType {
return Util.equalsIgnoreCase(this.paymentDepositAddress, depositAddress) ? PayInType.PAYMENT : PayInType.DEPOSIT;
}
}
Loading
Loading