@@ -35,6 +35,10 @@ import '@agoric/zoe/exported.js';
35
35
import './internal-types.js' ;
36
36
import './types.js' ;
37
37
38
+ // The localTimerService uses a resolution of 1 millisecond.
39
+ const LOCAL_TIMER_NO_DELAY = 0n ;
40
+ const LOCAL_TIMER_ONE_SECOND = 1000n ;
41
+
38
42
// does nothing
39
43
const noActionStateChangeHandler = _newState => { } ;
40
44
@@ -48,6 +52,45 @@ const cmp = (a, b) => {
48
52
return - 1 ;
49
53
} ;
50
54
55
+ /**
56
+ * @param {ERef<TimerService> | undefined } timerService
57
+ * @param {(stamp: bigint) => void } updateClock
58
+ * @param {bigint } timerDelay
59
+ * @param {bigint } timerInterval
60
+ * @returns {Promise<void> }
61
+ */
62
+ const initializeClock = async (
63
+ timerService ,
64
+ updateClock ,
65
+ timerDelay ,
66
+ timerInterval ,
67
+ ) => {
68
+ if ( ! timerService ) {
69
+ return ;
70
+ }
71
+
72
+ // Get a baseline.
73
+ const time0 = await E ( timerService ) . getCurrentTimestamp ( ) ;
74
+ updateClock ( time0 ) ;
75
+
76
+ const notifier = await E ( timerService ) . makeNotifier (
77
+ timerDelay ,
78
+ timerInterval ,
79
+ ) ;
80
+
81
+ // Subscribe to future updates.
82
+ observeNotifier ( notifier , {
83
+ updateState : updateClock ,
84
+ } ) . catch ( e => {
85
+ console . error (
86
+ `Observing localTimerService` ,
87
+ timerService ,
88
+ 'failed with:' ,
89
+ e ,
90
+ ) ;
91
+ } ) ;
92
+ } ;
93
+
51
94
/**
52
95
* @typedef {Object } MakeWalletParams
53
96
* @property {ERef<ZoeService> } zoe
@@ -75,33 +118,37 @@ export function makeWallet({
75
118
*
76
119
* @type {number | undefined }
77
120
*/
78
- let nowMs ;
79
-
80
- // Subscribe to the timer service to update our stamp.
81
- if ( localTimerService ) {
82
- observeNotifier ( E ( localTimerService ) . makeNotifier ( 0n , 1000n ) , {
83
- updateState ( bigStamp ) {
84
- // We need to convert the bigint to a number (for easy Javascript date math).
85
- nowMs = parseInt ( `${ bigStamp } ` , 10 ) ;
86
- } ,
87
- } ) ;
88
- }
89
-
121
+ let nowStamp ;
90
122
let lastSequence = 0 ;
123
+
124
+ /**
125
+ * Add or update a record's `meta` property. Note that the Stamps are in
126
+ * milliseconds since the epoch, and they are only added if this backend has
127
+ * been supplied a `localTimerService`.
128
+ *
129
+ * The `sequence` is guaranteed to be monotonically increasing, even if this
130
+ * backend doesn't have a `localTimerService`, or the stamp has not yet
131
+ * increased.
132
+ *
133
+ * @template {Record<string, any>} T
134
+ * @param {T } record what to add metadata to
135
+ * @returns {T & { meta: T['meta'] & RecordMetadata } }
136
+ */
91
137
const addMeta = record => {
92
138
const { meta : oldMeta = { } } = record ;
139
+ /** @type {Record<string, any> & T['meta'] } */
93
140
const meta = { ...oldMeta } ;
94
141
if ( ! meta . sequence ) {
95
142
// Add a sequence number to the record.
96
143
lastSequence += 1 ;
97
144
meta . sequence = lastSequence ;
98
145
}
99
- if ( nowMs !== undefined ) {
146
+ if ( nowStamp !== undefined ) {
100
147
if ( ! meta . creationStamp ) {
101
148
// Set the creationStamp to be right now.
102
- meta . creationStamp = nowMs ;
149
+ meta . creationStamp = nowStamp ;
103
150
}
104
- meta . updatedStamp = nowMs ;
151
+ meta . updatedStamp = nowStamp ;
105
152
}
106
153
return { ...record , meta } ;
107
154
} ;
@@ -562,7 +609,7 @@ export function makeWallet({
562
609
563
610
const { inviteP, purseKeywordRecord, proposal } = await compiledOfferP ;
564
611
565
- // Track from whence our the payment came.
612
+ // Track from whence our payment came.
566
613
/** @type {Map<Payment, Purse> } */
567
614
const paymentToPurse = new Map ( ) ;
568
615
@@ -1576,6 +1623,8 @@ export function makeWallet({
1576
1623
return offerResult . uiNotifier ;
1577
1624
}
1578
1625
1626
+ const { notifier : clockNotifier , updater : clockUpdater } = makeNotifierKit ( ) ;
1627
+
1579
1628
const wallet = Far ( 'wallet' , {
1580
1629
saveOfferResult,
1581
1630
getOfferResult,
@@ -1671,9 +1720,32 @@ export function makeWallet({
1671
1720
) ;
1672
1721
return E ( namesByAddress ) . lookup ( ...path ) ;
1673
1722
} ,
1723
+ getClockNotifier : ( ) => clockNotifier ,
1674
1724
} ) ;
1675
1725
1726
+ const updateNowStamp = bigStamp => {
1727
+ // We convert the milliseconds from a bigint to a number (for easy
1728
+ // Javascript date math).
1729
+ const nextStamp = parseInt ( `${ bigStamp } ` , 10 ) ;
1730
+
1731
+ if ( nowStamp && nowStamp >= nextStamp ) {
1732
+ // Don't make an unnecessary update.
1733
+ return ;
1734
+ }
1735
+
1736
+ nowStamp = nextStamp ;
1737
+ clockUpdater . updateState ( nowStamp ) ;
1738
+ } ;
1739
+
1676
1740
const initialize = async ( ) => {
1741
+ // Subscribe to the timer service to update our stamp.
1742
+ await initializeClock (
1743
+ localTimerService ,
1744
+ updateNowStamp ,
1745
+ LOCAL_TIMER_NO_DELAY ,
1746
+ LOCAL_TIMER_ONE_SECOND ,
1747
+ ) ;
1748
+
1677
1749
// Allow people to send us payments.
1678
1750
const selfDepositFacet = Far ( 'contact' , {
1679
1751
receive ( payment ) {
@@ -1743,5 +1815,9 @@ export function makeWallet({
1743
1815
feePurse ,
1744
1816
) ;
1745
1817
} ;
1746
- return { admin : wallet , initialized : initialize ( ) , importBankAssets } ;
1818
+ return {
1819
+ admin : wallet ,
1820
+ initialized : initialize ( ) ,
1821
+ importBankAssets,
1822
+ } ;
1747
1823
}
0 commit comments