@agoric/smart-wallet 0.5.4-dev-c658d31.0.c658d31 → 0.5.4-dev-58c131c.0.58c131c
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 +16 -14
- package/src/offerWatcher.d.ts.map +1 -1
- package/src/offerWatcher.js +14 -1
- package/src/offers.d.ts +50 -2
- package/src/offers.d.ts.map +1 -1
- package/src/offers.js +27 -2
- package/src/smartWallet.d.ts +20 -9
- package/src/smartWallet.d.ts.map +1 -1
- package/src/smartWallet.js +106 -15
- package/src/typeGuards.js +29 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/smart-wallet",
|
|
3
|
-
"version": "0.5.4-dev-
|
|
3
|
+
"version": "0.5.4-dev-58c131c.0.58c131c",
|
|
4
4
|
"description": "Wallet contract",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"prepack": "yarn run -T tsc --build tsconfig.build.json",
|
|
11
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,9 +18,9 @@
|
|
|
17
18
|
"lint:eslint": "yarn run -T eslint ."
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
|
-
"@agoric/casting": "0.4.3-dev-
|
|
21
|
-
"@agoric/cosmic-proto": "0.4.1-dev-
|
|
22
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
21
|
+
"@agoric/casting": "0.4.3-dev-58c131c.0.58c131c",
|
|
22
|
+
"@agoric/cosmic-proto": "0.4.1-dev-58c131c.0.58c131c",
|
|
23
|
+
"@agoric/swingset-vat": "0.32.3-dev-58c131c.0.58c131c",
|
|
23
24
|
"@endo/bundle-source": "^4.1.2",
|
|
24
25
|
"@endo/captp": "^4.4.8",
|
|
25
26
|
"@endo/init": "^1.1.12",
|
|
@@ -27,20 +28,21 @@
|
|
|
27
28
|
"import-meta-resolve": "^4.1.0"
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@agoric/ertp": "0.16.3-dev-
|
|
31
|
-
"@agoric/internal": "0.3.3-dev-
|
|
32
|
-
"@agoric/notifier": "0.6.3-dev-
|
|
33
|
-
"@agoric/store": "0.9.3-dev-
|
|
34
|
-
"@agoric/vat-data": "0.5.3-dev-
|
|
35
|
-
"@agoric/vats": "0.15.2-dev-
|
|
36
|
-
"@agoric/vow": "0.1.1-dev-
|
|
37
|
-
"@agoric/zoe": "0.26.3-dev-
|
|
38
|
-
"@agoric/zone": "0.2.3-dev-
|
|
31
|
+
"@agoric/ertp": "0.16.3-dev-58c131c.0.58c131c",
|
|
32
|
+
"@agoric/internal": "0.3.3-dev-58c131c.0.58c131c",
|
|
33
|
+
"@agoric/notifier": "0.6.3-dev-58c131c.0.58c131c",
|
|
34
|
+
"@agoric/store": "0.9.3-dev-58c131c.0.58c131c",
|
|
35
|
+
"@agoric/vat-data": "0.5.3-dev-58c131c.0.58c131c",
|
|
36
|
+
"@agoric/vats": "0.15.2-dev-58c131c.0.58c131c",
|
|
37
|
+
"@agoric/vow": "0.1.1-dev-58c131c.0.58c131c",
|
|
38
|
+
"@agoric/zoe": "0.26.3-dev-58c131c.0.58c131c",
|
|
39
|
+
"@agoric/zone": "0.2.3-dev-58c131c.0.58c131c",
|
|
39
40
|
"@endo/errors": "^1.2.13",
|
|
40
41
|
"@endo/eventual-send": "^1.3.4",
|
|
41
42
|
"@endo/far": "^1.1.14",
|
|
42
43
|
"@endo/marshal": "^1.8.0",
|
|
43
44
|
"@endo/nat": "^5.1.3",
|
|
45
|
+
"@endo/patterns": "^1.7.0",
|
|
44
46
|
"@endo/promise-kit": "^1.1.13"
|
|
45
47
|
},
|
|
46
48
|
"files": [
|
|
@@ -72,5 +74,5 @@
|
|
|
72
74
|
"typeCoverage": {
|
|
73
75
|
"atLeast": 94.51
|
|
74
76
|
},
|
|
75
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "58c131c9c15c6332a869028df690eec5be42a873"
|
|
76
78
|
}
|
|
@@ -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;
|
|
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"}
|
package/src/offerWatcher.js
CHANGED
|
@@ -274,7 +274,20 @@ export const prepareOfferWatcher = (baggage, vowTools) => {
|
|
|
274
274
|
resultWatcher: {
|
|
275
275
|
onFulfilled(result) {
|
|
276
276
|
const { facets } = this;
|
|
277
|
-
|
|
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,79 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
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
|
+
* }} InvokeEntryMessage
|
|
22
|
+
*/
|
|
7
23
|
/**
|
|
8
24
|
* @typedef {{
|
|
9
25
|
* id: OfferId;
|
|
10
26
|
* invitationSpec: import('./invitations.js').InvitationSpec;
|
|
11
27
|
* proposal: Proposal;
|
|
12
28
|
* offerArgs?: any;
|
|
29
|
+
* saveResult?: ResultPlan;
|
|
13
30
|
* }} OfferSpec
|
|
31
|
+
* If `saveResult` is provided, the result of the invocation will be saved to
|
|
32
|
+
* the specified location. Otherwise it will be published directly to vstorage
|
|
33
|
+
* (or 'UNPUBLISHED' if it cannot be).
|
|
14
34
|
*/
|
|
15
35
|
/** Value for "result" field when the result can't be published */
|
|
16
36
|
export const UNPUBLISHED_RESULT: "UNPUBLISHED";
|
|
17
37
|
export type OfferId = number | string;
|
|
38
|
+
export type ResultPlan = {
|
|
39
|
+
/**
|
|
40
|
+
* by which to save the item
|
|
41
|
+
*/
|
|
42
|
+
name: string;
|
|
43
|
+
/**
|
|
44
|
+
* whether to overwrite an existing item.
|
|
45
|
+
* If false and there is a conflict, the contract will autogen a similar
|
|
46
|
+
* name.
|
|
47
|
+
*/
|
|
48
|
+
overwrite?: boolean | undefined;
|
|
49
|
+
};
|
|
50
|
+
export type InvokeEntryMessage = {
|
|
51
|
+
targetName: string;
|
|
52
|
+
method: string;
|
|
53
|
+
args: Passable[];
|
|
54
|
+
saveResult?: ResultPlan;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* If `saveResult` is provided, the result of the invocation will be saved to
|
|
58
|
+
* the specified location. Otherwise it will be published directly to vstorage
|
|
59
|
+
* (or 'UNPUBLISHED' if it cannot be).
|
|
60
|
+
*/
|
|
18
61
|
export type OfferSpec = {
|
|
19
62
|
id: OfferId;
|
|
20
63
|
invitationSpec: import("./invitations.js").InvitationSpec;
|
|
21
64
|
proposal: Proposal;
|
|
22
65
|
offerArgs?: any;
|
|
66
|
+
saveResult?: ResultPlan;
|
|
23
67
|
};
|
|
24
68
|
export type OfferStatus = OfferSpec & {
|
|
25
69
|
error?: string;
|
|
26
70
|
numWantsSatisfied?: number;
|
|
27
|
-
result?: unknown | typeof UNPUBLISHED_RESULT
|
|
71
|
+
result?: unknown | typeof UNPUBLISHED_RESULT | {
|
|
72
|
+
name: string;
|
|
73
|
+
passStyle: string;
|
|
74
|
+
};
|
|
28
75
|
payouts?: AmountKeywordRecord;
|
|
29
76
|
};
|
|
77
|
+
import type { Passable } from '@endo/pass-style';
|
|
30
78
|
import type { Proposal } from '@agoric/zoe';
|
|
31
79
|
//# sourceMappingURL=offers.d.ts.map
|
package/src/offers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH;;;;;;GAMG;AAEH;;;;;;;GAOG;AAEH;;;;;;;;;;;GAWG;AAEH,kEAAkE;AAClE,iCAAkC,aAAa,CAAC;sBAlCnC,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;CACzB;;;;;;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;8BAjDuB,kBAAkB;8BADlB,aAAa"}
|
package/src/offers.js
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @import {
|
|
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
|
+
* }} InvokeEntryMessage
|
|
25
|
+
*/
|
|
26
|
+
|
|
9
27
|
/**
|
|
10
28
|
* @typedef {{
|
|
11
29
|
* id: OfferId;
|
|
12
30
|
* invitationSpec: import('./invitations.js').InvitationSpec;
|
|
13
31
|
* proposal: Proposal;
|
|
14
32
|
* offerArgs?: any;
|
|
33
|
+
* saveResult?: ResultPlan;
|
|
15
34
|
* }} OfferSpec
|
|
35
|
+
* If `saveResult` is provided, the result of the invocation will be saved to
|
|
36
|
+
* the specified location. Otherwise it will be published directly to vstorage
|
|
37
|
+
* (or 'UNPUBLISHED' if it cannot be).
|
|
16
38
|
*/
|
|
17
39
|
|
|
18
40
|
/** Value for "result" field when the result can't be published */
|
|
@@ -22,7 +44,10 @@ export const UNPUBLISHED_RESULT = 'UNPUBLISHED';
|
|
|
22
44
|
* @typedef {OfferSpec & {
|
|
23
45
|
* error?: string;
|
|
24
46
|
* numWantsSatisfied?: number;
|
|
25
|
-
* result?:
|
|
47
|
+
* result?:
|
|
48
|
+
* | unknown
|
|
49
|
+
* | typeof UNPUBLISHED_RESULT
|
|
50
|
+
* | { name: string; passStyle: string };
|
|
26
51
|
* payouts?: AmountKeywordRecord;
|
|
27
52
|
* }} OfferStatus
|
|
28
53
|
*/
|
package/src/smartWallet.d.ts
CHANGED
|
@@ -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
|
|
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.
|
|
@@ -194,6 +203,7 @@ export type ImmutableState = Readonly<UniqueParams & {
|
|
|
194
203
|
liveOffers: MapStore<OfferId, OfferStatus>;
|
|
195
204
|
liveOfferSeats: MapStore<OfferId, UserSeat<unknown>>;
|
|
196
205
|
liveOfferPayments: MapStore<OfferId, MapStore<Brand, Payment>>;
|
|
206
|
+
myStore: MapStore;
|
|
197
207
|
}>;
|
|
198
208
|
export type PurseRecord = BrandDescriptor & {
|
|
199
209
|
purse: Purse;
|
|
@@ -202,8 +212,9 @@ export type MutableState = {};
|
|
|
202
212
|
export type SmartWallet = EReturn<EReturn<typeof prepareSmartWallet>>;
|
|
203
213
|
import type { Payment } from '@agoric/ertp';
|
|
204
214
|
import type { Amount } from '@agoric/ertp';
|
|
215
|
+
import type { InvokeEntryMessage } from './offers.js';
|
|
216
|
+
import type { OfferSpec } from './offers.js';
|
|
205
217
|
import type { OfferId } from './offers.js';
|
|
206
|
-
import type { Proposal } from '@agoric/zoe';
|
|
207
218
|
import type { Brand } from '@agoric/ertp';
|
|
208
219
|
import type { OfferStatus } from './offers.js';
|
|
209
220
|
import type { Issuer } from '@agoric/ertp';
|
package/src/smartWallet.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"smartWallet.d.ts","sourceRoot":"","sources":["smartWallet.js"],"names":[],"mappings":"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"}
|
package/src/smartWallet.js
CHANGED
|
@@ -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
|
|
@@ -211,6 +207,7 @@ const trace = makeTracer('SmrtWlt');
|
|
|
211
207
|
* liveOffers: MapStore<OfferId, OfferStatus>;
|
|
212
208
|
* liveOfferSeats: MapStore<OfferId, UserSeat<unknown>>;
|
|
213
209
|
* liveOfferPayments: MapStore<OfferId, MapStore<Brand, Payment>>;
|
|
210
|
+
* myStore: MapStore;
|
|
214
211
|
* }
|
|
215
212
|
* >} ImmutableState
|
|
216
213
|
*
|
|
@@ -400,6 +397,9 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
400
397
|
durable: true,
|
|
401
398
|
},
|
|
402
399
|
),
|
|
400
|
+
// NB: Wallets before this state property was added do not support
|
|
401
|
+
// saving results or invoking the saved items.
|
|
402
|
+
myStore: zone.detached().mapStore('my items'),
|
|
403
403
|
};
|
|
404
404
|
|
|
405
405
|
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').RecorderKit<UpdateRecord>} */
|
|
@@ -453,6 +453,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
453
453
|
logWalletInfo: M.call().rest(M.arrayOf(M.any())).returns(),
|
|
454
454
|
logWalletError: M.call().rest(M.arrayOf(M.any())).returns(),
|
|
455
455
|
getLiveOfferPayments: M.call().returns(M.remotable('mapStore')),
|
|
456
|
+
saveEntry: M.call(shape.ResultPlan, M.any()).returns(M.string()),
|
|
457
|
+
findUnusedName: M.call(M.string()).returns(M.string()),
|
|
456
458
|
}),
|
|
457
459
|
|
|
458
460
|
deposit: M.interface('depositFacetI', {
|
|
@@ -471,11 +473,19 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
471
473
|
executeOffer: M.call(shape.OfferSpec).returns(M.promise()),
|
|
472
474
|
tryExitOffer: M.call(M.scalar()).returns(M.promise()),
|
|
473
475
|
}),
|
|
476
|
+
invoke: M.interface('invoke', {
|
|
477
|
+
invokeEntry: M.callWhen(shape.InvokeEntryMessage).returns(),
|
|
478
|
+
}),
|
|
479
|
+
resultStepWatcher: M.interface('resultStepWatcher', {
|
|
480
|
+
onFulfilled: M.call(M.any(), shape.ResultPlan).returns(),
|
|
481
|
+
onRejected: M.call(M.any(), M.any()).returns(),
|
|
482
|
+
}),
|
|
474
483
|
self: M.interface('selfFacetI', {
|
|
475
484
|
handleBridgeAction: M.call(shape.StringCapData, M.boolean()).returns(
|
|
476
485
|
M.promise(),
|
|
477
486
|
),
|
|
478
487
|
getDepositFacet: M.call().returns(M.remotable()),
|
|
488
|
+
getInvokeFacet: M.call().returns(M.remotable()),
|
|
479
489
|
getOffersFacet: M.call().returns(M.remotable()),
|
|
480
490
|
getCurrentSubscriber: M.call().returns(SubscriberShape),
|
|
481
491
|
getUpdatesSubscriber: M.call().returns(SubscriberShape),
|
|
@@ -745,6 +755,35 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
745
755
|
}
|
|
746
756
|
return baggage.get(state.address);
|
|
747
757
|
},
|
|
758
|
+
/** @param {string} suggestion */
|
|
759
|
+
findUnusedName(suggestion) {
|
|
760
|
+
const { myStore } = this.state;
|
|
761
|
+
let nonce = 0;
|
|
762
|
+
let name = suggestion;
|
|
763
|
+
while (myStore.has(name)) {
|
|
764
|
+
nonce += myStore.getSize(); // avoid linear work
|
|
765
|
+
name = `${suggestion}.${nonce}`;
|
|
766
|
+
}
|
|
767
|
+
return name;
|
|
768
|
+
},
|
|
769
|
+
/**
|
|
770
|
+
* @param {ResultPlan} plan
|
|
771
|
+
* @param {unknown} value
|
|
772
|
+
*/
|
|
773
|
+
saveEntry(plan, value) {
|
|
774
|
+
const { myStore } = this.state;
|
|
775
|
+
const name = plan.overwrite
|
|
776
|
+
? plan.name
|
|
777
|
+
: this.facets.helper.findUnusedName(plan.name);
|
|
778
|
+
|
|
779
|
+
if (myStore.has(name)) {
|
|
780
|
+
myStore.set(name, value);
|
|
781
|
+
} else {
|
|
782
|
+
myStore.init(name, value);
|
|
783
|
+
}
|
|
784
|
+
trace('set', name, '=', value);
|
|
785
|
+
return name;
|
|
786
|
+
},
|
|
748
787
|
},
|
|
749
788
|
/**
|
|
750
789
|
* Similar to {DepositFacet} but async because it has to look up the
|
|
@@ -1019,6 +1058,44 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1019
1058
|
await E(seatRef).tryExit();
|
|
1020
1059
|
},
|
|
1021
1060
|
},
|
|
1061
|
+
|
|
1062
|
+
invoke: {
|
|
1063
|
+
/**
|
|
1064
|
+
* @param {InvokeEntryMessage} message
|
|
1065
|
+
*/
|
|
1066
|
+
async invokeEntry(message) {
|
|
1067
|
+
trace('invokeEntry', message);
|
|
1068
|
+
const { myStore } = this.state;
|
|
1069
|
+
const { resultStepWatcher } = this.facets;
|
|
1070
|
+
|
|
1071
|
+
const { targetName: name, method, args, saveResult } = message;
|
|
1072
|
+
myStore.has(name) || Fail`cannot invoke ${q(name)}: no such item`;
|
|
1073
|
+
const value = myStore.get(name);
|
|
1074
|
+
trace('entry', name, value);
|
|
1075
|
+
trace('invoke', value, '.', method, '(', args, ')');
|
|
1076
|
+
const callP = E(value)[method](...args);
|
|
1077
|
+
if (saveResult) {
|
|
1078
|
+
vowTools.watch(callP, resultStepWatcher, saveResult);
|
|
1079
|
+
} else {
|
|
1080
|
+
void callP;
|
|
1081
|
+
}
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
|
|
1085
|
+
resultStepWatcher: {
|
|
1086
|
+
/**
|
|
1087
|
+
* @param {unknown} result
|
|
1088
|
+
* @param {ResultPlan} saveResult
|
|
1089
|
+
*/
|
|
1090
|
+
onFulfilled(result, saveResult) {
|
|
1091
|
+
trace('resultStepWatcher result', result);
|
|
1092
|
+
this.facets.helper.saveEntry(saveResult, result);
|
|
1093
|
+
},
|
|
1094
|
+
onRejected(reason, saveResult) {
|
|
1095
|
+
trace('rejected', reason, 'saveResult', saveResult);
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
1098
|
+
|
|
1022
1099
|
self: {
|
|
1023
1100
|
/**
|
|
1024
1101
|
* Umarshals the actionCapData and delegates to the appropriate action
|
|
@@ -1030,8 +1107,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1030
1107
|
* @returns {Promise<void>}
|
|
1031
1108
|
*/
|
|
1032
1109
|
handleBridgeAction(actionCapData, canSpend = false) {
|
|
1033
|
-
const { facets } = this;
|
|
1034
|
-
const { offers } = facets;
|
|
1110
|
+
const { facets, state } = this;
|
|
1111
|
+
const { offers, invoke } = facets;
|
|
1035
1112
|
const { publicMarshaller } = shared;
|
|
1036
1113
|
|
|
1037
1114
|
/** @param {Error} err */
|
|
@@ -1044,6 +1121,8 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1044
1121
|
});
|
|
1045
1122
|
};
|
|
1046
1123
|
|
|
1124
|
+
const walletHasNameHub = 'myStore' in state && state.myStore != null;
|
|
1125
|
+
|
|
1047
1126
|
// use E.when to retain distributed stack trace
|
|
1048
1127
|
return E.when(
|
|
1049
1128
|
E(publicMarshaller).fromCapData(actionCapData),
|
|
@@ -1053,12 +1132,21 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1053
1132
|
switch (action.method) {
|
|
1054
1133
|
case 'executeOffer': {
|
|
1055
1134
|
canSpend || Fail`executeOffer requires spend authority`;
|
|
1135
|
+
if (action.offer.saveResult != null && !walletHasNameHub) {
|
|
1136
|
+
Fail`executeOffer saveResult requires a new smart wallet with myStore`;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1056
1139
|
return offers.executeOffer(action.offer);
|
|
1057
1140
|
}
|
|
1058
1141
|
case 'tryExitOffer': {
|
|
1059
1142
|
assert(canSpend, 'tryExitOffer requires spend authority');
|
|
1060
1143
|
return offers.tryExitOffer(action.offerId);
|
|
1061
1144
|
}
|
|
1145
|
+
case 'invokeEntry': {
|
|
1146
|
+
walletHasNameHub ||
|
|
1147
|
+
Fail`invokeEntry requires a new smart wallet with myStore`;
|
|
1148
|
+
return invoke.invokeEntry(action.message);
|
|
1149
|
+
}
|
|
1062
1150
|
default: {
|
|
1063
1151
|
throw Fail`invalid handle bridge action ${q(action)}`;
|
|
1064
1152
|
}
|
|
@@ -1077,6 +1165,9 @@ export const prepareSmartWallet = (baggage, shared) => {
|
|
|
1077
1165
|
getDepositFacet() {
|
|
1078
1166
|
return this.facets.deposit;
|
|
1079
1167
|
},
|
|
1168
|
+
getInvokeFacet() {
|
|
1169
|
+
return this.facets.invoke;
|
|
1170
|
+
},
|
|
1080
1171
|
getOffersFacet() {
|
|
1081
1172
|
return this.facets.offers;
|
|
1082
1173
|
},
|
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 },
|
|
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
|
-
{
|
|
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
|
/**
|