@agoric/smart-wallet 0.5.4-ymax-v0.2-alpha-dev-8e37faa.0 → 0.6.0-u22.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/smart-wallet",
3
- "version": "0.5.4-ymax-v0.2-alpha-dev-8e37faa.0+8e37faa",
3
+ "version": "0.6.0-u22.1",
4
4
  "description": "Wallet contract",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -8,8 +8,9 @@
8
8
  "build": "yarn build:bundles",
9
9
  "build:bundles": "node ./scripts/build-bundles.js",
10
10
  "prepack": "yarn run -T tsc --build tsconfig.build.json",
11
- "postpack": "git clean -f '*.d.ts*' '*.tsbuildinfo'",
11
+ "postpack": "git clean -f '*.d.*ts*' '*.tsbuildinfo'",
12
12
  "test": "ava",
13
+ "test:c8": "c8 --all $C8_OPTIONS ava",
13
14
  "test:xs": "exit 0",
14
15
  "lint": "yarn run -T run-s --continue-on-error 'lint:*'",
15
16
  "lint-fix": "yarn lint:eslint --fix",
@@ -17,31 +18,32 @@
17
18
  "lint:eslint": "yarn run -T eslint ."
18
19
  },
19
20
  "devDependencies": {
20
- "@agoric/casting": "workspace:*",
21
- "@agoric/cosmic-proto": "workspace:*",
22
- "@agoric/swingset-vat": "workspace:*",
23
- "@endo/bundle-source": "^4.0.0",
24
- "@endo/captp": "^4.4.5",
25
- "@endo/init": "^1.1.9",
21
+ "@agoric/casting": "0.5.0-u22.1",
22
+ "@agoric/cosmic-proto": "0.5.0-u22.1",
23
+ "@agoric/swingset-vat": "0.33.0-u22.1",
24
+ "@endo/bundle-source": "^4.1.2",
25
+ "@endo/captp": "^4.4.8",
26
+ "@endo/init": "^1.1.12",
26
27
  "ava": "^5.3.0",
27
28
  "import-meta-resolve": "^4.1.0"
28
29
  },
29
30
  "dependencies": {
30
- "@agoric/ertp": "workspace:*",
31
- "@agoric/internal": "workspace:*",
32
- "@agoric/notifier": "workspace:*",
33
- "@agoric/store": "workspace:*",
34
- "@agoric/vat-data": "workspace:*",
35
- "@agoric/vats": "workspace:*",
36
- "@agoric/vow": "workspace:*",
37
- "@agoric/zoe": "workspace:*",
38
- "@agoric/zone": "workspace:*",
39
- "@endo/errors": "^1.2.10",
40
- "@endo/eventual-send": "^1.3.1",
41
- "@endo/far": "^1.1.11",
42
- "@endo/marshal": "^1.6.4",
43
- "@endo/nat": "^5.1.0",
44
- "@endo/promise-kit": "^1.1.10"
31
+ "@agoric/ertp": "0.17.0-u22.1",
32
+ "@agoric/internal": "0.4.0-u22.1",
33
+ "@agoric/notifier": "0.7.0-u22.1",
34
+ "@agoric/store": "0.10.0-u22.1",
35
+ "@agoric/vat-data": "0.6.0-u22.1",
36
+ "@agoric/vats": "0.16.0-u22.1",
37
+ "@agoric/vow": "0.2.0-u22.1",
38
+ "@agoric/zoe": "0.27.0-u22.1",
39
+ "@agoric/zone": "0.3.0-u22.1",
40
+ "@endo/errors": "^1.2.13",
41
+ "@endo/eventual-send": "^1.3.4",
42
+ "@endo/far": "^1.1.14",
43
+ "@endo/marshal": "^1.8.0",
44
+ "@endo/nat": "^5.1.3",
45
+ "@endo/patterns": "^1.7.0",
46
+ "@endo/promise-kit": "^1.1.13"
45
47
  },
46
48
  "files": [
47
49
  "src/"
@@ -72,5 +74,8 @@
72
74
  "typeCoverage": {
73
75
  "atLeast": 94.51
74
76
  },
75
- "gitHead": "8e37faaf5265f55433fc80e67c8785a66480c7f4"
77
+ "engines": {
78
+ "node": "^20.9 || ^22.11"
79
+ },
80
+ "gitHead": "83a42d0f343b01448a918631dce159b5bdb69b7e"
76
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAyEO,iDADK,QAAQ,cAKP,eAAe,QACf,QAAQ,oBAiBpB;AAmCM,6CAHI,OAAO,YACP,QAAQ;aAWO,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC;;;QAgBvD;;WAEG;yCADQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAQlC;;;;;WAKG;sCAJQ,MAAM,oBACN,MAAM,CAAC,KAAK,CAAC,oBACb,OAAO,YAAY,EAAE,gBAAgB,qBACrC,OAAO,YAAY,EAAE,iBAAiB;QAkBjD,uDAAuD;8BAA3C,QAAQ,GAAG,qBAAqB;QAoC5C;;;;;;WAMG;yBADQ,KAAK;;IAclB,gDAAgD;oBAArC,eAAe,CAAC,gBAAgB,CAAC;IA+B5C,+CAA+C;mBAApC,eAAe,CAAC,eAAe,CAAC;IA0B3C,iDAAiD;qBAAtC,eAAe,CAAC,iBAAiB,CAAC;GA2BlD;;;;gCA5SkB,CAAC,oBACP,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;8BAI7B;IACR,aAAa,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC7C,eAAe,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;CAC5D;+BAsSU,UAAU,CAAC,OAAO,mBAAmB,CAAC;2BACtC,UAAU,CAAC,gBAAgB,CAAC;8BArTV,aAAa;8BAC2B,aAAa;6BAF3D,kBAAkB;+BAJhB,aAAa;8BAEd,kBAAkB;2CADL,YAAY;oCAEnB,4BAA4B;2CAGW,aAAa"}
1
+ {"version":3,"file":"offerWatcher.d.ts","sourceRoot":"","sources":["offerWatcher.js"],"names":[],"mappings":"AAyEO,iDADK,QAAQ,cAKP,eAAe,QACf,QAAQ,oBAiBpB;AAmCM,6CAHI,OAAO,YACP,QAAQ;aAWO,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC;;;QAgBvD;;WAEG;yCADQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAQlC;;;;;WAKG;sCAJQ,MAAM,oBACN,MAAM,CAAC,KAAK,CAAC,oBACb,OAAO,YAAY,EAAE,gBAAgB,qBACrC,OAAO,YAAY,EAAE,iBAAiB;QAkBjD,uDAAuD;8BAA3C,QAAQ,GAAG,qBAAqB;QAoC5C;;;;;;WAMG;yBADQ,KAAK;;IAclB,gDAAgD;oBAArC,eAAe,CAAC,gBAAgB,CAAC;IA+B5C,+CAA+C;mBAApC,eAAe,CAAC,eAAe,CAAC;IAuC3C,iDAAiD;qBAAtC,eAAe,CAAC,iBAAiB,CAAC;GA2BlD;;;;gCAzTkB,CAAC,oBACP,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;8BAI7B;IACR,aAAa,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC7C,eAAe,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;CAC5D;+BAmTU,UAAU,CAAC,OAAO,mBAAmB,CAAC;2BACtC,UAAU,CAAC,gBAAgB,CAAC;8BAlUV,aAAa;8BAC2B,aAAa;6BAF3D,kBAAkB;+BAJhB,aAAa;8BAEd,kBAAkB;2CADL,YAAY;oCAEnB,4BAA4B;2CAGW,aAAa"}
@@ -274,7 +274,20 @@ export const prepareOfferWatcher = (baggage, vowTools) => {
274
274
  resultWatcher: {
275
275
  onFulfilled(result) {
276
276
  const { facets } = this;
277
- facets.helper.publishResult(result);
277
+ const { walletHelper } = this.state;
278
+ const { saveResult } = this.state.status;
279
+ if (saveResult) {
280
+ // Note: result is passable and storable since it was received from another vat
281
+ const name = walletHelper.saveEntry(saveResult, result);
282
+ facets.helper.updateStatus({
283
+ result: {
284
+ name,
285
+ passStyle: passStyleOf(result),
286
+ },
287
+ });
288
+ } else {
289
+ facets.helper.publishResult(result);
290
+ }
278
291
  },
279
292
  /**
280
293
  * If promise disconnected, watch again. Or if there's an Error, handle
package/src/offers.d.ts CHANGED
@@ -1,31 +1,81 @@
1
1
  /**
2
- * @import {InvitationDetails, Proposal} from '@agoric/zoe';
2
+ * @import {Proposal} from '@agoric/zoe';
3
+ * @import {Passable} from '@endo/pass-style';
3
4
  */
4
5
  /**
5
6
  * @typedef {number | string} OfferId
6
7
  */
8
+ /**
9
+ * @typedef {object} ResultPlan
10
+ * @property {string} name by which to save the item
11
+ * @property {boolean} [overwrite=false] whether to overwrite an existing item.
12
+ * If false and there is a conflict, the contract will autogen a similar
13
+ * name.
14
+ */
15
+ /**
16
+ * @typedef {{
17
+ * targetName: string;
18
+ * method: string;
19
+ * args: Passable[];
20
+ * saveResult?: ResultPlan;
21
+ * id?: number | string;
22
+ * }} InvokeEntryMessage
23
+ */
7
24
  /**
8
25
  * @typedef {{
9
26
  * id: OfferId;
10
27
  * invitationSpec: import('./invitations.js').InvitationSpec;
11
28
  * proposal: Proposal;
12
29
  * offerArgs?: any;
30
+ * saveResult?: ResultPlan;
13
31
  * }} OfferSpec
32
+ * If `saveResult` is provided, the result of the invocation will be saved to
33
+ * the specified location. Otherwise it will be published directly to vstorage
34
+ * (or 'UNPUBLISHED' if it cannot be).
14
35
  */
15
36
  /** Value for "result" field when the result can't be published */
16
37
  export const UNPUBLISHED_RESULT: "UNPUBLISHED";
17
38
  export type OfferId = number | string;
39
+ export type ResultPlan = {
40
+ /**
41
+ * by which to save the item
42
+ */
43
+ name: string;
44
+ /**
45
+ * whether to overwrite an existing item.
46
+ * If false and there is a conflict, the contract will autogen a similar
47
+ * name.
48
+ */
49
+ overwrite?: boolean | undefined;
50
+ };
51
+ export type InvokeEntryMessage = {
52
+ targetName: string;
53
+ method: string;
54
+ args: Passable[];
55
+ saveResult?: ResultPlan;
56
+ id?: number | string;
57
+ };
58
+ /**
59
+ * If `saveResult` is provided, the result of the invocation will be saved to
60
+ * the specified location. Otherwise it will be published directly to vstorage
61
+ * (or 'UNPUBLISHED' if it cannot be).
62
+ */
18
63
  export type OfferSpec = {
19
64
  id: OfferId;
20
65
  invitationSpec: import("./invitations.js").InvitationSpec;
21
66
  proposal: Proposal;
22
67
  offerArgs?: any;
68
+ saveResult?: ResultPlan;
23
69
  };
24
70
  export type OfferStatus = OfferSpec & {
25
71
  error?: string;
26
72
  numWantsSatisfied?: number;
27
- result?: unknown | typeof UNPUBLISHED_RESULT;
73
+ result?: unknown | typeof UNPUBLISHED_RESULT | {
74
+ name: string;
75
+ passStyle: string;
76
+ };
28
77
  payouts?: AmountKeywordRecord;
29
78
  };
79
+ import type { Passable } from '@endo/pass-style';
30
80
  import type { Proposal } from '@agoric/zoe';
31
81
  //# sourceMappingURL=offers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AAEH;;;;;;;GAOG;AAEH,kEAAkE;AAClE,iCAAkC,aAAa,CAAC;sBAbnC,MAAM,GAAG,MAAM;wBAIf;IACR,EAAE,EAAE,OAAO,CAAC;IACZ,cAAc,EAAE,OAAO,kBAAkB,EAAE,cAAc,CAAC;IAC1D,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;0BAOS,SAAS,GAAG;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,kBAAkB,CAAC;IAC7C,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;8BAzB0C,aAAa"}
1
+ {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH;;;;;;GAMG;AAEH;;;;;;;;GAQG;AAEH;;;;;;;;;;;GAWG;AAEH,kEAAkE;AAClE,iCAAkC,aAAa,CAAC;sBAnCnC,MAAM,GAAG,MAAM;;;;;UAKd,MAAM;;;;;;;;iCAOP;IACR,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;;;;;;wBAIS;IACR,EAAE,EAAE,OAAO,CAAC;IACZ,cAAc,EAAE,OAAO,kBAAkB,EAAE,cAAc,CAAC;IAC1D,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;0BAUS,SAAS,GAAG;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EACH,OAAO,GACP,OAAO,kBAAkB,GACzB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;8BAlDuB,kBAAkB;8BADlB,aAAa"}
package/src/offers.js CHANGED
@@ -1,18 +1,41 @@
1
1
  /**
2
- * @import {InvitationDetails, Proposal} from '@agoric/zoe';
2
+ * @import {Proposal} from '@agoric/zoe';
3
+ * @import {Passable} from '@endo/pass-style';
3
4
  */
4
5
 
5
6
  /**
6
7
  * @typedef {number | string} OfferId
7
8
  */
8
9
 
10
+ /**
11
+ * @typedef {object} ResultPlan
12
+ * @property {string} name by which to save the item
13
+ * @property {boolean} [overwrite=false] whether to overwrite an existing item.
14
+ * If false and there is a conflict, the contract will autogen a similar
15
+ * name.
16
+ */
17
+
18
+ /**
19
+ * @typedef {{
20
+ * targetName: string;
21
+ * method: string;
22
+ * args: Passable[];
23
+ * saveResult?: ResultPlan;
24
+ * id?: number | string;
25
+ * }} InvokeEntryMessage
26
+ */
27
+
9
28
  /**
10
29
  * @typedef {{
11
30
  * id: OfferId;
12
31
  * invitationSpec: import('./invitations.js').InvitationSpec;
13
32
  * proposal: Proposal;
14
33
  * offerArgs?: any;
34
+ * saveResult?: ResultPlan;
15
35
  * }} OfferSpec
36
+ * If `saveResult` is provided, the result of the invocation will be saved to
37
+ * the specified location. Otherwise it will be published directly to vstorage
38
+ * (or 'UNPUBLISHED' if it cannot be).
16
39
  */
17
40
 
18
41
  /** Value for "result" field when the result can't be published */
@@ -22,7 +45,10 @@ export const UNPUBLISHED_RESULT = 'UNPUBLISHED';
22
45
  * @typedef {OfferSpec & {
23
46
  * error?: string;
24
47
  * numWantsSatisfied?: number;
25
- * result?: unknown | typeof UNPUBLISHED_RESULT;
48
+ * result?:
49
+ * | unknown
50
+ * | typeof UNPUBLISHED_RESULT
51
+ * | { name: string; passStyle: string };
26
52
  * payouts?: AmountKeywordRecord;
27
53
  * }} OfferStatus
28
54
  */
@@ -25,6 +25,12 @@ export function prepareSmartWallet(baggage: import("@agoric/vat-data").Baggage,
25
25
  */
26
26
  receive(payment: Payment): Promise<Amount>;
27
27
  }>;
28
+ getInvokeFacet(): import("@endo/exo").Guarded<{
29
+ /**
30
+ * @param {InvokeEntryMessage} message
31
+ */
32
+ invokeEntry(message: InvokeEntryMessage): Promise<void>;
33
+ }>;
28
34
  getOffersFacet(): import("@endo/exo").Guarded<{
29
35
  /**
30
36
  * Take an offer description provided in capData, augment it with
@@ -63,13 +69,6 @@ export function prepareSmartWallet(baggage: import("@agoric/vat-data").Baggage,
63
69
  };
64
70
  };
65
71
  }>>;
66
- export type OfferId = number | string;
67
- export type OfferSpec = {
68
- id: OfferId;
69
- invitationSpec: import("./invitations").InvitationSpec;
70
- proposal: Proposal;
71
- offerArgs?: any;
72
- };
73
72
  export type ExecutorPowers = {
74
73
  logger: {
75
74
  info: (...args: any[]) => void;
@@ -86,7 +85,17 @@ export type TryExitOfferAction = {
86
85
  method: "tryExitOffer";
87
86
  offerId: OfferId;
88
87
  };
89
- export type BridgeAction = ExecuteOfferAction | TryExitOfferAction;
88
+ export type InvokeStoreEntryAction = {
89
+ /**
90
+ * BridgeAction discriminator
91
+ */
92
+ method: "invokeEntry";
93
+ /**
94
+ * object method call to make
95
+ */
96
+ message: InvokeEntryMessage;
97
+ };
98
+ export type BridgeAction = ExecuteOfferAction | TryExitOfferAction | InvokeStoreEntryAction;
90
99
  /**
91
100
  * Purses is an array to support a future requirement of multiple purses per
92
101
  * brand.
@@ -145,6 +154,14 @@ export type UpdateRecord = {
145
154
  status: {
146
155
  error: string;
147
156
  };
157
+ } | {
158
+ updated: "invocation";
159
+ id: string | number;
160
+ error?: string;
161
+ result?: {
162
+ name?: string;
163
+ passStyle: string;
164
+ };
148
165
  };
149
166
  /**
150
167
  * For use by clients to describe brands to users. Includes `displayInfo` to
@@ -194,6 +211,7 @@ export type ImmutableState = Readonly<UniqueParams & {
194
211
  liveOffers: MapStore<OfferId, OfferStatus>;
195
212
  liveOfferSeats: MapStore<OfferId, UserSeat<unknown>>;
196
213
  liveOfferPayments: MapStore<OfferId, MapStore<Brand, Payment>>;
214
+ myStore: MapStore;
197
215
  }>;
198
216
  export type PurseRecord = BrandDescriptor & {
199
217
  purse: Purse;
@@ -202,8 +220,9 @@ export type MutableState = {};
202
220
  export type SmartWallet = EReturn<EReturn<typeof prepareSmartWallet>>;
203
221
  import type { Payment } from '@agoric/ertp';
204
222
  import type { Amount } from '@agoric/ertp';
223
+ import type { InvokeEntryMessage } from './offers.js';
224
+ import type { OfferSpec } from './offers.js';
205
225
  import type { OfferId } from './offers.js';
206
- import type { Proposal } from '@agoric/zoe';
207
226
  import type { Brand } from '@agoric/ertp';
208
227
  import type { OfferStatus } from './offers.js';
209
228
  import type { Issuer } from '@agoric/ertp';
@@ -1 +1 @@
1
- {"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Fail, q } from '@endo/errors';
2
- import { E } from '@endo/far';
2
+ import { E, passStyleOf } from '@endo/far';
3
3
  import {
4
4
  AmountShape,
5
5
  BrandShape,
@@ -49,8 +49,9 @@ import { prepareOfferWatcher, makeWatchOfferOutcomes } from './offerWatcher.js';
49
49
  * @import {Amount, Brand, Issuer, Payment, Purse} from '@agoric/ertp';
50
50
  * @import {WeakMapStore, MapStore} from '@agoric/store'
51
51
  * @import {InvitationDetails, PaymentPKeywordRecord, Proposal, UserSeat} from '@agoric/zoe';
52
+ * @import {CopyRecord} from '@endo/pass-style';
52
53
  * @import {EReturn} from '@endo/far';
53
- * @import {OfferId, OfferStatus} from './offers.js';
54
+ * @import {OfferId, OfferStatus, OfferSpec, InvokeEntryMessage, ResultPlan} from './offers.js';
54
55
  */
55
56
 
56
57
  const trace = makeTracer('SmrtWlt');
@@ -60,17 +61,6 @@ const trace = makeTracer('SmrtWlt');
60
61
  * @see {@link ../README.md} }
61
62
  */
62
63
 
63
- /** @typedef {number | string} OfferId */
64
-
65
- /**
66
- * @typedef {{
67
- * id: OfferId;
68
- * invitationSpec: import('./invitations').InvitationSpec;
69
- * proposal: Proposal;
70
- * offerArgs?: any;
71
- * }} OfferSpec
72
- */
73
-
74
64
  /**
75
65
  * @typedef {{
76
66
  * logger: {
@@ -96,10 +86,16 @@ const trace = makeTracer('SmrtWlt');
96
86
  * }} TryExitOfferAction
97
87
  */
98
88
 
89
+ /**
90
+ * @typedef {object} InvokeStoreEntryAction
91
+ * @property {'invokeEntry'} method BridgeAction discriminator
92
+ * @property {InvokeEntryMessage} message object method call to make
93
+ */
94
+
99
95
  // Discriminated union. Possible future messages types:
100
96
  // maybe suggestIssuer for https://github.com/Agoric/agoric-sdk/issues/6132
101
97
  // setting petnames and adding brands for https://github.com/Agoric/agoric-sdk/issues/6126
102
- /** @typedef {ExecuteOfferAction | TryExitOfferAction} BridgeAction */
98
+ /** @typedef {ExecuteOfferAction | TryExitOfferAction | InvokeStoreEntryAction} BridgeAction */
103
99
 
104
100
  /**
105
101
  * Purses is an array to support a future requirement of multiple purses per
@@ -138,7 +134,13 @@ const trace = makeTracer('SmrtWlt');
138
134
  /**
139
135
  * @typedef {{ updated: 'offerStatus'; status: OfferStatus }
140
136
  * | { updated: 'balance'; currentAmount: Amount }
141
- * | { updated: 'walletAction'; status: { error: string } }} UpdateRecord
137
+ * | { updated: 'walletAction'; status: { error: string } }
138
+ * | {
139
+ * updated: 'invocation';
140
+ * id: string | number;
141
+ * error?: string;
142
+ * result?: { name?: string; passStyle: string };
143
+ * }} UpdateRecord
142
144
  * Record of an update to the state of this wallet.
143
145
  *
144
146
  * Client is responsible for coalescing updates into a current state. See
@@ -211,6 +213,7 @@ const trace = makeTracer('SmrtWlt');
211
213
  * liveOffers: MapStore<OfferId, OfferStatus>;
212
214
  * liveOfferSeats: MapStore<OfferId, UserSeat<unknown>>;
213
215
  * liveOfferPayments: MapStore<OfferId, MapStore<Brand, Payment>>;
216
+ * myStore: MapStore;
214
217
  * }
215
218
  * >} ImmutableState
216
219
  *
@@ -400,6 +403,9 @@ export const prepareSmartWallet = (baggage, shared) => {
400
403
  durable: true,
401
404
  },
402
405
  ),
406
+ // NB: Wallets before this state property was added do not support
407
+ // saving results or invoking the saved items.
408
+ myStore: zone.detached().mapStore('my items'),
403
409
  };
404
410
 
405
411
  /** @type {import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<UpdateRecord>} */
@@ -432,6 +438,11 @@ export const prepareSmartWallet = (baggage, shared) => {
432
438
  };
433
439
  };
434
440
 
441
+ const invocationResultShape = M.splitRecord(
442
+ {},
443
+ { id: M.or(M.string(), M.number()), saveResult: shape.ResultPlan },
444
+ );
445
+
435
446
  const behaviorGuards = {
436
447
  helper: M.interface('helperFacetI', {
437
448
  assertUniqueOfferId: M.call(M.string()).returns(),
@@ -453,6 +464,8 @@ export const prepareSmartWallet = (baggage, shared) => {
453
464
  logWalletInfo: M.call().rest(M.arrayOf(M.any())).returns(),
454
465
  logWalletError: M.call().rest(M.arrayOf(M.any())).returns(),
455
466
  getLiveOfferPayments: M.call().returns(M.remotable('mapStore')),
467
+ saveEntry: M.call(shape.ResultPlan, M.any()).returns(M.string()),
468
+ findUnusedName: M.call(M.string()).returns(M.string()),
456
469
  }),
457
470
 
458
471
  deposit: M.interface('depositFacetI', {
@@ -471,11 +484,19 @@ export const prepareSmartWallet = (baggage, shared) => {
471
484
  executeOffer: M.call(shape.OfferSpec).returns(M.promise()),
472
485
  tryExitOffer: M.call(M.scalar()).returns(M.promise()),
473
486
  }),
487
+ invoke: M.interface('invoke', {
488
+ invokeEntry: M.callWhen(shape.InvokeEntryMessage).returns(),
489
+ }),
490
+ resultStepWatcher: M.interface('resultStepWatcher', {
491
+ onFulfilled: M.call(M.any(), invocationResultShape).returns(),
492
+ onRejected: M.call(M.any(), invocationResultShape).returns(),
493
+ }),
474
494
  self: M.interface('selfFacetI', {
475
495
  handleBridgeAction: M.call(shape.StringCapData, M.boolean()).returns(
476
496
  M.promise(),
477
497
  ),
478
498
  getDepositFacet: M.call().returns(M.remotable()),
499
+ getInvokeFacet: M.call().returns(M.remotable()),
479
500
  getOffersFacet: M.call().returns(M.remotable()),
480
501
  getCurrentSubscriber: M.call().returns(SubscriberShape),
481
502
  getUpdatesSubscriber: M.call().returns(SubscriberShape),
@@ -745,6 +766,35 @@ export const prepareSmartWallet = (baggage, shared) => {
745
766
  }
746
767
  return baggage.get(state.address);
747
768
  },
769
+ /** @param {string} suggestion */
770
+ findUnusedName(suggestion) {
771
+ const { myStore } = this.state;
772
+ let nonce = 0;
773
+ let name = suggestion;
774
+ while (myStore.has(name)) {
775
+ nonce += myStore.getSize(); // avoid linear work
776
+ name = `${suggestion}.${nonce}`;
777
+ }
778
+ return name;
779
+ },
780
+ /**
781
+ * @param {ResultPlan} plan
782
+ * @param {unknown} value
783
+ */
784
+ saveEntry(plan, value) {
785
+ const { myStore } = this.state;
786
+ const name = plan.overwrite
787
+ ? plan.name
788
+ : this.facets.helper.findUnusedName(plan.name);
789
+
790
+ if (myStore.has(name)) {
791
+ myStore.set(name, value);
792
+ } else {
793
+ myStore.init(name, value);
794
+ }
795
+ trace('set', name, '=', value);
796
+ return name;
797
+ },
748
798
  },
749
799
  /**
750
800
  * Similar to {DepositFacet} but async because it has to look up the
@@ -1019,6 +1069,78 @@ export const prepareSmartWallet = (baggage, shared) => {
1019
1069
  await E(seatRef).tryExit();
1020
1070
  },
1021
1071
  },
1072
+
1073
+ invoke: {
1074
+ /**
1075
+ * @param {InvokeEntryMessage} message
1076
+ */
1077
+ async invokeEntry(message) {
1078
+ trace('invokeEntry', message);
1079
+ const { myStore } = this.state;
1080
+ const { resultStepWatcher } = this.facets;
1081
+
1082
+ const { targetName: name, method, args, saveResult, id } = message;
1083
+ myStore.has(name) || Fail`cannot invoke ${q(name)}: no such item`;
1084
+ const value = myStore.get(name);
1085
+ trace('entry', name, value);
1086
+ trace('invoke', value, '.', method, '(', args, ')');
1087
+ if (id) {
1088
+ const { updateRecorderKit } = this.state;
1089
+ void updateRecorderKit.recorder.write({
1090
+ updated: 'invocation',
1091
+ id,
1092
+ });
1093
+ }
1094
+ const callP = E(value)[method](...args);
1095
+ if (id || saveResult) {
1096
+ vowTools.watch(callP, resultStepWatcher, { id, saveResult });
1097
+ } else {
1098
+ void callP;
1099
+ }
1100
+ },
1101
+ },
1102
+
1103
+ resultStepWatcher: {
1104
+ /**
1105
+ * @param {unknown} result
1106
+ * @param {{ id?: string | number; saveResult?: ResultPlan }} opts
1107
+ */
1108
+ onFulfilled(result, opts) {
1109
+ trace('resultStepWatcher opts', opts);
1110
+ const { id, saveResult } = opts;
1111
+ if (saveResult) {
1112
+ this.facets.helper.saveEntry(saveResult, result);
1113
+ }
1114
+ const passStyle = passStyleOf(result);
1115
+ const { updateRecorderKit } = this.state;
1116
+ if (id) {
1117
+ void updateRecorderKit.recorder.write({
1118
+ updated: 'invocation',
1119
+ id,
1120
+ result: {
1121
+ ...(saveResult?.name ? { name: saveResult.name } : {}),
1122
+ passStyle,
1123
+ },
1124
+ });
1125
+ }
1126
+ },
1127
+ /**
1128
+ * @param {unknown} reason
1129
+ * @param {{ id: string | number; saveResult?: ResultPlan }} opts
1130
+ */
1131
+ onRejected(reason, opts) {
1132
+ trace('rejected', reason, opts);
1133
+ if (opts.id) {
1134
+ const { updateRecorderKit } = this.state;
1135
+ void updateRecorderKit.recorder.write({
1136
+ updated: 'invocation',
1137
+ id: opts.id,
1138
+ error: String(reason),
1139
+ });
1140
+ }
1141
+ },
1142
+ },
1143
+
1022
1144
  self: {
1023
1145
  /**
1024
1146
  * Umarshals the actionCapData and delegates to the appropriate action
@@ -1030,8 +1152,8 @@ export const prepareSmartWallet = (baggage, shared) => {
1030
1152
  * @returns {Promise<void>}
1031
1153
  */
1032
1154
  handleBridgeAction(actionCapData, canSpend = false) {
1033
- const { facets } = this;
1034
- const { offers } = facets;
1155
+ const { facets, state } = this;
1156
+ const { offers, invoke } = facets;
1035
1157
  const { publicMarshaller } = shared;
1036
1158
 
1037
1159
  /** @param {Error} err */
@@ -1044,6 +1166,8 @@ export const prepareSmartWallet = (baggage, shared) => {
1044
1166
  });
1045
1167
  };
1046
1168
 
1169
+ const walletHasNameHub = 'myStore' in state && state.myStore != null;
1170
+
1047
1171
  // use E.when to retain distributed stack trace
1048
1172
  return E.when(
1049
1173
  E(publicMarshaller).fromCapData(actionCapData),
@@ -1053,12 +1177,21 @@ export const prepareSmartWallet = (baggage, shared) => {
1053
1177
  switch (action.method) {
1054
1178
  case 'executeOffer': {
1055
1179
  canSpend || Fail`executeOffer requires spend authority`;
1180
+ if (action.offer.saveResult != null && !walletHasNameHub) {
1181
+ Fail`executeOffer saveResult requires a new smart wallet with myStore`;
1182
+ }
1183
+
1056
1184
  return offers.executeOffer(action.offer);
1057
1185
  }
1058
1186
  case 'tryExitOffer': {
1059
1187
  assert(canSpend, 'tryExitOffer requires spend authority');
1060
1188
  return offers.tryExitOffer(action.offerId);
1061
1189
  }
1190
+ case 'invokeEntry': {
1191
+ walletHasNameHub ||
1192
+ Fail`invokeEntry requires a new smart wallet with myStore`;
1193
+ return invoke.invokeEntry(action.message);
1194
+ }
1062
1195
  default: {
1063
1196
  throw Fail`invalid handle bridge action ${q(action)}`;
1064
1197
  }
@@ -1077,6 +1210,9 @@ export const prepareSmartWallet = (baggage, shared) => {
1077
1210
  getDepositFacet() {
1078
1211
  return this.facets.deposit;
1079
1212
  },
1213
+ getInvokeFacet() {
1214
+ return this.facets.invoke;
1215
+ },
1080
1216
  getOffersFacet() {
1081
1217
  return this.facets.offers;
1082
1218
  },
package/src/typeGuards.js CHANGED
@@ -4,6 +4,28 @@ import {
4
4
  ProposalShape,
5
5
  } from '@agoric/zoe/src/typeGuards.js';
6
6
 
7
+ /**
8
+ * @import {TypedPattern} from '@agoric/internal';
9
+ * @import {InvokeEntryMessage, ResultPlan} from './offers';
10
+ */
11
+
12
+ /** @type {TypedPattern<ResultPlan>} */
13
+ const ResultPlanShape = M.splitRecord(
14
+ { name: M.string() },
15
+ { overwrite: M.boolean() },
16
+ {},
17
+ );
18
+ /** @type {TypedPattern<InvokeEntryMessage>} */
19
+ const InvokeEntryMessageShape = M.splitRecord(
20
+ {
21
+ targetName: M.string(),
22
+ method: M.string(),
23
+ args: M.array(),
24
+ },
25
+ { saveResult: ResultPlanShape, id: M.or(M.number(), M.string()) },
26
+ {},
27
+ );
28
+
7
29
  export const shape = {
8
30
  // smartWallet
9
31
  StringCapData: {
@@ -51,8 +73,14 @@ export const shape = {
51
73
  invitationSpec: M.any(),
52
74
  proposal: ProposalShape,
53
75
  },
54
- { offerArgs: M.any() },
76
+ {
77
+ offerArgs: M.any(),
78
+ saveResult: ResultPlanShape,
79
+ },
80
+ {},
55
81
  ),
82
+ ResultPlan: ResultPlanShape,
83
+ InvokeEntryMessage: InvokeEntryMessageShape,
56
84
 
57
85
  // walletFactory
58
86
  /**