Skip to content

Commit

Permalink
feat(transaction): add backfill trx details script
Browse files Browse the repository at this point in the history
  • Loading branch information
dragosp1011 committed Jan 29, 2025
1 parent 0975ab1 commit 8238718
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 38 deletions.
124 changes: 124 additions & 0 deletions packages/wallet/backend/src/backfillTrxDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { createContainer } from '@/createContainer'
import { env } from '@/config/env'
import { Account } from '@/account/model'
import { Transaction } from '@/transaction/model'
import { Model } from 'objection'
import { transformBalance, urlToPaymentId } from '@/utils/helpers'

async function backfillTrxDetails() {
const container = await createContainer(env)
const knex = container.resolve('knex')
Model.knex(knex)
const rafikiClient = container.resolve('rafikiClient')
const rafikiService = container.resolve('rafikiService')
const gateHubClient = container.resolve('gateHubClient')

async function getOutgoingPaymentSecondParty(paymentId: string) {
try {
const outgoingPayment =
await rafikiClient.getOutgoingPaymentById(paymentId)

return rafikiService.getOutgoingPaymentSecondPartyByIncomingPaymentId(
urlToPaymentId(outgoingPayment.receiver)
)
} catch (e) {
console.warn('Error on getting receiver wallet address', e)
}
}

async function getIncomingPaymentSecondParty(paymentId: string) {
return rafikiService.getIncomingPaymentSenders(paymentId)
}

async function backfillCardTrx(account: Account) {
if (!account.cardId || !account.user?.gateHubUserId) {
return
}

let page = 1
const pageSize = 10
let shouldFetchNext = true
while (shouldFetchNext) {
const transactionsResponse = await gateHubClient.getCardTransactions(
account.cardId,
account.user.gateHubUserId,
pageSize,
page
)

if (transactionsResponse.data.length < pageSize) {
shouldFetchNext = false
}

for (const cardTrx of transactionsResponse.data) {
console.log('processing trx: ', cardTrx.id)
const existentTrx = await Transaction.query().findOne(
'paymentId',
cardTrx.id
)
if (!existentTrx) {
console.log('trx not found: ', cardTrx.id)
continue
}

await Transaction.query()
.where('id', existentTrx.id)
.update({
secondParty: cardTrx.merchantName,
txAmount: cardTrx.transactionAmount
? transformBalance(Number(cardTrx.transactionAmount), 2)
: undefined,
conversionRate: cardTrx.mastercardConversion?.convRate,
txCurrency: cardTrx.transactionCurrency,
cardTxType: cardTrx.type
})
console.log('trx updated: ', existentTrx.paymentId)
}

page++
}
}

try {
const accounts = await Account.query().withGraphFetched('user')

for (const account of accounts) {
console.log('processing account: ', account)
const rafikiTransactions = await Transaction.query()
.where('accountId', account.id)
.whereNull('isCard')
for (const tx of rafikiTransactions) {
console.log('processing trx: ', tx)
if (!tx.walletAddressId) {
continue
}

let secondParty
if (tx.type === 'INCOMING') {
secondParty = await getIncomingPaymentSecondParty(tx.paymentId)
} else {
secondParty = await getOutgoingPaymentSecondParty(tx.paymentId)
}
await Transaction.query().where('id', tx.id).update({ secondParty })
console.log('trx updated')
}

await backfillCardTrx(account)
}
} catch (error: unknown) {
console.log(`An error occurred: ${(error as Error).message}`)
} finally {
await knex.destroy()
await container.dispose()
}
}

backfillTrxDetails()
.then(() => {
console.log('finished')
process.exit(0)
})
.catch((error) => {
console.error(`Script failed: ${error.message}`)
process.exit(1)
})
14 changes: 14 additions & 0 deletions packages/wallet/backend/src/rafiki/backend/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1637,6 +1637,13 @@ export type CreateIncomingPaymentMutationVariables = Exact<{

export type CreateIncomingPaymentMutation = { __typename?: 'Mutation', createIncomingPayment: { __typename?: 'IncomingPaymentResponse', payment?: { __typename?: 'IncomingPayment', createdAt: string, metadata?: any | null, expiresAt: string, id: string, walletAddressId: string, state: IncomingPaymentState, incomingAmount?: { __typename?: 'Amount', assetCode: string, assetScale: number, value: bigint } | null, receivedAmount: { __typename?: 'Amount', assetCode: string, assetScale: number, value: bigint } } | null } };

export type GetIncomingPaymentQueryVariables = Exact<{
id: Scalars['String']['input'];
}>;


export type GetIncomingPaymentQuery = { __typename?: 'Query', incomingPayment?: { __typename?: 'IncomingPayment', id: string, walletAddressId: string } | null };

export type WithdrawLiquidityMutationVariables = Exact<{
eventId: Scalars['String']['input'];
idempotencyKey: Scalars['String']['input'];
Expand Down Expand Up @@ -1671,6 +1678,13 @@ export type GetOutgoingPaymentsQueryVariables = Exact<{

export type GetOutgoingPaymentsQuery = { __typename?: 'Query', outgoingPayments: { __typename?: 'OutgoingPaymentConnection', edges: Array<{ __typename?: 'OutgoingPaymentEdge', cursor: string, node: { __typename?: 'OutgoingPayment', id: string, walletAddressId: string, receiver: string, grantId?: string | null, state: OutgoingPaymentState, createdAt: string, sentAmount: { __typename?: 'Amount', assetCode: string, assetScale: number, value: bigint } } }>, pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor?: string | null } } };

export type GetOutgoingPaymentQueryVariables = Exact<{
id: Scalars['String']['input'];
}>;


export type GetOutgoingPaymentQuery = { __typename?: 'Query', outgoingPayment?: { __typename?: 'OutgoingPayment', id: string, walletAddressId: string, receiver: string, grantId?: string | null, state: OutgoingPaymentState, createdAt: string, sentAmount: { __typename?: 'Amount', assetCode: string, assetScale: number, value: bigint } } | null };

export type CreateQuoteMutationVariables = Exact<{
input: CreateQuoteInput;
}>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ export const createIncomingPaymentMutation = gql`
}
}
`

export const getIncomingPaymentQuery = gql`
query GetIncomingPaymentQuery($id: String!) {
incomingPayment(id: $id) {
id
walletAddressId
}
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ export const getOutgoingPayments = gql`
}
`

export const getOutgoingPaymentQuery = gql`
query GetOutgoingPaymentQuery($id: String!) {
outgoingPayment(id: $id) {
id
walletAddressId
receiver
grantId
sentAmount {
assetCode
assetScale
value
}
state
createdAt
}
}
`

export type OutgoingPaymentsGqlResponse = Pick<
OutgoingPayment,
| 'id'
Expand Down
32 changes: 30 additions & 2 deletions packages/wallet/backend/src/rafiki/rafiki-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,28 @@ import {
GetReceiverQueryVariables,
QueryOutgoingPaymentsArgs,
GetOutgoingPaymentsQuery,
GetOutgoingPaymentsQueryVariables
GetOutgoingPaymentsQueryVariables,
GetOutgoingPaymentQuery,
GetOutgoingPaymentQueryVariables,
GetIncomingPaymentQuery,
GetIncomingPaymentQueryVariables
} from './backend/generated/graphql'
import {
createAssetMutation,
getAssetQuery,
getAssetsQuery
} from './backend/request/asset.request'
import { createIncomingPaymentMutation } from './backend/request/incoming-payment.request'
import {
createIncomingPaymentMutation,
getIncomingPaymentQuery
} from './backend/request/incoming-payment.request'
import {
depositLiquidityMutation,
withdrawLiquidityMutation
} from './backend/request/liquidity.request'
import {
createOutgoingPaymentMutation,
getOutgoingPaymentQuery,
getOutgoingPayments,
OutgoingPaymentsGqlResponse
} from './backend/request/outgoing-payment.request'
Expand Down Expand Up @@ -417,4 +425,24 @@ export class RafikiClient implements IRafikiClient {
(el: { node: OutgoingPaymentsGqlResponse }) => el.node
)
}

public async getOutgoingPaymentById(
id: string
): Promise<OutgoingPaymentsGqlResponse> {
const response = await this.backendGraphQLClient.request<
GetOutgoingPaymentQuery,
GetOutgoingPaymentQueryVariables
>(getOutgoingPaymentQuery, { id })

return response.outgoingPayment as OutgoingPaymentsGqlResponse
}

public async getIncomingPaymentById(id: string): Promise<IncomingPayment> {
const response = await this.backendGraphQLClient.request<
GetIncomingPaymentQuery,
GetIncomingPaymentQueryVariables
>(getIncomingPaymentQuery, { id })

return response.incomingPayment as IncomingPayment
}
}
95 changes: 60 additions & 35 deletions packages/wallet/backend/src/rafiki/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,28 +231,7 @@ export class RafikiService implements IRafikiService {

await this.rafikiClient.withdrawLiqudity(wh.id)

let senders
try {
const outgoingPayments =
await this.rafikiClient.getOutgoingPaymentsByReceiver(
`${this.env.OPEN_PAYMENTS_HOST}/incoming-payments/${wh.data.id}`
)

const walletAddressIds = outgoingPayments.map(
(payment) => payment.walletAddressId
)
const walletAddresses =
await this.walletAddressService.getByIds(walletAddressIds)
senders = walletAddresses
.filter((wa) => wa.account?.user)
.map((wa) => `${wa.account.user.firstName} ${wa.account.user.lastName}`)
.join(', ')
} catch (e) {
this.logger.warn(
'Error on getting outgoing payments by incoming payment',
e
)
}
const senders = await this.getIncomingPaymentSenders(wh.data.id)

await this.transactionService.updateTransaction(
{ paymentId: wh.data.id },
Expand Down Expand Up @@ -295,19 +274,9 @@ export class RafikiService implements IRafikiService {
return
}

let secondParty
try {
const receiver = await this.rafikiClient.getReceiverById(wh.data.receiver)
const receiverWA = await this.walletAddressService.getByUrl(
receiver.walletAddressUrl
)

if (receiverWA?.account?.user) {
secondParty = `${receiverWA.account.user.firstName} ${receiverWA.account.user.lastName}`
}
} catch (e) {
this.logger.warn('Error on getting receiver wallet address', e)
}
const secondParty = await this.getOutgoingPaymentSecondPartyByReceiver(
wh.data.receiver
)

await this.transactionService.createOutgoingTransaction(
wh.data,
Expand Down Expand Up @@ -457,4 +426,60 @@ export class RafikiService implements IRafikiService {
gateHubUserId: account.user.gateHubUserId
}
}

async getIncomingPaymentSenders(id: string) {
try {
const outgoingPayments =
await this.rafikiClient.getOutgoingPaymentsByReceiver(
`${this.env.OPEN_PAYMENTS_HOST}/incoming-payments/${id}`
)

const walletAddressIds = outgoingPayments.map(
(payment) => payment.walletAddressId
)
const walletAddresses =
await this.walletAddressService.getByIds(walletAddressIds)
// return senders
return walletAddresses
.filter((wa) => wa.account?.user)
.map((wa) => `${wa.account.user.firstName} ${wa.account.user.lastName}`)
.join(', ')
} catch (e) {
this.logger.warn(
'Error on getting outgoing payments by incoming payment',
e
)
}
}

async getOutgoingPaymentSecondPartyByReceiver(receiverId: string) {
try {
const receiver = await this.rafikiClient.getReceiverById(receiverId)
const receiverWA = await this.walletAddressService.getByUrl(
receiver.walletAddressUrl
)

if (receiverWA?.account?.user) {
return `${receiverWA.account.user.firstName} ${receiverWA.account.user.lastName}`
}
} catch (e) {
this.logger.warn('Error on getting receiver wallet address', e)
}
}

async getOutgoingPaymentSecondPartyByIncomingPaymentId(paymentId: string) {
try {
const receiver = await this.rafikiClient.getIncomingPaymentById(paymentId)

const receiverWA = await this.walletAddressService.getByIdWIthUserDetails(
receiver.walletAddressId
)

if (receiverWA?.account?.user) {
return `${receiverWA.account.user.firstName} ${receiverWA.account.user.lastName}`
}
} catch (e) {
this.logger.warn('Error on getting receiver wallet address', e)
}
}
}
8 changes: 8 additions & 0 deletions packages/wallet/backend/src/walletAddress/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,12 @@ export class WalletAddressService implements IWalletAddressService {

return walletAddress
}

async getByIdWIthUserDetails(id: string): Promise<WalletAddress | undefined> {
const walletAddress = await WalletAddress.query()
.findById(id)
.withGraphFetched('account.[user]')

return walletAddress
}
}
2 changes: 1 addition & 1 deletion packages/wallet/frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
})

let NEXT_PUBLIC_FEATURES_ENABLED = 'true'
let NEXT_PUBLIC_FEATURES_ENABLED = 'false'

if (
process.env.NODE_ENV === 'production' &&
Expand Down

0 comments on commit 8238718

Please sign in to comment.