@agoric/smart-wallet 0.5.4-dev-e68f280.0 → 0.5.4-dev-6f05870.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/smart-wallet",
3
- "version": "0.5.4-dev-e68f280.0+e68f280",
3
+ "version": "0.5.4-dev-6f05870.0+6f05870",
4
4
  "description": "Wallet contract",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -16,23 +16,24 @@
16
16
  "lint:eslint": "eslint ."
17
17
  },
18
18
  "devDependencies": {
19
- "@agoric/cosmic-proto": "0.3.1-dev-e68f280.0+e68f280",
19
+ "@agoric/cosmic-proto": "0.3.1-dev-6f05870.0+6f05870",
20
+ "@endo/bundle-source": "^2.5.2",
20
21
  "@endo/captp": "^3.1.2",
21
22
  "@endo/init": "^0.5.57",
22
23
  "ava": "^5.3.0",
23
24
  "import-meta-resolve": "^2.2.1"
24
25
  },
25
26
  "dependencies": {
26
- "@agoric/assert": "0.6.1-dev-e68f280.0+e68f280",
27
- "@agoric/casting": "0.4.3-dev-e68f280.0+e68f280",
28
- "@agoric/ertp": "0.16.3-dev-e68f280.0+e68f280",
29
- "@agoric/internal": "0.3.3-dev-e68f280.0+e68f280",
30
- "@agoric/notifier": "0.6.3-dev-e68f280.0+e68f280",
31
- "@agoric/store": "0.9.3-dev-e68f280.0+e68f280",
32
- "@agoric/swingset-vat": "0.32.3-dev-e68f280.0+e68f280",
33
- "@agoric/vat-data": "0.5.3-dev-e68f280.0+e68f280",
34
- "@agoric/vats": "0.15.2-dev-e68f280.0+e68f280",
35
- "@agoric/zoe": "0.26.3-dev-e68f280.0+e68f280",
27
+ "@agoric/assert": "0.6.1-dev-6f05870.0+6f05870",
28
+ "@agoric/casting": "0.4.3-dev-6f05870.0+6f05870",
29
+ "@agoric/ertp": "0.16.3-dev-6f05870.0+6f05870",
30
+ "@agoric/internal": "0.3.3-dev-6f05870.0+6f05870",
31
+ "@agoric/notifier": "0.6.3-dev-6f05870.0+6f05870",
32
+ "@agoric/store": "0.9.3-dev-6f05870.0+6f05870",
33
+ "@agoric/swingset-vat": "0.32.3-dev-6f05870.0+6f05870",
34
+ "@agoric/vat-data": "0.5.3-dev-6f05870.0+6f05870",
35
+ "@agoric/vats": "0.15.2-dev-6f05870.0+6f05870",
36
+ "@agoric/zoe": "0.26.3-dev-6f05870.0+6f05870",
36
37
  "@endo/eventual-send": "^0.17.3",
37
38
  "@endo/far": "^0.2.19",
38
39
  "@endo/marshal": "^0.8.6",
@@ -62,5 +63,5 @@
62
63
  "publishConfig": {
63
64
  "access": "public"
64
65
  },
65
- "gitHead": "e68f2805dde79871d1421e50c60f08e854e1851d"
66
+ "gitHead": "6f05870eef00470eb99022513e2df5ff62e81785"
66
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;;;;;;;GAOG;AAEH,kEAAkE;AAClE,+CAAgD;AAwBzC;SAVI,KAAK,UAAU,CAAC;;mCACW,QAAQ,MAAM,CAAC;;sBAC1C,KAAK,OAAO,KAAK,CAAC,CAAC;;gBAEnB,KAAK,OAAO,EAAE,MAAM,GAAE,OAAO,CAAC;mCACvB,OAAO,eAAe,EAAE,cAAc,KAAK,KAAK,UAAU,CAAC;+BAC1D,KAAK,KAAK,QAAQ,KAAK,CAAC;;6BACvB,WAAW,KAAK,IAAI;oCACnB,MAAM,oBAAoB,OAAO,KAAK,CAAC,oBAAoB,OAAO,SAAS,EAAE,gBAAgB,qBAAqB,OAAO,SAAS,EAAE,iBAAiB,GAAG,OAAO,iCAAiC,EAAE,YAAY,KAAM,QAAQ,IAAI,CAAC;;IAalP;;;;;;;OAOG;4BAJQ,SAAS,2BACC,QAAQ,KAAK,IAAI,GACzB,QAAQ,IAAI,CAAC;EAyI7B;sBA9LY,MAAM,GAAG,MAAM;wBAIf;IACZ,EAAM,EAAE,OAAO,CAAC;IAChB,cAAkB,EAAE,OAAO,eAAe,EAAE,cAAc,CAAC;IAC3D,QAAY,EAAE,QAAQ,CAAC;IACvB,SAAa,CAAC,EAAE,OAAO,CAAA;CACpB;0BAOS,OAAO,aAAa,EAAE,SAAS,GAAG;IAC9C,KAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAQ,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;IAC/C,OAAS,CAAC,EAAE,mBAAmB,CAAC;CAC7B"}
1
+ {"version":3,"file":"offers.d.ts","sourceRoot":"","sources":["offers.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;;;;;GAOG;AAEH,kEAAkE;AAClE,+CAAgD;AAwBzC;SAVI,KAAK,UAAU,CAAC;;mCACW,QAAQ,MAAM,CAAC;;sBAC1C,KAAK,OAAO,KAAK,CAAC,CAAC;;gBAEnB,KAAK,OAAO,EAAE,MAAM,GAAE,OAAO,CAAC;mCACvB,OAAO,eAAe,EAAE,cAAc,KAAK,KAAK,UAAU,CAAC;+BAC1D,KAAK,KAAK,QAAQ,KAAK,CAAC;;6BACvB,WAAW,KAAK,IAAI;oCACnB,MAAM,oBAAoB,OAAO,KAAK,CAAC,oBAAoB,OAAO,SAAS,EAAE,gBAAgB,qBAAqB,OAAO,SAAS,EAAE,iBAAiB,GAAG,OAAO,iCAAiC,EAAE,YAAY,KAAM,QAAQ,IAAI,CAAC;;IAalP;;;;;;;OAOG;4BAJQ,SAAS,2BACC,QAAQ,KAAK,IAAI,GACzB,QAAQ,IAAI,CAAC;EAyI7B;sBA9LY,MAAM,GAAG,MAAM;wBAIf;IACZ,EAAM,EAAE,OAAO,CAAC;IAChB,cAAkB,EAAE,OAAO,eAAe,EAAE,cAAc,CAAC;IAC3D,QAAY,EAAE,QAAQ,CAAC;IACvB,SAAa,CAAC,EAAE,OAAO,CAAA;CACpB;0BAOS,OAAO,aAAa,EAAE,SAAS,GAAG;IAC9C,KAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAQ,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC;IAC/C,OAAS,CAAC,EAAE,mBAAmB,CAAC;CAC7B"}
package/src/offers.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { E, passStyleOf } from '@endo/far';
2
+ import { deeplyFulfilledObject } from '@agoric/internal';
2
3
  import { makePaymentsHelper } from './payments.js';
3
4
 
4
5
  /**
@@ -80,15 +81,15 @@ export const makeOfferExecutor = ({
80
81
  // 1. Prepare values and validate synchronously.
81
82
  const { id, invitationSpec, proposal, offerArgs } = offerSpec;
82
83
 
84
+ /** @type {PaymentKeywordRecord | undefined} */
85
+ const paymentKeywordRecord = await (proposal?.give &&
86
+ deeplyFulfilledObject(paymentsManager.withdrawGive(proposal.give)));
87
+
83
88
  const invitation = invitationFromSpec(invitationSpec);
84
89
  const invitationAmount = await E(invitationIssuer).getAmountOf(
85
90
  invitation,
86
91
  );
87
92
 
88
- const paymentKeywordRecord = proposal?.give
89
- ? paymentsManager.withdrawGive(proposal.give)
90
- : undefined;
91
-
92
93
  // 2. Begin executing offer
93
94
  // No explicit signal to user that we reached here but if anything above
94
95
  // failed they'd get an 'error' status update.
@@ -1,3 +1,4 @@
1
+ export const BRAND_TO_PURSES_KEY: "brandToPurses";
1
2
  export function prepareSmartWallet(baggage: MapStore<string, unknown>, shared: SharedParams): (uniqueWithoutChildNodes: Omit<UniqueParams, "currentStorageNode" | "walletStorageNode"> & {
2
3
  walletStorageNode: ERef<StorageNode>;
3
4
  }) => Promise<{
@@ -15,10 +16,11 @@ export function prepareSmartWallet(baggage: MapStore<string, unknown>, shared: S
15
16
  *
16
17
  * If the purse doesn't exist, we hold the payment in durable storage.
17
18
  *
18
- * @param {import('@endo/far').FarRef<Payment>} payment
19
- * @returns {Promise<Amount>} amounts for deferred deposits will be empty
19
+ * @param {Payment} payment
20
+ * @returns {Promise<Amount>}
21
+ * @throws if there's not yet a purse, though the payment is held to try again when there is
20
22
  */
21
- receive(payment: import('@endo/far').FarRef<Payment>): Promise<Amount>;
23
+ receive(payment: Payment): Promise<Amount>;
22
24
  };
23
25
  getOffersFacet(): {
24
26
  /**
@@ -149,7 +151,7 @@ export type SharedParams = {
149
151
  */
150
152
  export type State = ImmutableState & MutableState;
151
153
  export type ImmutableState = Readonly<UniqueParams & {
152
- paymentQueues: MapStore<Brand, Array<import('@endo/far').FarRef<Payment>>>;
154
+ paymentQueues: MapStore<Brand, Array<Payment>>;
153
155
  offerToInvitationMakers: MapStore<string, import('./types').InvitationMakers>;
154
156
  offerToPublicSubscriberPaths: MapStore<string, Record<string, string>>;
155
157
  offerToUsedInvitation: MapStore<string, Amount>;
@@ -159,6 +161,9 @@ export type ImmutableState = Readonly<UniqueParams & {
159
161
  liveOffers: MapStore<import('./offers.js').OfferId, import('./offers.js').OfferStatus>;
160
162
  liveOfferSeats: WeakMapStore<import('./offers.js').OfferId, UserSeat<unknown>>;
161
163
  }>;
164
+ export type PurseRecord = BrandDescriptor & {
165
+ purse: Purse;
166
+ };
162
167
  export type MutableState = {};
163
168
  export type SmartWallet = Awaited<ReturnType<ReturnType<typeof prepareSmartWallet>>>;
164
169
  //# sourceMappingURL=smartWallet.d.ts.map
@@ -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,4 @@
1
1
  import {
2
- AmountMath,
3
2
  AmountShape,
4
3
  BrandShape,
5
4
  DisplayInfoShape,
@@ -7,15 +6,23 @@ import {
7
6
  PaymentShape,
8
7
  PurseShape,
9
8
  } from '@agoric/ertp';
10
- import { StorageNodeShape } from '@agoric/internal';
9
+ import { StorageNodeShape, makeTracer } from '@agoric/internal';
11
10
  import { observeNotifier } from '@agoric/notifier';
12
11
  import { M, mustMatch } from '@agoric/store';
13
- import { appendToStoredArray } from '@agoric/store/src/stores/store-utils.js';
14
- import { makeScalarBigMapStore, prepareExoClassKit } from '@agoric/vat-data';
15
12
  import {
16
- prepareRecorderKit,
13
+ appendToStoredArray,
14
+ provideLazy,
15
+ } from '@agoric/store/src/stores/store-utils.js';
16
+ import {
17
+ makeScalarBigMapStore,
18
+ makeScalarBigWeakMapStore,
19
+ prepareExoClassKit,
20
+ provide,
21
+ } from '@agoric/vat-data';
22
+ import {
17
23
  SubscriberShape,
18
24
  TopicsRecordShape,
25
+ prepareRecorderKit,
19
26
  } from '@agoric/zoe/src/contractSupport/index.js';
20
27
  import { E } from '@endo/far';
21
28
  import { makeInvitationsHelper } from './invitations.js';
@@ -25,6 +32,8 @@ import { objectMapStoragePath } from './utils.js';
25
32
 
26
33
  const { Fail, quote: q } = assert;
27
34
 
35
+ const trace = makeTracer('SmrtWlt');
36
+
28
37
  /**
29
38
  * @file Smart wallet module
30
39
  *
@@ -129,7 +138,7 @@ const { Fail, quote: q } = assert;
129
138
  * - `purseBalances` is a cache of what we've received from purses. Held so we can publish all balances on change.
130
139
  *
131
140
  * @typedef {Readonly<UniqueParams & {
132
- * paymentQueues: MapStore<Brand, Array<import('@endo/far').FarRef<Payment>>>,
141
+ * paymentQueues: MapStore<Brand, Array<Payment>>,
133
142
  * offerToInvitationMakers: MapStore<string, import('./types').InvitationMakers>,
134
143
  * offerToPublicSubscriberPaths: MapStore<string, Record<string, string>>,
135
144
  * offerToUsedInvitation: MapStore<string, Amount>,
@@ -140,16 +149,66 @@ const { Fail, quote: q } = assert;
140
149
  * liveOfferSeats: WeakMapStore<import('./offers.js').OfferId, UserSeat<unknown>>,
141
150
  * }>} ImmutableState
142
151
  *
152
+ * @typedef {BrandDescriptor & { purse: Purse }} PurseRecord
143
153
  * @typedef {{
144
154
  * }} MutableState
145
155
  */
146
156
 
157
+ /**
158
+ * NameHub reverse-lookup, finding 0 or more names for a target value
159
+ *
160
+ * TODO: consider moving to nameHub.js?
161
+ *
162
+ * @param {unknown} target - passable Key
163
+ * @param {ERef<NameHub>} nameHub
164
+ */
165
+ const namesOf = async (target, nameHub) => {
166
+ const entries = await E(nameHub).entries();
167
+ const matches = [];
168
+ for (const [name, candidate] of entries) {
169
+ if (candidate === target) {
170
+ matches.push(name);
171
+ }
172
+ }
173
+ return harden(matches);
174
+ };
175
+
176
+ /**
177
+ * Check that an issuer and its brand belong to each other.
178
+ *
179
+ * TODO: move to ERTP?
180
+ *
181
+ * @param {Issuer} issuer
182
+ * @param {Brand} brand
183
+ * @returns {Promise<boolean>} true iff the the brand and issuer match
184
+ */
185
+ const checkMutual = (issuer, brand) =>
186
+ Promise.all([
187
+ E(issuer)
188
+ .getBrand()
189
+ .then(b => b === brand),
190
+ E(brand).isMyIssuer(issuer),
191
+ ]).then(checks => checks.every(Boolean));
192
+
193
+ export const BRAND_TO_PURSES_KEY = 'brandToPurses';
194
+
195
+ const getBrandToPurses = (walletPurses, key) => {
196
+ const brandToPurses = provideLazy(walletPurses, key, _k => {
197
+ /** @type {MapStore<Brand, PurseRecord[]>} */
198
+ const store = makeScalarBigMapStore('purses by brand', {
199
+ durable: true,
200
+ });
201
+ return store;
202
+ });
203
+ return brandToPurses;
204
+ };
205
+
147
206
  /**
148
207
  * @param {import('@agoric/vat-data').Baggage} baggage
149
208
  * @param {SharedParams} shared
150
209
  */
151
210
  export const prepareSmartWallet = (baggage, shared) => {
152
- const { registry: _, ...passableShared } = shared;
211
+ const { registry: _r, ...passableShared } = shared;
153
212
  mustMatch(
154
213
  harden(passableShared),
155
214
  harden({
@@ -164,6 +223,15 @@ export const prepareSmartWallet = (baggage, shared) => {
164
223
 
165
224
  const makeRecorderKit = prepareRecorderKit(baggage, shared.publicMarshaller);
166
225
 
226
+ const walletPurses = provide(baggage, BRAND_TO_PURSES_KEY, () => {
227
+ trace('make purses by wallet and save in baggage at', BRAND_TO_PURSES_KEY);
228
+ /** @type {WeakMapStore<unknown, MapStore<Brand, PurseRecord[]>>} */
229
+ const store = makeScalarBigWeakMapStore('purses by wallet', {
230
+ durable: true,
231
+ });
232
+ return store;
233
+ });
234
+
167
235
  /**
168
236
  *
169
237
  * @param {UniqueParams} unique
@@ -242,6 +310,9 @@ export const prepareSmartWallet = (baggage, shared) => {
242
310
  helper: M.interface('helperFacetI', {
243
311
  assertUniqueOfferId: M.call(M.string()).returns(),
244
312
  updateBalance: M.call(PurseShape, AmountShape).optional('init').returns(),
313
+ getPurseIfKnownBrand: M.call(BrandShape)
314
+ .optional(M.eref(M.remotable()))
315
+ .returns(M.promise()),
245
316
  publishCurrentState: M.call().returns(),
246
317
  watchPurse: M.call(M.eref(PurseShape)).returns(M.promise()),
247
318
  }),
@@ -366,6 +437,63 @@ export const prepareSmartWallet = (baggage, shared) => {
366
437
  },
367
438
  });
368
439
  },
440
+
441
+ /**
442
+ * Provide a purse given a NameHub of issuers and their
443
+ * brands.
444
+ *
445
+ * We current support only one NameHub, agoricNames, and
446
+ * hence one purse per brand. But we store an array of them
447
+ * to facilitate a transition to decentralized introductions.
448
+ *
449
+ * @param {Brand} brand
450
+ * @param {ERef<NameHub>} known - namehub with brand, issuer branches
451
+ * @returns {Promise<Purse | undefined>} undefined if brand is not known
452
+ */
453
+ async getPurseIfKnownBrand(brand, known) {
454
+ const { helper, self } = this.facets;
455
+ const brandToPurses = getBrandToPurses(walletPurses, self);
456
+
457
+ if (brandToPurses.has(brand)) {
458
+ const purses = brandToPurses.get(brand);
459
+ if (purses.length > 0) {
460
+ // UNTIL https://github.com/Agoric/agoric-sdk/issues/6126
461
+ // multiple purses
462
+ return purses[0].purse;
463
+ }
464
+ }
465
+
466
+ const found = await namesOf(brand, E(known).lookup('brand'));
467
+ if (found.length === 0) {
468
+ return undefined;
469
+ }
470
+ const [edgeName] = found;
471
+ const issuer = await E(known).lookup('issuer', edgeName);
472
+
473
+ // Even though we rely on this nameHub, double-check
474
+ // that the issuer and the brand belong to each other.
475
+ if (!(await checkMutual(issuer, brand))) {
476
+ // if they don't, it's not a "known" brand in a coherent way
477
+ return undefined;
478
+ }
479
+
480
+ // Accept the issuer; rely on it in future offers.
481
+ const [displayInfo, purse] = await Promise.all([
482
+ E(issuer).getDisplayInfo(),
483
+ E(issuer).makeEmptyPurse(),
484
+ ]);
485
+
486
+ // adopt edgeName as petname
487
+ // NOTE: for decentralized introductions, qualify edgename by nameHub petname
488
+ const petname = edgeName;
489
+ const assetInfo = { petname, brand, issuer, purse, displayInfo };
490
+ appendToStoredArray(brandToPurses, brand, assetInfo);
491
+ // NOTE: when we decentralize introduction of issuers,
492
+ // process queued payments for this brand.
493
+
494
+ void helper.watchPurse(purse);
495
+ return purse;
496
+ },
369
497
  },
370
498
  /**
371
499
  * Similar to {DepositFacet} but async because it has to look up the purse.
@@ -376,10 +504,12 @@ export const prepareSmartWallet = (baggage, shared) => {
376
504
  *
377
505
  * If the purse doesn't exist, we hold the payment in durable storage.
378
506
  *
379
- * @param {import('@endo/far').FarRef<Payment>} payment
380
- * @returns {Promise<Amount>} amounts for deferred deposits will be empty
507
+ * @param {Payment} payment
508
+ * @returns {Promise<Amount>}
509
+ * @throws if there's not yet a purse, though the payment is held to try again when there is
381
510
  */
382
511
  async receive(payment) {
512
+ const { helper } = this.facets;
383
513
  const { paymentQueues: queues, bank, invitationPurse } = this.state;
384
514
  const { registry, invitationBrand } = shared;
385
515
  const brand = await E(payment).getAllegedBrand();
@@ -387,17 +517,24 @@ export const prepareSmartWallet = (baggage, shared) => {
387
517
  // When there is a purse deposit into it
388
518
  if (registry.has(brand)) {
389
519
  const purse = E(bank).getPurse(brand);
390
- // @ts-expect-error deposit does take a FarRef<Payment>
391
520
  return E(purse).deposit(payment);
392
521
  } else if (invitationBrand === brand) {
393
- // @ts-expect-error deposit does take a FarRef<Payment>
522
+ // @ts-expect-error narrow assetKind to 'set'
394
523
  return E(invitationPurse).deposit(payment);
395
524
  }
396
525
 
526
+ const purse = await helper.getPurseIfKnownBrand(
527
+ brand,
528
+ shared.agoricNames,
529
+ );
530
+ if (purse) {
531
+ return E(purse).deposit(payment);
532
+ }
533
+
397
534
  // When there is no purse, save the payment into a queue.
398
535
  // It's not yet ever read but a future version of the contract can
399
536
  appendToStoredArray(queues, brand, payment);
400
- return AmountMath.makeEmpty(brand);
537
+ throw Fail`cannot deposit payment with brand ${brand}: no purse`;
401
538
  },
402
539
  },
403
540
  offers: {
@@ -445,12 +582,21 @@ export const prepareSmartWallet = (baggage, shared) => {
445
582
  * @returns {Promise<Purse>}
446
583
  */
447
584
  purseForBrand: async brand => {
585
+ const { helper } = facets;
448
586
  if (registry.has(brand)) {
449
587
  // @ts-expect-error virtual purse
450
588
  return E(bank).getPurse(brand);
451
589
  } else if (invitationBrand === brand) {
452
590
  return invitationPurse;
453
591
  }
592
+
593
+ const purse = await helper.getPurseIfKnownBrand(
594
+ brand,
595
+ shared.agoricNames,
596
+ );
597
+ if (purse) {
598
+ return purse;
599
+ }
454
600
  throw Fail`cannot find/make purse for ${brand}`;
455
601
  },
456
602
  logger,
@@ -35,7 +35,7 @@ export function start(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
35
35
  provideSmartWallet(address: string, bank: ERef<import('@agoric/vats/src/vat-bank').Bank>, namesByAddressAdmin: ERef<import('@agoric/vats/').NameAdmin>): Promise<[wallet: {
36
36
  handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
37
37
  getDepositFacet(): {
38
- receive(payment: import("@endo/far").FarRef<Payment<AssetKind>, import("@endo/eventual-send").DataOnly<Payment<AssetKind>>>): Promise<Amount<AssetKind>>;
38
+ receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
39
39
  };
40
40
  getOffersFacet(): {
41
41
  executeOffer(offerSpec: import("./offers.js").OfferSpec): Promise<void>;
@@ -68,7 +68,7 @@ export function start(zcf: ZCF<SmartWalletContractTerms>, privateArgs: {
68
68
  provideSmartWallet(address: string, bank: ERef<import('@agoric/vats/src/vat-bank').Bank>, namesByAddressAdmin: ERef<import('@agoric/vats/').NameAdmin>): Promise<[wallet: {
69
69
  handleBridgeAction(actionCapData: import("@endo/marshal").CapData<string>, canSpend?: boolean | undefined): Promise<void>;
70
70
  getDepositFacet(): {
71
- receive(payment: import("@endo/far").FarRef<Payment<AssetKind>, import("@endo/eventual-send").DataOnly<Payment<AssetKind>>>): Promise<Amount<AssetKind>>;
71
+ receive(payment: Payment<AssetKind>): Promise<Amount<AssetKind>>;
72
72
  };
73
73
  getOffersFacet(): {
74
74
  executeOffer(offerSpec: import("./offers.js").OfferSpec): Promise<void>;