Skip to content
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

feat(fast-usdc): publish feeConfig to vstorage #10583

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { Fail } from '@endo/errors';
import { documentStorageSchema } from '@agoric/internal/src/storage-test-utils.js';
import {
defaultMarshaller,
documentStorageSchema,
} from '@agoric/internal/src/storage-test-utils.js';
import type { CosmosValidatorAddress } from '@agoric/orchestration';
import type { start as startStakeIca } from '@agoric/orchestration/src/examples/stake-ica.contract.js';
import type { Instance } from '@agoric/zoe/src/zoeService/utils.js';
Expand Down Expand Up @@ -52,6 +55,7 @@ test.serial('config', async t => {
await documentStorageSchema(t, storage, {
note: 'Chain info for Orchestration',
node: 'agoricNames.chain',
showValue: v => defaultMarshaller.fromCapData(JSON.parse(v)),
});
}

Expand All @@ -73,6 +77,7 @@ test.serial('config', async t => {
await documentStorageSchema(t, storage, {
note: 'Chain connections for Orchestration',
node: 'agoricNames.chainConnection',
showValue: v => defaultMarshaller.fromCapData(JSON.parse(v)),
});
}
{
Expand Down
2,076 changes: 1,961 additions & 115 deletions packages/boot/test/bootstrapTests/snapshots/orchestration.test.ts.md

Large diffs are not rendered by default.

Binary file not shown.
14 changes: 13 additions & 1 deletion packages/boot/test/fast-usdc/fast-usdc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { documentStorageSchema } from '@agoric/governance/tools/storageDoc.js';
import { Fail } from '@endo/errors';
import { unmarshalFromVstorage } from '@agoric/internal/src/marshal.js';
import { makeMarshal } from '@endo/marshal';
import { defaultMarshaller } from '@agoric/internal/src/storage-test-utils.js';
import {
makeWalletFactoryContext,
type WalletFactoryTestContext,
Expand Down Expand Up @@ -110,9 +111,20 @@ test.serial(

test.serial('writes feed policy to vstorage', async t => {
const { storage } = t.context;
const doc = {
const opts = {
node: 'fastUsdc.feedPolicy',
owner: 'the general and chain-specific policies for the Fast USDC feed',
showValue: JSON.parse,
};
await documentStorageSchema(t, storage, opts);
});

test.serial('writes fee config to vstorage', async t => {
const { storage } = t.context;
const doc = {
node: 'fastUsdc.feeConfig',
owner: 'the fee configuration for Fast USDC',
showValue: v => defaultMarshaller.fromCapData(JSON.parse(v)),
};
await documentStorageSchema(t, storage, doc);
});
Expand Down
60 changes: 57 additions & 3 deletions packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,61 @@ Generated by [AVA](https://avajs.dev).
[
[
'published.fastUsdc.feedPolicy',
'{"blockHeight":"0","values":["{\\"chainPolicies\\":{\\"Arbitrum\\":{\\"cctpTokenMessengerAddress\\":\\"0x19330d10D9Cc8751218eaf51E8885D058642E08A\\",\\"chainId\\":42161,\\"confirmations\\":2,\\"nobleContractAddress\\":\\"0x19330d10D9Cc8751218eaf51E8885D058642E08A\\"}},\\"nobleAgoricChannelId\\":\\"channel-21\\",\\"nobleDomainId\\":4}"]}',
{
chainPolicies: {
Arbitrum: {
cctpTokenMessengerAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
chainId: 42161,
confirmations: 2,
nobleContractAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
},
},
nobleAgoricChannelId: 'channel-21',
nobleDomainId: 4,
},
],
]

## writes fee config to vstorage

> Under "published", the "fastUsdc.feeConfig" node is delegated to the fee configuration for Fast USDC.
> The example below illustrates the schema of the data published there.
>
> See also board marshalling conventions (_to appear_).

[
[
'published.fastUsdc.feeConfig',
{
contractRate: {
denominator: {
brand: Object @Alleged: USDC brand {},
value: 10n,
},
numerator: {
brand: Object @Alleged: USDC brand {},
value: 2n,
},
},
flat: {
brand: Object @Alleged: USDC brand {},
value: 10000n,
},
maxVariable: {
brand: Object @Alleged: USDC brand {},
value: 5000000n,
},
variableRate: {
denominator: {
brand: Object @Alleged: USDC brand {},
value: 100n,
},
numerator: {
brand: Object @Alleged: USDC brand {},
value: 1n,
},
},
},
],
]

Expand All @@ -28,10 +82,10 @@ Generated by [AVA](https://avajs.dev).
[
[
'published.fastUsdc.status.0xc81bc6105b60a234c7c50ac17816ebcd5561d366df8bf3be59ff387552761702',
'{"blockHeight":"0","values":["OBSERVED"]}',
'OBSERVED',
],
[
'published.fastUsdc.status.0xd81bc6105b60a234c7c50ac17816ebcd5561d366df8bf3be59ff387552761799',
'{"blockHeight":"0","values":["OBSERVED"]}',
'OBSERVED',
],
]
Binary file modified packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap
Binary file not shown.
22 changes: 18 additions & 4 deletions packages/fast-usdc/src/fast-usdc.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ import * as flows from './fast-usdc.flows.js';
const trace = makeTracer('FastUsdc');

const STATUS_NODE = 'status';
const FEE_NODE = 'feeConfig';

/**
* @import {HostInterface} from '@agoric/async-flow';
* @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount} from '@agoric/orchestration';
* @import {OrchestrationPowers, OrchestrationTools} from '@agoric/orchestration/src/utils/start-helper.js';
* @import {Vow} from '@agoric/vow';
* @import {Remote} from '@agoric/internal';
* @import {Marshaller, StorageNode} from '@agoric/internal/src/lib-chainStorage.js'
* @import {Zone} from '@agoric/zone';
* @import {OperatorKit} from './exos/operator-kit.js';
* @import {CctpTxEvidence, FeeConfig} from './types.js';
Expand Down Expand Up @@ -63,6 +65,17 @@ export const meta = {
};
harden(meta);

/**
* @param {Remote<StorageNode>} node
* @param {ERef<Marshaller>} marshaller
* @param {FeeConfig} feeConfig
*/
const publishFeeConfig = async (node, marshaller, feeConfig) => {
const feeNode = E(node).makeChildNode(FEE_NODE);
const value = await E(marshaller).toCapData(feeConfig);
return E(feeNode).setValue(JSON.stringify(value));
};

/**
* @param {ZCF<FastUsdcTerms>} zcf
* @param {OrchestrationPowers & {
Expand All @@ -80,14 +93,13 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
assert('USDC' in terms.brands, 'no USDC brand');
assert('usdcDenom' in terms, 'no usdcDenom');

const { feeConfig, marshaller } = privateArgs;
const { feeConfig, marshaller, storageNode } = privateArgs;
const { makeRecorderKit } = prepareRecorderKitMakers(
zone.mapStore('vstorage'),
marshaller,
);

const makeStatusNode = () =>
E(privateArgs.storageNode).makeChildNode(STATUS_NODE);
const makeStatusNode = () => E(storageNode).makeChildNode(STATUS_NODE);
const statusManager = prepareStatusManager(zone, makeStatusNode);

const { USDC } = terms.brands;
Expand Down Expand Up @@ -209,6 +221,8 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
// So we use zone.exoClassKit above to define the liquidity pool kind
// and pass the shareMint into the maker / init function.

void publishFeeConfig(storageNode, marshaller, feeConfig);

const shareMint = await provideSingleton(
zone.mapStore('mint'),
'PoolShare',
Expand Down
37 changes: 28 additions & 9 deletions packages/internal/src/storage-test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { makeTracer } from './debug.js';
import { isStreamCell, makeChainStorageRoot } from './lib-chainStorage.js';
import { bindAllMethods } from './method-tools.js';
import { eventLoopIteration } from './testing-utils.js';
import { NonNullish } from './errors.js';

/**
* @import {TotalMap} from './types.js';
Expand Down Expand Up @@ -250,30 +251,48 @@ export const makeMockChainStorageRoot = () => {
* @param {import('ava').ExecutionContext<unknown>} t
* @param {MockChainStorageRoot | FakeStorageKit} storage
* @param {({ note: string } | { node: string; owner: string }) &
* ({ pattern: string; replacement: string } | {})} opts
* ({ pattern: string; replacement: string } | {}) & {
* showValue?: (v: string) => unknown;
* }} opts
*/
export const documentStorageSchema = async (t, storage, opts) => {
// chainStorage publication is unsynchronized
await eventLoopIteration();

const getLast = (/** @type {string} */ cell) =>
JSON.parse(cell).values.at(-1) || assert.fail();
const { showValue = s => s } = opts;
/** @type {(d: Map<string, string>, k: string) => unknown} */
const getBodyDefault = (d, k) => showValue(getLast(NonNullish(d.get(k))));

const [keys, getBody] =
'keys' in storage
? [storage.keys(), (/** @type {string} */ k) => storage.getBody(k)]
: [storage.data.keys(), (/** @type {string} */ k) => storage.data.get(k)];
: [
storage.data.keys(),
(/** @type {string} */ k) => getBodyDefault(storage.data, k),
];

const { pattern, replacement } =
'pattern' in opts
? opts
: { pattern: 'mockChainStorageRoot.', replacement: 'published.' };
const illustration = [...keys].sort().map(

const pruned = [...keys]
.sort()
.filter(
'node' in opts
? key =>
key
.replace(pattern, replacement)
.startsWith(`published.${opts.node}`)
: _entry => true,
);

const illustration = pruned.map(
/** @type {(k: string) => [string, unknown]} */
key => [key.replace(pattern, replacement), getBody(key)],
);
const pruned = illustration.filter(
'node' in opts
? ([key, _]) => key.startsWith(`published.${opts.node}`)
: _entry => true,
);

const note =
'note' in opts
Expand All @@ -283,5 +302,5 @@ export const documentStorageSchema = async (t, storage, opts) => {
The example below illustrates the schema of the data published there.

See also board marshalling conventions (_to appear_).`;
t.snapshot(pruned, note + boilerplate);
t.snapshot(illustration, note + boilerplate);
};
Loading