diff --git a/.env.example b/.env.example index f8d739561..2f45d28b9 100644 --- a/.env.example +++ b/.env.example @@ -71,6 +71,7 @@ MATTERS_SLACK_TOKEN= MATTERS_SLACK_PAYOUT_CHANNEL= MATTERS_SLACK_STRIPE_ALERT_CHANNEL= MATTERS_SLACK_QUEUE_CHANNEL= +MATTERS_SLACK_CURATION_VAULT_CHANNEL= APOLLO_KEY= APOLLO_GRAPH_REF= MATTERS_OPENSEA_API_BASE=https://rinkeby-api.opensea.io/api/v1 diff --git a/package.json b/package.json index 8b3059bf6..bfb07dfc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matters-server", - "version": "5.6.2", + "version": "5.8.0", "description": "Matters Server", "author": "Matters ", "main": "build/index.js", diff --git a/src/common/enums/payment.ts b/src/common/enums/payment.ts index 107ee6895..0e225c27d 100644 --- a/src/common/enums/payment.ts +++ b/src/common/enums/payment.ts @@ -81,6 +81,12 @@ export const BLOCKCHAIN_RPC: { [chainId: string]: string } = { [optimismSepolia.id]: `https://opt-sepolia.g.alchemy.com/v2/${environment.alchemyApiKey}`, } +export const BLOCKCHAIN_EXPLORER = { + [BLOCKCHAIN.Optimism]: isProd + ? optimism.blockExplorers.default + : optimismSepolia.blockExplorers.default, // TODO: update to etherscan +} + // via https://support.kraken.com/hc/en-us/articles/203325283-Cryptocurrency-deposit-processing-times export const BLOCKCHAIN_SAFE_CONFIRMS: { [key in GQLChain]: number } = { Polygon: 70, diff --git a/src/common/environment.ts b/src/common/environment.ts index b667448cf..a4b53f447 100644 --- a/src/common/environment.ts +++ b/src/common/environment.ts @@ -122,6 +122,8 @@ export const environment = { slackPayoutChannel: process.env.MATTERS_SLACK_PAYOUT_CHANNEL || '', slackStripeAlertChannel: process.env.MATTERS_SLACK_STRIPE_ALERT_CHANNEL || '', slackStripeQueueChannel: process.env.MATTERS_SLACK_QUEUE_CHANNEL || '', + slackCurationVaultChannel: + process.env.MATTERS_SLACK_CURATION_VAULT_CHANNEL || '', openseaAPIBase: process.env.MATTERS_OPENSEA_API_BASE || (isProd diff --git a/src/connectors/slack/index.ts b/src/connectors/slack/index.ts index e2ce41939..95b2800f8 100644 --- a/src/connectors/slack/index.ts +++ b/src/connectors/slack/index.ts @@ -87,6 +87,41 @@ class SlackService { } } + public sendVaultWithdrawMessage = async ({ + amount, + state, + txDbId, + userName, + txHash, + }: { + amount: number | string + state: SLACK_MESSAGE_STATE + txDbId: string + userName: string + txHash?: string + }) => { + try { + await this.client.chat.postMessage({ + channel: environment.slackCurationVaultChannel, + text: `[${environment.env}] - Vault withdraw request is ${state}.`, + attachments: [ + { + color: this.getMessageColor(state), + text: + '\n' + + `\n- *Matters ID:* ${userName}` + + `\n- *DB Tx ID*: ${txDbId}` + + `\n- *On-chain Tx*: ${txHash || 'N/A'}` + + `\n- *Amount*: ${amount} USD`, + }, + ], + markdown: true, + }) + } catch (error) { + logger.error(error) + } + } + /** * Send alert realted to stripe issues. */ diff --git a/src/mutations/user/withdrawLockedTokens.ts b/src/mutations/user/withdrawLockedTokens.ts index d41f2e534..ce4703a34 100644 --- a/src/mutations/user/withdrawLockedTokens.ts +++ b/src/mutations/user/withdrawLockedTokens.ts @@ -4,10 +4,13 @@ import { v4 } from 'uuid' import { formatUnits } from 'viem' import { + BLOCKCHAIN, + BLOCKCHAIN_EXPLORER, BLOCKCHAIN_TRANSACTION_STATE, NOTICE_TYPE, PAYMENT_CURRENCY, PAYMENT_PROVIDER, + SLACK_MESSAGE_STATE, TRANSACTION_PURPOSE, TRANSACTION_STATE, USER_STATE, @@ -19,6 +22,7 @@ import { ServerError, } from 'common/errors' import { CurationVaultContract } from 'connectors/blockchain/curationVault' +import SlackService from 'connectors/slack' const resolver: GQLMutationResolvers['withdrawLockedTokens'] = async ( _, @@ -66,6 +70,7 @@ const resolver: GQLMutationResolvers['withdrawLockedTokens'] = async ( const contract = new CurationVaultContract() const client = await contract.getClient() + const slack = new SlackService() // check withdraw amount const vaultAmount = await contract.getWithdrawableUSDTAmount(viewer.id) @@ -129,6 +134,14 @@ const resolver: GQLMutationResolvers['withdrawLockedTokens'] = async ( { type: 'target', entityTable: 'transaction', entity: transaction }, ], }) + + slack.sendVaultWithdrawMessage({ + amount: transaction.amount, + state: SLACK_MESSAGE_STATE.successful, + txDbId: transaction.id, + userName: viewer.userName, + txHash: `${BLOCKCHAIN_EXPLORER[BLOCKCHAIN.Optimism].url}/tx/${txHash}`, + }) } catch (error) { console.error(error) @@ -154,6 +167,13 @@ const resolver: GQLMutationResolvers['withdrawLockedTokens'] = async ( ], }) + slack.sendVaultWithdrawMessage({ + amount: transaction.amount, + state: SLACK_MESSAGE_STATE.failed, + txDbId: transaction.id, + userName: viewer.userName, + }) + throw new ServerError('failed to withdraw locked tokens') } diff --git a/src/queries/user/wallet/balance.ts b/src/queries/user/wallet/balance.ts index 640853ea7..aa9a74608 100644 --- a/src/queries/user/wallet/balance.ts +++ b/src/queries/user/wallet/balance.ts @@ -12,6 +12,7 @@ const resolver: GQLWalletResolvers['balance'] = async ( HKD: 0, } } + const HKD = await paymentService.calculateBalance({ userId: id, currency: PAYMENT_CURRENCY.HKD,