@agoric/client-utils 0.1.1-dev-d4385f0.0 → 0.1.1-dev-1dd4589.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 +7 -7
- package/src/main.js +1 -0
- package/src/vstorage-kit.js +2 -120
- package/src/vstorage.js +125 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/client-utils",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-1dd4589.0+1dd4589",
|
|
4
4
|
"description": "Utilities for building Agoric clients",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"ts-blank-space": "^0.4.1"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agoric/casting": "0.4.3-dev-
|
|
31
|
-
"@agoric/ertp": "0.16.3-dev-
|
|
32
|
-
"@agoric/internal": "0.3.3-dev-
|
|
33
|
-
"@agoric/smart-wallet": "0.5.4-dev-
|
|
34
|
-
"@agoric/vats": "0.15.2-dev-
|
|
30
|
+
"@agoric/casting": "0.4.3-dev-1dd4589.0+1dd4589",
|
|
31
|
+
"@agoric/ertp": "0.16.3-dev-1dd4589.0+1dd4589",
|
|
32
|
+
"@agoric/internal": "0.3.3-dev-1dd4589.0+1dd4589",
|
|
33
|
+
"@agoric/smart-wallet": "0.5.4-dev-1dd4589.0+1dd4589",
|
|
34
|
+
"@agoric/vats": "0.15.2-dev-1dd4589.0+1dd4589",
|
|
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": "
|
|
61
|
+
"gitHead": "1dd458941b740258ee2d43de48a8a1b9e0fdcae8"
|
|
62
62
|
}
|
package/src/main.js
CHANGED
package/src/vstorage-kit.js
CHANGED
|
@@ -1,135 +1,17 @@
|
|
|
1
|
-
/* global Buffer */
|
|
2
1
|
import {
|
|
3
2
|
boardSlottingMarshaller,
|
|
4
3
|
makeBoardRemote,
|
|
5
4
|
} from '@agoric/vats/tools/board-utils.js';
|
|
5
|
+
import { makeVStorage } from './vstorage.js';
|
|
6
6
|
|
|
7
7
|
export { boardSlottingMarshaller };
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @import {MinimalNetworkConfig} from './rpc.js';
|
|
11
11
|
* @import {TypedPublished} from './types.js';
|
|
12
|
+
* @import {VStorage} from './vstorage.js';
|
|
12
13
|
*/
|
|
13
14
|
|
|
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
15
|
/** @deprecated */
|
|
134
16
|
export const makeFromBoard = () => {
|
|
135
17
|
const cache = new Map();
|
package/src/vstorage.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/* global Buffer */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @import {MinimalNetworkConfig} from './rpc.js';
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {object} powers
|
|
9
|
+
* @param {typeof window.fetch} powers.fetch
|
|
10
|
+
* @param {MinimalNetworkConfig} config
|
|
11
|
+
*/
|
|
12
|
+
export const makeVStorage = (powers, config) => {
|
|
13
|
+
/** @param {string} path */
|
|
14
|
+
const getJSON = path => {
|
|
15
|
+
const url = config.rpcAddrs[0] + path;
|
|
16
|
+
// console.warn('fetching', url);
|
|
17
|
+
return powers.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 */
|