@agoric/smart-wallet 0.5.4-u15.0 → 0.5.4-u16.0
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/package.json +32 -28
- package/src/invitations.d.ts +14 -10
- package/src/invitations.d.ts.map +1 -1
- package/src/invitations.js +32 -28
- package/src/marshal-contexts.d.ts +44 -41
- package/src/marshal-contexts.d.ts.map +1 -1
- package/src/marshal-contexts.js +65 -58
- package/src/offerWatcher.d.ts +21 -39
- package/src/offerWatcher.d.ts.map +1 -1
- package/src/offerWatcher.js +34 -24
- package/src/offers.d.ts +7 -7
- package/src/offers.d.ts.map +1 -1
- package/src/offers.js +9 -9
- package/src/proposals/upgrade-wallet-factory2-proposal.d.ts.map +1 -1
- package/src/proposals/upgrade-wallet-factory2-proposal.js +2 -1
- package/src/proposals/upgrade-walletFactory-proposal.d.ts +1 -1
- package/src/proposals/upgrade-walletFactory-proposal.d.ts.map +1 -1
- package/src/proposals/upgrade-walletFactory-proposal.js +45 -21
- package/src/smartWallet.d.ts +80 -60
- package/src/smartWallet.d.ts.map +1 -1
- package/src/smartWallet.js +156 -109
- package/src/typeGuards.d.ts +1 -1
- package/src/types.d.ts +14 -13
- package/src/utils.d.ts +17 -14
- package/src/utils.d.ts.map +1 -1
- package/src/utils.js +18 -6
- package/src/walletFactory.d.ts +24 -80
- package/src/walletFactory.d.ts.map +1 -1
- package/src/walletFactory.js +55 -36
- package/CHANGELOG.md +0 -250
package/src/smartWallet.js
CHANGED
|
@@ -42,149 +42,176 @@ import { shape } from './typeGuards.js';
|
|
|
42
42
|
import { objectMapStoragePath } from './utils.js';
|
|
43
43
|
import { prepareOfferWatcher, watchOfferOutcomes } from './offerWatcher.js';
|
|
44
44
|
|
|
45
|
+
/** @import {OfferId, OfferStatus} from './offers.js'; */
|
|
46
|
+
|
|
45
47
|
const { Fail, quote: q } = assert;
|
|
46
48
|
|
|
47
49
|
const trace = makeTracer('SmrtWlt');
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
52
|
* @file Smart wallet module
|
|
51
|
-
*
|
|
52
|
-
* @see {@link ../README.md}}
|
|
53
|
+
* @see {@link ../README.md} }
|
|
53
54
|
*/
|
|
54
55
|
|
|
55
56
|
/** @typedef {number | string} OfferId */
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* @typedef {{
|
|
59
|
-
* id: OfferId
|
|
60
|
-
* invitationSpec: import('./invitations').InvitationSpec
|
|
61
|
-
* proposal: Proposal
|
|
62
|
-
* offerArgs?:
|
|
60
|
+
* id: OfferId;
|
|
61
|
+
* invitationSpec: import('./invitations').InvitationSpec;
|
|
62
|
+
* proposal: Proposal;
|
|
63
|
+
* offerArgs?: any;
|
|
63
64
|
* }} OfferSpec
|
|
64
65
|
*/
|
|
65
66
|
|
|
66
67
|
/**
|
|
67
68
|
* @typedef {{
|
|
68
|
-
* logger:
|
|
69
|
-
*
|
|
70
|
-
*
|
|
69
|
+
* logger: {
|
|
70
|
+
* info: (...args: any[]) => void;
|
|
71
|
+
* error: (...args: any[]) => void;
|
|
72
|
+
* };
|
|
73
|
+
* makeOfferWatcher: import('./offerWatcher.js').MakeOfferWatcher;
|
|
74
|
+
* invitationFromSpec: ERef<Invitation>;
|
|
71
75
|
* }} ExecutorPowers
|
|
72
76
|
*/
|
|
73
77
|
|
|
74
78
|
/**
|
|
75
79
|
* @typedef {{
|
|
76
|
-
* method: 'executeOffer'
|
|
77
|
-
* offer: OfferSpec
|
|
80
|
+
* method: 'executeOffer';
|
|
81
|
+
* offer: OfferSpec;
|
|
78
82
|
* }} ExecuteOfferAction
|
|
79
83
|
*/
|
|
80
84
|
|
|
81
85
|
/**
|
|
82
86
|
* @typedef {{
|
|
83
|
-
* method: 'tryExitOffer'
|
|
84
|
-
* offerId: OfferId
|
|
87
|
+
* method: 'tryExitOffer';
|
|
88
|
+
* offerId: OfferId;
|
|
85
89
|
* }} TryExitOfferAction
|
|
86
90
|
*/
|
|
87
91
|
|
|
88
92
|
// Discriminated union. Possible future messages types:
|
|
89
93
|
// maybe suggestIssuer for https://github.com/Agoric/agoric-sdk/issues/6132
|
|
90
94
|
// setting petnames and adding brands for https://github.com/Agoric/agoric-sdk/issues/6126
|
|
91
|
-
/**
|
|
92
|
-
* @typedef { ExecuteOfferAction | TryExitOfferAction } BridgeAction
|
|
93
|
-
*/
|
|
95
|
+
/** @typedef {ExecuteOfferAction | TryExitOfferAction} BridgeAction */
|
|
94
96
|
|
|
95
97
|
/**
|
|
96
|
-
* Purses is an array to support a future requirement of multiple purses per
|
|
98
|
+
* Purses is an array to support a future requirement of multiple purses per
|
|
99
|
+
* brand.
|
|
97
100
|
*
|
|
98
|
-
* Each map is encoded as an array of entries because a Map doesn't serialize
|
|
99
|
-
* We also considered having a vstorage key for each offer but for now
|
|
101
|
+
* Each map is encoded as an array of entries because a Map doesn't serialize
|
|
102
|
+
* directly. We also considered having a vstorage key for each offer but for now
|
|
103
|
+
* are sticking with this design.
|
|
100
104
|
*
|
|
101
105
|
* Cons
|
|
102
|
-
*
|
|
103
|
-
*
|
|
106
|
+
*
|
|
107
|
+
* - Reserializes previously written results when a new result is added
|
|
108
|
+
* - Optimizes reads though writes are on-chain (~100 machines) and reads are
|
|
109
|
+
* off-chain (to 1 machine)
|
|
104
110
|
*
|
|
105
111
|
* Pros
|
|
106
|
-
* - Reading all offer results happens much more (>100) often than storing a new offer result
|
|
107
|
-
* - Reserialization and writes are paid in execution gas, whereas reads are not
|
|
108
112
|
*
|
|
109
|
-
*
|
|
113
|
+
* - Reading all offer results happens much more (>100) often than storing a new
|
|
114
|
+
* offer result
|
|
115
|
+
* - Reserialization and writes are paid in execution gas, whereas reads are not
|
|
116
|
+
*
|
|
117
|
+
* This design should be revisited if ever batch querying across vstorage keys
|
|
118
|
+
* become cheaper or reads be paid.
|
|
110
119
|
*
|
|
111
120
|
* @typedef {{
|
|
112
|
-
* purses:
|
|
113
|
-
* offerToUsedInvitation:
|
|
114
|
-
* offerToPublicSubscriberPaths:
|
|
115
|
-
*
|
|
121
|
+
* purses: { brand: Brand; balance: Amount }[];
|
|
122
|
+
* offerToUsedInvitation: [offerId: string, usedInvitation: Amount][];
|
|
123
|
+
* offerToPublicSubscriberPaths: [
|
|
124
|
+
* offerId: string,
|
|
125
|
+
* publicTopics: { [subscriberName: string]: string },
|
|
126
|
+
* ][];
|
|
127
|
+
* liveOffers: [OfferId, OfferStatus][];
|
|
116
128
|
* }} CurrentWalletRecord
|
|
117
129
|
*/
|
|
118
130
|
|
|
119
131
|
/**
|
|
120
|
-
* @typedef {{ updated: 'offerStatus'
|
|
132
|
+
* @typedef {{ updated: 'offerStatus'; status: OfferStatus }
|
|
121
133
|
* | { updated: 'balance'; currentAmount: Amount }
|
|
122
|
-
* | { updated: 'walletAction'; status: { error: string } }
|
|
123
|
-
*
|
|
134
|
+
* | { updated: 'walletAction'; status: { error: string } }} UpdateRecord
|
|
135
|
+
* Record of an update to the state of this wallet.
|
|
124
136
|
*
|
|
125
|
-
*
|
|
137
|
+
* Client is responsible for coalescing updates into a current state. See
|
|
138
|
+
* `coalesceUpdates` utility.
|
|
126
139
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
140
|
+
* The reason for this burden on the client is that publishing the full history
|
|
141
|
+
* of offers with each change is untenable.
|
|
129
142
|
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* the amount suffices.
|
|
143
|
+
* `balance` update supports forward-compatibility for more than one purse per
|
|
144
|
+
* brand. An additional key will be needed to disambiguate. For now the brand
|
|
145
|
+
* in the amount suffices.
|
|
133
146
|
*/
|
|
134
147
|
|
|
135
148
|
/**
|
|
136
149
|
* @typedef {{
|
|
137
|
-
* brand: Brand
|
|
138
|
-
* displayInfo: DisplayInfo
|
|
139
|
-
* issuer: Issuer
|
|
140
|
-
* petname: import('./types.js').Petname
|
|
150
|
+
* brand: Brand;
|
|
151
|
+
* displayInfo: DisplayInfo;
|
|
152
|
+
* issuer: Issuer;
|
|
153
|
+
* petname: import('./types.js').Petname;
|
|
141
154
|
* }} BrandDescriptor
|
|
142
|
-
*
|
|
155
|
+
* For use by clients to describe brands to users. Includes `displayInfo` to
|
|
156
|
+
* save a remote call.
|
|
143
157
|
*/
|
|
144
158
|
|
|
145
159
|
/**
|
|
146
160
|
* @typedef {{
|
|
147
|
-
* address: string
|
|
148
|
-
* bank: ERef<import('@agoric/vats/src/vat-bank.js').Bank
|
|
149
|
-
* currentStorageNode: StorageNode
|
|
150
|
-
* invitationPurse: Purse<'set'
|
|
151
|
-
* walletStorageNode: StorageNode
|
|
161
|
+
* address: string;
|
|
162
|
+
* bank: ERef<import('@agoric/vats/src/vat-bank.js').Bank>;
|
|
163
|
+
* currentStorageNode: StorageNode;
|
|
164
|
+
* invitationPurse: Purse<'set', InvitationDetails>;
|
|
165
|
+
* walletStorageNode: StorageNode;
|
|
152
166
|
* }} UniqueParams
|
|
153
167
|
*
|
|
168
|
+
*
|
|
154
169
|
* @typedef {Pick<MapStore<Brand, BrandDescriptor>, 'has' | 'get' | 'values'>} BrandDescriptorRegistry
|
|
170
|
+
*
|
|
171
|
+
*
|
|
155
172
|
* @typedef {{
|
|
156
|
-
* agoricNames: ERef<import('@agoric/vats').NameHub
|
|
157
|
-
* registry: BrandDescriptorRegistry
|
|
158
|
-
* invitationIssuer: Issuer<'set'
|
|
159
|
-
* invitationBrand: Brand<'set'
|
|
160
|
-
* invitationDisplayInfo: DisplayInfo
|
|
161
|
-
* publicMarshaller: Marshaller
|
|
162
|
-
* zoe: ERef<ZoeService
|
|
163
|
-
* secretWalletFactoryKey: any
|
|
173
|
+
* agoricNames: ERef<import('@agoric/vats').NameHub>;
|
|
174
|
+
* registry: BrandDescriptorRegistry;
|
|
175
|
+
* invitationIssuer: Issuer<'set'>;
|
|
176
|
+
* invitationBrand: Brand<'set'>;
|
|
177
|
+
* invitationDisplayInfo: DisplayInfo;
|
|
178
|
+
* publicMarshaller: Marshaller;
|
|
179
|
+
* zoe: ERef<ZoeService>;
|
|
180
|
+
* secretWalletFactoryKey: any;
|
|
164
181
|
* }} SharedParams
|
|
165
182
|
*
|
|
166
|
-
* @typedef {ImmutableState & MutableState} State
|
|
167
|
-
* - `brandPurses` is precious and closely held. defined as late as possible to reduce its scope.
|
|
168
|
-
* - `offerToInvitationMakers` is precious and closely held.
|
|
169
|
-
* - `offerToPublicSubscriberPaths` is precious and closely held.
|
|
170
|
-
* - `purseBalances` is a cache of what we've received from purses. Held so we can publish all balances on change.
|
|
171
183
|
*
|
|
172
|
-
* @typedef {
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* purseBalances
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
+
* @typedef {ImmutableState & MutableState} State - `brandPurses` is precious
|
|
185
|
+
* and closely held. defined as late as possible to reduce its scope.
|
|
186
|
+
*
|
|
187
|
+
* - `offerToInvitationMakers` is precious and closely held.
|
|
188
|
+
* - `offerToPublicSubscriberPaths` is precious and closely held.
|
|
189
|
+
* - `purseBalances` is a cache of what we've received from purses. Held so we can
|
|
190
|
+
* publish all balances on change.
|
|
191
|
+
*
|
|
192
|
+
*
|
|
193
|
+
* @typedef {Readonly<
|
|
194
|
+
* UniqueParams & {
|
|
195
|
+
* paymentQueues: MapStore<Brand, Payment[]>;
|
|
196
|
+
* offerToInvitationMakers: MapStore<
|
|
197
|
+
* string,
|
|
198
|
+
* import('./types.js').InvitationMakers
|
|
199
|
+
* >;
|
|
200
|
+
* offerToPublicSubscriberPaths: MapStore<string, Record<string, string>>;
|
|
201
|
+
* offerToUsedInvitation: MapStore<string, Amount<'set'>>;
|
|
202
|
+
* purseBalances: MapStore<Purse, Amount>;
|
|
203
|
+
* updateRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<UpdateRecord>;
|
|
204
|
+
* currentRecorderKit: import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<CurrentWalletRecord>;
|
|
205
|
+
* liveOffers: MapStore<OfferId, OfferStatus>;
|
|
206
|
+
* liveOfferSeats: MapStore<OfferId, UserSeat<unknown>>;
|
|
207
|
+
* liveOfferPayments: MapStore<OfferId, MapStore<Brand, Payment>>;
|
|
208
|
+
* }
|
|
209
|
+
* >} ImmutableState
|
|
210
|
+
*
|
|
184
211
|
*
|
|
185
212
|
* @typedef {BrandDescriptor & { purse: Purse }} PurseRecord
|
|
186
|
-
*
|
|
187
|
-
* }} MutableState
|
|
213
|
+
*
|
|
214
|
+
* @typedef {{}} MutableState
|
|
188
215
|
*/
|
|
189
216
|
|
|
190
217
|
/**
|
|
@@ -296,8 +323,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
296
323
|
(purse, helper) => ({ purse, helper }),
|
|
297
324
|
{
|
|
298
325
|
/**
|
|
299
|
-
* @param {{ value: Amount
|
|
300
|
-
* @param {
|
|
326
|
+
* @param {{ value: Amount; updateCount: bigint | undefined }} updateRecord
|
|
327
|
+
* @param {Notifier<Amount>} notifier
|
|
301
328
|
* @returns {void}
|
|
302
329
|
*/
|
|
303
330
|
onFulfilled(updateRecord, notifier) {
|
|
@@ -458,9 +485,10 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
458
485
|
|
|
459
486
|
// TODO move to top level so its type can be exported
|
|
460
487
|
/**
|
|
461
|
-
* Make the durable object to return, but taking some parameters that are
|
|
462
|
-
* This is necessary because the class kit
|
|
463
|
-
*
|
|
488
|
+
* Make the durable object to return, but taking some parameters that are
|
|
489
|
+
* awaited by a wrapping function. This is necessary because the class kit
|
|
490
|
+
* construction helpers, `initState` and `finish` run synchronously and the
|
|
491
|
+
* child storage node must be awaited until we have durable promises.
|
|
464
492
|
*/
|
|
465
493
|
const makeWalletWithResolvedStorageNodes = prepareExoClassKit(
|
|
466
494
|
baggage,
|
|
@@ -548,26 +576,24 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
548
576
|
// publish purse's balance and changes
|
|
549
577
|
const notifier = await E(purse).getCurrentAmountNotifier();
|
|
550
578
|
const startP = E(notifier).getUpdateSince(undefined);
|
|
551
|
-
// @ts-expect-error import watchPromise's type is unknown
|
|
552
579
|
watchPromise(startP, handler, notifier);
|
|
553
580
|
},
|
|
554
581
|
|
|
555
582
|
watchNextBalance(handler, notifier, updateCount) {
|
|
556
583
|
const nextP = E(notifier).getUpdateSince(updateCount);
|
|
557
|
-
// @ts-expect-error import watchPromise's type is unknown
|
|
558
584
|
watchPromise(nextP, handler, notifier);
|
|
559
585
|
},
|
|
560
586
|
|
|
561
587
|
/**
|
|
562
|
-
* Provide a purse given a NameHub of issuers and their
|
|
563
|
-
* brands.
|
|
588
|
+
* Provide a purse given a NameHub of issuers and their brands.
|
|
564
589
|
*
|
|
565
|
-
* We currently support only one NameHub, agoricNames, and
|
|
566
|
-
*
|
|
567
|
-
*
|
|
590
|
+
* We currently support only one NameHub, agoricNames, and hence one
|
|
591
|
+
* purse per brand. But we store an array of them to facilitate a
|
|
592
|
+
* transition to decentralized introductions.
|
|
568
593
|
*
|
|
569
594
|
* @param {Brand} brand
|
|
570
|
-
* @param {ERef<import('@agoric/vats').NameHub>} known - namehub with
|
|
595
|
+
* @param {ERef<import('@agoric/vats').NameHub>} known - namehub with
|
|
596
|
+
* brand, issuer branches
|
|
571
597
|
* @returns {Promise<Purse | undefined>} undefined if brand is not known
|
|
572
598
|
*/
|
|
573
599
|
async getPurseIfKnownBrand(brand, known) {
|
|
@@ -670,9 +696,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
670
696
|
const tempInvitation = invitationFromSpec(
|
|
671
697
|
offerSpec.invitationSpec,
|
|
672
698
|
);
|
|
673
|
-
invitationAmount =
|
|
674
|
-
tempInvitation
|
|
675
|
-
);
|
|
699
|
+
invitationAmount =
|
|
700
|
+
await E(invitationIssuer).getAmountOf(tempInvitation);
|
|
676
701
|
void E(invitationIssuer).burn(tempInvitation);
|
|
677
702
|
}
|
|
678
703
|
|
|
@@ -709,7 +734,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
709
734
|
void helper.watchPurse(invitationPurse);
|
|
710
735
|
},
|
|
711
736
|
|
|
712
|
-
/** @param {
|
|
737
|
+
/** @param {OfferStatus} offerStatus */
|
|
713
738
|
updateStatus(offerStatus) {
|
|
714
739
|
const { state, facets } = this;
|
|
715
740
|
facets.helper.logWalletInfo('offerStatus', offerStatus);
|
|
@@ -736,6 +761,13 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
736
761
|
}
|
|
737
762
|
}
|
|
738
763
|
},
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* @param {string} offerId
|
|
767
|
+
* @param {Amount<'set'>} invitationAmount
|
|
768
|
+
* @param {import('./types.js').InvitationMakers} invitationMakers
|
|
769
|
+
* @param {import('./types.js').PublicSubscribers} publicSubscribers
|
|
770
|
+
*/
|
|
739
771
|
async addContinuingOffer(
|
|
740
772
|
offerId,
|
|
741
773
|
invitationAmount,
|
|
@@ -763,7 +795,6 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
763
795
|
const { registry, invitationBrand } = shared;
|
|
764
796
|
|
|
765
797
|
if (registry.has(brand)) {
|
|
766
|
-
// @ts-expect-error virtual purse
|
|
767
798
|
return E(state.bank).getPurse(brand);
|
|
768
799
|
} else if (invitationBrand === brand) {
|
|
769
800
|
return state.invitationPurse;
|
|
@@ -809,7 +840,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
809
840
|
},
|
|
810
841
|
},
|
|
811
842
|
/**
|
|
812
|
-
* Similar to {DepositFacet} but async because it has to look up the
|
|
843
|
+
* Similar to {DepositFacet} but async because it has to look up the
|
|
844
|
+
* purse.
|
|
813
845
|
*/
|
|
814
846
|
deposit: {
|
|
815
847
|
/**
|
|
@@ -819,7 +851,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
819
851
|
*
|
|
820
852
|
* @param {Payment} payment
|
|
821
853
|
* @returns {Promise<Amount>}
|
|
822
|
-
* @throws if there's not yet a purse, though the payment is held to try
|
|
854
|
+
* @throws if there's not yet a purse, though the payment is held to try
|
|
855
|
+
* again when there is
|
|
823
856
|
*/
|
|
824
857
|
async receive(payment) {
|
|
825
858
|
const {
|
|
@@ -834,6 +867,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
834
867
|
// When there is a purse deposit into it
|
|
835
868
|
if (registry.has(brand)) {
|
|
836
869
|
const purse = E(bank).getPurse(brand);
|
|
870
|
+
// @ts-expect-error narrow assetKind to 'nat'
|
|
837
871
|
return E(purse).deposit(payment);
|
|
838
872
|
} else if (invitationBrand === brand) {
|
|
839
873
|
// @ts-expect-error narrow assetKind to 'set'
|
|
@@ -857,9 +891,11 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
857
891
|
|
|
858
892
|
payments: {
|
|
859
893
|
/**
|
|
860
|
-
* Withdraw the offered amount from the appropriate purse of this
|
|
894
|
+
* Withdraw the offered amount from the appropriate purse of this
|
|
895
|
+
* wallet.
|
|
861
896
|
*
|
|
862
|
-
* Save its amount in liveOfferPayments in case we need to reclaim the
|
|
897
|
+
* Save its amount in liveOfferPayments in case we need to reclaim the
|
|
898
|
+
* payment.
|
|
863
899
|
*
|
|
864
900
|
* @param {AmountKeywordRecord} give
|
|
865
901
|
* @param {OfferId} offerId
|
|
@@ -899,7 +935,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
899
935
|
},
|
|
900
936
|
|
|
901
937
|
/**
|
|
902
|
-
* Find the live payments for the offer and deposit them back in the
|
|
938
|
+
* Find the live payments for the offer and deposit them back in the
|
|
939
|
+
* appropriate purses.
|
|
903
940
|
*
|
|
904
941
|
* @param {OfferId} offerId
|
|
905
942
|
* @returns {Promise<Amount[]>}
|
|
@@ -940,11 +977,14 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
940
977
|
|
|
941
978
|
offers: {
|
|
942
979
|
/**
|
|
943
|
-
* Take an offer description provided in capData, augment it with
|
|
980
|
+
* Take an offer description provided in capData, augment it with
|
|
981
|
+
* payments and call zoe.offer()
|
|
944
982
|
*
|
|
945
983
|
* @param {OfferSpec} offerSpec
|
|
946
|
-
* @returns {Promise<void>} after the offer has been both seated and
|
|
947
|
-
*
|
|
984
|
+
* @returns {Promise<void>} after the offer has been both seated and
|
|
985
|
+
* exited by Zoe.
|
|
986
|
+
* @throws if any parts of the offer can be determined synchronously to
|
|
987
|
+
* be invalid
|
|
948
988
|
*/
|
|
949
989
|
async executeOffer(offerSpec) {
|
|
950
990
|
const { facets, state } = this;
|
|
@@ -956,6 +996,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
956
996
|
|
|
957
997
|
await null;
|
|
958
998
|
|
|
999
|
+
/** @type {UserSeat} */
|
|
959
1000
|
let seatRef;
|
|
960
1001
|
let watcher;
|
|
961
1002
|
try {
|
|
@@ -974,7 +1015,6 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
974
1015
|
|
|
975
1016
|
const invitation = invitationFromSpec(offerSpec.invitationSpec);
|
|
976
1017
|
|
|
977
|
-
// prettier-ignore
|
|
978
1018
|
const invitationAmount =
|
|
979
1019
|
await E(invitationIssuer).getAmountOf(invitation);
|
|
980
1020
|
|
|
@@ -1013,19 +1053,19 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1013
1053
|
|
|
1014
1054
|
// await so that any errors are caught and handled below
|
|
1015
1055
|
await watchOfferOutcomes(watcher, seatRef);
|
|
1016
|
-
} catch (
|
|
1056
|
+
} catch (reason) {
|
|
1017
1057
|
// This block only runs if the block above fails during one vat incarnation.
|
|
1018
|
-
facets.helper.logWalletError('IMMEDIATE OFFER ERROR:',
|
|
1058
|
+
facets.helper.logWalletError('IMMEDIATE OFFER ERROR:', reason);
|
|
1019
1059
|
|
|
1020
1060
|
// Update status to observers
|
|
1021
|
-
if (
|
|
1061
|
+
if (isUpgradeDisconnection(reason)) {
|
|
1022
1062
|
// The offer watchers will reconnect. Don't reclaim or exit
|
|
1023
1063
|
return;
|
|
1024
1064
|
} else if (watcher) {
|
|
1025
1065
|
// The watcher's onRejected will updateStatus()
|
|
1026
1066
|
} else {
|
|
1027
1067
|
facets.helper.updateStatus({
|
|
1028
|
-
error:
|
|
1068
|
+
error: reason.toString(),
|
|
1029
1069
|
...offerSpec,
|
|
1030
1070
|
});
|
|
1031
1071
|
}
|
|
@@ -1044,7 +1084,7 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1044
1084
|
|
|
1045
1085
|
// XXX tests rely on throwing immediate errors, not covering the
|
|
1046
1086
|
// error handling in the event the failure is after an upgrade
|
|
1047
|
-
throw
|
|
1087
|
+
throw reason;
|
|
1048
1088
|
}
|
|
1049
1089
|
},
|
|
1050
1090
|
/**
|
|
@@ -1074,9 +1114,11 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1074
1114
|
},
|
|
1075
1115
|
self: {
|
|
1076
1116
|
/**
|
|
1077
|
-
* Umarshals the actionCapData and delegates to the appropriate action
|
|
1117
|
+
* Umarshals the actionCapData and delegates to the appropriate action
|
|
1118
|
+
* handler.
|
|
1078
1119
|
*
|
|
1079
|
-
* @param {import('@endo/marshal').CapData<string>} actionCapData
|
|
1120
|
+
* @param {import('@endo/marshal').CapData<string | null>} actionCapData
|
|
1121
|
+
* of type BridgeAction
|
|
1080
1122
|
* @param {boolean} [canSpend]
|
|
1081
1123
|
* @returns {Promise<void>}
|
|
1082
1124
|
*/
|
|
@@ -1192,7 +1234,12 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1192
1234
|
);
|
|
1193
1235
|
|
|
1194
1236
|
/**
|
|
1195
|
-
* @param {Omit<
|
|
1237
|
+
* @param {Omit<
|
|
1238
|
+
* UniqueParams,
|
|
1239
|
+
* 'currentStorageNode' | 'walletStorageNode'
|
|
1240
|
+
* > & {
|
|
1241
|
+
* walletStorageNode: ERef<StorageNode>;
|
|
1242
|
+
* }} uniqueWithoutChildNodes
|
|
1196
1243
|
*/
|
|
1197
1244
|
const makeSmartWallet = async uniqueWithoutChildNodes => {
|
|
1198
1245
|
const [walletStorageNode, currentStorageNode] = await Promise.all([
|
package/src/typeGuards.d.ts
CHANGED
package/src/types.d.ts
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
* Downside is it can't reference any ambient types, which most of agoric-sdk type are presently.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { ERef
|
|
8
|
+
import type { ERef } from '@endo/far';
|
|
9
9
|
import type { CapData } from '@endo/marshal';
|
|
10
|
-
import type {
|
|
10
|
+
import type { agoric } from '@agoric/cosmic-proto';
|
|
11
11
|
import type { AgoricNamesRemotes } from '@agoric/vats/tools/board-utils.js';
|
|
12
|
+
import type { StoredFacet } from '@agoric/internal/src/lib-chainStorage.js';
|
|
12
13
|
import type { OfferSpec } from './offers.js';
|
|
13
14
|
|
|
14
15
|
declare const CapDataShape: unique symbol;
|
|
@@ -21,33 +22,33 @@ declare const CapDataShape: unique symbol;
|
|
|
21
22
|
*/
|
|
22
23
|
export type Petname = string | string[];
|
|
23
24
|
|
|
24
|
-
export type
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Record<string, (...args: any[]) => Promise<Invitation>>
|
|
25
|
+
export type InvitationMakers = Record<
|
|
26
|
+
string,
|
|
27
|
+
(...args: any[]) => Promise<Invitation>
|
|
28
28
|
>;
|
|
29
29
|
|
|
30
30
|
export type PublicSubscribers = Record<string, ERef<StoredFacet>>;
|
|
31
31
|
|
|
32
|
+
export interface ContinuingOfferResult {
|
|
33
|
+
invitationMakers: InvitationMakers;
|
|
34
|
+
publicSubscribers: PublicSubscribers;
|
|
35
|
+
}
|
|
36
|
+
|
|
32
37
|
export type Cell<T> = {
|
|
33
38
|
get: () => T;
|
|
34
39
|
set(val: T): void;
|
|
35
40
|
};
|
|
36
41
|
|
|
37
|
-
export type BridgeActionCapData = WalletCapData<
|
|
38
|
-
import('./smartWallet.js').BridgeAction
|
|
39
|
-
>;
|
|
40
|
-
|
|
41
42
|
/**
|
|
42
43
|
* Defined by walletAction struct in msg_server.go
|
|
43
44
|
*
|
|
44
|
-
* @see {
|
|
45
|
+
* @see {agoric.swingset.MsgWalletAction} and walletSpendAction in msg_server.go
|
|
45
46
|
*/
|
|
46
47
|
export type WalletActionMsg = {
|
|
47
48
|
type: 'WALLET_ACTION';
|
|
48
49
|
/** base64 of Uint8Array of bech32 data */
|
|
49
50
|
owner: string;
|
|
50
|
-
/** JSON of
|
|
51
|
+
/** JSON of marshalled BridgeAction */
|
|
51
52
|
action: string;
|
|
52
53
|
blockHeight: unknown; // int64
|
|
53
54
|
blockTime: unknown; // int64
|
|
@@ -56,7 +57,7 @@ export type WalletActionMsg = {
|
|
|
56
57
|
/**
|
|
57
58
|
* Defined by walletSpendAction struct in msg_server.go
|
|
58
59
|
*
|
|
59
|
-
* @see {MsgWalletSpendAction} and walletSpendAction in msg_server.go
|
|
60
|
+
* @see {agoric.swingset.MsgWalletSpendAction} and walletSpendAction in msg_server.go
|
|
60
61
|
*/
|
|
61
62
|
export type WalletSpendActionMsg = {
|
|
62
63
|
type: 'WALLET_SPEND_ACTION';
|
package/src/utils.d.ts
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
+
/** @import {OfferId, OfferStatus} from './offers.js'; */
|
|
1
2
|
export const NO_SMART_WALLET_ERROR: "no smart wallet";
|
|
2
|
-
export function makeWalletStateCoalescer(invitationBrand?: Brand<"set"> | undefined): {
|
|
3
|
+
export function makeWalletStateCoalescer(invitationBrand?: globalThis.Brand<"set"> | undefined): {
|
|
3
4
|
state: {
|
|
4
|
-
invitationsReceived: Map<
|
|
5
|
-
acceptedIn:
|
|
5
|
+
invitationsReceived: Map<OfferId, {
|
|
6
|
+
acceptedIn: OfferId;
|
|
6
7
|
description: string;
|
|
7
8
|
instance: Instance;
|
|
8
9
|
}>;
|
|
9
|
-
offerStatuses: Map<
|
|
10
|
-
balances: Map<Brand
|
|
10
|
+
offerStatuses: Map<OfferId, OfferStatus>;
|
|
11
|
+
balances: Map<globalThis.Brand, globalThis.Amount>;
|
|
11
12
|
};
|
|
12
|
-
update: (updateRecord: import(
|
|
13
|
+
update: (updateRecord: import("./smartWallet.js").UpdateRecord | {}) => void;
|
|
13
14
|
};
|
|
14
|
-
export function coalesceUpdates(updates: ERef<Subscriber<import(
|
|
15
|
-
invitationsReceived: Map<
|
|
16
|
-
acceptedIn:
|
|
15
|
+
export function coalesceUpdates(updates: ERef<Subscriber<import("./smartWallet.js").UpdateRecord>>, invitationBrand?: globalThis.Brand<"set"> | undefined): {
|
|
16
|
+
invitationsReceived: Map<OfferId, {
|
|
17
|
+
acceptedIn: OfferId;
|
|
17
18
|
description: string;
|
|
18
19
|
instance: Instance;
|
|
19
20
|
}>;
|
|
20
|
-
offerStatuses: Map<
|
|
21
|
-
balances: Map<Brand
|
|
21
|
+
offerStatuses: Map<OfferId, OfferStatus>;
|
|
22
|
+
balances: Map<globalThis.Brand, globalThis.Amount>;
|
|
22
23
|
};
|
|
23
|
-
export function assertHasData(follower: import(
|
|
24
|
-
export function objectMapStoragePath(subscribers?: import("@agoric/zoe/src/contractSupport").TopicsRecord | import("./types.js").PublicSubscribers | undefined): ERef<Record<string, string>> | null;
|
|
25
|
-
export type CoalescedWalletState = ReturnType<typeof makeWalletStateCoalescer>[
|
|
24
|
+
export function assertHasData(follower: import("@agoric/casting").Follower<any>): Promise<void>;
|
|
25
|
+
export function objectMapStoragePath(subscribers?: import("@agoric/zoe/src/contractSupport/topics.js").TopicsRecord | import("./types.js").PublicSubscribers | undefined): ERef<Record<string, string>> | null;
|
|
26
|
+
export type CoalescedWalletState = ReturnType<typeof makeWalletStateCoalescer>["state"];
|
|
27
|
+
import type { OfferId } from './offers.js';
|
|
28
|
+
import type { OfferStatus } from './offers.js';
|
|
26
29
|
//# sourceMappingURL=utils.d.ts.map
|
package/src/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["utils.js"],"names":[],"mappings":"AAIA,yDAAyD;AAEzD,sDAAuD;AAKhD;;;wBAYc,OAAO;yBACN,MAAM;sBACT,QAAQ;;;;;2BAOd,OAAO,kBAAkB,EAAE,YAAY,GAAG,EAAE;EAgExD;AAaM,yCAHI,IAAI,CAAC,UAAU,CAAC,OAAO,kBAAkB,EAAE,YAAY,CAAC,CAAC;;oBAnF/C,OAAO;qBACN,MAAM;kBACT,QAAQ;;;;EA6F1B;AAMM,wCAHI,OAAO,iBAAiB,EAAE,QAAQ,CAAC,GAAG,CAAC,iBAYjD;AASM,2KAFM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAW/C;mCAtDa,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC,OAAO,CAAC;6BA7F1B,aAAa;iCAAb,aAAa"}
|