@antseed/node 0.2.152 → 0.2.154
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/buyer-identity-context.d.ts +2 -0
- package/dist/buyer-identity-context.d.ts.map +1 -1
- package/dist/buyer-identity-context.js +1 -0
- package/dist/buyer-identity-context.js.map +1 -1
- package/dist/discovery/announcer.d.ts +2 -0
- package/dist/discovery/announcer.d.ts.map +1 -1
- package/dist/discovery/announcer.js +11 -9
- package/dist/discovery/announcer.js.map +1 -1
- package/dist/health/gas-health-monitor.d.ts +19 -0
- package/dist/health/gas-health-monitor.d.ts.map +1 -1
- package/dist/health/gas-health-monitor.js +21 -0
- package/dist/health/gas-health-monitor.js.map +1 -1
- package/dist/health/model-health-checker.d.ts +52 -0
- package/dist/health/model-health-checker.d.ts.map +1 -1
- package/dist/health/model-health-checker.js +139 -7
- package/dist/health/model-health-checker.js.map +1 -1
- package/dist/health/seller-events.d.ts +24 -0
- package/dist/health/seller-events.d.ts.map +1 -0
- package/dist/health/seller-events.js +71 -0
- package/dist/health/seller-events.js.map +1 -0
- package/dist/health/upstream-credit.d.ts +8 -0
- package/dist/health/upstream-credit.d.ts.map +1 -0
- package/dist/health/upstream-credit.js +22 -0
- package/dist/health/upstream-credit.js.map +1 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/seller-provider.d.ts +4 -1
- package/dist/interfaces/seller-provider.d.ts.map +1 -1
- package/dist/metering/index.d.ts +1 -1
- package/dist/metering/index.d.ts.map +1 -1
- package/dist/metering/index.js.map +1 -1
- package/dist/metering/seller-session-tracker.d.ts +7 -0
- package/dist/metering/seller-session-tracker.d.ts.map +1 -1
- package/dist/metering/seller-session-tracker.js +29 -0
- package/dist/metering/seller-session-tracker.js.map +1 -1
- package/dist/metering/storage.d.ts +146 -6
- package/dist/metering/storage.d.ts.map +1 -1
- package/dist/metering/storage.js +209 -14
- package/dist/metering/storage.js.map +1 -1
- package/dist/node.d.ts +44 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +122 -11
- package/dist/node.js.map +1 -1
- package/dist/payments/channel-store.d.ts +10 -0
- package/dist/payments/channel-store.d.ts.map +1 -1
- package/dist/payments/channel-store.js +17 -0
- package/dist/payments/channel-store.js.map +1 -1
- package/dist/payments/evm/seller-pools-client.d.ts +9 -0
- package/dist/payments/evm/seller-pools-client.d.ts.map +1 -1
- package/dist/payments/evm/seller-pools-client.js +23 -0
- package/dist/payments/evm/seller-pools-client.js.map +1 -1
- package/dist/payments/free-tier-delegation.d.ts +65 -0
- package/dist/payments/free-tier-delegation.d.ts.map +1 -0
- package/dist/payments/free-tier-delegation.js +145 -0
- package/dist/payments/free-tier-delegation.js.map +1 -0
- package/dist/payments/free-tier-program.d.ts +97 -0
- package/dist/payments/free-tier-program.d.ts.map +1 -0
- package/dist/payments/free-tier-program.js +267 -0
- package/dist/payments/free-tier-program.js.map +1 -0
- package/dist/payments/free-tier-stake-resolver.d.ts +79 -0
- package/dist/payments/free-tier-stake-resolver.d.ts.map +1 -0
- package/dist/payments/free-tier-stake-resolver.js +152 -0
- package/dist/payments/free-tier-stake-resolver.js.map +1 -0
- package/dist/payments/free-tier-stake.d.ts +101 -0
- package/dist/payments/free-tier-stake.d.ts.map +1 -0
- package/dist/payments/free-tier-stake.js +116 -0
- package/dist/payments/free-tier-stake.js.map +1 -0
- package/dist/payments/index.d.ts +7 -1
- package/dist/payments/index.d.ts.map +1 -1
- package/dist/payments/index.js +3 -0
- package/dist/payments/index.js.map +1 -1
- package/dist/payments/seller-free-tier-limiter.d.ts +124 -6
- package/dist/payments/seller-free-tier-limiter.d.ts.map +1 -1
- package/dist/payments/seller-free-tier-limiter.js +342 -32
- package/dist/payments/seller-free-tier-limiter.js.map +1 -1
- package/dist/payments/seller-free-usage-manager.d.ts.map +1 -1
- package/dist/payments/seller-free-usage-manager.js +5 -1
- package/dist/payments/seller-free-usage-manager.js.map +1 -1
- package/dist/seller-request-handler.d.ts.map +1 -1
- package/dist/seller-request-handler.js +113 -19
- package/dist/seller-request-handler.js.map +1 -1
- package/dist/storage/migrate.d.ts +6 -0
- package/dist/storage/migrate.d.ts.map +1 -1
- package/dist/storage/migrate.js +11 -0
- package/dist/storage/migrate.js.map +1 -1
- package/dist/storage/migrations/metering/004_add_free_tier_staked_usage.d.ts +3 -0
- package/dist/storage/migrations/metering/004_add_free_tier_staked_usage.d.ts.map +1 -0
- package/dist/storage/migrations/metering/004_add_free_tier_staked_usage.js +21 -0
- package/dist/storage/migrations/metering/004_add_free_tier_staked_usage.js.map +1 -0
- package/dist/storage/migrations/metering/005_add_free_tier_scope.d.ts +8 -0
- package/dist/storage/migrations/metering/005_add_free_tier_scope.d.ts.map +1 -0
- package/dist/storage/migrations/metering/005_add_free_tier_scope.js +23 -0
- package/dist/storage/migrations/metering/005_add_free_tier_scope.js.map +1 -0
- package/dist/storage/migrations/metering/006_add_event_service.d.ts +4 -0
- package/dist/storage/migrations/metering/006_add_event_service.d.ts.map +1 -0
- package/dist/storage/migrations/metering/006_add_event_service.js +11 -0
- package/dist/storage/migrations/metering/006_add_event_service.js.map +1 -0
- package/dist/storage/migrations/metering/007_add_event_detail.d.ts +4 -0
- package/dist/storage/migrations/metering/007_add_event_detail.d.ts.map +1 -0
- package/dist/storage/migrations/metering/007_add_event_detail.js +12 -0
- package/dist/storage/migrations/metering/007_add_event_detail.js.map +1 -0
- package/dist/storage/migrations/metering/008_add_event_request_id.d.ts +4 -0
- package/dist/storage/migrations/metering/008_add_event_request_id.d.ts.map +1 -0
- package/dist/storage/migrations/metering/008_add_event_request_id.js +10 -0
- package/dist/storage/migrations/metering/008_add_event_request_id.js.map +1 -0
- package/dist/storage/migrations/metering/009_index_receipts_by_event.d.ts +4 -0
- package/dist/storage/migrations/metering/009_index_receipts_by_event.d.ts.map +1 -0
- package/dist/storage/migrations/metering/009_index_receipts_by_event.js +9 -0
- package/dist/storage/migrations/metering/009_index_receipts_by_event.js.map +1 -0
- package/dist/storage/migrations/metering/010_repair_free_tier_usage.d.ts +8 -0
- package/dist/storage/migrations/metering/010_repair_free_tier_usage.d.ts.map +1 -0
- package/dist/storage/migrations/metering/010_repair_free_tier_usage.js +35 -0
- package/dist/storage/migrations/metering/010_repair_free_tier_usage.js.map +1 -0
- package/dist/storage/migrations/metering/index.d.ts.map +1 -1
- package/dist/storage/migrations/metering/index.js +8 -1
- package/dist/storage/migrations/metering/index.js.map +1 -1
- package/dist/types/metering.d.ts +8 -0
- package/dist/types/metering.d.ts.map +1 -1
- package/dist/utils/file-lock.d.ts +12 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +58 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/package.json +11 -3
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staked free-tier program: how much more free usage a seller grants buyers
|
|
3
|
+
* who lock ANTS in that seller's pool.
|
|
4
|
+
*
|
|
5
|
+
* Tiers are measured in staking power, the same quantity the seller pool uses
|
|
6
|
+
* for rewards: ANTS amount × epochs of lock remaining (one epoch is a week).
|
|
7
|
+
* Power is zero until a position activates and shrinks as the lock runs down,
|
|
8
|
+
* so a tier rewards long commitments over short-lived stake.
|
|
9
|
+
*
|
|
10
|
+
* Sellers advertise the program in their signed peer metadata as capability
|
|
11
|
+
* strings, so buyers and indexers can read it without a metadata version bump:
|
|
12
|
+
*
|
|
13
|
+
* free-tier.v1.base[.a<perAddress>][.i<perIp>].w<windowMs>[.s1][.t1]
|
|
14
|
+
* free-tier.v1.tier.p<minPower>.x<multiplier> (x0 = unlimited)
|
|
15
|
+
*
|
|
16
|
+
* A service with its own program advertises the same strings scoped by
|
|
17
|
+
* `m<first 8 hex of keccak256(serviceId)>` after the version, e.g.
|
|
18
|
+
* `free-tier.v1.m1a2b3c4d.base.a10.w86400000.s1`. Services without one fall
|
|
19
|
+
* back to the unscoped, seller-wide program.
|
|
20
|
+
*
|
|
21
|
+
* `s1` marks a stakers-only program. `t1` on a scoped base means the program
|
|
22
|
+
* uses the seller-wide tiers, so it costs one capability string, not five.
|
|
23
|
+
*
|
|
24
|
+
* On a priced service, its own program is a free allowance: requests it covers
|
|
25
|
+
* are free, the rest are paid. The seller-wide program covers free services only.
|
|
26
|
+
*/
|
|
27
|
+
import { id } from 'ethers';
|
|
28
|
+
/** Epochs in one year of lock; tiers are documented as "ANTS locked for a year". */
|
|
29
|
+
export const FREE_TIER_EPOCHS_PER_YEAR = 52;
|
|
30
|
+
/**
|
|
31
|
+
* Network default: 10k / 50k / 200k ANTS locked for a year earn 5×, 20× and
|
|
32
|
+
* unlimited free usage on the seller they are staked on.
|
|
33
|
+
*/
|
|
34
|
+
export const DEFAULT_FREE_TIER_STAKE_TIERS = Object.freeze([
|
|
35
|
+
{ minPower: 10_000 * FREE_TIER_EPOCHS_PER_YEAR, multiplier: 5 },
|
|
36
|
+
{ minPower: 50_000 * FREE_TIER_EPOCHS_PER_YEAR, multiplier: 20 },
|
|
37
|
+
{ minPower: 200_000 * FREE_TIER_EPOCHS_PER_YEAR, multiplier: 'unlimited' },
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* Response header a seller sets, to `FREE_TIER_SERVED_COVERED`, on a request
|
|
41
|
+
* to a priced service that the service's free allowance covered: the buyer
|
|
42
|
+
* owes nothing for it. A buyer that ignores it pays the listed price.
|
|
43
|
+
*/
|
|
44
|
+
export const FREE_TIER_SERVED_HEADER = 'x-antseed-free-tier';
|
|
45
|
+
export const FREE_TIER_SERVED_COVERED = 'covered';
|
|
46
|
+
export const MAX_FREE_TIER_STAKE_TIERS = 4;
|
|
47
|
+
export const MAX_FREE_TIER_MULTIPLIER = 10_000;
|
|
48
|
+
const CAPABILITY_PREFIX = 'free-tier.v1.';
|
|
49
|
+
const ANTS_WEI = 10n ** 18n;
|
|
50
|
+
const SCOPE_PATTERN = /^m[0-9a-f]{8}$/;
|
|
51
|
+
/** Capability scope of a service's own program: `m` + the first 8 hex of keccak256(serviceId). */
|
|
52
|
+
export function freeTierServiceScope(serviceId) {
|
|
53
|
+
return `m${id(serviceId).slice(2, 10)}`;
|
|
54
|
+
}
|
|
55
|
+
/** Throws when `tiers` is not a valid program: increasing power, increasing multipliers, unlimited last. */
|
|
56
|
+
export function validateFreeTierStakeTiers(tiers, label = 'freeTier.stakeTiers') {
|
|
57
|
+
if (tiers.length > MAX_FREE_TIER_STAKE_TIERS) {
|
|
58
|
+
throw new Error(`${label} accepts at most ${MAX_FREE_TIER_STAKE_TIERS} tiers`);
|
|
59
|
+
}
|
|
60
|
+
let previousPower = 0;
|
|
61
|
+
// A first tier may be 1x: on a stakers-only program it grants the base limits.
|
|
62
|
+
let previousMultiplier = 0;
|
|
63
|
+
let sawUnlimited = false;
|
|
64
|
+
tiers.forEach((tier, index) => {
|
|
65
|
+
const at = `${label}[${index}]`;
|
|
66
|
+
if (!Number.isSafeInteger(tier.minPower) || tier.minPower < 1) {
|
|
67
|
+
throw new Error(`${at}.minPower must be a positive safe integer`);
|
|
68
|
+
}
|
|
69
|
+
if (tier.minPower <= previousPower) {
|
|
70
|
+
throw new Error(`${at}.minPower must be greater than the previous tier`);
|
|
71
|
+
}
|
|
72
|
+
if (sawUnlimited) {
|
|
73
|
+
throw new Error(`${at} follows an unlimited tier`);
|
|
74
|
+
}
|
|
75
|
+
if (tier.multiplier === 'unlimited') {
|
|
76
|
+
sawUnlimited = true;
|
|
77
|
+
}
|
|
78
|
+
else if (!Number.isSafeInteger(tier.multiplier)
|
|
79
|
+
|| tier.multiplier <= previousMultiplier
|
|
80
|
+
|| tier.multiplier > MAX_FREE_TIER_MULTIPLIER) {
|
|
81
|
+
throw new Error(`${at}.multiplier must be an integer above the previous tier (minimum 1, maximum ${MAX_FREE_TIER_MULTIPLIER}) or "unlimited"`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
previousMultiplier = tier.multiplier;
|
|
85
|
+
}
|
|
86
|
+
previousPower = tier.minPower;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Highest tier `power` (raw on-chain power: ANTS wei × epochs) qualifies for, or null. */
|
|
90
|
+
export function freeTierStakeTierForPower(tiers, power) {
|
|
91
|
+
let match = null;
|
|
92
|
+
for (const tier of tiers) {
|
|
93
|
+
if (power >= BigInt(tier.minPower) * ANTS_WEI)
|
|
94
|
+
match = tier;
|
|
95
|
+
}
|
|
96
|
+
return match;
|
|
97
|
+
}
|
|
98
|
+
/** Raw on-chain power (ANTS wei × epochs) as whole ANTS-epochs. */
|
|
99
|
+
export function powerToAntsEpochs(power) {
|
|
100
|
+
const whole = power / ANTS_WEI;
|
|
101
|
+
return whole > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(whole);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Capability strings advertising `program` in peer metadata: the seller-wide
|
|
105
|
+
* program, or `serviceId`'s own program when given.
|
|
106
|
+
*/
|
|
107
|
+
export function encodeFreeTierCapabilities(program, serviceId, options = {}) {
|
|
108
|
+
const { base } = program;
|
|
109
|
+
const inheritTiers = serviceId !== undefined
|
|
110
|
+
&& options.sellerWideTiers !== undefined
|
|
111
|
+
&& program.stakeTiers.length > 0
|
|
112
|
+
&& sameStakeTiers(program.stakeTiers, options.sellerWideTiers);
|
|
113
|
+
const prefix = serviceId === undefined ? CAPABILITY_PREFIX : `${CAPABILITY_PREFIX}${freeTierServiceScope(serviceId)}.`;
|
|
114
|
+
const baseParts = [
|
|
115
|
+
`${prefix}base`,
|
|
116
|
+
...(base.maxRequestsPerAddress !== null ? [`a${base.maxRequestsPerAddress}`] : []),
|
|
117
|
+
...(base.maxRequestsPerIp !== null ? [`i${base.maxRequestsPerIp}`] : []),
|
|
118
|
+
`w${base.windowMs}`,
|
|
119
|
+
...(base.stakersOnly ? ['s1'] : []),
|
|
120
|
+
...(inheritTiers ? ['t1'] : []),
|
|
121
|
+
];
|
|
122
|
+
return [
|
|
123
|
+
baseParts.join('.'),
|
|
124
|
+
...(inheritTiers ? [] : program.stakeTiers).map((tier) => `${prefix}tier.p${tier.minPower}.x${tier.multiplier === 'unlimited' ? 0 : tier.multiplier}`),
|
|
125
|
+
];
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Read a seller's free-tier program from its advertised capabilities: the
|
|
129
|
+
* program `serviceId` is served under when given (its own, else the
|
|
130
|
+
* seller-wide one), otherwise the seller-wide program. Returns null when there
|
|
131
|
+
* is none or its strings are malformed.
|
|
132
|
+
*/
|
|
133
|
+
export function parseFreeTierProgram(capabilities, serviceId) {
|
|
134
|
+
if (!capabilities)
|
|
135
|
+
return null;
|
|
136
|
+
if (serviceId !== undefined) {
|
|
137
|
+
const scope = freeTierServiceScope(serviceId);
|
|
138
|
+
if (capabilities.some((capability) => capability.startsWith(`${CAPABILITY_PREFIX}${scope}.`))) {
|
|
139
|
+
return parseScopedFreeTierProgram(capabilities, scope);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return parseScopedFreeTierProgram(capabilities, null);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Whether a service charges anything, the way the seller decides it: any
|
|
146
|
+
* token price, image price or priced unit-billing component makes it paid.
|
|
147
|
+
*/
|
|
148
|
+
export function isPricedService(prices) {
|
|
149
|
+
const positive = (value) => typeof value === 'number' && value > 0;
|
|
150
|
+
if (positive(prices.inputUsdPerMillion) || positive(prices.outputUsdPerMillion)
|
|
151
|
+
|| positive(prices.cachedInputUsdPerMillion) || positive(prices.maxImageUsdPerImage))
|
|
152
|
+
return true;
|
|
153
|
+
return Object.values(prices.unitBillingModels ?? {}).some((model) => (model?.components ?? []).some((component) => !(component.priceUsd <= 0)));
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The program a buyer of `serviceId` is served under: on a free service its
|
|
157
|
+
* own or the seller-wide one, on a priced service only its own free allowance.
|
|
158
|
+
* Paid video is never covered (it is paid through one-off channels), so it has none.
|
|
159
|
+
*/
|
|
160
|
+
export function freeTierProgramForService(capabilities, serviceId, priced, options = {}) {
|
|
161
|
+
if (!priced)
|
|
162
|
+
return parseFreeTierProgram(capabilities, serviceId);
|
|
163
|
+
return options.video ? null : parseServiceFreeTierProgram(capabilities, serviceId);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Only `serviceId`'s own program, never the seller-wide fallback. A priced
|
|
167
|
+
* service's free allowance is always its own program, so this is the one to
|
|
168
|
+
* read for a paid service.
|
|
169
|
+
*/
|
|
170
|
+
export function parseServiceFreeTierProgram(capabilities, serviceId) {
|
|
171
|
+
if (!capabilities)
|
|
172
|
+
return null;
|
|
173
|
+
const scope = freeTierServiceScope(serviceId);
|
|
174
|
+
if (!capabilities.some((capability) => capability.startsWith(`${CAPABILITY_PREFIX}${scope}.`)))
|
|
175
|
+
return null;
|
|
176
|
+
return parseScopedFreeTierProgram(capabilities, scope);
|
|
177
|
+
}
|
|
178
|
+
function sameStakeTiers(a, b) {
|
|
179
|
+
return a.length === b.length && a.every((tier, index) => tier.minPower === b[index].minPower && tier.multiplier === b[index].multiplier);
|
|
180
|
+
}
|
|
181
|
+
function parseScopedFreeTierProgram(capabilities, scope) {
|
|
182
|
+
let base = null;
|
|
183
|
+
let inheritTiers = false;
|
|
184
|
+
const stakeTiers = [];
|
|
185
|
+
for (const capability of capabilities) {
|
|
186
|
+
if (!capability.startsWith(CAPABILITY_PREFIX))
|
|
187
|
+
continue;
|
|
188
|
+
const parts = capability.split('.');
|
|
189
|
+
const capabilityScope = SCOPE_PATTERN.test(parts[2] ?? '') ? parts[2] : null;
|
|
190
|
+
if (capabilityScope !== scope)
|
|
191
|
+
continue;
|
|
192
|
+
const [kind, ...fields] = parts.slice(capabilityScope === null ? 2 : 3);
|
|
193
|
+
const values = new Map();
|
|
194
|
+
for (const field of fields) {
|
|
195
|
+
const match = /^([a-z])(\d{1,16})$/.exec(field);
|
|
196
|
+
if (!match)
|
|
197
|
+
return null;
|
|
198
|
+
const value = Number(match[2]);
|
|
199
|
+
if (!Number.isSafeInteger(value))
|
|
200
|
+
return null;
|
|
201
|
+
values.set(match[1], value);
|
|
202
|
+
}
|
|
203
|
+
if (kind === 'base') {
|
|
204
|
+
const windowMs = values.get('w');
|
|
205
|
+
if (windowMs === undefined || windowMs < 1_000)
|
|
206
|
+
return null;
|
|
207
|
+
base = {
|
|
208
|
+
maxRequestsPerAddress: values.get('a') ?? null,
|
|
209
|
+
maxRequestsPerIp: values.get('i') ?? null,
|
|
210
|
+
windowMs,
|
|
211
|
+
...(values.get('s') === 1 ? { stakersOnly: true } : {}),
|
|
212
|
+
};
|
|
213
|
+
inheritTiers = scope !== null && values.get('t') === 1;
|
|
214
|
+
}
|
|
215
|
+
else if (kind === 'tier') {
|
|
216
|
+
const minPower = values.get('p');
|
|
217
|
+
const multiplier = values.get('x');
|
|
218
|
+
if (minPower === undefined || multiplier === undefined)
|
|
219
|
+
return null;
|
|
220
|
+
stakeTiers.push({ minPower, multiplier: multiplier === 0 ? 'unlimited' : multiplier });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (!base)
|
|
224
|
+
return null;
|
|
225
|
+
if (inheritTiers) {
|
|
226
|
+
const sellerWide = parseScopedFreeTierProgram(capabilities, null);
|
|
227
|
+
if (!sellerWide)
|
|
228
|
+
return null;
|
|
229
|
+
stakeTiers.push(...sellerWide.stakeTiers);
|
|
230
|
+
}
|
|
231
|
+
stakeTiers.sort((a, b) => a.minPower - b.minPower);
|
|
232
|
+
try {
|
|
233
|
+
validateFreeTierStakeTiers(stakeTiers);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
return { base, stakeTiers };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* A free-tier program passed on as JSON (by a buyer's catalog), validated the
|
|
242
|
+
* same way as advertised capabilities. Returns null when it is not one.
|
|
243
|
+
*/
|
|
244
|
+
export function normalizeFreeTierProgram(value) {
|
|
245
|
+
if (!value || typeof value !== 'object')
|
|
246
|
+
return null;
|
|
247
|
+
const { base, stakeTiers } = value;
|
|
248
|
+
if (!base || typeof base !== 'object' || !Array.isArray(stakeTiers))
|
|
249
|
+
return null;
|
|
250
|
+
const limits = base;
|
|
251
|
+
const count = (field) => field === null || field === undefined ? null : Number.isSafeInteger(field) && field >= 0 ? field : undefined;
|
|
252
|
+
const maxRequestsPerAddress = count(limits.maxRequestsPerAddress);
|
|
253
|
+
const maxRequestsPerIp = count(limits.maxRequestsPerIp);
|
|
254
|
+
const windowMs = count(limits.windowMs);
|
|
255
|
+
if (maxRequestsPerAddress === undefined || maxRequestsPerIp === undefined || !windowMs)
|
|
256
|
+
return null;
|
|
257
|
+
const tiers = stakeTiers.map((tier) => tier);
|
|
258
|
+
if (tiers.some((tier) => !tier || typeof tier.minPower !== 'number' || (tier.multiplier !== 'unlimited' && typeof tier.multiplier !== 'number')))
|
|
259
|
+
return null;
|
|
260
|
+
return parseFreeTierProgram(encodeFreeTierCapabilities({
|
|
261
|
+
base: { maxRequestsPerAddress, maxRequestsPerIp, windowMs, ...(limits.stakersOnly === true ? { stakersOnly: true } : {}) },
|
|
262
|
+
stakeTiers: tiers,
|
|
263
|
+
}));
|
|
264
|
+
}
|
|
265
|
+
// Stake projections (browser-safe, no ethers): also at `@antseed/node/free-tier-stake`.
|
|
266
|
+
export * from './free-tier-stake.js';
|
|
267
|
+
//# sourceMappingURL=free-tier-program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-program.js","sourceRoot":"","sources":["../../src/payments/free-tier-program.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { MAX_FREE_TIER_COUNTED_POSITIONS } from './free-tier-stake.js';
|
|
2
|
+
/** A seller-pool position and its staking power at the current epoch. */
|
|
3
|
+
export interface FreeTierStakePosition {
|
|
4
|
+
id: number;
|
|
5
|
+
/** ANTS wei × epochs of lock remaining. */
|
|
6
|
+
power: bigint;
|
|
7
|
+
}
|
|
8
|
+
/** On-chain reads the staked free tier needs. */
|
|
9
|
+
export interface FreeTierStakeReader {
|
|
10
|
+
/** The seller's agent id in the seller pools, or 0 when it has none. */
|
|
11
|
+
sellerAgentId(): Promise<number>;
|
|
12
|
+
currentEpoch(): Promise<number>;
|
|
13
|
+
/** `staker`'s positions with power in `agentId`'s pool at `epoch`. */
|
|
14
|
+
stakerPositions(staker: string, agentId: number, epoch: number): Promise<FreeTierStakePosition[]>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A buyer whose own stake plus its delegated stake has power in this seller's
|
|
18
|
+
* pool. Which tier that power earns depends on the program a request is under.
|
|
19
|
+
*/
|
|
20
|
+
export interface FreeTierStakeStanding {
|
|
21
|
+
/** Addresses whose stake counts: the buyer and every staker that delegated to it. */
|
|
22
|
+
stakers: string[];
|
|
23
|
+
/** Combined power of every counted position. */
|
|
24
|
+
power: bigint;
|
|
25
|
+
/**
|
|
26
|
+
* Positions the allowance is counted on. Usage follows the positions, not
|
|
27
|
+
* the staker, so transferring a position carries its used allowance along.
|
|
28
|
+
*/
|
|
29
|
+
positionIds: number[];
|
|
30
|
+
}
|
|
31
|
+
export interface FreeTierStakeResolverOptions {
|
|
32
|
+
/** How long a standing and a staker's positions are reused. Default: 10 minutes. */
|
|
33
|
+
cacheTtlMs?: number;
|
|
34
|
+
/** How long a failed lookup is remembered before retrying. Default: 30 seconds. */
|
|
35
|
+
failureTtlMs?: number;
|
|
36
|
+
/** Lookups slower than this fall back to base limits for this request. Default: 3 seconds. */
|
|
37
|
+
lookupTimeoutMs?: number;
|
|
38
|
+
maxEntries?: number;
|
|
39
|
+
now?: () => number;
|
|
40
|
+
}
|
|
41
|
+
/** Most positions one request is counted on; the strongest positions come first. */
|
|
42
|
+
export { MAX_FREE_TIER_COUNTED_POSITIONS };
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a buyer's staked standing on this seller.
|
|
45
|
+
*
|
|
46
|
+
* The buyer's own stake counts, plus the stake of every staker that signed a
|
|
47
|
+
* delegation to it (verified by the caller). Their positions in this seller's
|
|
48
|
+
* pool are pooled: power is summed and usage is counted on every position.
|
|
49
|
+
* Any read failure resolves to no standing, so the buyer keeps the base limits:
|
|
50
|
+
* an RPC outage can only make the free tier stricter, never looser.
|
|
51
|
+
*/
|
|
52
|
+
export declare class FreeTierStakeResolver {
|
|
53
|
+
private readonly _reader;
|
|
54
|
+
private readonly _cacheTtlMs;
|
|
55
|
+
private readonly _failureTtlMs;
|
|
56
|
+
private readonly _lookupTimeoutMs;
|
|
57
|
+
private readonly _maxEntries;
|
|
58
|
+
private readonly _now;
|
|
59
|
+
private readonly _standings;
|
|
60
|
+
private readonly _positions;
|
|
61
|
+
private readonly _inFlight;
|
|
62
|
+
private _agentId;
|
|
63
|
+
private _epoch;
|
|
64
|
+
private _seq;
|
|
65
|
+
constructor(_reader: FreeTierStakeReader, options?: FreeTierStakeResolverOptions);
|
|
66
|
+
/**
|
|
67
|
+
* The staked standing of `buyerAddress` together with `delegatedStakers`
|
|
68
|
+
* (already verified), or null when none of them has power in the pool.
|
|
69
|
+
*/
|
|
70
|
+
resolve(buyerAddress: string, delegatedStakers?: readonly string[]): Promise<FreeTierStakeStanding | null>;
|
|
71
|
+
/** The standing of `stakers`, and when the earliest snapshot it was built from expires. */
|
|
72
|
+
private _lookup;
|
|
73
|
+
private _stakerPositions;
|
|
74
|
+
private _sellerAgentId;
|
|
75
|
+
private _currentEpoch;
|
|
76
|
+
/** Stores `value` unless a read that started later already stored a result, which is kept and returned instead. */
|
|
77
|
+
private _remember;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=free-tier-stake-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-stake-resolver.d.ts","sourceRoot":"","sources":["../../src/payments/free-tier-stake-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,sEAAsE;IACtE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;CACnG;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,4BAA4B;IAC3C,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AASD,oFAAoF;AACpF,OAAO,EAAE,+BAA+B,EAAE,CAAC;AAE3C;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;IAc9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAb1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+D;IAC1F,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0D;IACrF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IACtF,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,IAAI,CAAK;gBAGE,OAAO,EAAE,mBAAmB,EAC7C,OAAO,GAAE,4BAAiC;IAS5C;;;OAGG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,gBAAgB,GAAE,SAAS,MAAM,EAAO,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IA2CpH,2FAA2F;YAC7E,OAAO;YAmBP,gBAAgB;YAOhB,cAAc;YAOd,aAAa;IAO3B,mHAAmH;IACnH,OAAO,CAAC,SAAS;CAmBlB"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { debugWarn } from '../utils/debug.js';
|
|
2
|
+
import { MAX_FREE_TIER_COUNTED_POSITIONS } from './free-tier-stake.js';
|
|
3
|
+
/** Most positions one request is counted on; the strongest positions come first. */
|
|
4
|
+
export { MAX_FREE_TIER_COUNTED_POSITIONS };
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a buyer's staked standing on this seller.
|
|
7
|
+
*
|
|
8
|
+
* The buyer's own stake counts, plus the stake of every staker that signed a
|
|
9
|
+
* delegation to it (verified by the caller). Their positions in this seller's
|
|
10
|
+
* pool are pooled: power is summed and usage is counted on every position.
|
|
11
|
+
* Any read failure resolves to no standing, so the buyer keeps the base limits:
|
|
12
|
+
* an RPC outage can only make the free tier stricter, never looser.
|
|
13
|
+
*/
|
|
14
|
+
export class FreeTierStakeResolver {
|
|
15
|
+
_reader;
|
|
16
|
+
_cacheTtlMs;
|
|
17
|
+
_failureTtlMs;
|
|
18
|
+
_lookupTimeoutMs;
|
|
19
|
+
_maxEntries;
|
|
20
|
+
_now;
|
|
21
|
+
_standings = new Map();
|
|
22
|
+
_positions = new Map();
|
|
23
|
+
_inFlight = new Map();
|
|
24
|
+
_agentId = null;
|
|
25
|
+
_epoch = null;
|
|
26
|
+
_seq = 0;
|
|
27
|
+
constructor(_reader, options = {}) {
|
|
28
|
+
this._reader = _reader;
|
|
29
|
+
this._cacheTtlMs = options.cacheTtlMs ?? 10 * 60_000;
|
|
30
|
+
this._failureTtlMs = options.failureTtlMs ?? 30_000;
|
|
31
|
+
this._lookupTimeoutMs = options.lookupTimeoutMs ?? 3_000;
|
|
32
|
+
this._maxEntries = options.maxEntries ?? 20_000;
|
|
33
|
+
this._now = options.now ?? Date.now;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The staked standing of `buyerAddress` together with `delegatedStakers`
|
|
37
|
+
* (already verified), or null when none of them has power in the pool.
|
|
38
|
+
*/
|
|
39
|
+
async resolve(buyerAddress, delegatedStakers = []) {
|
|
40
|
+
const stakers = [...new Set([buyerAddress, ...delegatedStakers].map((address) => address.toLowerCase()))];
|
|
41
|
+
const key = stakers.join(',');
|
|
42
|
+
const cached = this._standings.get(key);
|
|
43
|
+
if (cached && cached.expiresAt > this._now())
|
|
44
|
+
return cached.value;
|
|
45
|
+
let pending = this._inFlight.get(key);
|
|
46
|
+
if (!pending) {
|
|
47
|
+
const seq = ++this._seq;
|
|
48
|
+
const lookup = this._lookup(stakers, seq)
|
|
49
|
+
.then(({ value: standing, expiresAt }) => {
|
|
50
|
+
// A standing never outlives the stake snapshots it was derived from.
|
|
51
|
+
return this._remember(this._standings, key, standing, expiresAt, seq).value;
|
|
52
|
+
})
|
|
53
|
+
.catch((err) => {
|
|
54
|
+
debugWarn(`[FreeTierStake] Stake lookup failed for ${stakers[0]}: ${err instanceof Error ? err.message : err}`);
|
|
55
|
+
// A lookup that timed out and was replaced must not overwrite its replacement's result.
|
|
56
|
+
this._remember(this._standings, key, null, this._now() + this._failureTtlMs, seq);
|
|
57
|
+
return null;
|
|
58
|
+
})
|
|
59
|
+
.finally(() => {
|
|
60
|
+
if (this._inFlight.get(key) === lookup)
|
|
61
|
+
this._inFlight.delete(key);
|
|
62
|
+
});
|
|
63
|
+
pending = lookup;
|
|
64
|
+
this._inFlight.set(key, pending);
|
|
65
|
+
}
|
|
66
|
+
const current = pending;
|
|
67
|
+
let timer;
|
|
68
|
+
const timeout = new Promise((resolve) => {
|
|
69
|
+
timer = setTimeout(() => {
|
|
70
|
+
// A stalled lookup must not block the next request from trying again.
|
|
71
|
+
if (this._inFlight.get(key) === current)
|
|
72
|
+
this._inFlight.delete(key);
|
|
73
|
+
resolve(null);
|
|
74
|
+
}, this._lookupTimeoutMs);
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
return await Promise.race([pending, timeout]);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
clearTimeout(timer);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** The standing of `stakers`, and when the earliest snapshot it was built from expires. */
|
|
84
|
+
async _lookup(stakers, seq) {
|
|
85
|
+
const agentId = await this._sellerAgentId(seq);
|
|
86
|
+
if (agentId.value <= 0)
|
|
87
|
+
return { value: null, expiresAt: agentId.expiresAt };
|
|
88
|
+
const epoch = await this._currentEpoch(seq);
|
|
89
|
+
const holdings = await Promise.all(stakers.map((staker) => this._stakerPositions(staker, agentId.value, epoch.value, seq)));
|
|
90
|
+
const expiresAt = Math.min(agentId.expiresAt, epoch.expiresAt, ...holdings.map((entry) => entry.expiresAt));
|
|
91
|
+
const unique = new Map();
|
|
92
|
+
for (const position of holdings.flatMap((entry) => entry.value))
|
|
93
|
+
unique.set(position.id, position);
|
|
94
|
+
// Only the positions that are charged for usage may count toward a tier,
|
|
95
|
+
// so stake left out by the cap cannot back a second, untouched allowance.
|
|
96
|
+
const counted = [...unique.values()]
|
|
97
|
+
.sort((a, b) => (a.power === b.power ? a.id - b.id : a.power > b.power ? -1 : 1))
|
|
98
|
+
.slice(0, MAX_FREE_TIER_COUNTED_POSITIONS);
|
|
99
|
+
const power = counted.reduce((sum, position) => sum + position.power, 0n);
|
|
100
|
+
if (power <= 0n)
|
|
101
|
+
return { value: null, expiresAt };
|
|
102
|
+
return { value: { stakers, power, positionIds: counted.map((position) => position.id) }, expiresAt };
|
|
103
|
+
}
|
|
104
|
+
async _stakerPositions(staker, agentId, epoch, seq) {
|
|
105
|
+
const cached = this._positions.get(staker);
|
|
106
|
+
if (cached && cached.expiresAt > this._now())
|
|
107
|
+
return cached;
|
|
108
|
+
const positions = await this._reader.stakerPositions(staker, agentId, epoch);
|
|
109
|
+
return this._remember(this._positions, staker, positions, this._now() + this._cacheTtlMs, seq);
|
|
110
|
+
}
|
|
111
|
+
async _sellerAgentId(seq) {
|
|
112
|
+
if (this._agentId && this._agentId.expiresAt > this._now())
|
|
113
|
+
return this._agentId;
|
|
114
|
+
const agentId = await this._reader.sellerAgentId();
|
|
115
|
+
this._agentId = newer(this._agentId, { value: agentId, expiresAt: this._now() + this._cacheTtlMs, seq });
|
|
116
|
+
return this._agentId;
|
|
117
|
+
}
|
|
118
|
+
async _currentEpoch(seq) {
|
|
119
|
+
if (this._epoch && this._epoch.expiresAt > this._now())
|
|
120
|
+
return this._epoch;
|
|
121
|
+
const epoch = await this._reader.currentEpoch();
|
|
122
|
+
this._epoch = newer(this._epoch, { value: epoch, expiresAt: this._now() + this._cacheTtlMs, seq });
|
|
123
|
+
return this._epoch;
|
|
124
|
+
}
|
|
125
|
+
/** Stores `value` unless a read that started later already stored a result, which is kept and returned instead. */
|
|
126
|
+
_remember(cache, key, value, expiresAt, seq) {
|
|
127
|
+
const existing = cache.get(key);
|
|
128
|
+
if (existing && existing.seq > seq)
|
|
129
|
+
return existing;
|
|
130
|
+
cache.delete(key);
|
|
131
|
+
if (cache.size >= this._maxEntries) {
|
|
132
|
+
const now = this._now();
|
|
133
|
+
for (const [entryKey, entry] of cache) {
|
|
134
|
+
if (entry.expiresAt <= now)
|
|
135
|
+
cache.delete(entryKey);
|
|
136
|
+
}
|
|
137
|
+
while (cache.size >= this._maxEntries) {
|
|
138
|
+
const oldest = cache.keys().next().value;
|
|
139
|
+
if (oldest === undefined)
|
|
140
|
+
break;
|
|
141
|
+
cache.delete(oldest);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const entry = { value, expiresAt, seq };
|
|
145
|
+
cache.set(key, entry);
|
|
146
|
+
return entry;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function newer(existing, candidate) {
|
|
150
|
+
return existing && existing.seq > candidate.seq ? existing : candidate;
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=free-tier-stake-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-stake-resolver.js","sourceRoot":"","sources":["../../src/payments/free-tier-stake-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staked free-tier projections: the power a buyer's counted seller-pool stake
|
|
3
|
+
* has at a given time, the tier it earns under a program, and when that
|
|
4
|
+
* drops. Pure and browser-safe (no ethers), so desktop, the gateway console
|
|
5
|
+
* and the CLI share one implementation; re-exported from
|
|
6
|
+
* `@antseed/node/free-tier-program`.
|
|
7
|
+
*/
|
|
8
|
+
import type { FreeTierStakeTier } from './free-tier-program.js';
|
|
9
|
+
/** Most positions a seller counts toward one buyer's tier; the strongest are counted first. */
|
|
10
|
+
export declare const MAX_FREE_TIER_COUNTED_POSITIONS = 64;
|
|
11
|
+
/** Epochs of power a max-locked position keeps (the seller pool's `MAX_STAKE_EPOCHS`). */
|
|
12
|
+
export declare const FREE_TIER_MAX_LOCK_EPOCHS = 104;
|
|
13
|
+
/**
|
|
14
|
+
* One seller-pool position whose stake counts toward a buyer's free tier: the
|
|
15
|
+
* buyer's own, or a staker's that shared it with a code.
|
|
16
|
+
*/
|
|
17
|
+
export interface FreeTierStakePositionView {
|
|
18
|
+
id: number;
|
|
19
|
+
staker: string;
|
|
20
|
+
/** Weighted ANTS (whole ANTS, may be fractional); power is this × epochs of lock remaining. */
|
|
21
|
+
ants: number;
|
|
22
|
+
/** First epoch the position has power (it activates a week or more after staking). */
|
|
23
|
+
startEpoch: number;
|
|
24
|
+
/** Epoch the lock ends; power reaches zero then (not while max-locked). */
|
|
25
|
+
endEpoch: number;
|
|
26
|
+
/** Epoch a moved, split or merged position stops counting (its replacements take over), or null. */
|
|
27
|
+
closedAtEpoch: number | null;
|
|
28
|
+
/** Max lock is on this epoch: power is `ants × FREE_TIER_MAX_LOCK_EPOCHS`. */
|
|
29
|
+
maxLocked: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Max lock is on from the next epoch. Turning it on or off takes effect at
|
|
32
|
+
* the next epoch, so this can differ from `maxLocked` until then.
|
|
33
|
+
*/
|
|
34
|
+
maxLockedNext: boolean;
|
|
35
|
+
/** Unix seconds the staker's code expires, or null for the buyer's own stake. */
|
|
36
|
+
expiresAt: number | null;
|
|
37
|
+
}
|
|
38
|
+
/** A buyer's stake in one seller's pool, as that seller's staked free tier counts it. */
|
|
39
|
+
export interface FreeTierPoolStakeView {
|
|
40
|
+
agentId: number;
|
|
41
|
+
positions: FreeTierStakePositionView[];
|
|
42
|
+
}
|
|
43
|
+
/** Every pool a buyer has counted stake in, and the epoch clock to date its changes. */
|
|
44
|
+
export interface FreeTierStakeView {
|
|
45
|
+
currentEpoch: number;
|
|
46
|
+
/** Unix seconds epoch 0 starts. */
|
|
47
|
+
genesis: number;
|
|
48
|
+
/** Seconds per epoch. */
|
|
49
|
+
epochDuration: number;
|
|
50
|
+
pools: FreeTierPoolStakeView[];
|
|
51
|
+
}
|
|
52
|
+
/** Unix seconds `epoch` starts. */
|
|
53
|
+
export declare function freeTierEpochStart(view: Pick<FreeTierStakeView, 'genesis' | 'epochDuration'>, epoch: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* Power of `positions` at unix second `at`, in ANTS-epochs, as sellers count
|
|
56
|
+
* it: each position from activation, `ants × epochs left` (max lock:
|
|
57
|
+
* `ants × FREE_TIER_MAX_LOCK_EPOCHS`), until it closes or its code expires,
|
|
58
|
+
* summed over the strongest `MAX_FREE_TIER_COUNTED_POSITIONS`.
|
|
59
|
+
* Locks change at epoch boundaries; a code stops counting the second it expires.
|
|
60
|
+
*/
|
|
61
|
+
export declare function freeTierPowerAt(view: Pick<FreeTierStakeView, 'currentEpoch' | 'genesis' | 'epochDuration'>, positions: readonly FreeTierStakePositionView[], at: number): number;
|
|
62
|
+
/** The tier `power` (ANTS-epochs) reaches, or null below the first. */
|
|
63
|
+
export declare function freeTierTierAt(tiers: readonly FreeTierStakeTier[], power: number): FreeTierStakeTier | null;
|
|
64
|
+
/** Where a buyer's stake in one pool stands against a program's tiers, and when that changes. */
|
|
65
|
+
export interface FreeTierOutlook {
|
|
66
|
+
/** Power now, in ANTS-epochs. */
|
|
67
|
+
power: number;
|
|
68
|
+
tier: FreeTierStakeTier | null;
|
|
69
|
+
/** Unix seconds the stake first earns a lower tier, or null when it holds (max lock) or is below every tier. */
|
|
70
|
+
dropsAt: number | null;
|
|
71
|
+
/** The tier from `dropsAt` on; null means below every tier. */
|
|
72
|
+
tierAfterDrop: FreeTierStakeTier | null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The tier `pool`'s stake earns at `now` (unix seconds) under `tiers`, and
|
|
76
|
+
* when it first earns less: power shrinks every epoch as locks run down, and
|
|
77
|
+
* a staker's code stops counting when it expires.
|
|
78
|
+
*/
|
|
79
|
+
export declare function freeTierOutlook(view: Pick<FreeTierStakeView, 'currentEpoch' | 'genesis' | 'epochDuration'>, pool: {
|
|
80
|
+
readonly positions: readonly FreeTierStakePositionView[];
|
|
81
|
+
} | null | undefined, tiers: readonly FreeTierStakeTier[], now?: number): FreeTierOutlook;
|
|
82
|
+
/** How a pool's counted stake changes from now: steady, or shrinking weekly until a date. */
|
|
83
|
+
export interface FreeTierStakeTrend {
|
|
84
|
+
/** Power now, in ANTS-epochs. */
|
|
85
|
+
power: number;
|
|
86
|
+
/** Counted power never drops from here (max lock, no code expiring): it holds. */
|
|
87
|
+
steady: boolean;
|
|
88
|
+
/** Counted power drops at some epoch boundary as a lock runs down (not only when a code expires). */
|
|
89
|
+
shrinking: boolean;
|
|
90
|
+
/** Unix seconds counted power reaches zero, or null when it never does. */
|
|
91
|
+
endsAt: number | null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* How `pool`'s counted power changes from `now`, following the same rules as
|
|
95
|
+
* `freeTierPowerAt` (only the strongest positions count), so positions that
|
|
96
|
+
* are never counted do not make a steady stake look like it shrinks.
|
|
97
|
+
*/
|
|
98
|
+
export declare function freeTierStakeTrend(view: Pick<FreeTierStakeView, 'currentEpoch' | 'genesis' | 'epochDuration'>, pool: {
|
|
99
|
+
readonly positions: readonly FreeTierStakePositionView[];
|
|
100
|
+
}, now?: number): FreeTierStakeTrend;
|
|
101
|
+
//# sourceMappingURL=free-tier-stake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-stake.d.ts","sourceRoot":"","sources":["../../src/payments/free-tier-stake.ts"],"names":[],"mappings":"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"}
|