Skip to content
Open
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
7 changes: 7 additions & 0 deletions packages/wallet/backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,13 @@ export class App {

async processResources() {
process.nextTick(() => this.processPendingTransactions())
setInterval(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the same approach with setTimeout after getting a response, this why the next processing will be set only after the previous one finishes and it will avoid parallel processing in case of slow responses

() => {
const transactionService = this.container.resolve('transactionService')
transactionService.approveTransactions()
},
1 * 60 * 1000
).unref()
}

ensureGateHubProductionEnv = async (
Expand Down
49 changes: 49 additions & 0 deletions packages/wallet/backend/src/gatehub/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createHmac } from 'crypto'
import {
HTTP_METHODS,
IApprovePendingTransaction,
IApproveUserToGatewayRequest,
IApproveUserToGatewayResponse,
IConnectUserToGatewayResponse,
Expand All @@ -17,6 +18,7 @@ import {
IGetWalletResponse,
IOverrideUserRiskLevelRequest,
IOverrideUserRiskLevelResponse,
IPendingTransaction,
IRatesResponse,
ITokenRequest,
ITokenResponse,
Expand Down Expand Up @@ -335,6 +337,53 @@ export class GateHubClient {
return response
}

async approvePendingTransactions(
transactionUuid: string
): Promise<IApprovePendingTransaction> {
const url = `${this.apiUrl}/core/v1/transactions/${transactionUuid}/serviceStatus`
const body = {
serviceStatus: 3,
substatus: 0,
reason: 'test'
}
const response = await this.request<IApprovePendingTransaction>(
'PUT',
url,
JSON.stringify(body)
)
if (response.state !== 4) {
throw new Error(`Approval failed, transactionUuid: ${transactionUuid}`)
}
return response
}

async getPendingTransactions(): Promise<IPendingTransaction[]> {
const url = `${this.apiUrl}/core/v1/gateways/${this.env.GATEHUB_GATEWAY_UUID}/transactions`
const payload = {
filters: {
state: {
value: 3
},
created_at: {},
amount: {},
define_range: {
offset: 0,
limit: 20
},
order: {
field: 'id',
direction: 'desc'
}
}
}
const response = await this.request<IPendingTransaction[]>(
'GET',
url,
JSON.stringify(payload)
)
return response
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leave a new line between blocks and returns for better readability

}

async getWallet(
userUuid: string,
walletId: string
Expand Down
44 changes: 44 additions & 0 deletions packages/wallet/backend/src/gatehub/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,50 @@ export interface IGetWalletResponse {
address: string
}

interface IWalletInfo {
uuid: string
created_at: string
address: string
name: string
}
interface IGateway {
uuid: string
created_at: string
updated_at: string
status: number
name: string
terms: string
insurance: number
}
export interface IPendingTransaction {
uuid: string
state: number
created_at: string
completed_at: string
amount: string
total_amount: string
fee: string
type: number
status: number
substatus: number
sending_wallet: IWalletInfo
receiving_wallet: IWalletInfo
vault: IVault
message: string
reason: string
gateway: IGateway
announcement_uuid: string
}

export interface IApprovePendingTransaction extends IPendingTransaction {
receiving_user: {
uuid: string
email: string
created_at: string
updated_at: string
}
}

export interface ICreateTransactionRequest {
amount: number
receiving_amount?: string
Expand Down
22 changes: 22 additions & 0 deletions packages/wallet/backend/src/transaction/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,28 @@ export class TransactionService implements ITransactionService {
}
}

async approveTransactions() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asa the trx are GateHub trx, I think it should be in gatehub service

try {
const transactions = await this.gateHubClient.getPendingTransactions()
const pendingTransactions = transactions.filter(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this filter necessary?

Copy link
Copy Markdown
Contributor

@Tymmmy Tymmmy May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, getPendingTransactions should already filter for state=3

(transaction) => transaction.state === 3
)
if (!pendingTransactions.length) {
console.log('No pending Transactions!')
return
}
for (const transaction of pendingTransactions) {
try {
await this.gateHubClient.approvePendingTransactions(transaction.uuid)
} catch (err) {
console.error(`Error: ${err}`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use logger

}
}
} catch (err) {
console.error(`Automatic approval failed - ${err}`)
}
}

async processPendingIncomingPayments(): Promise<string | undefined> {
return this.knex.transaction(async (trx) => {
// Giving a Rafiki a little more time to process the payments before we process them.
Expand Down
Loading