Skip to content

Commit b3c7184

Browse files
committed
feat(network): API endpoint listing bids
refs akash-network#767
1 parent f853bf0 commit b3c7184

File tree

12 files changed

+460
-60
lines changed

12 files changed

+460
-60
lines changed

apps/api/src/app.ts

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { RequestContextInterceptor } from "@src/core/services/request-context-in
1616
import { HonoInterceptor } from "@src/core/types/hono-interceptor.type";
1717
import packageJson from "../package.json";
1818
import { apiKeysRouter } from "./auth/routes/api-keys/api-keys.router";
19+
import { bidsRouter } from "./bid/routes/bids/bids.router";
1920
import { chainDb, syncUserSchema, userDb } from "./db/dbConnection";
2021
import { deploymentSettingRouter } from "./deployment/routes/deployment-setting/deployment-setting.router";
2122
import { clientInfoMiddleware } from "./middlewares/clientInfoMiddleware";
@@ -87,6 +88,7 @@ appHono.route("/", getAnonymousUserRouter);
8788
appHono.route("/", sendVerificationEmailRouter);
8889
appHono.route("/", deploymentSettingRouter);
8990
appHono.route("/", apiKeysRouter);
91+
appHono.route("/", bidsRouter);
9092

9193
appHono.get("/status", c => {
9294
const version = packageJson.version;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { BidHttpService } from "@akashnetwork/http-sdk";
2+
import { singleton } from "tsyringe";
3+
4+
import { AuthService, Protected } from "@src/auth/services/auth.service";
5+
import { ListBidsResponse } from "@src/bid/http-schemas/bid.schema";
6+
import { UserWalletRepository } from "@src/billing/repositories";
7+
8+
@singleton()
9+
export class BidController {
10+
constructor(
11+
private readonly bidHttpService: BidHttpService,
12+
private readonly authService: AuthService,
13+
private readonly userWalletRepository: UserWalletRepository,
14+
) {}
15+
16+
@Protected([{ action: "sign", subject: "UserWallet" }])
17+
async list(dseq: string, userId?: string): Promise<ListBidsResponse> {
18+
const { currentUser, ability } = this.authService;
19+
20+
const wallets = await this.userWalletRepository.accessibleBy(ability, "sign").findByUserId(userId ?? currentUser.userId);
21+
const bids = await this.bidHttpService.list(wallets[0].address, dseq);
22+
23+
return { data: bids };
24+
}
25+
}
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { z } from "zod";
2+
3+
const DeploymentResource_V3 = z.object({
4+
cpu: z.object({
5+
units: z.object({
6+
val: z.string(),
7+
}),
8+
attributes: z.array(z.object({
9+
key: z.string(),
10+
value: z.string(),
11+
})),
12+
}),
13+
gpu: z.object({
14+
units: z.object({
15+
val: z.string(),
16+
}),
17+
attributes: z.array(z.object({
18+
key: z.string(),
19+
value: z.string(),
20+
})),
21+
}),
22+
memory: z.object({
23+
quantity: z.object({
24+
val: z.string(),
25+
}),
26+
attributes: z.array(z.object({
27+
key: z.string(),
28+
value: z.string(),
29+
})),
30+
}),
31+
storage: z.array(z.object({
32+
name: z.string(),
33+
quantity: z.object({
34+
val: z.string(),
35+
}),
36+
attributes: z.array(z.object({
37+
key: z.string(),
38+
value: z.string(),
39+
})),
40+
})),
41+
endpoints: z.array(z.object({
42+
kind: z.string(),
43+
sequence_number: z.number()
44+
}))
45+
});
46+
47+
export const BidResponseSchema = z.object({
48+
bid: z.object({
49+
bid_id: z.object({
50+
owner: z.string(),
51+
dseq: z.string(),
52+
gseq: z.number(),
53+
oseq: z.number(),
54+
provider: z.string(),
55+
}),
56+
state: z.string(),
57+
price: z.object({
58+
denom: z.string(),
59+
amount: z.string(),
60+
}),
61+
created_at: z.string(),
62+
resources_offer: z.array(z.object({
63+
resources: DeploymentResource_V3,
64+
count: z.number(),
65+
}))
66+
}),
67+
escrow_account: z.object({
68+
id: z.object({
69+
scope: z.string(),
70+
xid: z.string(),
71+
}),
72+
owner: z.string(),
73+
state: z.string(),
74+
balance: z.object({
75+
denom: z.string(),
76+
amount: z.string(),
77+
}),
78+
transferred: z.object({
79+
denom: z.string(),
80+
amount: z.string(),
81+
}),
82+
settled_at: z.string(),
83+
depositor: z.string(),
84+
funds: z.object({
85+
denom: z.string(),
86+
amount: z.string(),
87+
}),
88+
})
89+
});
90+
91+
export const ListBidsQuerySchema = z.object({
92+
dseq: z.string(),
93+
userId: z.optional(z.string()),
94+
});
95+
96+
export const ListBidsResponseSchema = z.object({
97+
data: z.array(BidResponseSchema)
98+
});
99+
100+
export type ListBidsResponse = z.infer<typeof ListBidsResponseSchema>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { createRoute } from "@hono/zod-openapi";
2+
import { container } from "tsyringe";
3+
4+
import { BidController } from "@src/bid/controllers/bid/bid.controller";
5+
import { ListBidsQuerySchema, ListBidsResponseSchema } from "@src/bid/http-schemas/bid.schema";
6+
import { OpenApiHonoHandler } from "@src/core/services/open-api-hono-handler/open-api-hono-handler";
7+
8+
const listRoute = createRoute({
9+
method: "get",
10+
path: "/v1/bids",
11+
summary: "List bids",
12+
tags: ["Bids"],
13+
request: {
14+
query: ListBidsQuerySchema
15+
},
16+
responses: {
17+
200: {
18+
description: "List of bids",
19+
content: {
20+
"application/json": {
21+
schema: ListBidsResponseSchema
22+
}
23+
}
24+
}
25+
}
26+
});
27+
28+
export const bidsRouter = new OpenApiHonoHandler();
29+
30+
bidsRouter.openapi(listRoute, async function routeListBids(c) {
31+
const { dseq, userId } = c.req.valid("query");
32+
const result = await container.resolve(BidController).list(dseq, userId);
33+
return c.json(result, 200);
34+
});
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { AuthzHttpService, BalanceHttpService, BlockHttpService } from "@akashnetwork/http-sdk";
1+
import { AuthzHttpService, BalanceHttpService, BidHttpService, BlockHttpService } from "@akashnetwork/http-sdk";
22
import { container } from "tsyringe";
33

44
import { apiNodeUrl } from "@src/utils/constants";
55

6-
const SERVICES = [BalanceHttpService, AuthzHttpService, BlockHttpService];
6+
const SERVICES = [BalanceHttpService, AuthzHttpService, BlockHttpService, BidHttpService];
77

88
SERVICES.forEach(Service => container.register(Service, { useValue: new Service({ baseURL: apiNodeUrl }) }));

apps/api/src/deployment/services/gpu-bids-creator/gpu-bids-creator.service.ts

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { MsgCloseDeployment, MsgCreateDeployment } from "@akashnetwork/akash-api/v1beta3";
22
import { SDL } from "@akashnetwork/akashjs/build/sdl";
33
import { getAkashTypeRegistry } from "@akashnetwork/akashjs/build/stargate";
4+
import { BidHttpService } from "@akashnetwork/http-sdk";
45
import { LoggerService } from "@akashnetwork/logging";
56
import { DirectSecp256k1HdWallet, EncodeObject, Registry } from "@cosmjs/proto-signing";
67
import { calculateFee, SigningStargateClient } from "@cosmjs/stargate";
@@ -10,7 +11,6 @@ import { singleton } from "tsyringe";
1011

1112
import { BillingConfigService } from "@src/billing/services/billing-config/billing-config.service";
1213
import { getGpuModelsAvailability } from "@src/routes/v1/gpu";
13-
import { RestAkashBidListResponseType } from "@src/types/rest";
1414
import { apiNodeUrl } from "@src/utils/constants";
1515
import { sleep } from "@src/utils/delay";
1616
import { env } from "@src/utils/env";
@@ -20,7 +20,10 @@ import { sdlTemplateWithRam, sdlTemplateWithRamAndInterface } from "./sdl-templa
2020
export class GpuBidsCreatorService {
2121
private readonly logger = LoggerService.forContext(GpuBidsCreatorService.name);
2222

23-
constructor(private readonly config: BillingConfigService) {}
23+
constructor(
24+
private readonly config: BillingConfigService,
25+
private readonly bidHttpService: BidHttpService,
26+
) { }
2427

2528
async createGpuBids() {
2629
if (!env.GPU_BOT_WALLET_MNEMONIC) throw new Error("The env variable GPU_BOT_WALLET_MNEMONIC is not set.");
@@ -107,9 +110,9 @@ export class GpuBidsCreatorService {
107110

108111
await sleep(30_000);
109112

110-
const bids = await this.getBids(walletAddress, dseq);
113+
const bids = await this.bidHttpService.list(walletAddress, dseq);
111114

112-
this.logger.info(`Got ${bids.bids.length} bids. Closing deployment...`);
115+
this.logger.info({ event: "DEPLOYMENT_CLOSING", bidsCount: bids.length });
113116

114117
await this.closeDeployment(client, walletAddress, dseq);
115118

@@ -163,12 +166,6 @@ export class GpuBidsCreatorService {
163166
await this.signAndBroadcast(owner, client, [message]);
164167
}
165168

166-
private async getBids(owner: string, dseq: string) {
167-
const response = await axios.get<RestAkashBidListResponseType>(`${apiNodeUrl}/akash/market/v1beta4/bids/list?filters.owner=${owner}&filters.dseq=${dseq}`);
168-
169-
return response.data;
170-
}
171-
172169
private getModelSdl(vendor: string, model: string, ram: string, gpuInterface?: string) {
173170
let gpuSdl = gpuInterface ? sdlTemplateWithRamAndInterface : sdlTemplateWithRam;
174171
gpuSdl = gpuSdl.replace("<VENDOR>", vendor);

apps/api/src/types/rest/akashBidListResponse.ts

-47
This file was deleted.

apps/api/src/types/rest/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export * from "./akashBidListResponse";
21
export * from "./akashDeploymentListResponse";
32
export * from "./akashLeaseListResponse";
43
export * from "./akashDeploymentInfoResponse";

0 commit comments

Comments
 (0)