@agoric/casting 0.4.2 → 0.4.3-calypso-dev-84eb287.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.
Files changed (40) hide show
  1. package/README.md +3 -3
  2. package/package.json +25 -22
  3. package/src/casting-spec.d.ts +8 -8
  4. package/src/casting-spec.d.ts.map +1 -1
  5. package/src/casting-spec.js +7 -9
  6. package/src/change-follower.d.ts +1 -1
  7. package/src/change-follower.d.ts.map +1 -1
  8. package/src/change-follower.js +2 -2
  9. package/src/defaults.d.ts +2 -2
  10. package/src/defaults.d.ts.map +1 -1
  11. package/src/defaults.js +1 -1
  12. package/src/follower-cosmjs.d.ts +1 -1
  13. package/src/follower-cosmjs.d.ts.map +1 -1
  14. package/src/follower-cosmjs.js +39 -15
  15. package/src/follower.d.ts +1 -1
  16. package/src/follower.d.ts.map +1 -1
  17. package/src/follower.js +6 -6
  18. package/src/iterable.d.ts +12 -12
  19. package/src/iterable.d.ts.map +1 -1
  20. package/src/iterable.js +2 -1
  21. package/src/leader-netconfig.d.ts +2 -2
  22. package/src/leader-netconfig.d.ts.map +1 -1
  23. package/src/leader.d.ts +1 -1
  24. package/src/main.js +2 -0
  25. package/src/makeHttpClient.d.ts +2 -0
  26. package/src/makeHttpClient.d.ts.map +1 -0
  27. package/src/makeHttpClient.js +56 -0
  28. package/src/netconfig.d.ts.map +1 -1
  29. package/src/shuffle.d.ts +1 -1
  30. package/src/shuffle.d.ts.map +1 -1
  31. package/src/types.d.ts +13 -7
  32. package/src/types.d.ts.map +1 -1
  33. package/src/types.js +11 -8
  34. package/test/interpose-net-access.test.js +118 -0
  35. package/test/{test-mvp.js → mvp.test.js} +57 -1
  36. package/test/net-access-fixture.js +196 -0
  37. package/tsconfig.build.json +6 -0
  38. package/{jsconfig.json → tsconfig.json} +1 -0
  39. package/jsconfig.build.json +0 -12
  40. /package/test/{test-netconfig.js → netconfig.test.js} +0 -0
package/README.md CHANGED
@@ -42,7 +42,7 @@ The `followerOpts` argument in `makeFollower(leader, key, followerOpts)` provide
42
42
  - the `decode` option is a function to translate `buf: Uint8Array` into `data: string`
43
43
  - (default) - interpret buf as a utf-8 string, then `JSON.parse` it
44
44
  - the `unserializer` option can be
45
- - (default) - release unserialized objects using `@agoric/marshal`'s `makeMarshal()`
45
+ - (default) - release unserialized objects using [@endo/marshal](https://www.npmjs.com/package/@endo/marshal)'s `makeMarshal()`
46
46
  - `null` - don't additionally unserialize data before releasing it
47
47
  - any unserializer object supporting `E(unserializer).fromCapData(data)`
48
48
  - the `crasher` option can be
@@ -65,8 +65,8 @@ The `followerOpts` argument in `makeFollower(leader, key, followerOpts)` provide
65
65
 
66
66
  This package currently depends on:
67
67
  - Hardened Javascript
68
- - `@agoric/notify` async iterable adapters to implement `iterateLatest`
69
- - `@endo/marshal` for default object unserialization
68
+ - [@agoric/notifier](../notifier) async iterable adapters to implement `iterateLatest`
69
+ - [@endo/marshal](https://www.npmjs.com/package/@endo/marshal) for default object unserialization
70
70
  - [CosmJS](https://github.com/cosmos/cosmjs) for proof verification, although [it does not yet support light client tracking of the validator set](https://github.com/cosmos/cosmjs/issues/492)
71
71
  - a bespoke follower of [WebSocket Tendermint events](https://docs.tendermint.com/master/tendermint-core/subscription.html#legacy-streaming-api)
72
72
 
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@agoric/casting",
3
- "version": "0.4.2",
3
+ "version": "0.4.3-calypso-dev-84eb287.0+84eb287",
4
4
  "description": "Agoric's OCap broadcasting system",
5
5
  "type": "module",
6
6
  "main": "src/main.js",
7
7
  "repository": "https://github.com/Agoric/agoric-sdk",
8
8
  "scripts": {
9
9
  "build": "exit 0",
10
- "prepack": "tsc --build jsconfig.build.json",
10
+ "prepack": "tsc --build tsconfig.build.json",
11
11
  "postpack": "git clean -f '*.d.ts*'",
12
12
  "demo": "node -e 'import(\"./test/fake-rpc-server.js\").then(ns => ns.develop())'",
13
13
  "test": "ava",
@@ -15,33 +15,33 @@
15
15
  "test:xs": "exit 0",
16
16
  "lint-fix": "yarn lint:eslint --fix",
17
17
  "lint": "run-s --continue-on-error lint:*",
18
- "lint:types": "tsc -p jsconfig.json",
18
+ "lint:types": "tsc",
19
19
  "lint:eslint": "eslint --ext .js,.ts ."
20
20
  },
21
21
  "keywords": [],
22
22
  "author": "Agoric",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@agoric/internal": "^0.3.2",
26
- "@agoric/notifier": "^0.6.2",
27
- "@agoric/spawner": "^0.6.8",
28
- "@agoric/store": "^0.9.2",
29
- "@cosmjs/encoding": "^0.30.1",
30
- "@cosmjs/proto-signing": "^0.30.1",
31
- "@cosmjs/stargate": "^0.30.1",
32
- "@cosmjs/tendermint-rpc": "^0.30.1",
33
- "@endo/far": "^0.2.18",
34
- "@endo/init": "^0.5.56",
35
- "@endo/lockdown": "^0.1.28",
36
- "@endo/marshal": "^0.8.5",
37
- "@endo/promise-kit": "^0.2.56",
25
+ "@agoric/internal": "0.3.3-calypso-dev-84eb287.0+84eb287",
26
+ "@agoric/notifier": "0.6.3-calypso-dev-84eb287.0+84eb287",
27
+ "@agoric/store": "0.9.3-calypso-dev-84eb287.0+84eb287",
28
+ "@cosmjs/encoding": "^0.32.3",
29
+ "@cosmjs/proto-signing": "^0.32.3",
30
+ "@cosmjs/stargate": "^0.32.3",
31
+ "@cosmjs/tendermint-rpc": "^0.32.3",
32
+ "@endo/far": "^1.1.2",
33
+ "@endo/init": "^1.1.2",
34
+ "@endo/lockdown": "^1.0.7",
35
+ "@endo/marshal": "^1.5.0",
36
+ "@endo/promise-kit": "^1.1.2",
38
37
  "node-fetch": "^2.6.0"
39
38
  },
40
39
  "devDependencies": {
41
- "@endo/ses-ava": "^0.2.40",
40
+ "@agoric/cosmic-proto": "0.4.1-calypso-dev-84eb287.0+84eb287",
41
+ "@endo/ses-ava": "^1.2.2",
42
42
  "@types/node-fetch": "^2.6.2",
43
- "ava": "^5.2.0",
44
- "c8": "^7.13.0",
43
+ "ava": "^5.3.0",
44
+ "c8": "^9.1.0",
45
45
  "express": "^4.17.1",
46
46
  "ws": "^7.2.0"
47
47
  },
@@ -49,14 +49,17 @@
49
49
  "access": "public"
50
50
  },
51
51
  "engines": {
52
- "node": ">=14.15.0"
52
+ "node": "^18.12 || ^20.9"
53
53
  },
54
54
  "ava": {
55
55
  "files": [
56
- "test/**/test-*.js"
56
+ "test/**/*.test.*"
57
57
  ],
58
58
  "timeout": "20m",
59
59
  "workerThreads": false
60
60
  },
61
- "gitHead": "b66bf7c881ae462fcb617cd6e8d41b5c40ec58ef"
61
+ "typeCoverage": {
62
+ "atLeast": 88.94
63
+ },
64
+ "gitHead": "84eb287915c8255d68e845a9b6e10c790f0d54cb"
62
65
  }
@@ -2,15 +2,15 @@ export function vstorageKeySpecToPath({ storeName, storeSubkey }: VStorageKey):
2
2
  /**
3
3
  * @param {string} storagePath
4
4
  * @param {string} [storeName]
5
- * @returns {import('./types').CastingSpec}
5
+ * @returns {import('./types.js').CastingSpec}
6
6
  */
7
- export function DEFAULT_PATH_CONVERTER(storagePath: string, storeName?: string | undefined): import('./types').CastingSpec;
7
+ export function DEFAULT_PATH_CONVERTER(storagePath: string, storeName?: string | undefined): import("./types.js").CastingSpec;
8
8
  /**
9
- * @type {Record<string, (path: string) => import('./types').CastingSpec>}
9
+ * @type {Record<string, (path: string) => import('./types.js').CastingSpec>}
10
10
  */
11
- export const pathPrefixToConverters: Record<string, (path: string) => import('./types').CastingSpec>;
12
- export function makeCastingSpecFromString(specString: string): import('./types').CastingSpec;
13
- export function makeCastingSpecFromObject(specObj: any): import('./types').CastingSpec;
14
- export function makeCastingSpecFromRef(specCap: ERef<any>): Promise<import('./types').CastingSpec>;
15
- export function makeCastingSpec(sourceP: ERef<unknown>): Promise<import('./types').CastingSpec>;
11
+ export const pathPrefixToConverters: Record<string, (path: string) => import("./types.js").CastingSpec>;
12
+ export function makeCastingSpecFromString(specString: string): import("./types.js").CastingSpec;
13
+ export function makeCastingSpecFromObject(specObj: any): import("./types.js").CastingSpec;
14
+ export function makeCastingSpecFromRef(specCap: ERef<any>): Promise<import("./types.js").CastingSpec>;
15
+ export function makeCastingSpec(sourceP: ERef<unknown>): Promise<import("./types.js").CastingSpec>;
16
16
  //# sourceMappingURL=casting-spec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"casting-spec.d.ts","sourceRoot":"","sources":["casting-spec.js"],"names":[],"mappings":"AA+CO,kEAHI,WAAW,GACT,MAAM,CAYlB;AAlCD;;;;GAIG;AACH,oDAJW,MAAM,mCAEJ,OAAO,SAAS,EAAE,WAAW,CAazC;AAsBD;;GAEG;AACH,2DAFgC,MAAM,KAAK,OAAO,SAAS,EAAE,WAAW,EAMrE;AAMI,sDAHI,MAAM,GACJ,OAAO,SAAS,EAAE,WAAW,CAczC;AAQM,mDAHI,GAAG,GACD,OAAO,SAAS,EAAE,WAAW,CAmCzC;AAMM,gDAHI,KAAK,GAAG,CAAC,GACP,QAAQ,OAAO,SAAS,EAAE,WAAW,CAAC,CAKlD;AAQM,yCAHI,KAAK,OAAO,CAAC,GACX,QAAQ,OAAO,SAAS,EAAE,WAAW,CAAC,CAgBlD"}
1
+ {"version":3,"file":"casting-spec.d.ts","sourceRoot":"","sources":["casting-spec.js"],"names":[],"mappings":"AA6CO,kEAHI,WAAW,GACT,MAAM,CAYlB;AAlCD;;;;GAIG;AACH,oDAJW,MAAM,mCAEJ,OAAO,YAAY,EAAE,WAAW,CAa5C;AAsBD;;GAEG;AACH,qCAFU,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,YAAY,EAAE,WAAW,CAAC,CAMzE;AAMI,sDAHI,MAAM,GACJ,OAAO,YAAY,EAAE,WAAW,CAc5C;AAQM,mDAHI,GAAG,GACD,OAAO,YAAY,EAAE,WAAW,CAmC5C;AAMM,gDAHI,IAAI,CAAC,GAAG,CAAC,GACP,OAAO,CAAC,OAAO,YAAY,EAAE,WAAW,CAAC,CAKrD;AAQM,yCAHI,IAAI,CAAC,OAAO,CAAC,GACX,OAAO,CAAC,OAAO,YAAY,EAAE,WAAW,CAAC,CAgBrD"}
@@ -1,13 +1,11 @@
1
1
  import * as encodingStar from '@cosmjs/encoding';
2
2
  import { E, getInterfaceOf } from '@endo/far';
3
3
 
4
- import './types.js';
5
-
6
4
  const { toAscii } = encodingStar;
7
5
 
8
6
  /**
9
7
  * @param {string} storagePath
10
- * @returns {import('./types').CastingSpec}
8
+ * @returns {import('./types.js').CastingSpec}
11
9
  */
12
10
  const swingsetPathToCastingSpec = storagePath =>
13
11
  harden({
@@ -24,7 +22,7 @@ const NO_DATA_VALUE = new Uint8Array([255]);
24
22
  /**
25
23
  * @param {string} storagePath
26
24
  * @param {string} [storeName]
27
- * @returns {import('./types').CastingSpec}
25
+ * @returns {import('./types.js').CastingSpec}
28
26
  */
29
27
  const vstoragePathToCastingSpec = (storagePath, storeName = 'vstorage') => {
30
28
  const elems = storagePath ? storagePath.split('.') : [];
@@ -60,7 +58,7 @@ export const vstorageKeySpecToPath = ({ storeName, storeSubkey }) => {
60
58
  export const DEFAULT_PATH_CONVERTER = vstoragePathToCastingSpec;
61
59
 
62
60
  /**
63
- * @type {Record<string, (path: string) => import('./types').CastingSpec>}
61
+ * @type {Record<string, (path: string) => import('./types.js').CastingSpec>}
64
62
  */
65
63
  export const pathPrefixToConverters = harden({
66
64
  'swingset:': swingsetPathToCastingSpec,
@@ -70,7 +68,7 @@ export const pathPrefixToConverters = harden({
70
68
 
71
69
  /**
72
70
  * @param {string} specString
73
- * @returns {import('./types').CastingSpec}
71
+ * @returns {import('./types.js').CastingSpec}
74
72
  */
75
73
  export const makeCastingSpecFromString = specString => {
76
74
  assert.typeof(specString, 'string');
@@ -90,7 +88,7 @@ const te = new TextEncoder();
90
88
 
91
89
  /**
92
90
  * @param {any} specObj
93
- * @returns {import('./types').CastingSpec}
91
+ * @returns {import('./types.js').CastingSpec}
94
92
  */
95
93
  export const makeCastingSpecFromObject = specObj => {
96
94
  const {
@@ -129,7 +127,7 @@ export const makeCastingSpecFromObject = specObj => {
129
127
 
130
128
  /**
131
129
  * @param {ERef<any>} specCap
132
- * @returns {Promise<import('./types').CastingSpec>}
130
+ * @returns {Promise<import('./types.js').CastingSpec>}
133
131
  */
134
132
  export const makeCastingSpecFromRef = async specCap => {
135
133
  const specObj = await E(specCap).getStoreKey();
@@ -140,7 +138,7 @@ export const makeCastingSpecFromRef = async specCap => {
140
138
  * Create an abstract type from a given source representation
141
139
  *
142
140
  * @param {ERef<unknown>} sourceP
143
- * @returns {Promise<import('./types').CastingSpec>}
141
+ * @returns {Promise<import('./types.js').CastingSpec>}
144
142
  */
145
143
  export const makeCastingSpec = async sourceP => {
146
144
  const spec = await sourceP;
@@ -1,2 +1,2 @@
1
- export function makePollingChangeFollower(leader: import('./types').Leader): Promise<import('./types.js').Follower<import('./types').CastingChange>>;
1
+ export function makePollingChangeFollower(leader: import("./types.js").Leader): Promise<import("./types.js").Follower<import("./types.js").CastingChange>>;
2
2
  //# sourceMappingURL=change-follower.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-follower.d.ts","sourceRoot":"","sources":["change-follower.js"],"names":[],"mappings":"AASO,kDAHI,OAAO,SAAS,EAAE,MAAM,GACtB,QAAQ,OAAO,YAAY,EAAE,QAAQ,CAAC,OAAO,SAAS,EAAE,aAAa,CAAC,CAAC,CA6CnF"}
1
+ {"version":3,"file":"change-follower.d.ts","sourceRoot":"","sources":["change-follower.js"],"names":[],"mappings":"AASO,kDAHI,OAAO,YAAY,EAAE,MAAM,GACzB,OAAO,CAAC,OAAO,YAAY,EAAE,QAAQ,CAAC,OAAO,YAAY,EAAE,aAAa,CAAC,CAAC,CA6CtF"}
@@ -4,8 +4,8 @@ import { DEFAULT_KEEP_POLLING } from './defaults.js';
4
4
  /**
5
5
  * Just return an unspecified allegedValue every poll period.
6
6
  *
7
- * @param {import('./types').Leader} leader
8
- * @returns {Promise<import('./types.js').Follower<import('./types').CastingChange>>}
7
+ * @param {import('./types.js').Leader} leader
8
+ * @returns {Promise<import('./types.js').Follower<import('./types.js').CastingChange>>}
9
9
  */
10
10
  export const makePollingChangeFollower = async leader => {
11
11
  const { keepPolling = DEFAULT_KEEP_POLLING } = await E(leader).getOptions();
package/src/defaults.d.ts CHANGED
@@ -15,7 +15,7 @@ export function MAKE_DEFAULT_DECODER(): (str: any) => any;
15
15
  /**
16
16
  * Unserialize the JSONable data.
17
17
  *
18
- * @type {() => import('./types').Unserializer}
18
+ * @type {() => import('./types.js').Unserializer}
19
19
  */
20
- export const MAKE_DEFAULT_UNSERIALIZER: () => import('./types').Unserializer;
20
+ export const MAKE_DEFAULT_UNSERIALIZER: () => import("./types.js").Unserializer;
21
21
  //# sourceMappingURL=defaults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["defaults.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,yDAA0D;AAE1D,uCAAwC;AAExC,mDAAoD;AAEpD,6CAA8C;AAUvC,0BAHI,MAAM,GACJ,QAAQ,IAAI,CAAC,CAEgD;AAMnE,qCAHI,MAAM,oCAKhB;AAOM,8HAEN;AAQM,sCAHI,MAAM,GACJ,QAAQ,IAAI,CAAC,CAMzB;AAUM,8CALI,MAAM,OACN,GAAG,iCAED,QAAQ,IAAI,CAAC,CASzB;AAOM,wCAFM,QAAQ,OAAO,CAAC,CAGgD;AAEtE,0DAaN;AAED;;;;GAIG;AACH,wCAFU,MAAM,OAAO,SAAS,EAAE,YAAY,CA2B5C"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["defaults.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,yDAA0D;AAE1D,uCAAwC;AAExC,mDAAoD;AAEpD,6CAA8C;AAUvC,0BAHI,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAEgD;AAMnE,qCAHI,MAAM,oCAKhB;AAOM,8HAEN;AAQM,sCAHI,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAMzB;AAUM,8CALI,MAAM,OACN,GAAG,iCAED,OAAO,CAAC,IAAI,CAAC,CASzB;AAOM,wCAFM,OAAO,CAAC,OAAO,CAAC,CAGgD;AAEtE,0DAaN;AAED;;;;GAIG;AACH,wCAFU,MAAM,OAAO,YAAY,EAAE,YAAY,CA2B/C"}
package/src/defaults.js CHANGED
@@ -95,7 +95,7 @@ export const MAKE_DEFAULT_DECODER = () => {
95
95
  /**
96
96
  * Unserialize the JSONable data.
97
97
  *
98
- * @type {() => import('./types').Unserializer}
98
+ * @type {() => import('./types.js').Unserializer}
99
99
  */
100
100
  export const MAKE_DEFAULT_UNSERIALIZER = () => {
101
101
  const ifaceAllegedPrefix = 'Alleged: ';
@@ -1,5 +1,5 @@
1
1
  export function makeCosmjsFollower<T>(sourceP: any, leaderOrMaker?: import("./types.js").LeaderOrMaker | undefined, options?: import("./types.js").FollowerOptions | undefined): ValueFollower<T>;
2
- export type ValueFollower<T> = import('./types.js').Follower<import('./types.js').ValueFollowerElement<T>>;
2
+ export type ValueFollower<T> = import("./types.js").Follower<import("./types.js").ValueFollowerElement<T>>;
3
3
  /**
4
4
  * The response of an ABCI query to Tendermint.
5
5
  * This is a subset of `tendermint34.AbciQueryResponse` in order
@@ -1 +1 @@
1
- {"version":3,"file":"follower-cosmjs.d.ts","sourceRoot":"","sources":["follower-cosmjs.js"],"names":[],"mappings":"AAiGO,+CALI,GAAG,gJAyeb;+BAnjByB,OAAO,YAAY,EAAE,QAAQ,CAAC,OAAO,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;;;;;;iCAIxF;IACZ,QAAY,CAAC,KAAK,EAAE,UAAU,CAAC;IAC/B,QAAY,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB"}
1
+ {"version":3,"file":"follower-cosmjs.d.ts","sourceRoot":"","sources":["follower-cosmjs.js"],"names":[],"mappings":"AAyGO,mCANM,CAAC,WACH,GAAG,+HAGD,aAAa,CAAC,CAAC,CAAC,CAsf5B;0BAnkBa,CAAC,IAAW,OAAO,YAAY,EAAE,QAAQ,CAAC,OAAO,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;;;;;;iCAIxF;IACZ,QAAY,CAAC,KAAK,EAAE,UAAU,CAAC;IAC/B,QAAY,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB"}
@@ -1,5 +1,4 @@
1
- /// <reference types="ses"/>
2
- /* eslint-disable no-await-in-loop, @jessie.js/no-nested-await */
1
+ /// <reference types="ses" />
3
2
 
4
3
  import { E, Far } from '@endo/far';
5
4
  import * as tendermint34 from '@cosmjs/tendermint-rpc';
@@ -11,6 +10,15 @@ import { MAKE_DEFAULT_DECODER, MAKE_DEFAULT_UNSERIALIZER } from './defaults.js';
11
10
  import { makeCastingSpec } from './casting-spec.js';
12
11
  import { makeLeader as defaultMakeLeader } from './leader-netconfig.js';
13
12
 
13
+ // A lot of cosmjs classes end up hardened through instances shared by this
14
+ // package so preemptively harden them all.
15
+ // However we cannot directly harden a module namespace object (exotic behavior
16
+ // for bindings) so spread the namespace instead
17
+ harden({
18
+ tendermint34: { ...tendermint34 },
19
+ stargateStar: { ...stargateStar },
20
+ });
21
+
14
22
  const { QueryClient } = stargateStar;
15
23
  const { Tendermint34Client } = tendermint34;
16
24
  const { details: X, quote: q, Fail } = assert;
@@ -91,8 +99,8 @@ const proofs = ['strict', 'none', 'optimistic'];
91
99
  /**
92
100
  * @template T
93
101
  * @param {any} sourceP
94
- * @param {import('./types').LeaderOrMaker} [leaderOrMaker]
95
- * @param {import('./types').FollowerOptions} [options]
102
+ * @param {import('./types.js').LeaderOrMaker} [leaderOrMaker]
103
+ * @param {import('./types.js').FollowerOptions} [options]
96
104
  * @returns {ValueFollower<T>}
97
105
  */
98
106
  export const makeCosmjsFollower = (
@@ -240,6 +248,7 @@ export const makeCosmjsFollower = (
240
248
  * @returns {Promise<QueryStoreResponse>}
241
249
  */
242
250
  const tryGetDataAtHeight = async blockHeight => {
251
+ await null;
243
252
  if (proof === 'strict') {
244
253
  // Crash hard if we can't prove.
245
254
  return getProvenDataAtHeight(blockHeight).catch(crash);
@@ -274,6 +283,7 @@ export const makeCosmjsFollower = (
274
283
  * @param {number} [blockHeight] desired height, or the latest height if not set
275
284
  */
276
285
  const getDataAtHeight = async blockHeight => {
286
+ await null;
277
287
  for (let attempt = 0; ; attempt += 1) {
278
288
  try {
279
289
  // AWAIT
@@ -330,11 +340,16 @@ export const makeCosmjsFollower = (
330
340
  blockHeight,
331
341
  currentBlockHeight,
332
342
  ) => {
333
- // AWAIT
334
- const value = await /** @type {T} */ (
335
- unserializer ? E(unserializer).fromCapData(data) : data
336
- );
337
- return { value, blockHeight, currentBlockHeight };
343
+ await null;
344
+ try {
345
+ // AWAIT
346
+ const value = await /** @type {T} */ (
347
+ unserializer ? E(unserializer).fromCapData(data) : data
348
+ );
349
+ return { value, blockHeight, currentBlockHeight };
350
+ } catch (e) {
351
+ return { blockHeight, currentBlockHeight, error: e, value: undefined };
352
+ }
338
353
  };
339
354
 
340
355
  /**
@@ -351,6 +366,7 @@ export const makeCosmjsFollower = (
351
366
  );
352
367
  }
353
368
  }
369
+ harden(allValuesFromCell);
354
370
 
355
371
  /**
356
372
  * @param {import('./types.js').StreamCell<T>} streamCell
@@ -366,6 +382,7 @@ export const makeCosmjsFollower = (
366
382
  );
367
383
  }
368
384
  }
385
+ harden(reverseValuesFromCell);
369
386
 
370
387
  /**
371
388
  * @param {import('./types.js').StreamCell<T>} streamCell
@@ -383,6 +400,7 @@ export const makeCosmjsFollower = (
383
400
  );
384
401
  }
385
402
  }
403
+ harden(lastValueFromCell);
386
404
 
387
405
  /**
388
406
  * @yields {ValueFollowerElement<T>}
@@ -391,6 +409,7 @@ export const makeCosmjsFollower = (
391
409
  /** @type {number | undefined} the last known latest height */
392
410
  let lastHeight;
393
411
  let lastValue;
412
+ await null;
394
413
  for (;;) {
395
414
  const latest = await getDataAtHeight();
396
415
  if (lastHeight && latest.height <= lastHeight) {
@@ -427,6 +446,7 @@ export const makeCosmjsFollower = (
427
446
  lastValue = latest.value;
428
447
  }
429
448
  }
449
+ harden(getLatestIterable);
430
450
 
431
451
  /**
432
452
  * @param {number} [cursorBlockHeight]
@@ -441,11 +461,13 @@ export const makeCosmjsFollower = (
441
461
  // block.
442
462
  // If the block has no corresponding data, wait for the first block to
443
463
  // contain data.
464
+ await null;
444
465
  for (;;) {
445
- ({ value: cursorData, height: cursorBlockHeight } = await getDataAtHeight(
446
- cursorBlockHeight,
447
- ));
466
+ let thisHeight;
467
+ ({ value: cursorData, height: thisHeight } =
468
+ await getDataAtHeight(cursorBlockHeight));
448
469
  if (cursorData.length !== 0) {
470
+ cursorBlockHeight = thisHeight;
449
471
  const cursorStreamCell = streamCellForData(
450
472
  cursorBlockHeight,
451
473
  cursorData,
@@ -543,6 +565,7 @@ export const makeCosmjsFollower = (
543
565
  cursorData = currentData;
544
566
  }
545
567
  }
568
+ harden(getEachIterableAtHeight);
546
569
 
547
570
  /**
548
571
  * @param {number} [cursorBlockHeight]
@@ -553,10 +576,10 @@ export const makeCosmjsFollower = (
553
576
  // cursorBlockHeight) so we know not to emit duplicates
554
577
  // of that cell.
555
578
  let cursorData;
579
+ await null;
556
580
  while (cursorBlockHeight === undefined || cursorBlockHeight > 0) {
557
- ({ value: cursorData, height: cursorBlockHeight } = await getDataAtHeight(
558
- cursorBlockHeight,
559
- ));
581
+ ({ value: cursorData, height: cursorBlockHeight } =
582
+ await getDataAtHeight(cursorBlockHeight));
560
583
  if (cursorData.length === 0) {
561
584
  // No data at the cursor height, so signal beginning of stream.
562
585
  return;
@@ -566,6 +589,7 @@ export const makeCosmjsFollower = (
566
589
  cursorBlockHeight = cursorStreamCell.blockHeight - 1;
567
590
  }
568
591
  }
592
+ harden(getReverseIterableAtHeight);
569
593
 
570
594
  /** @type {ValueFollower<T>} */
571
595
  return Far('chain follower', {
package/src/follower.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export function makeFollower<T>(specP: ERef<import('./types').CastingSpec> | string, leaderOrMaker?: import("./types").LeaderOrMaker | undefined, options?: import("./types").FollowerOptions | undefined): Promise<import("./follower-cosmjs.js").ValueFollower<T>>;
1
+ export function makeFollower<T>(specP: ERef<import("./types.js").CastingSpec> | string, leaderOrMaker?: import("./types.js").LeaderOrMaker | undefined, options?: import("./types.js").FollowerOptions | undefined): Promise<import("./follower-cosmjs.js").ValueFollower<T>>;
2
2
  //# sourceMappingURL=follower.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"follower.d.ts","sourceRoot":"","sources":["follower.js"],"names":[],"mappings":"AA4DO,uCALI,KAAK,OAAO,SAAS,EAAE,WAAW,CAAC,GAAG,MAAM,kLAYtD"}
1
+ {"version":3,"file":"follower.d.ts","sourceRoot":"","sources":["follower.js"],"names":[],"mappings":"AA4DO,6BANM,CAAC,SACH,IAAI,CAAC,OAAO,YAAY,EAAE,WAAW,CAAC,GAAG,MAAM,+HAG7C,OAAO,CAAC,OAAO,sBAAsB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CASpE"}
package/src/follower.js CHANGED
@@ -11,12 +11,12 @@ import { makeCastingSpec } from './casting-spec.js';
11
11
 
12
12
  /**
13
13
  * @template T
14
- * @param {ERef<import('./types').CastingSpec>} spec
14
+ * @param {ERef<import('./types.js').CastingSpec>} spec
15
15
  */
16
16
  const makeSubscriptionFollower = spec => {
17
17
  const transform = value =>
18
18
  harden({ value, blockHeight: NaN, currentBlockHeight: NaN });
19
- /** @type {import('./types').Follower<import('./types.js').ValueFollowerElement<T>>} */
19
+ /** @type {import('./types.js').Follower<import('./types.js').ValueFollowerElement<T>>} */
20
20
  const follower = Far('subscription/notifier follower', {
21
21
  getLatestIterable: async () => {
22
22
  const { notifier, subscription } = await spec;
@@ -53,10 +53,10 @@ const makeSubscriptionFollower = spec => {
53
53
 
54
54
  /**
55
55
  * @template T
56
- * @param {ERef<import('./types').CastingSpec> | string} specP
57
- * @param {import('./types').LeaderOrMaker} [leaderOrMaker]
58
- * @param {import('./types').FollowerOptions} [options]
59
- * @returns {Promise<import('./follower-cosmjs').ValueFollower<T>>}
56
+ * @param {ERef<import('./types.js').CastingSpec> | string} specP
57
+ * @param {import('./types.js').LeaderOrMaker} [leaderOrMaker]
58
+ * @param {import('./types.js').FollowerOptions} [options]
59
+ * @returns {Promise<import('./follower-cosmjs.js').ValueFollower<T>>}
60
60
  */
61
61
  export const makeFollower = async (specP, leaderOrMaker, options) => {
62
62
  const spec = await makeCastingSpec(specP);
package/src/iterable.d.ts CHANGED
@@ -1,24 +1,24 @@
1
1
  export function mapAsyncIterable<TIn, TOut>(iterable: AsyncIterable<TIn>, transform: (value: TIn) => TOut): AsyncIterable<TOut>;
2
- export function iterateLatest<T>(follower: ERef<import("./types").Follower<T>>): {
2
+ export function iterateLatest<T>(follower: ERef<import("./types.js").Follower<T>>): {
3
3
  /** @returns {AsyncIterator<T>} */
4
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
5
- } & import("@endo/eventual-send").RemotableBrand<{}, {
4
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
5
+ } & import("@endo/pass-style").RemotableObject<`Alleged: ${string}`> & import("@endo/eventual-send").RemotableBrand<{}, {
6
6
  /** @returns {AsyncIterator<T>} */
7
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
7
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
8
8
  }>;
9
- export function iterateEach<T>(follower: ERef<import("./types").Follower<T>>, options?: import("./types").IterateEachOptions | undefined): {
9
+ export function iterateEach<T>(follower: ERef<import("./types.js").Follower<T>>, options?: import("./types.js").IterateEachOptions | undefined): {
10
10
  /** @returns {AsyncIterator<T>} */
11
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
12
- } & import("@endo/eventual-send").RemotableBrand<{}, {
11
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
12
+ } & import("@endo/pass-style").RemotableObject<`Alleged: ${string}`> & import("@endo/eventual-send").RemotableBrand<{}, {
13
13
  /** @returns {AsyncIterator<T>} */
14
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
14
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
15
15
  }>;
16
- export function iterateReverse<T>(follower: ERef<import("./types").Follower<T>>, options?: import("./types").IterateEachOptions | undefined): {
16
+ export function iterateReverse<T>(follower: ERef<import("./types.js").Follower<T>>, options?: import("./types.js").IterateEachOptions | undefined): {
17
17
  /** @returns {AsyncIterator<T>} */
18
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
19
- } & import("@endo/eventual-send").RemotableBrand<{}, {
18
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
19
+ } & import("@endo/pass-style").RemotableObject<`Alleged: ${string}`> & import("@endo/eventual-send").RemotableBrand<{}, {
20
20
  /** @returns {AsyncIterator<T>} */
21
- [Symbol.asyncIterator]: () => AsyncIterator<T, any, undefined>;
21
+ [Symbol.asyncIterator]: () => AsyncIterator<T>;
22
22
  }>;
23
23
  export { subscribeEach, subscribeLatest } from "@agoric/notifier/subscribe.js";
24
24
  //# sourceMappingURL=iterable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"iterable.d.ts","sourceRoot":"","sources":["iterable.js"],"names":[],"mappings":"AAWO,gIAON;AAQM;IAGH,kCAAkC;;;IAAlC,kCAAkC;;GAQlC;AASG;IAGH,kCAAkC;;;IAAlC,kCAAkC;;GAQlC;AAOG;IAGH,kCAAkC;;;IAAlC,kCAAkC;;GAQlC"}
1
+ {"version":3,"file":"iterable.d.ts","sourceRoot":"","sources":["iterable.js"],"names":[],"mappings":"AAWO,iCANM,GAAG,EACH,IAAI,YACN,aAAa,CAAC,GAAG,CAAC,aAClB,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,GAClB,aAAa,CAAC,IAAI,CAAC,CAU/B;AAQM,8BAHM,CAAC,YACH,IAAI,CAAC,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAK7C,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;;IAA9B,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;GAQ9B;AASG,4BAJM,CAAC,YACH,IAAI,CAAC,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAM7C,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;;IAA9B,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;GAQ9B;AAOG,+BAJM,CAAC,YACH,IAAI,CAAC,OAAO,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAM7C,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;;IAA9B,kCAAkC;kCAApB,aAAa,CAAC,CAAC,CAAC;GAQ9B"}
package/src/iterable.js CHANGED
@@ -15,6 +15,7 @@ export const mapAsyncIterable = (iterable, transform) => {
15
15
  yield transform(value);
16
16
  }
17
17
  }
18
+ harden(transformGenerator);
18
19
  return transformGenerator();
19
20
  };
20
21
 
@@ -22,7 +23,7 @@ export const mapAsyncIterable = (iterable, transform) => {
22
23
  * TODO: Remove this function when we have an @endo/publish-kit that suppports pull topics
23
24
  *
24
25
  * @template T
25
- * @param {ERef<import('./types').Follower<T>>} follower
26
+ * @param {ERef<import('./types.js').Follower<T>>} follower
26
27
  */
27
28
  export const iterateLatest = follower =>
28
29
  // For now, just pass through the iterable.
@@ -1,4 +1,4 @@
1
- export function makeLeaderFromRpcAddresses(rpcAddrs: string[], leaderOptions?: import("./types.js").LeaderOptions | undefined): import('./types.js').Leader;
1
+ export function makeLeaderFromRpcAddresses(rpcAddrs: string[], leaderOptions?: import("./types.js").LeaderOptions | undefined): import("./types.js").Leader;
2
2
  export function makeLeaderFromNetworkConfig(netconfigURL: string, options?: import("./types.js").LeaderOptions | undefined): Promise<any>;
3
- export function makeLeader(bootstrap?: string | undefined, options?: import("./types.js").LeaderOptions | undefined): ERef<import('./types.js').Leader>;
3
+ export function makeLeader(bootstrap?: string | undefined, options?: import("./types.js").LeaderOptions | undefined): ERef<import("./types.js").Leader>;
4
4
  //# sourceMappingURL=leader-netconfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"leader-netconfig.d.ts","sourceRoot":"","sources":["leader-netconfig.js"],"names":[],"mappings":"AAgBO,qDAJI,MAAM,EAAE,mEAEN,OAAO,YAAY,EAAE,MAAM,CAevC;AAMM,0DAHI,MAAM,0EAoChB;AAOM,sHAFM,KAAK,OAAO,YAAY,EAAE,MAAM,CAAC,CAO7C"}
1
+ {"version":3,"file":"leader-netconfig.d.ts","sourceRoot":"","sources":["leader-netconfig.js"],"names":[],"mappings":"AAgBO,qDAJI,MAAM,EAAE,mEAEN,OAAO,YAAY,EAAE,MAAM,CAevC;AAMM,0DAHI,MAAM,0EAoChB;AAOM,sHAFM,IAAI,CAAC,OAAO,YAAY,EAAE,MAAM,CAAC,CAO7C"}
package/src/leader.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export function makeRoundRobinLeader(endpoints: string[], leaderOptions?: import('./types.js').LeaderOptions): import("./types.js").Leader;
1
+ export function makeRoundRobinLeader(endpoints: string[], leaderOptions?: import("./types.js").LeaderOptions): import("./types.js").Leader;
2
2
  //# sourceMappingURL=leader.d.ts.map
package/src/main.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // @jessie-check
2
2
 
3
+ /// <reference types="@agoric/internal/exported" />
4
+
3
5
  // eslint-disable-next-line import/export
4
6
  export * from './types.js'; // no named exports
5
7
  export * from './defaults.js';
@@ -0,0 +1,2 @@
1
+ export function makeHttpClient(url: string, fetch: typeof window.fetch): import("@cosmjs/tendermint-rpc").RpcClient;
2
+ //# sourceMappingURL=makeHttpClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeHttpClient.d.ts","sourceRoot":"","sources":["makeHttpClient.js"],"names":[],"mappings":"AA2BO,oCAJI,MAAM,SACN,OAAO,MAAM,CAAC,KAAK,GACjB,OAAO,wBAAwB,EAAE,SAAS,CA8BtD"}
@@ -0,0 +1,56 @@
1
+ // @ts-check
2
+
3
+ const { freeze } = Object;
4
+
5
+ const filterBadStatus = res => {
6
+ if (res.status >= 400) {
7
+ throw new Error(`Bad status on response: ${res.status}`);
8
+ }
9
+ return res;
10
+ };
11
+
12
+ /**
13
+ * Make an RpcClient using explicit access to the network.
14
+ *
15
+ * The RpcClient implementations included in cosmjs
16
+ * such as {@link https://cosmos.github.io/cosmjs/latest/tendermint-rpc/classes/HttpClient.html HttpClient}
17
+ * use ambient authority (fetch or axios) for network access.
18
+ *
19
+ * To facilitate cooperation without vulnerability,
20
+ * as well as unit testing, etc. this RpcClient maker takes
21
+ * network access as a parameter, following
22
+ * {@link https://github.com/Agoric/agoric-sdk/wiki/OCap-Discipline|OCap Discipline}.
23
+ *
24
+ * @param {string} url
25
+ * @param {typeof window.fetch} fetch
26
+ * @returns {import('@cosmjs/tendermint-rpc').RpcClient}
27
+ */
28
+ export const makeHttpClient = (url, fetch) => {
29
+ const headers = {}; // XXX needed?
30
+
31
+ // based on cosmjs 0.30.1:
32
+ // https://github.com/cosmos/cosmjs/blob/33271bc51cdc865cadb647a1b7ab55d873637f39/packages/tendermint-rpc/src/rpcclients/http.ts#L37
33
+ // https://github.com/cosmos/cosmjs/blob/33271bc51cdc865cadb647a1b7ab55d873637f39/packages/tendermint-rpc/src/rpcclients/httpclient.ts#L25
34
+ return freeze({
35
+ disconnect: () => {
36
+ // nothing to be done
37
+ },
38
+
39
+ /**
40
+ * @param {import('@cosmjs/json-rpc').JsonRpcRequest} request
41
+ */
42
+ execute: async request => {
43
+ const settings = {
44
+ method: 'POST',
45
+ body: request ? JSON.stringify(request) : undefined,
46
+ headers: {
47
+ 'Content-Type': 'application/json',
48
+ ...headers,
49
+ },
50
+ };
51
+ return fetch(url, settings)
52
+ .then(filterBadStatus)
53
+ .then(res => res.json());
54
+ },
55
+ });
56
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"netconfig.d.ts","sourceRoot":"","sources":["netconfig.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,kEAWE;AAQK,8CAJI,OAAO,qCAKuB;;;;;;;;;;cA3B3B,MAAM,EAAE;;;;eACR,MAAM"}
1
+ {"version":3,"file":"netconfig.d.ts","sourceRoot":"","sources":["netconfig.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,kEAWE;AAQK,8CAJI,OAAO,GACL,QAAQ,QAAQ,IAAI,aAAa,CAIL;;;;;;;;;;cA3B3B,MAAM,EAAE;;;;eACR,MAAM"}
package/src/shuffle.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export function shuffle<T>(a: T[]): void;
1
+ export function shuffle<T>(a: Array<T>): void;
2
2
  //# sourceMappingURL=shuffle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shuffle.d.ts","sourceRoot":"","sources":["shuffle.js"],"names":[],"mappings":"AAMO,yCAON"}
1
+ {"version":3,"file":"shuffle.d.ts","sourceRoot":"","sources":["shuffle.js"],"names":[],"mappings":"AAMO,wBAHM,CAAC,KACH,KAAK,CAAC,CAAC,CAAC,QASlB"}
package/src/types.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- export type ERef<T> = import('@endo/far').ERef<T>;
2
1
  export type LeaderOptions = {
3
2
  retryCallback?: ((where: string, err: any, attempt?: number) => Promise<void>) | null | undefined;
4
3
  jitter?: ((where: string) => Promise<void>) | undefined;
@@ -21,19 +20,24 @@ export type Follower<T> = {
21
20
  getEachIterable: (options?: IterateEachOptions) => Promise<AsyncIterable<T>>;
22
21
  getReverseIterable: (options?: IterateEachOptions) => Promise<AsyncIterable<T>>;
23
22
  };
24
- export type ValueFollowerElement<T> = {
25
- value: T;
23
+ export type ValueFollowerBase = {
26
24
  blockHeight: number;
27
25
  currentBlockHeight: number;
28
26
  };
29
- export type Unserializer = Pick<import('@endo/marshal').Marshal<unknown>, 'fromCapData' | 'unserialize'>;
27
+ export type ValueFollowerElement<T> = ValueFollowerBase & ({
28
+ value: T;
29
+ } | {
30
+ value: undefined;
31
+ error: any;
32
+ });
33
+ export type Unserializer = Pick<import("@endo/marshal").Marshal<unknown>, "fromCapData" | "unserialize">;
30
34
  export type Crasher = {
31
35
  crash: (...args: unknown[]) => void;
32
36
  };
33
37
  export type FollowerOptions = {
34
38
  unserializer?: import("@endo/far").FarRef<Unserializer, import("@endo/eventual-send").DataOnly<Unserializer>> | null | undefined;
35
39
  decode?: ((text: string) => any) | undefined;
36
- proof?: "strict" | "optimistic" | "none" | undefined;
40
+ proof?: "none" | "strict" | "optimistic" | undefined;
37
41
  crasher?: import("@endo/far").FarRef<Crasher, import("@endo/eventual-send").DataOnly<Crasher>> | undefined;
38
42
  };
39
43
  export type CastingSpec = {
@@ -41,8 +45,8 @@ export type CastingSpec = {
41
45
  storeSubkey?: Uint8Array | undefined;
42
46
  dataPrefixBytes?: Uint8Array | undefined;
43
47
  noDataValue?: Uint8Array | undefined;
44
- subscription?: ERef<Subscription<any>> | undefined;
45
- notifier?: ERef<Notifier<any>> | undefined;
48
+ subscription?: globalThis.ERef<Subscription<any>> | undefined;
49
+ notifier?: globalThis.ERef<Notifier<any>> | undefined;
46
50
  };
47
51
  export type IterateEachOptions = {
48
52
  height?: number | undefined;
@@ -51,4 +55,6 @@ export type StreamCell<T> = {
51
55
  blockHeight: number;
52
56
  values: Array<T>;
53
57
  };
58
+ import type { Subscription } from '@agoric/notifier';
59
+ import type { Notifier } from '@agoric/notifier';
54
60
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":"sBAO0B,OAAO,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;;6BAIvB,MAAM,OAAO,GAAG,YAAY,MAAM,KAAK,QAAQ,IAAI,CAAC;sBAC5D,MAAM,KAAK,QAAQ,IAAI,CAAC;2BACxB,MAAM,KAAK,QAAQ,OAAO,CAAC;;;;YAMnC,UAAU,EAAE;;;mBAKJ,MAAM,SAAS,GAAG,YAAY,MAAM,KAAK,QAAQ,IAAI,CAAC;oBACtD,MAAM,KAAK,QAAQ,IAAI,CAAC;gBAChC,MAAM,aAAa;6BACR,MAAM,uBAAuB,MAAM;yBACvC,KAAK,WAAW,CAAC,KAAK,QAAQ,SAAS,aAAa,CAAC,CAAC;;4BAG7D,KAAK,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;;uBAKnC,MAAM,QAAQ,cAAc,CAAC,CAAC,CAAC;gCACpB,kBAAkB,KAAK,QAAQ,cAAc,CAAC,CAAC,CAAC;mCAChD,kBAAkB,KAAK,QAAQ,cAAc,CAAC,CAAC,CAAC;;;WAO3D,CAAC;iBACD,MAAM;wBACN,MAAM;;2BAIP,KAAK,OAAO,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC;;qBAKlE,OAAO,EAAE,KAAK,IAAI;;;;qBAMrB,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;iBAuBrB,MAAM;YACN,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":";6BAW8B,MAAM,OAAO,GAAG,YAAY,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;sBAC5D,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;2BACxB,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC;;;;YAMnC,UAAU,EAAE;;;WAKZ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;YAC9D,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;gBAChC,MAAM,aAAa;kBACnB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC;kBAC9E,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;;4BAG7D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;qBAGpC,CAAC;uBAEA,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;qBAC/B,CAAC,OAAO,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;wBAC3D,CAAC,OAAO,CAAC,EAAE,kBAAkB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;;;iBAK3D,MAAM;wBACN,MAAM;;iCAKP,CAAC,IACD,iBAAiB,GAAG,CAAC;IAAE,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC;2BAIrE,IAAI,CAAC,OAAO,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,CAAC;;WAK5E,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI;;;;qBAMrB,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;uBAqBtB,CAAC;iBAEA,MAAM;YACN,KAAK,CAAC,CAAC,CAAC;;kCAnFmB,kBAAkB;8BAAlB,kBAAkB"}
package/src/types.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // @jessie-check
2
2
 
3
- // Make this a module.
4
- import '@agoric/notifier';
5
-
3
+ // Ensure this is a module.
6
4
  export {};
7
5
 
8
- /** @template T @typedef {import('@endo/far').ERef<T>} ERef */
6
+ /**
7
+ * @import {Notifier, Subscription} from '@agoric/notifier';
8
+ */
9
9
 
10
10
  /**
11
11
  * @typedef {object} LeaderOptions
@@ -40,14 +40,17 @@ export {};
40
40
  */
41
41
 
42
42
  /**
43
- * @see {ChangeFollower}
44
- * @template T
45
- * @typedef {object} ValueFollowerElement
46
- * @property {T} value
43
+ * @typedef {object} ValueFollowerBase
47
44
  * @property {number} blockHeight
48
45
  * @property {number} currentBlockHeight
49
46
  */
50
47
 
48
+ /**
49
+ * @see {ChangeFollower}
50
+ * @template T
51
+ * @typedef {ValueFollowerBase & ({ value: T } | { value: undefined, error: any })} ValueFollowerElement
52
+ */
53
+
51
54
  /**
52
55
  * @typedef {Pick<import('@endo/marshal').Marshal<unknown>, 'fromCapData' | 'unserialize'>} Unserializer
53
56
  */
@@ -0,0 +1,118 @@
1
+ // @ts-check
2
+ /* global globalThis */
3
+ import anyTest from 'ava';
4
+ import {
5
+ createProtobufRpcClient,
6
+ QueryClient,
7
+ setupBankExtension,
8
+ } from '@cosmjs/stargate';
9
+ import { Tendermint34Client } from '@cosmjs/tendermint-rpc';
10
+ import {
11
+ QueryChildrenRequest,
12
+ QueryChildrenResponse,
13
+ } from '@agoric/cosmic-proto/vstorage/query.js';
14
+
15
+ import { makeHttpClient } from '../src/makeHttpClient.js';
16
+ import { captureIO, replayIO, web1, web2 } from './net-access-fixture.js';
17
+
18
+ /** @type {import('ava').TestFn<Awaited<ReturnType<typeof makeTestContext>>>} */
19
+ const test = /** @type {any} */ (anyTest);
20
+
21
+ const RECORDING = false;
22
+
23
+ const makeTestContext = async () => {
24
+ return { fetch: globalThis.fetch };
25
+ };
26
+
27
+ test.before(async t => {
28
+ t.context = await makeTestContext();
29
+ });
30
+
31
+ const scenario1 = {
32
+ endpoint: 'https://emerynet.rpc.agoric.net/',
33
+ request: {
34
+ id: 1,
35
+ method: 'no-such-method',
36
+ params: [],
37
+ },
38
+ gov2: {
39
+ addr: 'agoric140dmkrz2e42ergjj7gyvejhzmjzurvqeq82ang',
40
+ balance: { amount: '25050000', denom: 'uist' },
41
+ },
42
+ };
43
+
44
+ test('interpose net access', async t => {
45
+ const fetchMock = replayIO(web1);
46
+ const rpcClient = makeHttpClient(scenario1.endpoint, fetchMock);
47
+
48
+ t.log('raw JSON RPC');
49
+ const res = await rpcClient.execute({
50
+ ...scenario1.request,
51
+ jsonrpc: '2.0',
52
+ });
53
+ t.like(res, { error: { message: 'Method not found' } });
54
+
55
+ t.log('Cosmos SDK RPC: balance query');
56
+ const tmClient = await Tendermint34Client.create(rpcClient);
57
+ const qClient = new QueryClient(tmClient);
58
+ const ext = setupBankExtension(qClient);
59
+ const actual = await ext.bank.balance(
60
+ scenario1.gov2.addr,
61
+ scenario1.gov2.balance.denom,
62
+ );
63
+
64
+ t.deepEqual(actual, scenario1.gov2.balance);
65
+ });
66
+
67
+ const scenario2 = {
68
+ endpoint: 'https://emerynet.rpc.agoric.net/',
69
+ children: [
70
+ 'activityhash',
71
+ 'beansOwing',
72
+ 'egress',
73
+ 'highPrioritySenders',
74
+ 'published',
75
+ 'swingStore',
76
+ ],
77
+ };
78
+
79
+ // XXX open code until https://github.com/Agoric/agoric-sdk/issues/9200
80
+ class QueryClientImpl {
81
+ rpc;
82
+
83
+ service;
84
+
85
+ constructor(rpc, opts) {
86
+ this.service = opts?.service || 'agoric.vstorage.Query';
87
+ this.rpc = rpc;
88
+ }
89
+
90
+ Children(request) {
91
+ const reqData = QueryChildrenRequest.encode(request).finish();
92
+ const promise = this.rpc.request(this.service, 'Children', reqData);
93
+ return promise.then(respData => QueryChildrenResponse.decode(respData));
94
+ }
95
+ }
96
+
97
+ test(`vstorage query: Children (RECORDING: ${RECORDING})`, async t => {
98
+ const { context: io } = t;
99
+
100
+ const { fetch: fetchMock, web } = io.recording
101
+ ? captureIO(io.fetch)
102
+ : { fetch: replayIO(web2), web: new Map() };
103
+ const rpcClient = makeHttpClient(scenario2.endpoint, fetchMock);
104
+
105
+ const tmClient = await Tendermint34Client.create(rpcClient);
106
+ const qClient = new QueryClient(tmClient);
107
+ const rpc = createProtobufRpcClient(qClient);
108
+ const queryService = new QueryClientImpl(rpc);
109
+
110
+ const children = await queryService.Children({ path: '' });
111
+ if (io.recording) {
112
+ t.snapshot(web);
113
+ }
114
+ t.deepEqual(children, {
115
+ children: scenario2.children,
116
+ pagination: undefined,
117
+ });
118
+ });
@@ -1,5 +1,8 @@
1
1
  // @ts-nocheck
2
- // eslint-disable-next-line import/order
2
+
3
+ import './lockdown.js';
4
+
5
+ import { makeMarshal } from '@endo/marshal';
3
6
  import { test } from './prepare-test-env-ava.js';
4
7
 
5
8
  import {
@@ -167,6 +170,59 @@ test('unrecognized proof', async t => {
167
170
  );
168
171
  });
169
172
 
173
+ test('yields error on bad capdata without terminating', async t => {
174
+ const marshal = makeMarshal();
175
+ const improperlyMarshalledData = { bad: 'data' };
176
+ const properlyMarshalledData = { foo: 'bar' };
177
+ const fakeValues = [
178
+ improperlyMarshalledData,
179
+ marshal.toCapData(harden(properlyMarshalledData)),
180
+ ];
181
+ t.plan(4);
182
+ const options = { batchSize: 1, marshaller: { toCapData: data => data } };
183
+ const { controller, PORT } = await t.context.startFakeServer(
184
+ t,
185
+ fakeValues,
186
+ options,
187
+ );
188
+ controller.advance(0);
189
+ /** @type {import('../src/types.js').LeaderOptions} */
190
+ const lo = {
191
+ retryCallback: null, // fail fast, no retries
192
+ keepPolling: () => delay(1000).then(() => true), // poll really quickly
193
+ jitter: null, // no jitter
194
+ };
195
+ /** @type {import('../src/types.js').FollowerOptions} */
196
+ const so = {
197
+ proof: 'none',
198
+ };
199
+
200
+ const leader = makeLeader(`http://localhost:${PORT}/network-config`, lo);
201
+ const castingSpec = makeCastingSpec(':mailbox.agoric1foobarbaz');
202
+ const follower = await makeFollower(castingSpec, leader, so);
203
+ let i = 0;
204
+
205
+ for await (const { value, error } of iterateEach(follower)) {
206
+ if (i === 0) {
207
+ t.log(`value from follower, should be undefined:`, value);
208
+ t.log(`error from follower, should be defined:`, error);
209
+
210
+ t.deepEqual(value, undefined);
211
+ t.assert(typeof error === 'object');
212
+
213
+ i += 1;
214
+ controller.advance(1);
215
+ } else if (i === 1) {
216
+ t.log(`value from follower, should be defined:`, value);
217
+ t.log(`error from follower, should be undefined:`, error);
218
+
219
+ t.deepEqual(value, properlyMarshalledData);
220
+ t.deepEqual(error, undefined);
221
+ break;
222
+ }
223
+ }
224
+ });
225
+
170
226
  test.before(t => {
171
227
  t.context.cleanups = [];
172
228
  t.context.startFakeServer = startFakeServer;
@@ -0,0 +1,196 @@
1
+ const { stringify: jq } = JSON;
2
+
3
+ /**
4
+ * @file to regenerate
5
+ * 1. set RECORDING=true in interpose-net-access.test.js
6
+ * 2. run: yarn test test/interpose-net-access.test.js --update-snapshots
7
+ * 3. for each map in interpose-net-access.test.js.md, copy it and
8
+ * 4. replace all occurences of => with : and paste as args to Object.fromEntries()
9
+ * 5. change RECORDING back to false
10
+ */
11
+ export const web1 = new Map([
12
+ [
13
+ jq([
14
+ 'https://emerynet.rpc.agoric.net/',
15
+ {
16
+ method: 'POST',
17
+ body: jq({
18
+ id: 1208387614,
19
+ method: 'no-such-method',
20
+ params: [],
21
+ jsonrpc: '2.0',
22
+ }),
23
+ headers: { 'Content-Type': 'application/json' },
24
+ },
25
+ ]),
26
+ {
27
+ error: {
28
+ code: -32601,
29
+ message: 'Method not found',
30
+ },
31
+ id: 1208387614,
32
+ jsonrpc: '2.0',
33
+ },
34
+ ],
35
+ [
36
+ jq([
37
+ 'https://emerynet.rpc.agoric.net/',
38
+ {
39
+ method: 'POST',
40
+ body: jq({
41
+ jsonrpc: '2.0',
42
+ id: 797030719,
43
+ method: 'abci_query',
44
+ params: {
45
+ path: '/cosmos.bank.v1beta1.Query/Balance',
46
+ data: '0a2d61676f726963313430646d6b727a326534326572676a6a37677976656a687a6d6a7a7572767165713832616e67120475697374',
47
+ prove: false,
48
+ },
49
+ }),
50
+ headers: { 'Content-Type': 'application/json' },
51
+ },
52
+ ]),
53
+ {
54
+ id: 797030719,
55
+ jsonrpc: '2.0',
56
+ result: {
57
+ response: {
58
+ code: 0,
59
+ codespace: '',
60
+ height: '123985',
61
+ index: '0',
62
+ info: '',
63
+ key: null,
64
+ log: '',
65
+ proofOps: null,
66
+ value: 'ChAKBHVpc3QSCDI1MDUwMDAw',
67
+ },
68
+ },
69
+ },
70
+ ],
71
+ ]);
72
+
73
+ export const web2 = new Map([
74
+ [
75
+ jq([
76
+ 'https://emerynet.rpc.agoric.net/',
77
+ {
78
+ method: 'POST',
79
+ body: jq({
80
+ jsonrpc: '2.0',
81
+ id: 1757612624,
82
+ method: 'abci_query',
83
+ params: {
84
+ path: '/agoric.vstorage.Query/Children',
85
+ data: '',
86
+ prove: false,
87
+ },
88
+ }),
89
+ headers: { 'Content-Type': 'application/json' },
90
+ },
91
+ ]),
92
+ {
93
+ id: 1757612624,
94
+ jsonrpc: '2.0',
95
+ result: {
96
+ response: {
97
+ code: 0,
98
+ codespace: '',
99
+ height: '123985',
100
+ index: '0',
101
+ info: '',
102
+ key: null,
103
+ log: '',
104
+ proofOps: null,
105
+ value:
106
+ 'CgxhY3Rpdml0eWhhc2gKCmJlYW5zT3dpbmcKBmVncmVzcwoTaGlnaFByaW9yaXR5U2VuZGVycwoJcHVibGlzaGVkCgpzd2luZ1N0b3Jl',
107
+ },
108
+ },
109
+ },
110
+ ],
111
+ ]);
112
+
113
+ /**
114
+ * @param {string} str
115
+ * ack: https://stackoverflow.com/a/7616484
116
+ */
117
+ const hashCode = str => {
118
+ let hash = 0;
119
+ let i;
120
+ let chr;
121
+ if (str.length === 0) return hash;
122
+ for (i = 0; i < str.length; i += 1) {
123
+ chr = str.charCodeAt(i);
124
+ // eslint-disable-next-line no-bitwise
125
+ hash = (hash << 5) - hash + chr;
126
+ // eslint-disable-next-line no-bitwise
127
+ hash |= 0; // Convert to 32bit integer
128
+ }
129
+ return hash;
130
+ };
131
+
132
+ /**
133
+ * Normalize JSON RPC request ID
134
+ *
135
+ * tendermint-rpc generates ids using ambient access to Math.random()
136
+ * So we normalize them to a hash of the rest of the JSON.
137
+ *
138
+ * Earlier, we tried a sequence number, but it was non-deterministic
139
+ * with multiple interleaved requests.
140
+ *
141
+ * @param {string} argsKey
142
+ */
143
+ const normalizeID = argsKey => {
144
+ // arbitrary string unlikely to occur in a request. from `pwgen 16 -1`
145
+ const placeholder = 'Ajaz1chei7ohnguv';
146
+
147
+ const noid = argsKey.replace(/\\"id\\":\d+/, `\\"id\\":${placeholder}`);
148
+ const id = Math.abs(hashCode(noid));
149
+ return noid.replace(placeholder, `${id}`);
150
+ };
151
+
152
+ /**
153
+ * Wrap `fetch` to capture JSON RPC IO traffic.
154
+ *
155
+ * @param {typeof window.fetch} fetch
156
+ * returns wraped fetch along with a .web map for use with {@link replayIO}
157
+ */
158
+ export const captureIO = fetch => {
159
+ const web = new Map();
160
+ /** @type {typeof window.fetch} */
161
+ // @ts-expect-error mock
162
+ const f = async (...args) => {
163
+ const key = normalizeID(JSON.stringify(args));
164
+ const resp = await fetch(...args);
165
+ return {
166
+ json: async () => {
167
+ const data = await resp.json();
168
+ web.set(key, data);
169
+ return data;
170
+ },
171
+ };
172
+ };
173
+ return { fetch: f, web };
174
+ };
175
+
176
+ /**
177
+ * Replay captured JSON RPC IO.
178
+ *
179
+ * @param {Map<string, any>} web map from
180
+ * JSON-stringified fetch args to fetched JSON data.
181
+ */
182
+ export const replayIO = web => {
183
+ /** @type {typeof window.fetch} */
184
+ // @ts-expect-error mock
185
+ const f = async (...args) => {
186
+ const key = normalizeID(JSON.stringify(args));
187
+ const data = web.get(key);
188
+ if (!data) {
189
+ throw Error(`no data for ${key}`);
190
+ }
191
+ return {
192
+ json: async () => data,
193
+ };
194
+ };
195
+ return f;
196
+ };
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": [
3
+ "./tsconfig.json",
4
+ "../../tsconfig-build-options.json"
5
+ ]
6
+ }
@@ -1,6 +1,7 @@
1
1
  // This file can contain .js-specific Typescript compiler config.
2
2
  {
3
3
  "extends": "../../tsconfig.json",
4
+ "compilerOptions": {},
4
5
  "include": [
5
6
  "*.js",
6
7
  "public/**/*.js",
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./jsconfig.json",
3
- "compilerOptions": {
4
- "noEmit": false,
5
- "declaration": true,
6
- "emitDeclarationOnly": true,
7
- "declarationMap": true
8
- },
9
- "exclude": [
10
- "test/"
11
- ]
12
- }
File without changes