Created
January 10, 2024 17:38
-
-
Save tgrecojs/4e4a64394b68b32dc86ffe1326268d74 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file endo plugin for cosmos network protocol primitives: RPC, LCD (aka API). | |
*/ | |
// @ts-check | |
/* global globalThis */ | |
import { Far } from '@endo/far'; | |
import { makeHttpClient, makeLCD } from './httpClient.js'; | |
assert.typeof(globalThis.fetch, 'function'); | |
export const make = _powers => { | |
/** @param { string } rpcURL */ | |
const makeRPCClient = rpcURL => makeHttpClient(rpcURL, globalThis.fetch); | |
/** @param { string } apiURL */ | |
const makeLCDClient = apiURL => makeLCD(apiURL, { fetch: globalThis.fetch }); | |
return Far('CosmosFetch', { | |
makeRPCClient, | |
makeLCDClient, | |
}); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @file cosmos network primitives with explicit `fetch` network access. | |
*/ | |
// @ts-check | |
import { Far } from '@endo/far'; | |
const { freeze } = Object; | |
const filterBadStatus = res => { | |
if (res.status >= 400) { | |
throw new Error(`Bad status on response: ${res.status}`); | |
} | |
return res; | |
}; | |
/** | |
* Make an RpcClient using explicit access to the network. | |
* | |
* The RpcClient implementations included in cosmjs | |
* such as {@link https://cosmos.github.io/cosmjs/latest/tendermint-rpc/classes/HttpClient.html HttpClient} | |
* use ambient authority (fetch or axios) for network access. | |
* | |
* To facilitate cooperation without vulnerability, | |
* as well as unit testing, etc. this RpcClient maker takes | |
* network access as a parameter, following | |
* {@link https://github.com/Agoric/agoric-sdk/wiki/OCap-Discipline|OCap Discipline}. | |
* | |
* @param {string} url | |
* @param {typeof window.fetch} fetch | |
* @returns {import('@cosmjs/tendermint-rpc').RpcClient} | |
*/ | |
export const makeHttpClient = (url, fetch) => { | |
// cribbed from @agoric/casting/src/makeHttpClient.js | |
const headers = {}; // XXX needed? | |
// based on cosmjs 0.30.1: | |
// https://github.com/cosmos/cosmjs/blob/33271bc51cdc865cadb647a1b7ab55d873637f39/packages/tendermint-rpc/src/rpcclients/http.ts#L37 | |
// https://github.com/cosmos/cosmjs/blob/33271bc51cdc865cadb647a1b7ab55d873637f39/packages/tendermint-rpc/src/rpcclients/httpclient.ts#L25 | |
return Far('RpcClient', { | |
disconnect: () => { | |
// nothing to be done | |
}, | |
/** | |
* @param {import('@cosmjs/json-rpc').JsonRpcRequest} request | |
*/ | |
execute: async request => { | |
const settings = { | |
method: 'POST', | |
body: request ? JSON.stringify(request) : undefined, | |
headers: { | |
// eslint-disable-next-line @typescript-eslint/naming-convention | |
'Content-Type': 'application/json', | |
...headers, | |
}, | |
}; | |
return fetch(url, settings) | |
.then(filterBadStatus) | |
.then(res => res.json()); | |
}, | |
}); | |
}; | |
/** | |
* @param {string} apiURL | |
* @param {object} io | |
* @param {typeof fetch} io.fetch | |
*/ | |
export const makeLCD = (apiURL, { fetch }) => { | |
assert.typeof(apiURL, 'string'); | |
/** | |
* @param {string} href | |
* @param {object} [options] | |
* @param {Record<string, string>} [options.headers] | |
*/ | |
const getJSON = (href, options = {}) => { | |
const opts = { | |
keepalive: true, | |
headers: { | |
'Content-Type': 'application/json', | |
...options.headers, | |
}, | |
}; | |
const url = `${apiURL}${href}`; | |
return fetch(url, opts).then(r => { | |
if (!r.ok) throw Error(r.statusText); | |
return r.json().then(data => { | |
return data; | |
}); | |
}); | |
}; | |
return Far('LCD', { | |
getJSON, | |
latestBlock: () => getJSON(`/cosmos/base/tendermint/v1beta1/blocks/latest`), | |
}); | |
}; | |
/** @typedef {ReturnType<makeLCD>} LCD */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Usage: | |
* $ endo make --UNSAFE src/cosmosFetch.js -n cosmos-fetch | |
* Object [Alleged: CosmosFetch] {} | |
* $ endo make test/net-local.js -n local -p cosmos-fetch | |
* { lcd: Object [Alleged: LCD] {}, rpc: Object [Alleged: RpcClient] {} } | |
*/ | |
import { E } from '@endo/far'; | |
const loc = { | |
lcd: 'http://localhost:1317', | |
rpc: 'http://localhost:26657', | |
}; | |
export const make = async net => { | |
const [lcd, rpc] = await Promise.all([ | |
E(net).makeLCDClient(loc.lcd), | |
E(net).makeRPCClient(loc.rpc), | |
]); | |
return harden({ lcd, rpc }); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment