-
Notifications
You must be signed in to change notification settings - Fork 254
feat(internal): add key mirror utility #12093
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // @ts-check | ||
| // @jessie-check | ||
|
|
||
| const { freeze, keys } = Object; | ||
|
|
||
| /** | ||
| * @template {Record<string, string | null>} Init | ||
| * @typedef {{ readonly [K in keyof Init]: K }} KeyMirrorResult | ||
| */ | ||
|
|
||
| /** | ||
|
Check warning on line 11 in packages/internal/src/keyMirror.js
|
||
| * Mirror the keys of an object to string values that match the key names. | ||
| * | ||
| * The provided record must only map property names to either `null` or the | ||
| * property name itself. The returned object has identical keys whose values are | ||
| * the string form of the key. | ||
| * | ||
| * @template {Record<string, string | null>} Init | ||
| * @param {Init & { readonly [K in keyof Init]: Init[K] extends null ? null : K }} | ||
|
Check warning on line 19 in packages/internal/src/keyMirror.js
|
||
| * record | ||
| * @returns {KeyMirrorResult<Init>} | ||
| */ | ||
| export const keyMirror = record => { | ||
| if (record === null || typeof record !== 'object') { | ||
| throw TypeError('keyMirror expects a record of string keys.'); | ||
| } | ||
|
|
||
| /** @type {Record<string, string>} */ | ||
| const mirrored = {}; | ||
| for (const key of keys(record)) { | ||
| const typedKey = /** @type {keyof Init & string} */ (key); | ||
| const value = record[typedKey]; | ||
| const stringValue = /** @type {string | null} */ (value); | ||
| if (stringValue !== null && stringValue !== typedKey) { | ||
| throw TypeError( | ||
| `Value for key "${typedKey}" must be null or the key string; got ${String(value)}.`, | ||
| ); | ||
| } | ||
| mirrored[typedKey] = typedKey; | ||
| } | ||
|
|
||
| return /** @type {KeyMirrorResult<Init>} */ (freeze(mirrored)); | ||
| }; | ||
|
|
||
| freeze(keyMirror); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,40 +2,44 @@ | |
|
|
||
| /// <reference types="ses" /> | ||
|
|
||
| import { keyMirror } from '@agoric/internal'; | ||
|
|
||
| /** | ||
| * Yield protocols for Proof of Concept. | ||
| * | ||
| * @enum {(typeof YieldProtocol)[keyof typeof YieldProtocol]} | ||
| */ | ||
| export const YieldProtocol = /** @type {const} */ ({ | ||
| Aave: 'Aave', | ||
| Compound: 'Compound', | ||
| USDN: 'USDN', | ||
| Beefy: 'Beefy', | ||
| export const YieldProtocol = keyMirror({ | ||
| Aave: null, | ||
| Compound: null, | ||
| USDN: null, | ||
| Beefy: null, | ||
| }); | ||
| harden(YieldProtocol); | ||
|
|
||
| /** | ||
| * @enum {(typeof AxelarChain)[keyof typeof AxelarChain]} | ||
| */ | ||
| export const AxelarChain = /** @type {const} */ ({ | ||
| Arbitrum: 'Arbitrum', | ||
| Avalanche: 'Avalanche', | ||
| Base: 'Base', | ||
| Ethereum: 'Ethereum', | ||
| Optimism: 'Optimism', | ||
| export const AxelarChain = keyMirror({ | ||
| Arbitrum: null, | ||
| Avalanche: null, | ||
| Base: null, | ||
| Ethereum: null, | ||
| Optimism: null, | ||
| }); | ||
| harden(AxelarChain); | ||
|
|
||
| /** | ||
| * @enum {(typeof SupportedChain)[keyof typeof SupportedChain]} | ||
| */ | ||
| export const SupportedChain = /** @type {const} */ ({ | ||
| export const SupportedChain = { | ||
| ...AxelarChain, | ||
| agoric: 'agoric', | ||
| noble: 'noble', | ||
| // XXX: check privateArgs for chainInfo for all of these | ||
| }); | ||
| ...keyMirror({ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this could be pulled to the enclosing expression. though it would repeat the traversal of |
||
| agoric: null, | ||
| noble: null, | ||
| // XXX: check privateArgs for chainInfo for all of these | ||
| }), | ||
| }; | ||
| harden(SupportedChain); | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,13 @@ | ||
| // XXX domain of @agoric/cosmic-proto | ||
| import { keyMirror } from '@agoric/internal'; | ||
|
|
||
| /** | ||
| * non-exhaustive list of powerFlags REMOTE_WALLET is currently a default. | ||
| * | ||
| * See also MsgProvision in golang/cosmos/proto/agoric/swingset/msgs.proto | ||
| */ | ||
| export const PowerFlags = /** @type {const} */ ({ | ||
| SMART_WALLET: 'SMART_WALLET', | ||
| export const PowerFlags = keyMirror({ | ||
| SMART_WALLET: null, | ||
| /** The ag-solo wallet is remote. */ | ||
| REMOTE_WALLET: 'REMOTE_WALLET', | ||
| REMOTE_WALLET: null, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this expression could be simplified with this approach.