mtok-verify 0.1.4 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +11 -0
  2. package/fee-policy.js +30 -0
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -25,6 +25,17 @@ const paid = await verifier.verifyDrawPaid(drawPaidTxHash, {
25
25
  if (!paid.ok) refuse(paid.reason); // else serve, bounded by paid.event
26
26
  ```
27
27
 
28
+ Seller hosts can use the same historical fee policy as the market and reference relay:
29
+
30
+ ```js
31
+ import { normalizeFeeSchedule, paymentFeeBpsAt } from 'mtok-verify/fee-policy';
32
+
33
+ const feeBps = paymentFeeBpsAt(normalizeFeeSchedule(config.feeSchedule), paid.paidAtMs);
34
+ ```
35
+
36
+ Refresh the public config before new claims. Keep completed and pending claims replayable
37
+ without applying a new fee policy. `paidAtMs` must come from the verifier, never the request.
38
+
28
39
 
29
40
  ---
30
41
 
package/fee-policy.js ADDED
@@ -0,0 +1,30 @@
1
+ export function normalizeFeeSchedule(schedule) {
2
+ if (!Array.isArray(schedule) || !schedule.length || schedule.length > 64) throw new TypeError('fee schedule must contain 1..64 activation records');
3
+ let previous = -1;
4
+ return schedule.map(({ effectiveAtMs, feeBps }, index) => {
5
+ if (!Number.isSafeInteger(effectiveAtMs) || effectiveAtMs <= previous || (index === 0 && effectiveAtMs !== 0)) {
6
+ throw new TypeError('fee activations must start at 0 and increase in integer milliseconds');
7
+ }
8
+ if (!Number.isSafeInteger(feeBps) || feeBps < 0 || feeBps > 10_000) throw new TypeError('feeBps must be an integer from 0 to 10000');
9
+ previous = effectiveAtMs;
10
+ return { effectiveAtMs, feeBps };
11
+ });
12
+ }
13
+
14
+ // Schedules are normalized when configuration is loaded. Historical payments
15
+ // use their verified block time, never the relay's boot or first-observation time.
16
+ export function feeBpsAt(schedule, timeMs) {
17
+ if (!Number.isSafeInteger(timeMs) || timeMs < 0) throw new TypeError('verified payment time is required for fee policy');
18
+ return schedule.findLast(entry => entry.effectiveAtMs <= timeMs).feeBps;
19
+ }
20
+
21
+ // A buyer can read config immediately before an activation, then mine just
22
+ // after it. The previous rate is valid for one minute, never for a relay's lifetime.
23
+ export function paymentFeeBpsAt(schedule, paidAtMs) {
24
+ const start = Math.max(0, paidAtMs - 60_000);
25
+ let minimum = Math.min(feeBpsAt(schedule, paidAtMs), feeBpsAt(schedule, start));
26
+ for (const entry of schedule) {
27
+ if (entry.effectiveAtMs > start && entry.effectiveAtMs <= paidAtMs) minimum = Math.min(minimum, entry.feeBps);
28
+ }
29
+ return minimum;
30
+ }
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "mtok-verify",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "The on-chain verify core for mtok.market sellers: decode + verify a MtokDripLedger DrawPaid receipt (and its USDC transfer legs) against a paid draw, with the canonical DrawPaid topic set. Dependency-free, runs anywhere fetch runs (node, a CF Worker). The SSOT the platform + reference relay + house seller all share.",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./onchain.js"
7
+ ".": "./onchain.js",
8
+ "./fee-policy": "./fee-policy.js"
8
9
  },
9
10
  "files": [
10
11
  "onchain.js",
11
12
  "errors.js",
13
+ "fee-policy.js",
12
14
  "README.md"
13
15
  ],
14
16
  "engines": {