Skip to content

Commit

Permalink
feat(chainHub): getChainInfoFromAddress helper
Browse files Browse the repository at this point in the history
- takes a ChainAddress.value, parses the bech32Prefix, and looks up the corresponding ChainInfo
  • Loading branch information
0xpatrickdev committed Oct 28, 2024
1 parent c8c7c8d commit bbcc8d7
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 0 deletions.
26 changes: 26 additions & 0 deletions packages/orchestration/src/exos/chain-hub.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const ChainHubI = M.interface('ChainHub', {
registerAsset: M.call(M.string(), DenomDetailShape).returns(),
getAsset: M.call(M.string()).returns(M.or(DenomDetailShape, M.undefined())),
getDenom: M.call(BrandShape).returns(M.or(M.string(), M.undefined())),
getChainInfoFromAddress: M.call(M.string()).returns(CosmosChainInfoShape),
});

/**
Expand Down Expand Up @@ -216,6 +217,11 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
keyShape: BrandShape,
valueShape: M.string(),
});
/** @type {MapStore<string, string>} */
const bech32PrefixToChainName = zone.mapStore('bech32PrefixToChainName', {
keyShape: M.string(),
valueShape: M.string(),
});

const lookupChainInfo = vowTools.retryable(
zone,
Expand All @@ -230,6 +236,9 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
// TODO consider makeAtomicProvider for vows
if (!chainInfos.has(chainName)) {
chainInfos.init(chainName, chainInfo);
if (chainInfo.bech32Prefix) {
bech32PrefixToChainName.init(chainInfo.bech32Prefix, chainName);
}
}
return chainInfo;
} catch (e) {
Expand Down Expand Up @@ -316,6 +325,9 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
*/
registerChain(name, chainInfo) {
chainInfos.init(name, chainInfo);
if (chainInfo.bech32Prefix) {
bech32PrefixToChainName.init(chainInfo.bech32Prefix, name);
}
},
/**
* @template {string} K
Expand Down Expand Up @@ -425,6 +437,20 @@ export const makeChainHub = (zone, agoricNames, vowTools) => {
}
return undefined;
},
/**
* @param {string} address bech32 address
* @returns {CosmosChainInfo} chainId
*/
getChainInfoFromAddress(address) {
const [prefix, rest] = address.split('1');
(prefix && rest) ||
Fail`Address contains invalid bech32 separator: ${q(address)}`;
if (bech32PrefixToChainName.has(prefix)) {
const chainName = bech32PrefixToChainName.get(prefix);
return chainInfos.get(chainName);
}
throw makeError(`Chain info not found for bech32Prefix: ${prefix}`);
},
});

return chainHub;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Generated by [AVA](https://avajs.dev).
chainHub: {
ChainHub_kindHandle: 'Alleged: kind',
ChainHub_singleton: 'Alleged: ChainHub',
bech32PrefixToChainName: {
agoric: 'agoric',
},
brandDenom: {},
chainInfos: {
agoric: {
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Generated by [AVA](https://avajs.dev).
chainHub: {
ChainHub_kindHandle: 'Alleged: kind',
ChainHub_singleton: 'Alleged: ChainHub',
bech32PrefixToChainName: {
agoric: 'agoric',
cosmos: 'cosmoshub',
},
brandDenom: {
'Alleged: BLD brand': 'ubld',
},
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ Generated by [AVA](https://avajs.dev).
chainHub: {
ChainHub_kindHandle: 'Alleged: kind',
ChainHub_singleton: 'Alleged: ChainHub',
bech32PrefixToChainName: {
agoric: 'agoric',
osmo: 'osmosis',
stride: 'stride',
},
brandDenom: {},
chainInfos: {
agoric: {
Expand Down
Binary file not shown.
30 changes: 30 additions & 0 deletions packages/orchestration/test/exos/chain-hub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,33 @@ test.serial('toward asset info in agoricNames (#9572)', async t => {
});
}
});

test.serial('getChainInfoFromAddress', async t => {
const { chainHub, nameAdmin, vt } = setup();
// use fetched chain info
await registerKnownChains(nameAdmin);

// call getChainInfo so ChainHub performs agoricNames lookup that populates its local cache
await vt.asPromise(chainHub.getChainInfo('osmosis'));

const MOCK_ICA_ADDRESS =
'osmo1ht7u569vpuryp6utadsydcne9ckeh2v8dkd38v5hptjl3u2ewppqc6kzgd';
t.like(chainHub.getChainInfoFromAddress(MOCK_ICA_ADDRESS), {
chainId: 'osmosis-1',
bech32Prefix: 'osmo',
});

t.throws(
() =>
chainHub.getChainInfoFromAddress(
MOCK_ICA_ADDRESS.replace('osmo1', 'foo1'),
),
{
message: 'Chain info not found for bech32Prefix: foo',
},
);

t.throws(() => chainHub.getChainInfoFromAddress('notbech32'), {
message: 'Address contains invalid bech32 separator: "notbech32"',
});
});

0 comments on commit bbcc8d7

Please sign in to comment.