@agoric/time 0.3.3-other-dev-8f8782b.0 → 0.3.3-other-dev-fbe72e7.0.fbe72e7

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/index.js CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from './src/timeMath.js';
2
2
  export * from './src/typeGuards.js';
3
+ // eslint-disable-next-line import/export -- just types
4
+ export * from './src/types-index.js';
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "@agoric/time",
3
- "version": "0.3.3-other-dev-8f8782b.0+8f8782b",
3
+ "version": "0.3.3-other-dev-fbe72e7.0.fbe72e7",
4
4
  "description": "Timestamps, time math, timer service API definition",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
+ "types": "index.js",
7
8
  "engines": {
8
- "node": ">=14.15.0"
9
+ "node": "^20.9 || ^22.11"
9
10
  },
10
11
  "scripts": {
11
12
  "build": "exit 0",
12
13
  "test": "ava",
13
14
  "test:xs": "exit 0",
14
- "lint": "run-s --continue-on-error lint:*",
15
- "lint:types": "tsc -p jsconfig.json",
16
- "lint:eslint": "eslint .",
15
+ "lint": "yarn run -T run-s --continue-on-error 'lint:*'",
16
+ "lint:types": "yarn run -T tsc",
17
+ "lint:eslint": "yarn run -T eslint .",
17
18
  "lint-fix": "yarn lint:eslint --fix"
18
19
  },
19
20
  "repository": {
@@ -30,14 +31,23 @@
30
31
  },
31
32
  "homepage": "https://github.com/Agoric/agoric-sdk#readme",
32
33
  "dependencies": {
33
- "@agoric/assert": "0.6.1-other-dev-8f8782b.0+8f8782b",
34
- "@agoric/store": "0.9.3-other-dev-8f8782b.0+8f8782b",
35
- "@endo/nat": "4.1.27"
34
+ "@agoric/store": "0.9.3-other-dev-fbe72e7.0.fbe72e7",
35
+ "@endo/errors": "^1.2.13",
36
+ "@endo/nat": "^5.1.3",
37
+ "@endo/patterns": "^1.7.0"
36
38
  },
37
39
  "devDependencies": {
38
- "@endo/far": "0.2.18",
39
- "@endo/init": "0.5.56",
40
- "ava": "^5.2.0"
40
+ "@endo/far": "^1.1.14",
41
+ "@endo/init": "^1.1.12",
42
+ "ava": "^5.3.0"
43
+ },
44
+ "ava": {
45
+ "require": [
46
+ "@endo/init/debug.js"
47
+ ],
48
+ "files": [
49
+ "test/**/*.test.*"
50
+ ]
41
51
  },
42
52
  "files": [
43
53
  "*.js",
@@ -47,5 +57,8 @@
47
57
  "publishConfig": {
48
58
  "access": "public"
49
59
  },
50
- "gitHead": "8f8782bc52393e9d4fc82523ecf31cab429b11b3"
60
+ "typeCoverage": {
61
+ "atLeast": 88.75
62
+ },
63
+ "gitHead": "fbe72e72107f9997f788674e668c660d92ec4492"
51
64
  }
package/src/timeMath.js CHANGED
@@ -1,16 +1,10 @@
1
- import { mustMatch } from '@agoric/store';
2
1
  import { Nat } from '@endo/nat';
2
+ import { Fail, q } from '@endo/errors';
3
+ import { mustMatch } from '@agoric/store';
3
4
  import { RelativeTimeRecordShape, TimestampRecordShape } from './typeGuards.js';
4
5
 
5
- const { Fail, quote: q } = assert;
6
6
  /**
7
- * @typedef {import('./types').TimerBrand} TimerBrand
8
- * @typedef {import('./types').Timestamp} Timestamp
9
- * @typedef {import('./types').RelativeTime} RelativeTime
10
- * @typedef {import('./types').RelativeTimeValue} RelativeTimeValue
11
- * @typedef {import('./types').TimestampValue} TimestampValue
12
- * @typedef {import('./types').TimeMathType} TimeMathType
13
- *
7
+ * @import {RelativeTime, RelativeTimeValue, TimerBrand, TimeMathType, Timestamp, TimestampRecord, TimestampValue} from './types.js';
14
8
  */
15
9
 
16
10
  /**
@@ -200,7 +194,7 @@ const modRelRel = (rel, step) =>
200
194
  * @param {Timestamp | RelativeTime} right
201
195
  * @param {bigint} v1
202
196
  * @param {bigint} v2
203
- * @returns {RankComparison}
197
+ * @returns {import('@endo/marshal').RankComparison}
204
198
  */
205
199
  const compareValues = (left, right, v1, v2) => {
206
200
  sharedTimerBrand(left, right);
@@ -253,7 +247,9 @@ export const TimeMath = harden({
253
247
  relValue,
254
248
  coerceTimestampRecord,
255
249
  coerceRelativeTimeRecord,
250
+ // @ts-expect-error xxx dynamic typing
256
251
  addAbsRel,
252
+ // @ts-expect-error xxx dynamic typing
257
253
  addRelRel,
258
254
  subtractAbsAbs,
259
255
  clampedSubtractAbsAbs,
package/src/typeGuards.js CHANGED
@@ -1,20 +1,36 @@
1
- import { M } from '@agoric/store';
1
+ import { M } from '@endo/patterns';
2
+
3
+ /**
4
+ * @import {TypedPattern} from '@agoric/internal';
5
+ * @import {TimestampRecord, TimestampValue, RelativeTimeValue, RelativeTimeRecord} from './types.js';
6
+ */
2
7
 
3
8
  export const TimerBrandShape = M.remotable('TimerBrand');
9
+
10
+ /** @type {TypedPattern<bigint>} */
4
11
  export const TimestampValueShape = M.nat();
12
+
13
+ /** @type {TypedPattern<bigint>} */
5
14
  export const RelativeTimeValueShape = M.nat(); // Should we allow negatives?
6
15
 
7
- export const TimestampRecordShape = harden({
16
+ /** @type {TypedPattern<TimestampRecord>} */
17
+ export const TimestampRecordShape = {
8
18
  timerBrand: TimerBrandShape,
9
19
  absValue: TimestampValueShape,
10
- });
20
+ };
21
+ harden(TimestampRecordShape);
11
22
 
12
- export const RelativeTimeRecordShape = harden({
23
+ /** @type {TypedPattern<RelativeTimeRecord>} */
24
+ export const RelativeTimeRecordShape = {
13
25
  timerBrand: TimerBrandShape,
14
26
  relValue: RelativeTimeValueShape,
15
- });
27
+ };
28
+ harden(RelativeTimeRecordShape);
16
29
 
30
+ /** @type {TypedPattern<TimestampRecord | TimestampValue>} */
17
31
  export const TimestampShape = M.or(TimestampRecordShape, TimestampValueShape);
32
+
33
+ /** @type {TypedPattern<RelativeTimeRecord | RelativeTimeValue>} */
18
34
  export const RelativeTimeShape = M.or(
19
35
  RelativeTimeRecordShape,
20
36
  RelativeTimeValueShape,
@@ -0,0 +1 @@
1
+ export type * from './types.js';
@@ -0,0 +1,2 @@
1
+ // Empty JS file to correspond with types.d.ts
2
+ export {};
@@ -1,22 +1,19 @@
1
- /* eslint-disable no-use-before-define, no-undef */
2
- import type { ERef } from '@endo/eventual-send';
1
+ import type { ERef, RemotableBrand } from '@endo/eventual-send';
3
2
 
4
- import type { RankComparison } from '@agoric/store';
5
-
6
- /// <reference types="@agoric/notifier/src/types.js"/>
3
+ import type { RankComparison, RemotableObject } from '@endo/marshal';
7
4
 
8
5
  // These aren't in the global runtime environment. They are just types that are
9
6
  // meant to be globally accessible as a side-effect of importing this module.
10
7
  /**
11
8
  * The TimerBrand is a unique object that represents the kind of Time
12
- * used in Timestamp/RelativeTime records. Time from different sources
13
- * is not comparable.
9
+ * used in Timestamp/RelativeTime records. Times from different sources
10
+ * are not comparable.
14
11
  *
15
12
  * Do not call `isMyTimerService(myTimerService)` on an untrusted
16
13
  * brand, because that will leak your closely-held timer authority. If
17
14
  * the goal is to check the suitability of a client-provided
18
15
  * Timestamp, use coerceTimestampRecord() or add/subtract it to a
19
- * known-good Timestamp, or extact its brand and === against
16
+ * known-good Timestamp, or extract its brand and === against
20
17
  * `timerService.getTimerBrand()`.
21
18
  *
22
19
  * TODO Not all Timestamps are labeled with the TimerBrand (in much
@@ -29,7 +26,7 @@ import type { RankComparison } from '@agoric/store';
29
26
  * See https://github.com/Agoric/agoric-sdk/issues/5798
30
27
  * and https://github.com/Agoric/agoric-sdk/pull/5821
31
28
  */
32
- export type TimerBrand = {
29
+ export type TimerBrand = RemotableObject & {
33
30
  isMyTimerService: (timer: TimerService) => ERef<boolean>;
34
31
  isMyClock: (clock: Clock) => ERef<boolean>;
35
32
  };
@@ -53,11 +50,21 @@ export type TimestampValue = bigint;
53
50
  */
54
51
  export type RelativeTimeValue = bigint;
55
52
 
53
+ /**
54
+ * The canonical representation of a typed absolute time. It bundles the brand
55
+ * with the time, as represented by a TimerService, which might represent time
56
+ * since the epoch, or blockheight on a particular chain.
57
+ */
56
58
  export type TimestampRecord = {
57
59
  timerBrand: TimerBrand;
58
60
  absValue: bigint;
59
61
  };
60
62
 
63
+ /**
64
+ * The canonical representation of a typed relative time. It bundles the brand
65
+ * with an elapsed time, as represented by a TimerService, which might represent
66
+ * time since the epoch, or blockheight on a particular chain.
67
+ */
61
68
  export type RelativeTimeRecord = {
62
69
  timerBrand: TimerBrand;
63
70
  relValue: bigint;
@@ -88,7 +95,8 @@ export type RelativeTime = RelativeTimeRecord | RelativeTimeValue;
88
95
  /**
89
96
  * A CancelToken is an arbitrary marker object, passed in with
90
97
  * each API call that creates a wakeup or repeater, and passed to
91
- * cancel() to cancel them all.
98
+ * cancel() to cancel them all. Multiple wakeups can rely on the same
99
+ * CancelToken so they can be cancelled collectively.
92
100
  */
93
101
  export type CancelToken = object;
94
102
 
@@ -97,7 +105,7 @@ export type CancelToken = object;
97
105
  * schedule a single wake() call, create a repeater that will allow scheduling
98
106
  * of events at regular intervals, or remove scheduled calls.
99
107
  */
100
- export interface TimerService {
108
+ export interface TimerServiceCommon {
101
109
  /**
102
110
  * Retrieve the latest timestamp
103
111
  */
@@ -111,7 +119,7 @@ export interface TimerService {
111
119
  cancelToken?: CancelToken,
112
120
  ) => TimestampRecord;
113
121
  /**
114
- * Create and return a promise that will resolve after the absolte
122
+ * Create and return a promise that will resolve after the absolute
115
123
  * time has passed.
116
124
  */
117
125
  wakeAt: (
@@ -157,7 +165,7 @@ export interface TimerService {
157
165
  delay: RelativeTime,
158
166
  interval: RelativeTime,
159
167
  cancelToken?: CancelToken,
160
- ) => Notifier<TimestampRecord>;
168
+ ) => import('@agoric/notifier').Notifier<TimestampRecord>;
161
169
  /**
162
170
  * Cancel a previously-established wakeup or repeater.
163
171
  */
@@ -171,7 +179,16 @@ export interface TimerService {
171
179
  */
172
180
  getTimerBrand: () => TimerBrand;
173
181
  }
182
+ // XXX copied from Remotable helper return type
183
+ export type TimerService = TimerServiceCommon &
184
+ RemotableObject<'TimerService'> &
185
+ RemotableBrand<object, TimerServiceCommon>;
174
186
 
187
+ /**
188
+ * Read-only access to a TimeService's current time. This allows reading the
189
+ * current time (e.g. to see if a deadline has passed) without the ability to
190
+ * schedule events.
191
+ */
175
192
  export interface Clock {
176
193
  /**
177
194
  * Retrieve the latest timestamp
@@ -183,6 +200,11 @@ export interface Clock {
183
200
  getTimerBrand: () => TimerBrand;
184
201
  }
185
202
 
203
+ /**
204
+ * The interface that must be implemented by objects which are to be invoked at
205
+ * scheduled times. Used by `TimerService.repeatAfter()`,
206
+ * `TimerService.setWakeup()`, and `TimerRepeater.schedule()`.
207
+ */
186
208
  export interface TimerWaker {
187
209
  /**
188
210
  * The timestamp passed to `wake()` is the time that the call was scheduled
@@ -191,6 +213,12 @@ export interface TimerWaker {
191
213
  wake: (timestamp: TimestampRecord) => void;
192
214
  }
193
215
 
216
+ /**
217
+ * Provides the ability to schedule wake() calls repeatedly at a regular
218
+ * interval, or to disable all future use of this TimerRepeater. Created by the
219
+ * deprecated makeRepeater(), new code should use repeatAfter(), which doesn't
220
+ * have a control object and doesn't require a second schedule step
221
+ */
194
222
  export interface TimerRepeater {
195
223
  /**
196
224
  * Returns the time scheduled for
@@ -206,6 +234,26 @@ export interface TimerRepeater {
206
234
  disable: () => void;
207
235
  }
208
236
 
237
+ /**
238
+ * TimeMath supports simple arithmetic on typed Time values, enforcing that
239
+ * values are combined in type-compatible ways. You can add 3 minutes to 3pm,
240
+ * or 5 minutes to a half hour, but it makes no sense to add 3pm and 5pm.
241
+ * Subtracting two Timestamps does produce a useful difference.
242
+ *
243
+ * The brands prevent you from accidentally combining time values from different
244
+ * TimerServices. Some chains track time in blocks, others follow wall clock
245
+ * time, some do both. Every local computer has its own unique notion of wall
246
+ * clock time. Even when these clocks are talking about the same thing (UTC),
247
+ * they can all drift in different ways. Using the correct brands lets you be
248
+ * precise about which particular source of time you mean, preventing confusion
249
+ * or attacks when the clocks diverge. Thus it is an error to e.g. use a time
250
+ * you got from chain A to schedule an event on chain B.
251
+ *
252
+ * The basic types are `RelativeTimeRecord` (durations) and `TimestampRecord`. The numeric
253
+ * values can be extracted from the typed values, but it's usually better to
254
+ * maintain values as their canonical typed form so these operations can be
255
+ * applied.
256
+ */
209
257
  export type TimeMathType = {
210
258
  /**
211
259
  * Validates that the operand represents a `Timestamp` and returns the bigint
@@ -240,17 +288,19 @@ export type TimeMathType = {
240
288
  ) => RelativeTimeRecord;
241
289
  /**
242
290
  * An absolute time + a relative time gives a new absolute time.
243
- *
244
- * @template {Timestamp} T
245
291
  */
246
- addAbsRel: (abs: T, rel: RelativeTime) => T;
292
+ addAbsRel: <T extends Timestamp>(
293
+ abs: T,
294
+ rel: RelativeTime,
295
+ ) => T extends TimestampRecord ? TimestampRecord : TimestampValue;
247
296
  /**
248
297
  * A relative time (i.e., a duration) + another relative time
249
298
  * gives a new relative time.
250
- *
251
- * @template {RelativeTime} T
252
299
  */
253
- addRelRel: (rel1: T, rel2: T) => T;
300
+ addRelRel: <T extends RelativeTime>(
301
+ rel1: T,
302
+ rel2: T,
303
+ ) => T extends RelativeTimeRecord ? RelativeTimeRecord : RelativeTimeValue;
254
304
  /**
255
305
  * The difference between two absolute times is a relative time. If abs1 > abs2
256
306
  * the difference would be negative, so this method throws instead.
package/CHANGELOG.md DELETED
@@ -1,45 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- ### [0.3.3-u11.0](https://github.com/Agoric/agoric-sdk/compare/@agoric/time@0.3.2...@agoric/time@0.3.3-u11.0) (2023-08-24)
7
-
8
- **Note:** Version bump only for package @agoric/time
9
-
10
-
11
-
12
-
13
-
14
- ### [0.3.2](https://github.com/Agoric/agoric-sdk/compare/@agoric/time@0.3.1...@agoric/time@0.3.2) (2023-06-02)
15
-
16
- **Note:** Version bump only for package @agoric/time
17
-
18
-
19
-
20
-
21
-
22
- ### [0.3.1](https://github.com/Agoric/agoric-sdk/compare/@agoric/time@0.3.0...@agoric/time@0.3.1) (2023-05-24)
23
-
24
- **Note:** Version bump only for package @agoric/time
25
-
26
-
27
-
28
-
29
-
30
- ## 0.3.0 (2023-05-19)
31
-
32
-
33
- ### Features
34
-
35
- * **auction:** add an auctioneer to manage vault liquidation ([#7000](https://github.com/Agoric/agoric-sdk/issues/7000)) ([398b70f](https://github.com/Agoric/agoric-sdk/commit/398b70f7e028f957afc1582f0ee31eb2574c94d0)), closes [#6992](https://github.com/Agoric/agoric-sdk/issues/6992) [#7047](https://github.com/Agoric/agoric-sdk/issues/7047) [#7074](https://github.com/Agoric/agoric-sdk/issues/7074)
36
- * create new @agoric/time package ([a61a3fb](https://github.com/Agoric/agoric-sdk/commit/a61a3fbb7a5ccfe07c715a310baa88ada8e572b2)), closes [#6003](https://github.com/Agoric/agoric-sdk/issues/6003)
37
-
38
-
39
- ### Bug Fixes
40
-
41
- * **time:** TimerService now returns branded TimestampRecord ([9137e9c](https://github.com/Agoric/agoric-sdk/commit/9137e9cab6f459c876b1a2ad8e681be7224749ce)), closes [#6003](https://github.com/Agoric/agoric-sdk/issues/6003)
42
- * clean up types ([6f53f19](https://github.com/Agoric/agoric-sdk/commit/6f53f1915ce21e65fefc2fff900b7d4b947be6b1))
43
- * move timer files to new package ([c105bde](https://github.com/Agoric/agoric-sdk/commit/c105bdefff2527a90b3c6b9d80d0462944dd51c3))
44
- * TimerBrand has isMyTimerService(), not isMyTimer() ([9f4e867](https://github.com/Agoric/agoric-sdk/commit/9f4e8670694504ebbd451c8840f900a1a24b902f))
45
- * **time:** fix the code/test to work in its new home ([504d333](https://github.com/Agoric/agoric-sdk/commit/504d3335cf632cc50e079fb27a82db604318bd4a))