Skip to content

Commit b095202

Browse files
authored
Merge pull request #3148 from DFXswiss/develop
Release: develop -> main
2 parents 0687398 + 9254fae commit b095202

8 files changed

Lines changed: 72 additions & 19 deletions

File tree

.github/workflows/api-dev.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ jobs:
5151
run: npm audit --audit-level=high
5252
continue-on-error: true
5353

54+
- name: Write version file
55+
run: echo "${{ github.sha }}" > dist/version.txt
56+
5457
- name: Deploy to Azure App Service (DEV)
5558
uses: azure/webapps-deploy@v3
5659
with:

.github/workflows/api-pr.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,39 @@ permissions:
1212

1313
env:
1414
NODE_VERSION: '20.x'
15+
DEV_API_URL: https://dev.api.dfx.swiss
1516

1617
jobs:
18+
verify-dev-deployment:
19+
name: Verify DEV Deployment
20+
if: github.base_ref == 'main' && github.head_ref == 'develop'
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Wait for DEV deployment
24+
timeout-minutes: 15
25+
run: |
26+
EXPECTED=$(curl -s https://api.github.com/repos/${{ github.repository }}/commits/develop | jq -r '.sha')
27+
echo "Expected commit: $EXPECTED"
28+
29+
for i in {1..30}; do
30+
if RESPONSE=$(curl -sf ${{ env.DEV_API_URL }}/version 2>&1); then
31+
ACTUAL=$(echo "$RESPONSE" | jq -r '.commit')
32+
echo "Attempt $i: DEV running $ACTUAL"
33+
34+
if [ "$EXPECTED" == "$ACTUAL" ]; then
35+
echo "DEV is running the latest develop commit"
36+
exit 0
37+
fi
38+
else
39+
echo "Attempt $i: DEV API not reachable"
40+
fi
41+
42+
sleep 30
43+
done
44+
45+
echo "::error::DEV is not running the latest develop commit after 15 minutes"
46+
exit 1
47+
1748
build:
1849
name: Build and test
1950
if: github.head_ref != 'develop'

.github/workflows/api-prd.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ jobs:
5151
run: npm audit --audit-level=high
5252
continue-on-error: true
5353

54+
- name: Write version file
55+
run: echo "${{ github.sha }}" > dist/version.txt
56+
5457
- name: Deploy to Azure App Service (PRD)
5558
uses: azure/webapps-deploy@v3
5659
with:

src/app.controller.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Controller, Get, Param, Query, Redirect, Req, Res, VERSION_NEUTRAL, Ver
22
import { ApiExcludeEndpoint } from '@nestjs/swagger';
33
import { Request, Response } from 'express';
44
import { UserAgent } from 'express-useragent';
5+
import { readFileSync } from 'fs';
56
import { RealIP } from 'nestjs-real-ip';
67
import { Config } from './config/config';
78
import { AdDto, AdSettings, AdvertisementDto } from './shared/dto/advertisement.dto';
@@ -27,6 +28,7 @@ enum Manufacturer {
2728

2829
@Controller('')
2930
export class AppController {
31+
private readonly startedAt = new Date();
3032
private readonly homepageUrl = 'https://dfx.swiss/';
3133
private readonly appleStoreUrl = 'https://apps.apple.com/app';
3234
private readonly googleStoreUrl = 'https://play.app.goo.gl/?link=https://play.google.com/store/apps/details';
@@ -60,6 +62,21 @@ export class AppController {
6062
// nothing to do (redirect to Swagger UI)
6163
}
6264

65+
@Get('version')
66+
@ApiExcludeEndpoint()
67+
@Version(VERSION_NEUTRAL)
68+
getVersion(): { commit: string; startedAt: Date } {
69+
return { commit: this.getCommit(), startedAt: this.startedAt };
70+
}
71+
72+
private getCommit(): string {
73+
try {
74+
return readFileSync('dist/version.txt', 'utf8').trim();
75+
} catch {
76+
return 'unknown';
77+
}
78+
}
79+
6380
@Get('app/announcements')
6481
@ApiExcludeEndpoint()
6582
async getAnnouncements(): Promise<AnnouncementDto[]> {

src/integration/blockchain/bitcoin-testnet4/services/bitcoin-testnet4-fee.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export class BitcoinTestnet4FeeService {
3535
return 1;
3636
}
3737

38-
return feeRate;
38+
return Math.max(feeRate, 1);
3939
},
4040
undefined,
4141
true, // fallbackToCache on error

src/integration/exchange/services/exchange.service.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export abstract class ExchangeService extends PricingProvider implements OnModul
165165
this.logger.verbose(`Could not update order ${order.id} price: ${JSON.stringify(updatedOrder)}`);
166166

167167
if (updatedOrder.status === OrderStatus.OPEN)
168-
await this.callApi((e) => e.cancelOrder(order.id, order.symbol)).catch((e) =>
168+
await this.cancelOrder(order.id, order.symbol).catch((e) =>
169169
this.logger.error(`Error while cancelling order ${order.id}:`, e),
170170
);
171171
}
@@ -376,6 +376,10 @@ export abstract class ExchangeService extends PricingProvider implements OnModul
376376
);
377377
}
378378

379+
protected async cancelOrder(orderId: string, symbol: string): Promise<void> {
380+
await this.callApi((e) => e.cancelOrder(orderId, symbol));
381+
}
382+
379383
// other
380384
protected async callApi<T>(action: (exchange: Exchange) => Promise<T>): Promise<T> {
381385
return this.queue.handle(() =>

src/integration/exchange/services/mexc.service.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,14 +355,17 @@ export class MexcService extends ExchangeService {
355355

356356
protected async updateOrderPrice(order: Order, amount: number, price: number): Promise<string> {
357357
// MEXC doesn't support editOrder, so cancel and create new
358-
await this.cancelOrderById(order.id, order.symbol);
358+
await this.cancelOrder(order.id, order.symbol);
359359

360360
const newOrder = await this.createOrder(order.symbol, order.side as OrderSide, amount, price);
361361
return newOrder.id;
362362
}
363363

364-
private async cancelOrderById(orderId: string, pair: string): Promise<void> {
364+
protected async cancelOrder(orderId: string, pair: string): Promise<void> {
365365
const symbol = pair.replace('/', '');
366-
await this.request<unknown>('DELETE', 'order', { symbol, orderId });
366+
await this.request<unknown>('DELETE', 'order', { symbol, orderId }).catch((e) => {
367+
// -2011 means order is already cancelled
368+
if (!e.message?.includes('-2011')) throw e;
369+
});
367370
}
368371
}

src/subdomains/core/liquidity-management/adapters/actions/clementine-bridge.adapter.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,14 @@ export class ClementineBridgeAdapter extends LiquidityActionAdapter {
213213
private async withdraw(order: LiquidityManagementOrder): Promise<CorrelationId> {
214214
const {
215215
pipeline: {
216-
rule: { targetAsset: bitcoinAsset },
216+
rule: { targetAsset: citreaAsset },
217217
},
218218
} = order;
219219

220-
// Validate asset is BTC on Bitcoin
221-
if (bitcoinAsset.type !== AssetType.COIN || bitcoinAsset.blockchain !== this.btcBlockchain) {
220+
// Validate asset is cBTC on Citrea (we withdraw FROM cBTC TO BTC)
221+
if (citreaAsset.type !== AssetType.COIN || citreaAsset.blockchain !== this.citreaBlockchain) {
222222
throw new OrderNotProcessableException(
223-
`Clementine withdraw only supports BTC (native coin) on ${this.btcBlockchain}`,
223+
`Clementine withdraw only supports cBTC (native coin) on ${this.citreaBlockchain}`,
224224
);
225225
}
226226

@@ -230,8 +230,8 @@ export class ClementineBridgeAdapter extends LiquidityActionAdapter {
230230
// Validate network consistency on first use
231231
await this.validateNetworkConsistency();
232232

233-
// Get the corresponding Citrea cBTC asset
234-
const citreaAsset = await this.getCitreaAsset();
233+
// Get the corresponding Bitcoin BTC asset
234+
const bitcoinAsset = await this.getBtcAsset();
235235

236236
// Check cBTC balance on Citrea - must have at least 10 cBTC (fixed bridge amount)
237237
const cbtcBalance = await this.citreaClient.getNativeCoinBalance();
@@ -739,10 +739,6 @@ export class ClementineBridgeAdapter extends LiquidityActionAdapter {
739739
return this.network === ClementineNetwork.TESTNET4;
740740
}
741741

742-
private get btcBlockchain(): Blockchain {
743-
return this.isTestnet ? Blockchain.BITCOIN_TESTNET4 : Blockchain.BITCOIN;
744-
}
745-
746742
private get citreaBlockchain(): Blockchain {
747743
return this.isTestnet ? Blockchain.CITREA_TESTNET : Blockchain.CITREA;
748744
}
@@ -751,10 +747,6 @@ export class ClementineBridgeAdapter extends LiquidityActionAdapter {
751747
return this.isTestnet ? this.assetService.getBitcoinTestnet4Coin() : this.assetService.getBtcCoin();
752748
}
753749

754-
private getCitreaAsset(): Promise<Asset> {
755-
return this.isTestnet ? this.assetService.getCitreaTestnetCoin() : this.assetService.getCitreaCoin();
756-
}
757-
758750
private getFeeRate(): Promise<number> {
759751
return this.isTestnet
760752
? this.bitcoinTestnet4FeeService.getRecommendedFeeRate()

0 commit comments

Comments
 (0)