Skip to content

Commit

Permalink
feat(wallet-ui): use new wallet.current node
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Sep 29, 2022
1 parent c911acb commit eb33d67
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 32 deletions.
17 changes: 8 additions & 9 deletions packages/wallet/ui/src/components/SmartWalletConnection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { bridgeStorageMessages } from '../util/BridgeStorage';
import { SmartConnectionMethod } from '../util/connections';
import {
makeBackendFromWalletBridge,
makeWalletBridgeFromFollower,
makeWalletBridgeFromFollowers,
} from '../util/WalletBackendAdapter';
import ProvisionDialog from './ProvisionDialog';

Expand Down Expand Up @@ -98,14 +98,13 @@ const SmartWalletConnection = ({
const follow = async () => {
const context = makeImportContext();
const leader = makeLeader(href);
const follower = makeFollower(
`:published.wallet.${publicAddress}`,
leader,
{ unserializer: context.fromMyWallet },
);
// TODO try making a smart-wallet version of this
const bridge = makeWalletBridgeFromFollower(
follower,
const followPublished = path =>
makeFollower(`:published.${path}`, leader, {
unserializer: context.fromMyWallet,
});
const bridge = makeWalletBridgeFromFollowers(
followPublished(`wallet.${publicAddress}.current`),
followPublished(`wallet.${publicAddress}`),
leader,
context.fromBoard,
publicAddress,
Expand Down
91 changes: 68 additions & 23 deletions packages/wallet/ui/src/util/WalletBackendAdapter.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// @ts-check
import { iterateEach } from '@agoric/casting';
import {
makeAsyncIterableFromNotifier,
makeNotifierKit,
} from '@agoric/notifier';
import {
getFirstHeight,
NO_SMART_WALLET_ERROR,
} from '@agoric/smart-wallet/src/utils.js';
import { NO_SMART_WALLET_ERROR } from '@agoric/smart-wallet/src/utils.js';
import { E } from '@endo/eventual-send';
import { Far } from '@endo/marshal';
import { getDappService } from '../service/Dapps.js';
import { getIssuerService } from '../service/Issuers.js';
import { getOfferService } from '../service/Offers.js';
import { getScopedBridge } from '../service/ScopedBridge.js';

/** @typedef {import('@agoric/smart-wallet/src/types.js').Petname} Petname */

const newId = kind => `${kind}${Math.random()}`;

/** @typedef {{actions: object, issuerSuggestions: Promise<AsyncIterator>}} BackendSchema */
Expand Down Expand Up @@ -76,6 +76,7 @@ export const makeBackendFromWalletBridge = walletBridge => {
dapps: iterateNotifier(E(walletBridge).getDappsNotifier()),
issuers: iterateNotifier(E(walletBridge).getIssuersNotifier()),
offers: wrapOffersIterator(
// @ts-expect-error xxx
iterateNotifier(E(walletBridge).getOffersNotifier()),
),
payments: iterateNotifier(E(walletBridge).getPaymentsNotifier()),
Expand All @@ -101,7 +102,8 @@ export const makeBackendFromWalletBridge = walletBridge => {
};

/**
* @param {import('@agoric/casting').Follower<any>} follower
* @param {import('@agoric/casting').ValueFollower<import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord>} currentFollower
* @param {import('@agoric/casting').ValueFollower<import('@agoric/smart-wallet/src/smartWallet').UpdateRecord>} updateFollower
* @param {import('@agoric/casting').Leader} leader
* @param {ReturnType<import('@endo/marshal').makeMarshal>} marshaller
* @param {string} publicAddress
Expand All @@ -110,8 +112,9 @@ export const makeBackendFromWalletBridge = walletBridge => {
* @param {(e: unknown) => void} [errorHandler]
* @param {() => void} [firstCallback]
*/
export const makeWalletBridgeFromFollower = (
follower,
export const makeWalletBridgeFromFollowers = (
currentFollower,
updateFollower,
leader,
marshaller,
publicAddress,
Expand Down Expand Up @@ -139,36 +142,74 @@ export const makeWalletBridgeFromFollower = (
);

// We assume just one cosmos purse per brand.
/** @type {Record<number, import('@agoric/smart-wallet/src/offers.js').OfferStatus & {status: 'accept' | 'rejected'}>} */
const offers = {};
/**
* @typedef {{
* brand?: Brand,
* brandPetname?: Petname,
* currentAmount: Amount,
* pursePetname?: Petname,
* displayInfo?: DisplayInfo,
* }} PurseInfo
* @type {Map<Brand, PurseInfo>}
*/
const brandToPurse = new Map();
/** @type {Map<Petname, Brand>} */
const pursePetnameToBrand = new Map();

if (firstCallback) {
firstCallback();
Object.values(notifierKits).forEach(({ updater }) =>
updater.updateState([]),
);
firstCallback = undefined;
}

const updatePurses = () => {
const purses = [];
for (const [brand, purse] of brandToPurse.entries()) {
if (purse.currentAmount && purse.brandPetname) {
assert(purse.pursePetname, 'missing purse.pursePetname');
pursePetnameToBrand.set(purse.pursePetname, brand);
purses.push(purse);
}
}
notifierKits.purses.updater.updateState(harden(purses));
};

const followLatest = async () => {
const firstHeight = await getFirstHeight(follower);
const fetchCurrent = async () => {
console.log('fetchCurrent()');
const latestIterable = await E(currentFollower).getLatestIterable();
const iterator = latestIterable[Symbol.asyncIterator]();
const latest = await iterator.next();
/** @type {import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord} */
const current = latest.value.value;
console.log('fetcHCurrent', current);
for (const purse of current.purses) {
console.log('registering purse', purse);
const brandDescriptor = current.brands.find(
bd => purse.brand === bd.brand,
);
assert(brandDescriptor, `missing descriptor for brand ${purse.brand}`);
/** @type {PurseInfo} */
const purseInfo = {
currentAmount: purse.balance,
brandPetname: brandDescriptor.petname,
pursePetname: brandDescriptor.petname,
displayInfo: brandDescriptor.displayInfo,
};
brandToPurse.set(purse.brand, purseInfo);
}
console.log('brandToPurse map', brandToPurse);
updatePurses();
};

for await (const { value } of iterateEach(follower, {
height: firstHeight,
})) {
const followLatest = async () => {
console.log('followLatest()');
for await (const { value } of iterateEach(updateFollower)) {
/** @type {import('@agoric/smart-wallet/src/smartWallet').UpdateRecord} */
const updateRecord = value;
if (firstCallback) {
firstCallback();
Object.values(notifierKits).forEach(({ updater }) =>
updater.updateState([]),
);
firstCallback = undefined;
}
switch (updateRecord.updated) {
case 'brand': {
const { descriptor } = updateRecord;
Expand Down Expand Up @@ -207,7 +248,7 @@ export const makeWalletBridgeFromFollower = (
if ('error' in status) {
offers[status.id] = {
...oldOffer,
id: `${status.id}`,
id: status.id,
status: 'rejected',
error: `${status.error}`,
};
Expand All @@ -217,24 +258,28 @@ export const makeWalletBridgeFromFollower = (
) {
offers[status.id] = {
...oldOffer,
id: `${status.id}`,
id: status.id,
status: 'accept',
};
}
notifierKits.offers.updater.updateState(
// @ts-expect-error xxx
harden(Object.values(offers)),
);
break;
}
default: {
// @ts-expect-error exhaustive switch
throw Error(`Unknown updateRecord ${updateRecord.updated}`);
}
}
}
};

const loadData = () => fetchCurrent().then(followLatest);

const retry = () => {
followLatest().catch(e => {
loadData().catch(e => {
if (e.message === NO_SMART_WALLET_ERROR) {
setTimeout(retry, 5000);
} else {
Expand All @@ -243,7 +288,7 @@ export const makeWalletBridgeFromFollower = (
});
};

followLatest().catch(e => {
loadData().catch(e => {
errorHandler(e);
if (e.message === NO_SMART_WALLET_ERROR) {
setTimeout(retry, 5000);
Expand Down

0 comments on commit eb33d67

Please sign in to comment.