@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 +2 -0
- package/package.json +25 -12
- package/src/timeMath.js +6 -10
- package/src/typeGuards.js +21 -5
- package/src/types-index.d.ts +1 -0
- package/src/types-index.js +2 -0
- package/src/{types.d.ts → types.ts} +69 -19
- package/CHANGELOG.md +0 -45
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/time",
|
|
3
|
-
"version": "0.3.3-other-dev-
|
|
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": "
|
|
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": "
|
|
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/
|
|
34
|
-
"@
|
|
35
|
-
"@endo/nat": "
|
|
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": "
|
|
39
|
-
"@endo/init": "
|
|
40
|
-
"ava": "^5.
|
|
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
|
-
"
|
|
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
|
-
* @
|
|
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 '@
|
|
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
|
-
|
|
16
|
+
/** @type {TypedPattern<TimestampRecord>} */
|
|
17
|
+
export const TimestampRecordShape = {
|
|
8
18
|
timerBrand: TimerBrandShape,
|
|
9
19
|
absValue: TimestampValueShape,
|
|
10
|
-
}
|
|
20
|
+
};
|
|
21
|
+
harden(TimestampRecordShape);
|
|
11
22
|
|
|
12
|
-
|
|
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';
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ERef } from '@endo/eventual-send';
|
|
1
|
+
import type { ERef, RemotableBrand } from '@endo/eventual-send';
|
|
3
2
|
|
|
4
|
-
import type { RankComparison } from '@
|
|
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.
|
|
13
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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))
|