@kadi.build/deploy-ability 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/targets/akash/bids.d.ts +183 -0
- package/dist/targets/akash/bids.d.ts.map +1 -0
- package/dist/targets/akash/bids.js +247 -0
- package/dist/targets/akash/bids.js.map +1 -0
- package/dist/targets/akash/certificate-manager.d.ts +89 -167
- package/dist/targets/akash/certificate-manager.d.ts.map +1 -1
- package/dist/targets/akash/certificate-manager.js +193 -301
- package/dist/targets/akash/certificate-manager.js.map +1 -1
- package/dist/targets/akash/client.d.ts +644 -0
- package/dist/targets/akash/client.d.ts.map +1 -0
- package/dist/targets/akash/client.js +972 -0
- package/dist/targets/akash/client.js.map +1 -0
- package/dist/targets/akash/constants.d.ts +12 -149
- package/dist/targets/akash/constants.d.ts.map +1 -1
- package/dist/targets/akash/constants.js +14 -136
- package/dist/targets/akash/constants.js.map +1 -1
- package/dist/targets/akash/deployer.d.ts +3 -82
- package/dist/targets/akash/deployer.d.ts.map +1 -1
- package/dist/targets/akash/deployer.js +122 -160
- package/dist/targets/akash/deployer.js.map +1 -1
- package/dist/targets/akash/environment.d.ts +16 -214
- package/dist/targets/akash/environment.d.ts.map +1 -1
- package/dist/targets/akash/environment.js +20 -210
- package/dist/targets/akash/environment.js.map +1 -1
- package/dist/targets/akash/index.d.ts +95 -189
- package/dist/targets/akash/index.d.ts.map +1 -1
- package/dist/targets/akash/index.js +69 -197
- package/dist/targets/akash/index.js.map +1 -1
- package/dist/targets/akash/lease-monitor.d.ts +3 -21
- package/dist/targets/akash/lease-monitor.d.ts.map +1 -1
- package/dist/targets/akash/lease-monitor.js +39 -56
- package/dist/targets/akash/lease-monitor.js.map +1 -1
- package/dist/targets/akash/logs.d.ts +103 -4
- package/dist/targets/akash/logs.d.ts.map +1 -1
- package/dist/targets/akash/logs.js +12 -3
- package/dist/targets/akash/logs.js.map +1 -1
- package/dist/targets/akash/pricing.d.ts +12 -191
- package/dist/targets/akash/pricing.d.ts.map +1 -1
- package/dist/targets/akash/pricing.js +12 -188
- package/dist/targets/akash/pricing.js.map +1 -1
- package/dist/targets/akash/provider-manager.d.ts +120 -0
- package/dist/targets/akash/provider-manager.d.ts.map +1 -0
- package/dist/targets/akash/provider-manager.js +574 -0
- package/dist/targets/akash/provider-manager.js.map +1 -0
- package/dist/targets/akash/sdl-generator.d.ts +2 -2
- package/dist/targets/akash/sdl-generator.d.ts.map +1 -1
- package/dist/targets/akash/sdl-generator.js +6 -39
- package/dist/targets/akash/sdl-generator.js.map +1 -1
- package/dist/targets/akash/types.d.ts +66 -243
- package/dist/targets/akash/types.d.ts.map +1 -1
- package/dist/targets/akash/types.js +4 -41
- package/dist/targets/akash/types.js.map +1 -1
- package/dist/targets/akash/wallet-manager.d.ts +35 -352
- package/dist/targets/akash/wallet-manager.d.ts.map +1 -1
- package/dist/targets/akash/wallet-manager.js +37 -439
- package/dist/targets/akash/wallet-manager.js.map +1 -1
- package/dist/targets/local/compose-generator.d.ts.map +1 -1
- package/dist/targets/local/compose-generator.js +1 -0
- package/dist/targets/local/compose-generator.js.map +1 -1
- package/dist/targets/local/deployer.js +4 -4
- package/dist/targets/local/deployer.js.map +1 -1
- package/dist/targets/local/types.d.ts +4 -0
- package/dist/targets/local/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/options.d.ts +45 -4
- package/dist/types/options.d.ts.map +1 -1
- package/dist/utils/registry/manager.js +6 -6
- package/dist/utils/registry/manager.js.map +1 -1
- package/dist/utils/registry/setup.js +4 -4
- package/dist/utils/registry/setup.js.map +1 -1
- package/docs/KADI_ABILITY_CONVERSION.md +1365 -0
- package/docs/PIPELINE_BUILDER_DESIGN.md +1149 -0
- package/package.json +8 -11
- package/dist/targets/akash/bid-selectors.d.ts +0 -251
- package/dist/targets/akash/bid-selectors.d.ts.map +0 -1
- package/dist/targets/akash/bid-selectors.js +0 -322
- package/dist/targets/akash/bid-selectors.js.map +0 -1
- package/dist/targets/akash/bid-types.d.ts +0 -297
- package/dist/targets/akash/bid-types.d.ts.map +0 -1
- package/dist/targets/akash/bid-types.js +0 -89
- package/dist/targets/akash/bid-types.js.map +0 -1
- package/dist/targets/akash/blockchain-client.d.ts +0 -577
- package/dist/targets/akash/blockchain-client.d.ts.map +0 -1
- package/dist/targets/akash/blockchain-client.js +0 -803
- package/dist/targets/akash/blockchain-client.js.map +0 -1
- package/dist/targets/akash/logs.types.d.ts +0 -102
- package/dist/targets/akash/logs.types.d.ts.map +0 -1
- package/dist/targets/akash/logs.types.js +0 -9
- package/dist/targets/akash/logs.types.js.map +0 -1
- package/dist/targets/akash/provider-client.d.ts +0 -114
- package/dist/targets/akash/provider-client.d.ts.map +0 -1
- package/dist/targets/akash/provider-client.js +0 -318
- package/dist/targets/akash/provider-client.js.map +0 -1
- package/dist/targets/akash/provider-metadata.d.ts +0 -228
- package/dist/targets/akash/provider-metadata.d.ts.map +0 -1
- package/dist/targets/akash/provider-metadata.js +0 -14
- package/dist/targets/akash/provider-metadata.js.map +0 -1
- package/dist/targets/akash/provider-service.d.ts +0 -133
- package/dist/targets/akash/provider-service.d.ts.map +0 -1
- package/dist/targets/akash/provider-service.js +0 -391
- package/dist/targets/akash/provider-service.js.map +0 -1
- package/dist/targets/akash/query-client.d.ts +0 -125
- package/dist/targets/akash/query-client.d.ts.map +0 -1
- package/dist/targets/akash/query-client.js +0 -332
- package/dist/targets/akash/query-client.js.map +0 -1
- package/docs/EXAMPLES.md +0 -293
- package/docs/PLACEMENT.md +0 -433
- package/docs/STORAGE.md +0 -318
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Bid Management
|
|
3
|
+
*
|
|
4
|
+
* Types, pricing calculations, and selection strategies for choosing providers
|
|
5
|
+
* based on cost, reliability, and other criteria.
|
|
6
|
+
*
|
|
7
|
+
* Key responsibilities:
|
|
8
|
+
* - Calculate bid pricing across multiple time periods (hour, day, week, month)
|
|
9
|
+
* - Convert prices between currencies (uAKT, AKT, USD)
|
|
10
|
+
* - Provide selection strategies (cheapest, most reliable, balanced)
|
|
11
|
+
* - Filter bids by criteria (price, uptime, audit status, location)
|
|
12
|
+
*
|
|
13
|
+
* @module targets/akash/bids
|
|
14
|
+
*/
|
|
15
|
+
import type { ProviderBid } from './client.js';
|
|
16
|
+
import type { ProviderInfo } from './types.js';
|
|
17
|
+
export type { ProviderBid };
|
|
18
|
+
/**
|
|
19
|
+
* Bid pricing across multiple time periods (block/hour/day/week/month) and
|
|
20
|
+
* currencies (uAKT/AKT/USD). All prices derived from raw per-block price.
|
|
21
|
+
*/
|
|
22
|
+
export interface BidPricing {
|
|
23
|
+
readonly raw: {
|
|
24
|
+
readonly denom: string;
|
|
25
|
+
readonly amount: string;
|
|
26
|
+
};
|
|
27
|
+
readonly uakt: {
|
|
28
|
+
readonly perBlock: number;
|
|
29
|
+
readonly perHour: number;
|
|
30
|
+
readonly perDay: number;
|
|
31
|
+
readonly perWeek: number;
|
|
32
|
+
readonly perMonth: number;
|
|
33
|
+
};
|
|
34
|
+
readonly akt: {
|
|
35
|
+
readonly perBlock: number;
|
|
36
|
+
readonly perHour: number;
|
|
37
|
+
readonly perDay: number;
|
|
38
|
+
readonly perWeek: number;
|
|
39
|
+
readonly perMonth: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Convert to USD. You provide the AKT price (library stays dependency-free).
|
|
43
|
+
* Get price from CoinGecko, your oracle, or hardcode for estimates.
|
|
44
|
+
*/
|
|
45
|
+
toUSD(aktPriceUSD: number): {
|
|
46
|
+
readonly perHour: number;
|
|
47
|
+
readonly perDay: number;
|
|
48
|
+
readonly perWeek: number;
|
|
49
|
+
readonly perMonth: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Provider bid enriched with pricing calculations and provider metadata.
|
|
54
|
+
* Wraps raw blockchain bid (ProviderBid) with pre-calculated data for
|
|
55
|
+
* bid selection.
|
|
56
|
+
*/
|
|
57
|
+
export interface EnhancedBid {
|
|
58
|
+
/** Unique ID from bid coordinates (owner/dseq/gseq/oseq/provider) */
|
|
59
|
+
readonly id: string;
|
|
60
|
+
/** Raw blockchain bid data */
|
|
61
|
+
readonly bid: ProviderBid;
|
|
62
|
+
/** Provider info (may have undefined fields for incomplete metadata) */
|
|
63
|
+
readonly provider: ProviderInfo;
|
|
64
|
+
/** Pre-calculated pricing across all time periods */
|
|
65
|
+
readonly pricing: BidPricing;
|
|
66
|
+
/** When the provider submitted this bid */
|
|
67
|
+
readonly createdAt: Date;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Function that selects a bid from available options.
|
|
71
|
+
* Return null if no acceptable bid found.
|
|
72
|
+
*/
|
|
73
|
+
export type BidSelector = ((bids: EnhancedBid[]) => Promise<EnhancedBid | null>) | ((bids: EnhancedBid[]) => EnhancedBid | null);
|
|
74
|
+
/**
|
|
75
|
+
* Create BidPricing from blockchain price data.
|
|
76
|
+
* Calculates all time-period prices from the raw per-block price.
|
|
77
|
+
*/
|
|
78
|
+
export declare function createBidPricing(price: {
|
|
79
|
+
denom: string;
|
|
80
|
+
amount: string;
|
|
81
|
+
}): BidPricing;
|
|
82
|
+
/**
|
|
83
|
+
* Select the cheapest bid by monthly price.
|
|
84
|
+
* For production, consider filtering for quality first (see filterBids).
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const result = await deployToAkash({
|
|
89
|
+
* bidSelector: selectCheapestBid
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function selectCheapestBid(bids: EnhancedBid[]): EnhancedBid | null;
|
|
94
|
+
/**
|
|
95
|
+
* Select the most reliable provider by uptime percentage.
|
|
96
|
+
* Providers without reliability data are excluded.
|
|
97
|
+
*
|
|
98
|
+
* @param bids - Available bids
|
|
99
|
+
* @param period - Uptime period to evaluate (default: 7d)
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const result = await deployToAkash({
|
|
104
|
+
* bidSelector: (bids) => selectMostReliableBid(bids, '30d')
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare function selectMostReliableBid(bids: EnhancedBid[], period?: '1d' | '7d' | '30d'): EnhancedBid | null;
|
|
109
|
+
/**
|
|
110
|
+
* Select bid using balanced scoring (price + reliability weighted).
|
|
111
|
+
* Default: 50/50 balance. Customize weights for your priorities.
|
|
112
|
+
*
|
|
113
|
+
* @param bids - Available bids
|
|
114
|
+
* @param weights - Scoring weights (default: 0.5 price, 0.5 reliability)
|
|
115
|
+
*
|
|
116
|
+
* @example Equal balance
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const result = await deployToAkash({
|
|
119
|
+
* bidSelector: selectBalancedBid // 50/50
|
|
120
|
+
* });
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example Prioritize reliability
|
|
124
|
+
* ```typescript
|
|
125
|
+
* const result = await deployToAkash({
|
|
126
|
+
* bidSelector: (bids) => selectBalancedBid(bids, {
|
|
127
|
+
* price: 0.3,
|
|
128
|
+
* reliability: 0.7
|
|
129
|
+
* })
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export declare function selectBalancedBid(bids: EnhancedBid[], weights?: {
|
|
134
|
+
price: number;
|
|
135
|
+
reliability: number;
|
|
136
|
+
}): EnhancedBid | null;
|
|
137
|
+
/**
|
|
138
|
+
* Filter bids by multiple criteria (price, reliability, audit, location, online status).
|
|
139
|
+
* All criteria are optional. Multiple criteria use AND logic.
|
|
140
|
+
*
|
|
141
|
+
* Use this to establish minimum quality standards, then apply a selection strategy.
|
|
142
|
+
*
|
|
143
|
+
* @param bids - Bids to filter
|
|
144
|
+
* @param criteria - Filter criteria (all optional)
|
|
145
|
+
*
|
|
146
|
+
* @example Filter by price and uptime
|
|
147
|
+
* ```typescript
|
|
148
|
+
* const result = await deployToAkash({
|
|
149
|
+
* bidSelector: (bids) => {
|
|
150
|
+
* const filtered = filterBids(bids, {
|
|
151
|
+
* maxPricePerMonth: { usd: 50, aktPrice: 0.45 },
|
|
152
|
+
* minUptime: { value: 0.95, period: '7d' }
|
|
153
|
+
* });
|
|
154
|
+
* return selectCheapestBid(filtered);
|
|
155
|
+
* }
|
|
156
|
+
* });
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @example Filter by audit and location
|
|
160
|
+
* ```typescript
|
|
161
|
+
* const filtered = filterBids(bids, {
|
|
162
|
+
* requireAudited: true,
|
|
163
|
+
* preferredRegions: ['US', 'EU'],
|
|
164
|
+
* requireOnline: true
|
|
165
|
+
* });
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
export declare function filterBids(bids: EnhancedBid[], criteria: {
|
|
169
|
+
readonly maxPricePerMonth?: {
|
|
170
|
+
uakt: number;
|
|
171
|
+
} | {
|
|
172
|
+
usd: number;
|
|
173
|
+
aktPrice: number;
|
|
174
|
+
};
|
|
175
|
+
readonly minUptime?: {
|
|
176
|
+
value: number;
|
|
177
|
+
period: '1d' | '7d' | '30d';
|
|
178
|
+
};
|
|
179
|
+
readonly requireAudited?: boolean;
|
|
180
|
+
readonly preferredRegions?: string[];
|
|
181
|
+
readonly requireOnline?: boolean;
|
|
182
|
+
}): EnhancedBid[];
|
|
183
|
+
//# sourceMappingURL=bids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bids.d.ts","sourceRoot":"","sources":["../../../src/targets/akash/bids.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Bid Management
|
|
3
|
+
*
|
|
4
|
+
* Types, pricing calculations, and selection strategies for choosing providers
|
|
5
|
+
* based on cost, reliability, and other criteria.
|
|
6
|
+
*
|
|
7
|
+
* Key responsibilities:
|
|
8
|
+
* - Calculate bid pricing across multiple time periods (hour, day, week, month)
|
|
9
|
+
* - Convert prices between currencies (uAKT, AKT, USD)
|
|
10
|
+
* - Provide selection strategies (cheapest, most reliable, balanced)
|
|
11
|
+
* - Filter bids by criteria (price, uptime, audit status, location)
|
|
12
|
+
*
|
|
13
|
+
* @module targets/akash/bids
|
|
14
|
+
*/
|
|
15
|
+
// ========================================
|
|
16
|
+
// Constants
|
|
17
|
+
// ========================================
|
|
18
|
+
/** Average block time on Akash Network (empirically determined, matches Akash Console) */
|
|
19
|
+
const AVERAGE_BLOCK_TIME_SECONDS = 6.098;
|
|
20
|
+
/** Average days in a month (365.25 / 12) for accurate monthly cost estimates */
|
|
21
|
+
const AVERAGE_DAYS_IN_MONTH = 30.437;
|
|
22
|
+
/** Conversion factor: 1 AKT = 1,000,000 uAKT */
|
|
23
|
+
const UAKT_PER_AKT = 1_000_000;
|
|
24
|
+
// ========================================
|
|
25
|
+
// Pricing Functions
|
|
26
|
+
// ========================================
|
|
27
|
+
/**
|
|
28
|
+
* Create BidPricing from blockchain price data.
|
|
29
|
+
* Calculates all time-period prices from the raw per-block price.
|
|
30
|
+
*/
|
|
31
|
+
export function createBidPricing(price) {
|
|
32
|
+
// Parse raw price per block
|
|
33
|
+
const pricePerBlock = parseFloat(price.amount);
|
|
34
|
+
// Calculate number of blocks for each time period
|
|
35
|
+
const blocksPerHour = (60 * 60) / AVERAGE_BLOCK_TIME_SECONDS;
|
|
36
|
+
const blocksPerDay = (24 * 60 * 60) / AVERAGE_BLOCK_TIME_SECONDS;
|
|
37
|
+
const blocksPerWeek = (7 * 24 * 60 * 60) / AVERAGE_BLOCK_TIME_SECONDS;
|
|
38
|
+
const blocksPerMonth = (AVERAGE_DAYS_IN_MONTH * 24 * 60 * 60) / AVERAGE_BLOCK_TIME_SECONDS;
|
|
39
|
+
// Calculate prices in uAKT for all time periods
|
|
40
|
+
const uaktPricing = {
|
|
41
|
+
perBlock: pricePerBlock,
|
|
42
|
+
perHour: pricePerBlock * blocksPerHour,
|
|
43
|
+
perDay: pricePerBlock * blocksPerDay,
|
|
44
|
+
perWeek: pricePerBlock * blocksPerWeek,
|
|
45
|
+
perMonth: pricePerBlock * blocksPerMonth,
|
|
46
|
+
};
|
|
47
|
+
// Calculate prices in AKT (divide uAKT by 1,000,000)
|
|
48
|
+
const aktPricing = {
|
|
49
|
+
perBlock: uaktPricing.perBlock / UAKT_PER_AKT,
|
|
50
|
+
perHour: uaktPricing.perHour / UAKT_PER_AKT,
|
|
51
|
+
perDay: uaktPricing.perDay / UAKT_PER_AKT,
|
|
52
|
+
perWeek: uaktPricing.perWeek / UAKT_PER_AKT,
|
|
53
|
+
perMonth: uaktPricing.perMonth / UAKT_PER_AKT,
|
|
54
|
+
};
|
|
55
|
+
// Return pricing object with USD conversion method
|
|
56
|
+
return {
|
|
57
|
+
raw: {
|
|
58
|
+
denom: price.denom,
|
|
59
|
+
amount: price.amount,
|
|
60
|
+
},
|
|
61
|
+
uakt: uaktPricing,
|
|
62
|
+
akt: aktPricing,
|
|
63
|
+
toUSD: (aktPriceUSD) => ({
|
|
64
|
+
perHour: aktPricing.perHour * aktPriceUSD,
|
|
65
|
+
perDay: aktPricing.perDay * aktPriceUSD,
|
|
66
|
+
perWeek: aktPricing.perWeek * aktPriceUSD,
|
|
67
|
+
perMonth: aktPricing.perMonth * aktPriceUSD,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// ========================================
|
|
72
|
+
// Selection Strategies
|
|
73
|
+
// ========================================
|
|
74
|
+
/**
|
|
75
|
+
* Select the cheapest bid by monthly price.
|
|
76
|
+
* For production, consider filtering for quality first (see filterBids).
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await deployToAkash({
|
|
81
|
+
* bidSelector: selectCheapestBid
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export function selectCheapestBid(bids) {
|
|
86
|
+
if (bids.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
return bids.reduce((cheapest, current) => current.pricing.uakt.perMonth < cheapest.pricing.uakt.perMonth
|
|
89
|
+
? current
|
|
90
|
+
: cheapest);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Select the most reliable provider by uptime percentage.
|
|
94
|
+
* Providers without reliability data are excluded.
|
|
95
|
+
*
|
|
96
|
+
* @param bids - Available bids
|
|
97
|
+
* @param period - Uptime period to evaluate (default: 7d)
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const result = await deployToAkash({
|
|
102
|
+
* bidSelector: (bids) => selectMostReliableBid(bids, '30d')
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function selectMostReliableBid(bids, period = '7d') {
|
|
107
|
+
if (bids.length === 0)
|
|
108
|
+
return null;
|
|
109
|
+
// Filter bids that have reliability data
|
|
110
|
+
const withReliability = bids.filter((bid) => bid.provider.reliability !== undefined);
|
|
111
|
+
// If no providers have reliability data, return first bid
|
|
112
|
+
if (withReliability.length === 0) {
|
|
113
|
+
return bids[0] ?? null;
|
|
114
|
+
}
|
|
115
|
+
// Determine uptime key based on period
|
|
116
|
+
const uptimeKey = `uptime${period}`;
|
|
117
|
+
// Find provider with highest uptime
|
|
118
|
+
return withReliability.reduce((best, current) => {
|
|
119
|
+
const bestUptime = best.provider.reliability[uptimeKey];
|
|
120
|
+
const currentUptime = current.provider.reliability[uptimeKey];
|
|
121
|
+
return currentUptime > bestUptime ? current : best;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Select bid using balanced scoring (price + reliability weighted).
|
|
126
|
+
* Default: 50/50 balance. Customize weights for your priorities.
|
|
127
|
+
*
|
|
128
|
+
* @param bids - Available bids
|
|
129
|
+
* @param weights - Scoring weights (default: 0.5 price, 0.5 reliability)
|
|
130
|
+
*
|
|
131
|
+
* @example Equal balance
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const result = await deployToAkash({
|
|
134
|
+
* bidSelector: selectBalancedBid // 50/50
|
|
135
|
+
* });
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @example Prioritize reliability
|
|
139
|
+
* ```typescript
|
|
140
|
+
* const result = await deployToAkash({
|
|
141
|
+
* bidSelector: (bids) => selectBalancedBid(bids, {
|
|
142
|
+
* price: 0.3,
|
|
143
|
+
* reliability: 0.7
|
|
144
|
+
* })
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export function selectBalancedBid(bids, weights = { price: 0.5, reliability: 0.5 }) {
|
|
149
|
+
if (bids.length === 0)
|
|
150
|
+
return null;
|
|
151
|
+
// Calculate price range for normalization
|
|
152
|
+
const prices = bids.map((bid) => bid.pricing.uakt.perMonth);
|
|
153
|
+
const minPrice = Math.min(...prices);
|
|
154
|
+
const maxPrice = Math.max(...prices);
|
|
155
|
+
const priceRange = maxPrice - minPrice;
|
|
156
|
+
// Calculate scores for each bid
|
|
157
|
+
const scored = bids.map((bid) => {
|
|
158
|
+
// Price score: 1.0 for cheapest, 0.0 for most expensive
|
|
159
|
+
// Handle case where all bids have same price
|
|
160
|
+
const priceScore = priceRange === 0
|
|
161
|
+
? 1.0
|
|
162
|
+
: 1.0 - (bid.pricing.uakt.perMonth - minPrice) / priceRange;
|
|
163
|
+
// Reliability score: uptime7d (0.0 to 1.0)
|
|
164
|
+
// Default to 0.5 if no reliability data available
|
|
165
|
+
const reliabilityScore = bid.provider.reliability?.uptime7d ?? 0.5;
|
|
166
|
+
// Weighted total score
|
|
167
|
+
const totalScore = priceScore * weights.price + reliabilityScore * weights.reliability;
|
|
168
|
+
return { bid, score: totalScore };
|
|
169
|
+
});
|
|
170
|
+
// Return bid with highest score
|
|
171
|
+
return scored.reduce((best, current) => current.score > best.score ? current : best).bid;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Filter bids by multiple criteria (price, reliability, audit, location, online status).
|
|
175
|
+
* All criteria are optional. Multiple criteria use AND logic.
|
|
176
|
+
*
|
|
177
|
+
* Use this to establish minimum quality standards, then apply a selection strategy.
|
|
178
|
+
*
|
|
179
|
+
* @param bids - Bids to filter
|
|
180
|
+
* @param criteria - Filter criteria (all optional)
|
|
181
|
+
*
|
|
182
|
+
* @example Filter by price and uptime
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const result = await deployToAkash({
|
|
185
|
+
* bidSelector: (bids) => {
|
|
186
|
+
* const filtered = filterBids(bids, {
|
|
187
|
+
* maxPricePerMonth: { usd: 50, aktPrice: 0.45 },
|
|
188
|
+
* minUptime: { value: 0.95, period: '7d' }
|
|
189
|
+
* });
|
|
190
|
+
* return selectCheapestBid(filtered);
|
|
191
|
+
* }
|
|
192
|
+
* });
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @example Filter by audit and location
|
|
196
|
+
* ```typescript
|
|
197
|
+
* const filtered = filterBids(bids, {
|
|
198
|
+
* requireAudited: true,
|
|
199
|
+
* preferredRegions: ['US', 'EU'],
|
|
200
|
+
* requireOnline: true
|
|
201
|
+
* });
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
export function filterBids(bids, criteria) {
|
|
205
|
+
return bids.filter((bid) => {
|
|
206
|
+
// Price filter
|
|
207
|
+
if (criteria.maxPricePerMonth) {
|
|
208
|
+
const maxPrice = 'uakt' in criteria.maxPricePerMonth
|
|
209
|
+
? criteria.maxPricePerMonth.uakt
|
|
210
|
+
: bid.pricing.toUSD(criteria.maxPricePerMonth.aktPrice).perMonth;
|
|
211
|
+
const bidPrice = 'uakt' in criteria.maxPricePerMonth
|
|
212
|
+
? bid.pricing.uakt.perMonth
|
|
213
|
+
: bid.pricing.toUSD(criteria.maxPricePerMonth.aktPrice).perMonth;
|
|
214
|
+
if (bidPrice > maxPrice)
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
// Uptime filter
|
|
218
|
+
if (criteria.minUptime) {
|
|
219
|
+
const { value, period } = criteria.minUptime;
|
|
220
|
+
const uptimeKey = `uptime${period}`;
|
|
221
|
+
const uptime = bid.provider.reliability?.[uptimeKey];
|
|
222
|
+
// If no reliability data, exclude this bid
|
|
223
|
+
if (uptime === undefined || uptime < value)
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
// Audit status filter
|
|
227
|
+
if (criteria.requireAudited && !bid.provider.isAudited) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
// Region filter
|
|
231
|
+
if (criteria.preferredRegions && criteria.preferredRegions.length > 0) {
|
|
232
|
+
const countryCode = bid.provider.location?.countryCode;
|
|
233
|
+
if (!countryCode || !criteria.preferredRegions.includes(countryCode)) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Online status filter
|
|
238
|
+
if (criteria.requireOnline) {
|
|
239
|
+
const isOnline = bid.provider.reliability?.isOnline;
|
|
240
|
+
if (isOnline !== true)
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
// All filters passed
|
|
244
|
+
return true;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=bids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bids.js","sourceRoot":"","sources":["../../../src/targets/akash/bids.ts"],"names":[],"mappings":"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"}
|