@antseed/node 0.2.152 → 0.2.153
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/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.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/storage.d.ts +66 -6
- package/dist/metering/storage.d.ts.map +1 -1
- package/dist/metering/storage.js +112 -12
- package/dist/metering/storage.js.map +1 -1
- package/dist/node.d.ts +30 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +93 -2
- package/dist/node.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 +105 -19
- package/dist/seller-request-handler.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/index.d.ts.map +1 -1
- package/dist/storage/migrations/metering/index.js +3 -1
- package/dist/storage/migrations/metering/index.js.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,65 @@
|
|
|
1
|
+
import { type TypedDataDomain, type TypedDataField } from 'ethers';
|
|
2
|
+
/**
|
|
3
|
+
* A staker's consent to let one buyer use its seller-pool stake for staked
|
|
4
|
+
* free-tier allowances. Signed with EIP-712 by the staker; the buyer sends it
|
|
5
|
+
* to sellers in the `x-antseed-free-tier-delegations` request header.
|
|
6
|
+
*
|
|
7
|
+
* The signature names the buyer, so a seller only honours it on that buyer's
|
|
8
|
+
* own authenticated connection: anyone who sees it cannot reuse it.
|
|
9
|
+
*/
|
|
10
|
+
export interface FreeTierDelegation {
|
|
11
|
+
staker: string;
|
|
12
|
+
buyer: string;
|
|
13
|
+
/** Unix seconds after which the delegation no longer counts. */
|
|
14
|
+
expiresAt: number;
|
|
15
|
+
signature: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const FREE_TIER_DELEGATIONS_HEADER = "x-antseed-free-tier-delegations";
|
|
18
|
+
/** Most delegations a buyer sends and a seller honours per request. */
|
|
19
|
+
export declare const MAX_FREE_TIER_DELEGATIONS = 8;
|
|
20
|
+
/** Default lifetime offered when signing a delegation. */
|
|
21
|
+
export declare const DEFAULT_FREE_TIER_DELEGATION_DAYS = 90;
|
|
22
|
+
export declare const FREE_TIER_DELEGATION_TYPES: Record<string, TypedDataField[]>;
|
|
23
|
+
export declare function makeFreeTierDelegationDomain(chainId: number): TypedDataDomain;
|
|
24
|
+
/** The typed-data payload a staker's wallet signs. */
|
|
25
|
+
export declare function freeTierDelegationMessage(delegation: Omit<FreeTierDelegation, 'signature'>): Record<string, unknown>;
|
|
26
|
+
/** Whether `delegation` is signed by its staker on `chainId`. Does not check expiry or the buyer. */
|
|
27
|
+
export declare function isFreeTierDelegationSigned(delegation: FreeTierDelegation, chainId: number): boolean;
|
|
28
|
+
/** A delegation that passed signature checks: who staked, and until when it counts. */
|
|
29
|
+
export interface VerifiedFreeTierDelegation {
|
|
30
|
+
staker: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Delegations to `buyer` that are signed and unexpired, with lower-case
|
|
35
|
+
* stakers, one per staker (latest expiry), at most `MAX_FREE_TIER_DELEGATIONS`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function verifyFreeTierDelegations(delegations: readonly FreeTierDelegation[], buyer: string, chainId: number, nowMs?: number): VerifiedFreeTierDelegation[];
|
|
38
|
+
/**
|
|
39
|
+
* Header value for `delegations`: comma-separated `staker:expiresAt:signature`.
|
|
40
|
+
* The buyer is implied by the connection, so it is not sent.
|
|
41
|
+
*/
|
|
42
|
+
export declare function encodeFreeTierDelegationsHeader(delegations: readonly FreeTierDelegation[]): string;
|
|
43
|
+
/** Parse a header from `buyer`'s connection. Malformed entries are skipped. */
|
|
44
|
+
export declare function decodeFreeTierDelegationsHeader(value: string | undefined, buyer: string): FreeTierDelegation[];
|
|
45
|
+
/** Prefix of a shareable delegation code, so a pasted code is recognisable. */
|
|
46
|
+
export declare const FREE_TIER_DELEGATION_CODE_PREFIX = "antseed-free-tier-";
|
|
47
|
+
/**
|
|
48
|
+
* A copy-pasteable code for `delegation`, for a staker to hand to a buyer:
|
|
49
|
+
* the prefix plus base64url of staker (20 bytes), buyer (20), expiresAt (u64)
|
|
50
|
+
* and signature (65).
|
|
51
|
+
*/
|
|
52
|
+
export declare function encodeFreeTierDelegationCode(delegation: FreeTierDelegation): string;
|
|
53
|
+
/** Parse a code from `encodeFreeTierDelegationCode`. Throws on anything malformed; does not check the signature. */
|
|
54
|
+
export declare function decodeFreeTierDelegationCode(code: string): FreeTierDelegation;
|
|
55
|
+
/**
|
|
56
|
+
* Decode a pasted code and check it is a usable delegation to `buyer` on
|
|
57
|
+
* `chainId`. Throws an error a buyer can act on otherwise.
|
|
58
|
+
*/
|
|
59
|
+
export declare function acceptFreeTierDelegationCode(code: string, buyer: string, chainId: number, nowMs?: number): FreeTierDelegation;
|
|
60
|
+
/**
|
|
61
|
+
* `delegations` with `delegation` added, replacing the same staker's earlier
|
|
62
|
+
* delegation to the same buyer. Throws when that buyer already has the most.
|
|
63
|
+
*/
|
|
64
|
+
export declare function withFreeTierDelegation(delegations: readonly FreeTierDelegation[], delegation: FreeTierDelegation): FreeTierDelegation[];
|
|
65
|
+
//# sourceMappingURL=free-tier-delegation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-delegation.d.ts","sourceRoot":"","sources":["../../src/payments/free-tier-delegation.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,QAAQ,CAAC;AAEhB;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,4BAA4B,oCAAoC,CAAC;AAC9E,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,0DAA0D;AAC1D,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAEpD,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAMvE,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAE7E;AAED,sDAAsD;AACtD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMpH;AAED,qGAAqG;AACrG,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAYnG;AAED,uFAAuF;AACvF,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,SAAS,kBAAkB,EAAE,EAC1C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,SAAa,GACjB,0BAA0B,EAAE,CAU9B;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAKlG;AAED,+EAA+E;AAC/E,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAU9G;AAED,+EAA+E;AAC/E,eAAO,MAAM,gCAAgC,uBAAuB,CAAC;AAErE;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAQnF;AAED,oHAAoH;AACpH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAkB7E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,kBAAkB,CAQjI;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,EAAE,UAAU,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,CAOvI"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { concat, decodeBase64, encodeBase64, getAddress, hexlify, isAddress, toBeHex, verifyTypedData, } from 'ethers';
|
|
2
|
+
export const FREE_TIER_DELEGATIONS_HEADER = 'x-antseed-free-tier-delegations';
|
|
3
|
+
/** Most delegations a buyer sends and a seller honours per request. */
|
|
4
|
+
export const MAX_FREE_TIER_DELEGATIONS = 8;
|
|
5
|
+
/** Default lifetime offered when signing a delegation. */
|
|
6
|
+
export const DEFAULT_FREE_TIER_DELEGATION_DAYS = 90;
|
|
7
|
+
export const FREE_TIER_DELEGATION_TYPES = {
|
|
8
|
+
FreeTierDelegation: [
|
|
9
|
+
{ name: 'staker', type: 'address' },
|
|
10
|
+
{ name: 'buyer', type: 'address' },
|
|
11
|
+
{ name: 'expiresAt', type: 'uint64' },
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
export function makeFreeTierDelegationDomain(chainId) {
|
|
15
|
+
return { name: 'AntseedFreeTier', version: '1', chainId };
|
|
16
|
+
}
|
|
17
|
+
/** The typed-data payload a staker's wallet signs. */
|
|
18
|
+
export function freeTierDelegationMessage(delegation) {
|
|
19
|
+
return {
|
|
20
|
+
staker: getAddress(delegation.staker),
|
|
21
|
+
buyer: getAddress(delegation.buyer),
|
|
22
|
+
expiresAt: delegation.expiresAt,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Whether `delegation` is signed by its staker on `chainId`. Does not check expiry or the buyer. */
|
|
26
|
+
export function isFreeTierDelegationSigned(delegation, chainId) {
|
|
27
|
+
try {
|
|
28
|
+
const recovered = verifyTypedData(makeFreeTierDelegationDomain(chainId), FREE_TIER_DELEGATION_TYPES, freeTierDelegationMessage(delegation), delegation.signature);
|
|
29
|
+
return recovered.toLowerCase() === delegation.staker.toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Delegations to `buyer` that are signed and unexpired, with lower-case
|
|
37
|
+
* stakers, one per staker (latest expiry), at most `MAX_FREE_TIER_DELEGATIONS`.
|
|
38
|
+
*/
|
|
39
|
+
export function verifyFreeTierDelegations(delegations, buyer, chainId, nowMs = Date.now()) {
|
|
40
|
+
const verified = new Map();
|
|
41
|
+
for (const delegation of delegations.slice(0, MAX_FREE_TIER_DELEGATIONS)) {
|
|
42
|
+
if (delegation.buyer.toLowerCase() !== buyer.toLowerCase())
|
|
43
|
+
continue;
|
|
44
|
+
if (delegation.expiresAt * 1000 <= nowMs)
|
|
45
|
+
continue;
|
|
46
|
+
if (!isFreeTierDelegationSigned(delegation, chainId))
|
|
47
|
+
continue;
|
|
48
|
+
const staker = delegation.staker.toLowerCase();
|
|
49
|
+
verified.set(staker, Math.max(verified.get(staker) ?? 0, delegation.expiresAt));
|
|
50
|
+
}
|
|
51
|
+
return [...verified].map(([staker, expiresAt]) => ({ staker, expiresAt }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Header value for `delegations`: comma-separated `staker:expiresAt:signature`.
|
|
55
|
+
* The buyer is implied by the connection, so it is not sent.
|
|
56
|
+
*/
|
|
57
|
+
export function encodeFreeTierDelegationsHeader(delegations) {
|
|
58
|
+
return delegations
|
|
59
|
+
.slice(0, MAX_FREE_TIER_DELEGATIONS)
|
|
60
|
+
.map((delegation) => `${delegation.staker.toLowerCase()}:${delegation.expiresAt}:${delegation.signature.toLowerCase()}`)
|
|
61
|
+
.join(',');
|
|
62
|
+
}
|
|
63
|
+
/** Parse a header from `buyer`'s connection. Malformed entries are skipped. */
|
|
64
|
+
export function decodeFreeTierDelegationsHeader(value, buyer) {
|
|
65
|
+
if (!value)
|
|
66
|
+
return [];
|
|
67
|
+
const delegations = [];
|
|
68
|
+
for (const entry of value.split(',').slice(0, MAX_FREE_TIER_DELEGATIONS)) {
|
|
69
|
+
const [staker, expiresAt, signature] = entry.trim().split(':');
|
|
70
|
+
if (!staker || !isAddress(staker) || !expiresAt || !/^\d{1,12}$/.test(expiresAt))
|
|
71
|
+
continue;
|
|
72
|
+
if (!signature || !/^0x[0-9a-fA-F]{130}$/.test(signature))
|
|
73
|
+
continue;
|
|
74
|
+
delegations.push({ staker, buyer, expiresAt: Number(expiresAt), signature });
|
|
75
|
+
}
|
|
76
|
+
return delegations;
|
|
77
|
+
}
|
|
78
|
+
/** Prefix of a shareable delegation code, so a pasted code is recognisable. */
|
|
79
|
+
export const FREE_TIER_DELEGATION_CODE_PREFIX = 'antseed-free-tier-';
|
|
80
|
+
/**
|
|
81
|
+
* A copy-pasteable code for `delegation`, for a staker to hand to a buyer:
|
|
82
|
+
* the prefix plus base64url of staker (20 bytes), buyer (20), expiresAt (u64)
|
|
83
|
+
* and signature (65).
|
|
84
|
+
*/
|
|
85
|
+
export function encodeFreeTierDelegationCode(delegation) {
|
|
86
|
+
const bytes = concat([
|
|
87
|
+
getAddress(delegation.staker),
|
|
88
|
+
getAddress(delegation.buyer),
|
|
89
|
+
toBeHex(delegation.expiresAt, 8),
|
|
90
|
+
delegation.signature,
|
|
91
|
+
]);
|
|
92
|
+
return FREE_TIER_DELEGATION_CODE_PREFIX + encodeBase64(bytes).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
93
|
+
}
|
|
94
|
+
/** Parse a code from `encodeFreeTierDelegationCode`. Throws on anything malformed; does not check the signature. */
|
|
95
|
+
export function decodeFreeTierDelegationCode(code) {
|
|
96
|
+
const trimmed = code.trim();
|
|
97
|
+
if (!trimmed.startsWith(FREE_TIER_DELEGATION_CODE_PREFIX))
|
|
98
|
+
throw new Error('Not a free-tier code: it should start with ' + FREE_TIER_DELEGATION_CODE_PREFIX);
|
|
99
|
+
const body = trimmed.slice(FREE_TIER_DELEGATION_CODE_PREFIX.length);
|
|
100
|
+
if (!/^[A-Za-z0-9_-]+$/.test(body))
|
|
101
|
+
throw new Error('Free-tier code is malformed');
|
|
102
|
+
let bytes;
|
|
103
|
+
try {
|
|
104
|
+
bytes = decodeBase64(body.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat((4 - (body.length % 4)) % 4));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new Error('Free-tier code is malformed');
|
|
108
|
+
}
|
|
109
|
+
if (bytes.length !== 113)
|
|
110
|
+
throw new Error('Free-tier code is incomplete');
|
|
111
|
+
return {
|
|
112
|
+
staker: getAddress(hexlify(bytes.slice(0, 20))),
|
|
113
|
+
buyer: getAddress(hexlify(bytes.slice(20, 40))),
|
|
114
|
+
expiresAt: Number(BigInt(hexlify(bytes.slice(40, 48)))),
|
|
115
|
+
signature: hexlify(bytes.slice(48)),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Decode a pasted code and check it is a usable delegation to `buyer` on
|
|
120
|
+
* `chainId`. Throws an error a buyer can act on otherwise.
|
|
121
|
+
*/
|
|
122
|
+
export function acceptFreeTierDelegationCode(code, buyer, chainId, nowMs = Date.now()) {
|
|
123
|
+
const delegation = decodeFreeTierDelegationCode(code);
|
|
124
|
+
if (delegation.buyer.toLowerCase() !== buyer.toLowerCase()) {
|
|
125
|
+
throw new Error(`This code is for buyer ${delegation.buyer}, not ${getAddress(buyer)}. Ask the staker for a code for your buyer address.`);
|
|
126
|
+
}
|
|
127
|
+
if (delegation.expiresAt * 1000 <= nowMs)
|
|
128
|
+
throw new Error('This code has expired. Ask the staker for a new one.');
|
|
129
|
+
if (!isFreeTierDelegationSigned(delegation, chainId))
|
|
130
|
+
throw new Error('This code is not signed by its staker on this network.');
|
|
131
|
+
return delegation;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* `delegations` with `delegation` added, replacing the same staker's earlier
|
|
135
|
+
* delegation to the same buyer. Throws when that buyer already has the most.
|
|
136
|
+
*/
|
|
137
|
+
export function withFreeTierDelegation(delegations, delegation) {
|
|
138
|
+
const sameBuyer = (entry) => entry.buyer.toLowerCase() === delegation.buyer.toLowerCase();
|
|
139
|
+
const kept = delegations.filter((entry) => !(sameBuyer(entry) && entry.staker.toLowerCase() === delegation.staker.toLowerCase()));
|
|
140
|
+
if (kept.filter(sameBuyer).length >= MAX_FREE_TIER_DELEGATIONS) {
|
|
141
|
+
throw new Error(`This buyer already has ${MAX_FREE_TIER_DELEGATIONS} stakers; remove one first.`);
|
|
142
|
+
}
|
|
143
|
+
return [...kept, delegation];
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=free-tier-delegation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-delegation.js","sourceRoot":"","sources":["../../src/payments/free-tier-delegation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,OAAO,EACP,SAAS,EACT,OAAO,EACP,eAAe,GAGhB,MAAM,QAAQ,CAAC;AAkBhB,MAAM,CAAC,MAAM,4BAA4B,GAAG,iCAAiC,CAAC;AAC9E,uEAAuE;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAC3C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,MAAM,CAAC,MAAM,0BAA0B,GAAqC;IAC1E,kBAAkB,EAAE;QAClB,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;QACnC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE;QAClC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE;KACtC;CACF,CAAC;AAEF,MAAM,UAAU,4BAA4B,CAAC,OAAe;IAC1D,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AAC5D,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,yBAAyB,CAAC,UAAiD;IACzF,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;QACrC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QACnC,SAAS,EAAE,UAAU,CAAC,SAAS;KAChC,CAAC;AACJ,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,0BAA0B,CAAC,UAA8B,EAAE,OAAe;IACxF,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,eAAe,CAC/B,4BAA4B,CAAC,OAAO,CAAC,EACrC,0BAA0B,EAC1B,yBAAyB,CAAC,UAAU,CAAC,EACrC,UAAU,CAAC,SAAS,CACrB,CAAC;QACF,OAAO,SAAS,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAQD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CACvC,WAA0C,EAC1C,KAAa,EACb,OAAe,EACf,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;IAElB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,UAAU,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC,EAAE,CAAC;QACzE,IAAI,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE;YAAE,SAAS;QACrE,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,KAAK;YAAE,SAAS;QACnD,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,OAAO,CAAC;YAAE,SAAS;QAC/D,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC/C,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAAC,WAA0C;IACxF,OAAO,WAAW;SACf,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC;SACnC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,SAAS,IAAI,UAAU,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;SACvH,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,+BAA+B,CAAC,KAAyB,EAAE,KAAa;IACtF,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,WAAW,GAAyB,EAAE,CAAC;IAC7C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,SAAS;QAC3F,IAAI,CAAC,SAAS,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,SAAS;QACpE,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gCAAgC,GAAG,oBAAoB,CAAC;AAErE;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,UAA8B;IACzE,MAAM,KAAK,GAAG,MAAM,CAAC;QACnB,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC;QAC7B,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QAC5B,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QAChC,UAAU,CAAC,SAAS;KACrB,CAAC,CAAC;IACH,OAAO,gCAAgC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3H,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,4BAA4B,CAAC,IAAY;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,gCAAgC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,GAAG,gCAAgC,CAAC,CAAC;IAC7J,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACpE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACnF,IAAI,KAAiB,CAAC;IACtB,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7G,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC1E,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/C,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;IAC3G,MAAM,UAAU,GAAG,4BAA4B,CAAC,IAAI,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,CAAC,KAAK,SAAS,UAAU,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC7I,CAAC;IACD,IAAI,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAClH,IAAI,CAAC,0BAA0B,CAAC,UAAU,EAAE,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAChI,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAA0C,EAAE,UAA8B;IAC/G,MAAM,SAAS,GAAG,CAAC,KAAyB,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9G,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAClI,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,IAAI,yBAAyB,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,0BAA0B,yBAAyB,6BAA6B,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** One staked tier. `minPower` is in ANTS-epochs (whole ANTS × epochs of lock remaining). */
|
|
2
|
+
export interface FreeTierStakeTier {
|
|
3
|
+
minPower: number;
|
|
4
|
+
/** Multiplier on the base allowance, or `'unlimited'`. */
|
|
5
|
+
multiplier: number | 'unlimited';
|
|
6
|
+
}
|
|
7
|
+
export interface FreeTierBaseLimits {
|
|
8
|
+
maxRequestsPerAddress: number | null;
|
|
9
|
+
maxRequestsPerIp: number | null;
|
|
10
|
+
windowMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* Only buyers whose stake reaches a tier are served; the base limits are
|
|
13
|
+
* then just the unit the tier multipliers apply to.
|
|
14
|
+
*/
|
|
15
|
+
stakersOnly?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface FreeTierProgram {
|
|
18
|
+
base: FreeTierBaseLimits;
|
|
19
|
+
stakeTiers: FreeTierStakeTier[];
|
|
20
|
+
}
|
|
21
|
+
/** Epochs in one year of lock; tiers are documented as "ANTS locked for a year". */
|
|
22
|
+
export declare const FREE_TIER_EPOCHS_PER_YEAR = 52;
|
|
23
|
+
/**
|
|
24
|
+
* Network default: 10k / 50k / 200k ANTS locked for a year earn 5×, 20× and
|
|
25
|
+
* unlimited free usage on the seller they are staked on.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_FREE_TIER_STAKE_TIERS: readonly FreeTierStakeTier[];
|
|
28
|
+
/**
|
|
29
|
+
* Response header a seller sets, to `FREE_TIER_SERVED_COVERED`, on a request
|
|
30
|
+
* to a priced service that the service's free allowance covered: the buyer
|
|
31
|
+
* owes nothing for it. A buyer that ignores it pays the listed price.
|
|
32
|
+
*/
|
|
33
|
+
export declare const FREE_TIER_SERVED_HEADER = "x-antseed-free-tier";
|
|
34
|
+
export declare const FREE_TIER_SERVED_COVERED = "covered";
|
|
35
|
+
export declare const MAX_FREE_TIER_STAKE_TIERS = 4;
|
|
36
|
+
export declare const MAX_FREE_TIER_MULTIPLIER = 10000;
|
|
37
|
+
/** Capability scope of a service's own program: `m` + the first 8 hex of keccak256(serviceId). */
|
|
38
|
+
export declare function freeTierServiceScope(serviceId: string): string;
|
|
39
|
+
/** Throws when `tiers` is not a valid program: increasing power, increasing multipliers, unlimited last. */
|
|
40
|
+
export declare function validateFreeTierStakeTiers(tiers: readonly FreeTierStakeTier[], label?: string): void;
|
|
41
|
+
/** Highest tier `power` (raw on-chain power: ANTS wei × epochs) qualifies for, or null. */
|
|
42
|
+
export declare function freeTierStakeTierForPower(tiers: readonly FreeTierStakeTier[], power: bigint): FreeTierStakeTier | null;
|
|
43
|
+
/** Raw on-chain power (ANTS wei × epochs) as whole ANTS-epochs. */
|
|
44
|
+
export declare function powerToAntsEpochs(power: bigint): number;
|
|
45
|
+
/**
|
|
46
|
+
* Capability strings advertising `program` in peer metadata: the seller-wide
|
|
47
|
+
* program, or `serviceId`'s own program when given.
|
|
48
|
+
*/
|
|
49
|
+
export declare function encodeFreeTierCapabilities(program: FreeTierProgram, serviceId?: string, options?: {
|
|
50
|
+
sellerWideTiers?: readonly FreeTierStakeTier[];
|
|
51
|
+
}): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Read a seller's free-tier program from its advertised capabilities: the
|
|
54
|
+
* program `serviceId` is served under when given (its own, else the
|
|
55
|
+
* seller-wide one), otherwise the seller-wide program. Returns null when there
|
|
56
|
+
* is none or its strings are malformed.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseFreeTierProgram(capabilities: readonly string[] | undefined, serviceId?: string): FreeTierProgram | null;
|
|
59
|
+
/** A service's advertised prices, as the free tier classifies them. */
|
|
60
|
+
export interface FreeTierServicePrices {
|
|
61
|
+
inputUsdPerMillion?: number | null;
|
|
62
|
+
outputUsdPerMillion?: number | null;
|
|
63
|
+
cachedInputUsdPerMillion?: number | null;
|
|
64
|
+
maxImageUsdPerImage?: number | null;
|
|
65
|
+
/** Unit-billing models by API protocol (images, video, per-request fees). */
|
|
66
|
+
unitBillingModels?: Record<string, {
|
|
67
|
+
components?: ReadonlyArray<{
|
|
68
|
+
priceUsd: number;
|
|
69
|
+
}>;
|
|
70
|
+
} | undefined> | null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether a service charges anything, the way the seller decides it: any
|
|
74
|
+
* token price, image price or priced unit-billing component makes it paid.
|
|
75
|
+
*/
|
|
76
|
+
export declare function isPricedService(prices: FreeTierServicePrices): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* The program a buyer of `serviceId` is served under: on a free service its
|
|
79
|
+
* own or the seller-wide one, on a priced service only its own free allowance.
|
|
80
|
+
* Paid video is never covered (it is paid through one-off channels), so it has none.
|
|
81
|
+
*/
|
|
82
|
+
export declare function freeTierProgramForService(capabilities: readonly string[] | undefined, serviceId: string, priced: boolean, options?: {
|
|
83
|
+
video?: boolean;
|
|
84
|
+
}): FreeTierProgram | null;
|
|
85
|
+
/**
|
|
86
|
+
* Only `serviceId`'s own program, never the seller-wide fallback. A priced
|
|
87
|
+
* service's free allowance is always its own program, so this is the one to
|
|
88
|
+
* read for a paid service.
|
|
89
|
+
*/
|
|
90
|
+
export declare function parseServiceFreeTierProgram(capabilities: readonly string[] | undefined, serviceId: string): FreeTierProgram | null;
|
|
91
|
+
/**
|
|
92
|
+
* A free-tier program passed on as JSON (by a buyer's catalog), validated the
|
|
93
|
+
* same way as advertised capabilities. Returns null when it is not one.
|
|
94
|
+
*/
|
|
95
|
+
export declare function normalizeFreeTierProgram(value: unknown): FreeTierProgram | null;
|
|
96
|
+
export * from './free-tier-stake.js';
|
|
97
|
+
//# sourceMappingURL=free-tier-program.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-tier-program.d.ts","sourceRoot":"","sources":["../../src/payments/free-tier-program.ts"],"names":[],"mappings":"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"}
|
|
@@ -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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"}
|