@agoric/client-utils 0.1.1-other-dev-3eb1a1d.0 → 0.2.0-u18.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/client-utils",
3
- "version": "0.1.1-other-dev-3eb1a1d.0+3eb1a1d",
3
+ "version": "0.2.0-u18.0",
4
4
  "description": "Utilities for building Agoric clients",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -24,14 +24,14 @@
24
24
  "devDependencies": {
25
25
  "ava": "^5.3.0",
26
26
  "c8": "^10.1.2",
27
- "ts-blank-space": "^0.4.1"
27
+ "ts-blank-space": "^0.4.4"
28
28
  },
29
29
  "dependencies": {
30
- "@agoric/casting": "0.4.3-other-dev-3eb1a1d.0+3eb1a1d",
31
- "@agoric/ertp": "0.16.3-other-dev-3eb1a1d.0+3eb1a1d",
32
- "@agoric/internal": "0.3.3-other-dev-3eb1a1d.0+3eb1a1d",
33
- "@agoric/smart-wallet": "0.5.4-other-dev-3eb1a1d.0+3eb1a1d",
34
- "@agoric/vats": "0.15.2-other-dev-3eb1a1d.0+3eb1a1d",
30
+ "@agoric/casting": "^0.4.3-u18.5",
31
+ "@agoric/ertp": "^0.16.3-u18.1",
32
+ "@agoric/internal": "^0.4.0-u18.1",
33
+ "@agoric/smart-wallet": "^0.5.4-u18.5",
34
+ "@agoric/vats": "^0.16.0-u18.5",
35
35
  "@cosmjs/stargate": "^0.32.3",
36
36
  "@cosmjs/tendermint-rpc": "^0.32.3",
37
37
  "@endo/common": "^1.2.8",
@@ -58,5 +58,5 @@
58
58
  ],
59
59
  "timeout": "20m"
60
60
  },
61
- "gitHead": "3eb1a1d2d75b2b4a94807cd3bf759bc9fc531f05"
61
+ "gitHead": "f8c45b8a2e29a51522a81a6692af25b2d7f6b50f"
62
62
  }
package/src/cli.js ADDED
@@ -0,0 +1,20 @@
1
+ import { LOCAL_CONFIG_KEY, fetchNetworkConfig } from './network-config.js';
2
+
3
+ /**
4
+ * @import {MinimalNetworkConfig} from './network-config.js';
5
+ */
6
+
7
+ /**
8
+ * Fetch the network config for the AGORIC_NET environment variable.
9
+ *
10
+ * If none is set or it's 'local', return a local chain config.
11
+ *
12
+ * @param {{ env: typeof process.env, fetch: typeof fetch }} io
13
+ * @returns {Promise<MinimalNetworkConfig>}
14
+ */
15
+
16
+ export const fetchEnvNetworkConfig = async ({ env, fetch }) => {
17
+ const net = env.AGORIC_NET || LOCAL_CONFIG_KEY;
18
+
19
+ return fetchNetworkConfig(net, { fetch });
20
+ };
package/src/main.js CHANGED
@@ -1,5 +1,9 @@
1
+ export * from './cli.js';
2
+ export * from './network-config.js';
1
3
  export * from './rpc.js';
4
+ export * from './smart-wallet-kit.js';
2
5
  export * from './sync-tools.js';
6
+ export * from './vstorage.js';
3
7
  export * from './vstorage-kit.js';
4
8
  export * from './wallet-utils.js';
5
9
 
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @typedef {{ rpcAddrs: string[], chainName: string }} MinimalNetworkConfig
3
+ */
4
+
5
+ export const toNetworkConfigUrl = agoricNetSubdomain =>
6
+ `https://${agoricNetSubdomain}.agoric.net/network-config`;
7
+
8
+ export const toRpcUrl = agoricNetSubdomain =>
9
+ `https://${agoricNetSubdomain}.rpc.agoric.net:443`;
10
+
11
+ /** @satisfies {MinimalNetworkConfig} */
12
+ export const LOCAL_CONFIG = {
13
+ rpcAddrs: ['http://0.0.0.0:26657'],
14
+ chainName: 'agoriclocal',
15
+ };
16
+
17
+ export const LOCAL_CONFIG_KEY = 'local';
18
+
19
+ /**
20
+ * Fetches the network config for the given network specifier.
21
+ *
22
+ * @param {string} spec
23
+ * @param {{ fetch: typeof fetch }} io
24
+ * @returns {Promise<MinimalNetworkConfig>}
25
+ */
26
+ export const fetchNetworkConfig = async (spec, { fetch }) => {
27
+ const [netName, chainName] = spec.split(',');
28
+
29
+ if (netName === LOCAL_CONFIG_KEY) {
30
+ return LOCAL_CONFIG;
31
+ }
32
+
33
+ if (chainName) {
34
+ return { chainName, rpcAddrs: [toRpcUrl(netName)] };
35
+ }
36
+
37
+ return fetch(toNetworkConfigUrl(netName))
38
+ .then(res => res.json())
39
+ .catch(err => {
40
+ throw Error(`cannot get network config (${spec}): ${err.message}`);
41
+ });
42
+ };
package/src/rpc.js CHANGED
@@ -3,7 +3,7 @@ import { StargateClient } from '@cosmjs/stargate';
3
3
  import { Tendermint34Client } from '@cosmjs/tendermint-rpc';
4
4
 
5
5
  /**
6
- * @typedef {{ rpcAddrs: string[], chainName: string }} MinimalNetworkConfig
6
+ * @import {MinimalNetworkConfig} from './network-config.js';
7
7
  */
8
8
 
9
9
  // TODO distribute load
@@ -0,0 +1,113 @@
1
+ import { makeWalletStateCoalescer } from '@agoric/smart-wallet/src/utils.js';
2
+ import { pollBlocks } from './chain.js';
3
+ import { makeStargateClient } from './rpc.js';
4
+ import { makeAgoricNames, makeVstorageKit } from './vstorage-kit.js';
5
+
6
+ /**
7
+ * @import {Amount, Brand} from '@agoric/ertp/src/types.js'
8
+ * @import {CurrentWalletRecord, UpdateRecord} from '@agoric/smart-wallet/src/smartWallet.js';
9
+ * @import {MinimalNetworkConfig} from './network-config.js';
10
+ */
11
+
12
+ /**
13
+ * Augment VstorageKit with addtional convenience methods for working with
14
+ * Agoric smart wallets.
15
+ *
16
+ * @param {object} root0
17
+ * @param {typeof globalThis.fetch} root0.fetch
18
+ * @param {(ms: number) => Promise<void>} root0.delay
19
+ * @param {MinimalNetworkConfig} networkConfig
20
+ */
21
+ export const makeSmartWalletKit = async ({ fetch, delay }, networkConfig) => {
22
+ const vsk = makeVstorageKit({ fetch }, networkConfig);
23
+
24
+ const client = await makeStargateClient(networkConfig, { fetch });
25
+
26
+ const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
27
+
28
+ /**
29
+ * @param {string} from
30
+ * @param {number|string} [minHeight]
31
+ */
32
+ const storedWalletState = async (from, minHeight = undefined) => {
33
+ const history = await vsk.vstorage.readFully(
34
+ `published.wallet.${from}`,
35
+ minHeight,
36
+ );
37
+
38
+ /** @type {{ Invitation: Brand<'set'> }} */
39
+ // @ts-expect-error XXX how to narrow AssetKind to set?
40
+ const { Invitation } = agoricNames.brand;
41
+ const coalescer = makeWalletStateCoalescer(Invitation);
42
+ // update with oldest first
43
+ for (const txt of history.reverse()) {
44
+ const { body, slots } = JSON.parse(txt);
45
+ const record = vsk.marshaller.fromCapData({ body, slots });
46
+ coalescer.update(record);
47
+ }
48
+ const coalesced = coalescer.state;
49
+ harden(coalesced);
50
+ return coalesced;
51
+ };
52
+
53
+ /**
54
+ * Get OfferStatus by id, polling until available.
55
+ *
56
+ * @param {string} from
57
+ * @param {string|number} id
58
+ * @param {number|string} minHeight
59
+ * @param {boolean} [untilNumWantsSatisfied]
60
+ */
61
+ const pollOffer = async (
62
+ from,
63
+ id,
64
+ minHeight,
65
+ untilNumWantsSatisfied = false,
66
+ ) => {
67
+ const poll = pollBlocks({
68
+ client,
69
+ delay,
70
+ retryMessage: 'offer not in wallet at block',
71
+ });
72
+
73
+ const lookup = async () => {
74
+ const { offerStatuses } = await storedWalletState(from, minHeight);
75
+ const offerStatus = [...offerStatuses.values()].find(s => s.id === id);
76
+ if (!offerStatus) throw Error('retry');
77
+ harden(offerStatus);
78
+ if (untilNumWantsSatisfied && !('numWantsSatisfied' in offerStatus)) {
79
+ throw Error('retry (no numWantsSatisfied yet)');
80
+ }
81
+ return offerStatus;
82
+ };
83
+ return poll(lookup);
84
+ };
85
+
86
+ /**
87
+ * @param {string} addr
88
+ * @returns {Promise<UpdateRecord>}
89
+ */
90
+ const getLastUpdate = addr => {
91
+ return vsk.readPublished(`wallet.${addr}`);
92
+ };
93
+
94
+ /**
95
+ * @param {string} addr
96
+ * @returns {Promise<CurrentWalletRecord>}
97
+ */
98
+ const getCurrentWalletRecord = addr => {
99
+ return vsk.readPublished(`wallet.${addr}.current`);
100
+ };
101
+
102
+ return {
103
+ // pass along all of VstorageKit
104
+ ...vsk,
105
+ agoricNames,
106
+ networkConfig,
107
+ getLastUpdate,
108
+ getCurrentWalletRecord,
109
+ storedWalletState,
110
+ pollOffer,
111
+ };
112
+ };
113
+ /** @typedef {Awaited<ReturnType<typeof makeSmartWalletKit>>} SmartWalletKit */
@@ -1,135 +1,18 @@
1
- /* global Buffer */
2
1
  import {
3
2
  boardSlottingMarshaller,
4
3
  makeBoardRemote,
5
4
  } from '@agoric/vats/tools/board-utils.js';
5
+ import { assertAllDefined } from '@agoric/internal';
6
+ import { makeVStorage } from './vstorage.js';
6
7
 
7
8
  export { boardSlottingMarshaller };
8
9
 
9
10
  /**
10
- * @import {MinimalNetworkConfig} from './rpc.js';
11
+ * @import {MinimalNetworkConfig} from './network-config.js';
11
12
  * @import {TypedPublished} from './types.js';
13
+ * @import {VStorage} from './vstorage.js';
12
14
  */
13
15
 
14
- /**
15
- * @param {object} powers
16
- * @param {typeof window.fetch} powers.fetch
17
- * @param {MinimalNetworkConfig} config
18
- */
19
- export const makeVStorage = (powers, config) => {
20
- /** @param {string} path */
21
- const getJSON = path => {
22
- const url = config.rpcAddrs[0] + path;
23
- // console.warn('fetching', url);
24
- return powers.fetch(url, { keepalive: true }).then(res => res.json());
25
- };
26
- // height=0 is the same as omitting height and implies the highest block
27
- const url = (path = 'published', { kind = 'children', height = 0 } = {}) =>
28
- `/abci_query?path=%22/custom/vstorage/${kind}/${path}%22&height=${height}`;
29
-
30
- const readStorage = (path = 'published', { kind = 'children', height = 0 }) =>
31
- getJSON(url(path, { kind, height }))
32
- .catch(err => {
33
- throw Error(`cannot read ${kind} of ${path}: ${err.message}`);
34
- })
35
- .then(data => {
36
- const {
37
- result: { response },
38
- } = data;
39
- if (response?.code !== 0) {
40
- /** @type {any} */
41
- const err = Error(
42
- `error code ${response?.code} reading ${kind} of ${path}: ${response.log}`,
43
- );
44
- err.code = response?.code;
45
- err.codespace = response?.codespace;
46
- throw err;
47
- }
48
- return data;
49
- });
50
-
51
- return {
52
- url,
53
- decode({ result: { response } }) {
54
- const { code } = response;
55
- if (code !== 0) {
56
- throw response;
57
- }
58
- const { value } = response;
59
- return Buffer.from(value, 'base64').toString();
60
- },
61
- /**
62
- *
63
- * @param {string} path
64
- * @returns {Promise<string>} latest vstorage value at path
65
- */
66
- async readLatest(path = 'published') {
67
- const raw = await readStorage(path, { kind: 'data' });
68
- return this.decode(raw);
69
- },
70
- async keys(path = 'published') {
71
- const raw = await readStorage(path, { kind: 'children' });
72
- return JSON.parse(this.decode(raw)).children;
73
- },
74
- /**
75
- * @param {string} path
76
- * @param {number} [height] default is highest
77
- * @returns {Promise<{blockHeight: number, values: string[]}>}
78
- */
79
- async readAt(path, height = undefined) {
80
- const raw = await readStorage(path, { kind: 'data', height });
81
- const txt = this.decode(raw);
82
- /** @type {{ value: string }} */
83
- const { value } = JSON.parse(txt);
84
- return JSON.parse(value);
85
- },
86
- /**
87
- * Read values going back as far as available
88
- *
89
- * @param {string} path
90
- * @param {number | string} [minHeight]
91
- * @returns {Promise<string[]>}
92
- */
93
- async readFully(path, minHeight = undefined) {
94
- const parts = [];
95
- // undefined the first iteration, to query at the highest
96
- let blockHeight;
97
- await null;
98
- do {
99
- // console.debug('READING', { blockHeight });
100
- let values;
101
- try {
102
- ({ blockHeight, values } = await this.readAt(
103
- path,
104
- blockHeight && Number(blockHeight) - 1,
105
- ));
106
- // console.debug('readAt returned', { blockHeight });
107
- } catch (err) {
108
- if (
109
- // CosmosSDK ErrInvalidRequest with particular message text;
110
- // misrepresentation of pruned data
111
- // TODO replace after incorporating a fix to
112
- // https://github.com/cosmos/cosmos-sdk/issues/19992
113
- err.codespace === 'sdk' &&
114
- err.code === 18 &&
115
- err.message.match(/pruned/)
116
- ) {
117
- // console.error(err);
118
- break;
119
- }
120
- throw err;
121
- }
122
- parts.push(values);
123
- // console.debug('PUSHED', values);
124
- // console.debug('NEW', { blockHeight, minHeight });
125
- if (minHeight && Number(blockHeight) <= Number(minHeight)) break;
126
- } while (blockHeight > 0);
127
- return parts.flat();
128
- },
129
- };
130
- };
131
- /** @typedef {ReturnType<typeof makeVStorage>} VStorage */
132
-
133
16
  /** @deprecated */
134
17
  export const makeFromBoard = () => {
135
18
  const cache = new Map();
@@ -191,6 +74,7 @@ harden(storageHelper);
191
74
  * @returns {Promise<import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes>}
192
75
  */
193
76
  export const makeAgoricNames = async (ctx, vstorage) => {
77
+ assertAllDefined({ ctx, vstorage });
194
78
  const reverse = {};
195
79
  const entries = await Promise.all(
196
80
  ['brand', 'instance', 'vbankAsset'].map(async kind => {
@@ -214,12 +98,10 @@ export const makeAgoricNames = async (ctx, vstorage) => {
214
98
  * @param {{ fetch: typeof window.fetch }} io
215
99
  * @param {MinimalNetworkConfig} config
216
100
  */
217
- export const makeVstorageKit = async ({ fetch }, config) => {
218
- await null;
101
+ export const makeVstorageKit = ({ fetch }, config) => {
219
102
  try {
220
103
  const vstorage = makeVStorage({ fetch }, config);
221
104
  const fromBoard = makeFromBoard();
222
- const agoricNames = await makeAgoricNames(fromBoard, vstorage);
223
105
 
224
106
  const marshaller = boardSlottingMarshaller(fromBoard.convertSlotToVal);
225
107
 
@@ -249,7 +131,6 @@ export const makeVstorageKit = async ({ fetch }, config) => {
249
131
  readLatestHead(`published.${subpath}`);
250
132
 
251
133
  return {
252
- agoricNames,
253
134
  fromBoard,
254
135
  marshaller,
255
136
  readLatestHead,
@@ -261,4 +142,4 @@ export const makeVstorageKit = async ({ fetch }, config) => {
261
142
  throw Error(`RPC failure (${config.rpcAddrs}): ${err.message}`);
262
143
  }
263
144
  };
264
- /** @typedef {Awaited<ReturnType<typeof makeVstorageKit>>} VstorageKit */
145
+ /** @typedef {ReturnType<typeof makeVstorageKit>} VstorageKit */
@@ -0,0 +1,125 @@
1
+ /* global Buffer */
2
+
3
+ /**
4
+ * @import {MinimalNetworkConfig} from './network-config.js';
5
+ */
6
+
7
+ /**
8
+ * @param {object} powers
9
+ * @param {typeof window.fetch} powers.fetch
10
+ * @param {MinimalNetworkConfig} config
11
+ */
12
+ export const makeVStorage = ({ fetch }, config) => {
13
+ /** @param {string} path */
14
+ const getJSON = path => {
15
+ const url = config.rpcAddrs[0] + path;
16
+ // console.warn('fetching', url);
17
+ return fetch(url, { keepalive: true }).then(res => res.json());
18
+ };
19
+ // height=0 is the same as omitting height and implies the highest block
20
+ const url = (path = 'published', { kind = 'children', height = 0 } = {}) =>
21
+ `/abci_query?path=%22/custom/vstorage/${kind}/${path}%22&height=${height}`;
22
+
23
+ const readStorage = (path = 'published', { kind = 'children', height = 0 }) =>
24
+ getJSON(url(path, { kind, height }))
25
+ .catch(err => {
26
+ throw Error(`cannot read ${kind} of ${path}: ${err.message}`);
27
+ })
28
+ .then(data => {
29
+ const {
30
+ result: { response },
31
+ } = data;
32
+ if (response?.code !== 0) {
33
+ /** @type {any} */
34
+ const err = Error(
35
+ `error code ${response?.code} reading ${kind} of ${path}: ${response.log}`,
36
+ );
37
+ err.code = response?.code;
38
+ err.codespace = response?.codespace;
39
+ throw err;
40
+ }
41
+ return data;
42
+ });
43
+
44
+ const vstorage = {
45
+ url,
46
+ decode({ result: { response } }) {
47
+ const { code } = response;
48
+ if (code !== 0) {
49
+ throw response;
50
+ }
51
+ const { value } = response;
52
+ return Buffer.from(value, 'base64').toString();
53
+ },
54
+ /**
55
+ *
56
+ * @param {string} path
57
+ * @returns {Promise<string>} latest vstorage value at path
58
+ */
59
+ async readLatest(path = 'published') {
60
+ const raw = await readStorage(path, { kind: 'data' });
61
+ return vstorage.decode(raw);
62
+ },
63
+ async keys(path = 'published') {
64
+ const raw = await readStorage(path, { kind: 'children' });
65
+ return JSON.parse(vstorage.decode(raw)).children;
66
+ },
67
+ /**
68
+ * @param {string} path
69
+ * @param {number} [height] default is highest
70
+ * @returns {Promise<{blockHeight: number, values: string[]}>}
71
+ */
72
+ async readAt(path, height = undefined) {
73
+ const raw = await readStorage(path, { kind: 'data', height });
74
+ const txt = vstorage.decode(raw);
75
+ /** @type {{ value: string }} */
76
+ const { value } = JSON.parse(txt);
77
+ return JSON.parse(value);
78
+ },
79
+ /**
80
+ * Read values going back as far as available
81
+ *
82
+ * @param {string} path
83
+ * @param {number | string} [minHeight]
84
+ * @returns {Promise<string[]>}
85
+ */
86
+ async readFully(path, minHeight = undefined) {
87
+ const parts = [];
88
+ // undefined the first iteration, to query at the highest
89
+ let blockHeight;
90
+ await null;
91
+ do {
92
+ // console.debug('READING', { blockHeight });
93
+ let values;
94
+ try {
95
+ ({ blockHeight, values } = await vstorage.readAt(
96
+ path,
97
+ blockHeight && Number(blockHeight) - 1,
98
+ ));
99
+ // console.debug('readAt returned', { blockHeight });
100
+ } catch (err) {
101
+ if (
102
+ // CosmosSDK ErrInvalidRequest with particular message text;
103
+ // misrepresentation of pruned data
104
+ // TODO replace after incorporating a fix to
105
+ // https://github.com/cosmos/cosmos-sdk/issues/19992
106
+ err.codespace === 'sdk' &&
107
+ err.code === 18 &&
108
+ err.message.match(/pruned/)
109
+ ) {
110
+ // console.error(err);
111
+ break;
112
+ }
113
+ throw err;
114
+ }
115
+ parts.push(values);
116
+ // console.debug('PUSHED', values);
117
+ // console.debug('NEW', { blockHeight, minHeight });
118
+ if (minHeight && Number(blockHeight) <= Number(minHeight)) break;
119
+ } while (blockHeight > 0);
120
+ return parts.flat();
121
+ },
122
+ };
123
+ return vstorage;
124
+ };
125
+ /** @typedef {ReturnType<typeof makeVStorage>} VStorage */
@@ -1,113 +1,8 @@
1
- import { makeWalletStateCoalescer } from '@agoric/smart-wallet/src/utils.js';
2
- import { pollBlocks } from './chain.js';
3
- import { makeStargateClient } from './rpc.js';
4
- import { boardSlottingMarshaller, makeVstorageKit } from './vstorage-kit.js';
1
+ /** @file backwards compat */
5
2
 
6
- /**
7
- * @import {Amount, Brand} from '@agoric/ertp/src/types.js'
8
- * @import {CurrentWalletRecord, UpdateRecord} from '@agoric/smart-wallet/src/smartWallet.js';
9
- * @import {MinimalNetworkConfig} from './rpc.js';
10
- */
3
+ import { makeSmartWalletKit } from './smart-wallet-kit.js';
11
4
 
12
- // XXX this is really a SmartWalletKit
13
- /**
14
- * Augment VstorageKit with addtional convenience methods for working with
15
- * Agoric smart wallets.
16
- *
17
- * @param {object} root0
18
- * @param {typeof globalThis.fetch} root0.fetch
19
- * @param {(ms: number) => Promise<void>} root0.delay
20
- * @param {MinimalNetworkConfig} networkConfig
21
- */
22
- export const makeWalletUtils = async ({ fetch, delay }, networkConfig) => {
23
- const vsk = await makeVstorageKit({ fetch }, networkConfig);
5
+ /** @typedef {import('./smart-wallet-kit.js').SmartWalletKit} WalletUtils */
24
6
 
25
- const m = boardSlottingMarshaller(vsk.fromBoard.convertSlotToVal);
26
-
27
- const client = await makeStargateClient(networkConfig, { fetch });
28
-
29
- /**
30
- * @param {string} from
31
- * @param {number|string} [minHeight]
32
- */
33
- const storedWalletState = async (from, minHeight = undefined) => {
34
- const history = await vsk.vstorage.readFully(
35
- `published.wallet.${from}`,
36
- minHeight,
37
- );
38
-
39
- /** @type {{ Invitation: Brand<'set'> }} */
40
- // @ts-expect-error XXX how to narrow AssetKind to set?
41
- const { Invitation } = vsk.agoricNames.brand;
42
- const coalescer = makeWalletStateCoalescer(Invitation);
43
- // update with oldest first
44
- for (const txt of history.reverse()) {
45
- const { body, slots } = JSON.parse(txt);
46
- const record = m.fromCapData({ body, slots });
47
- coalescer.update(record);
48
- }
49
- const coalesced = coalescer.state;
50
- harden(coalesced);
51
- return coalesced;
52
- };
53
-
54
- /**
55
- * Get OfferStatus by id, polling until available.
56
- *
57
- * @param {string} from
58
- * @param {string|number} id
59
- * @param {number|string} minHeight
60
- * @param {boolean} [untilNumWantsSatisfied]
61
- */
62
- const pollOffer = async (
63
- from,
64
- id,
65
- minHeight,
66
- untilNumWantsSatisfied = false,
67
- ) => {
68
- const poll = pollBlocks({
69
- client,
70
- delay,
71
- retryMessage: 'offer not in wallet at block',
72
- });
73
-
74
- const lookup = async () => {
75
- const { offerStatuses } = await storedWalletState(from, minHeight);
76
- const offerStatus = [...offerStatuses.values()].find(s => s.id === id);
77
- if (!offerStatus) throw Error('retry');
78
- harden(offerStatus);
79
- if (untilNumWantsSatisfied && !('numWantsSatisfied' in offerStatus)) {
80
- throw Error('retry (no numWantsSatisfied yet)');
81
- }
82
- return offerStatus;
83
- };
84
- return poll(lookup);
85
- };
86
-
87
- /**
88
- * @param {string} addr
89
- * @returns {Promise<UpdateRecord>}
90
- */
91
- const getLastUpdate = addr => {
92
- return vsk.readPublished(`wallet.${addr}`);
93
- };
94
-
95
- /**
96
- * @param {string} addr
97
- * @returns {Promise<CurrentWalletRecord>}
98
- */
99
- const getCurrentWalletRecord = addr => {
100
- return vsk.readPublished(`wallet.${addr}.current`);
101
- };
102
-
103
- return {
104
- // pass along all of VstorageKit
105
- ...vsk,
106
- networkConfig,
107
- getLastUpdate,
108
- getCurrentWalletRecord,
109
- storedWalletState,
110
- pollOffer,
111
- };
112
- };
113
- /** @typedef {Awaited<ReturnType<typeof makeWalletUtils>>} WalletUtils */
7
+ /** @deprecated use `makeSmartWalletKit` */
8
+ export const makeWalletUtils = makeSmartWalletKit;