Skip to content

Commit

Permalink
feat(fast-usdc): write chain policies to vstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
samsiegart committed Nov 20, 2024
1 parent 9c61393 commit ae29bc2
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 10 deletions.
27 changes: 27 additions & 0 deletions packages/boot/test/fast-usdc/fast-usdc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@ test.serial(
},
);

test.serial('writes feed policy to vstorage', async t => {
const { storage } = t.context;
t.truthy(storage.data.get('published.fastUsdc.feedPolicy'));
const feedPolicy = unmarshalFromVstorage(
storage.data,
'published.fastUsdc.feedPolicy',
makeMarshal().fromCapData,
-1,
);
t.deepEqual(feedPolicy, {
nobleAgoricChannelId: 'channel-21',
nobleDomainId: 4,
chainPolicies: {
42161: {
cctpTokenMessengerAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
chainName: 'Arbitrum',
confirmations: 1,
nobleContractAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
bridgeContractAddress: undefined,
eventFilter: undefined,
chainType: undefined,
isL2: undefined,
},
},
});
});

test.serial('restart contract', async t => {
const { EV } = t.context.runUtils;
await null;
Expand Down
37 changes: 31 additions & 6 deletions packages/fast-usdc/src/exos/transaction-feed.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { makeTracer } from '@agoric/internal';
import { prepareDurablePublishKit } from '@agoric/notifier';
import { M } from '@endo/patterns';
import { CctpTxEvidenceShape } from '../type-guards.js';
import { E } from '@endo/eventual-send';
import { CctpTxEvidenceShape, FeedPolicyShape } from '../type-guards.js';
import { defineInertInvitation } from '../utils/zoe.js';
import { prepareOperatorKit } from './operator-kit.js';

/**
* @import {Zone} from '@agoric/zone';
* @import {Remote} from '@agoric/internal'
* @import {MakeRecorderKit} from '@agoric/zoe/src/contractSupport/recorder.js'
* @import {OperatorKit} from './operator-kit.js';
* @import {CctpTxEvidence} from '../types.js';
* @import {CctpTxEvidence, FeedPolicy} from '../types.js';
*/

const trace = makeTracer('TxFeed', true);

/** Name in the invitation purse (keyed also by this contract instance) */
export const INVITATION_MAKERS_DESC = 'oracle operator invitation';

const POLICY_NODE_PATH = 'feedPolicy';

const TransactionFeedKitI = harden({
operatorPowers: M.interface('Transaction Feed Admin', {
submitEvidence: M.call(CctpTxEvidenceShape, M.any()).returns(),
Expand All @@ -25,6 +30,7 @@ const TransactionFeedKitI = harden({
initOperator: M.call(M.string()).returns(M.record()),
makeOperatorInvitation: M.call(M.string()).returns(M.promise()),
removeOperator: M.call(M.string()).returns(),
writePolicy: M.call(FeedPolicyShape).returns(M.promise()),
}),
public: M.interface('Transaction Feed Public', {
getEvidenceSubscriber: M.call().returns(M.remotable()),
Expand All @@ -34,8 +40,11 @@ const TransactionFeedKitI = harden({
/**
* @param {Zone} zone
* @param {ZCF} zcf
* @param {{
* makeRecorderKit: MakeRecorderKit;
* }} tools
*/
export const prepareTransactionFeedKit = (zone, zcf) => {
export const prepareTransactionFeedKit = (zone, zcf, tools) => {
const kinds = zone.mapStore('Kinds');
const makeDurablePublishKit = prepareDurablePublishKit(
kinds,
Expand All @@ -53,7 +62,10 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
return zone.exoClassKit(
'Fast USDC Feed',
TransactionFeedKitI,
() => {
/**
* @param {Remote<StorageNode>} node
*/
node => {
/** @type {MapStore<string, OperatorKit>} */
const operators = zone.mapStore('operators', {
durable: true,
Expand All @@ -62,13 +74,13 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
const pending = zone.mapStore('pending', {
durable: true,
});
return { operators, pending };
return { operators, pending, node };
},
{
creator: {
/**
* An "operator invitation" is an invitation to be an operator in the
* oracle netowrk, with the able to submit data to submit evidence of
* oracle network, with the able to submit data to submit evidence of
* CCTP transactions.
*
* @param {string} operatorId unique per contract instance
Expand Down Expand Up @@ -113,6 +125,19 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
operatorKit.admin.disable();
operators.delete(operatorId);
},

/**
* @param {FeedPolicy} feedPolicy
*/
async writePolicy(feedPolicy) {
const { node } = this.state;
const feedPolicyNode = await E(node).makeChildNode(POLICY_NODE_PATH);
const feedPolicyKit = tools.makeRecorderKit(
feedPolicyNode,
FeedPolicyShape,
);
await feedPolicyKit.recorder.write(harden(feedPolicy));
},
},
operatorPowers: {
/**
Expand Down
12 changes: 9 additions & 3 deletions packages/fast-usdc/src/fast-usdc.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const trace = makeTracer('FastUsdc');
* @import {OrchestrationPowers, OrchestrationTools} from '@agoric/orchestration/src/utils/start-helper.js';
* @import {Zone} from '@agoric/zone';
* @import {OperatorKit} from './exos/operator-kit.js';
* @import {CctpTxEvidence, FeeConfig} from './types.js';
* @import {CctpTxEvidence, FeeConfig, ChainPolicy, FastUSDCPolicy, FeedPolicy} from './types.js';
* @import {RepayAmountKWR, RepayPaymentKWR} from './exos/liquidity-pool.js';
*/

Expand Down Expand Up @@ -85,9 +85,9 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
statusManager,
vowTools,
});
const makeFeedKit = prepareTransactionFeedKit(zone, zcf);
const makeFeedKit = prepareTransactionFeedKit(zone, zcf, { makeRecorderKit });
assertAllDefined({ makeFeedKit, makeAdvancer, makeSettler, statusManager });
const feedKit = makeFeedKit();
const feedKit = makeFeedKit(privateArgs.storageNode);
const advancer = makeAdvancer(
// @ts-expect-error FIXME
{},
Expand Down Expand Up @@ -119,6 +119,12 @@ export const contract = async (zcf, privateArgs, zone, tools) => {
async makeOperatorInvitation(operatorId) {
return feedKit.creator.makeOperatorInvitation(operatorId);
},
/**
* @param {FeedPolicy} feedPolicy
*/
async writeFeedPolicy(feedPolicy) {
return feedKit.creator.writePolicy(feedPolicy);
},
/**
* @param {{ USDC: Amount<'nat'>}} amounts
*/
Expand Down
21 changes: 21 additions & 0 deletions packages/fast-usdc/src/fast-usdc.start.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,27 @@ export const startFastUSDC = async (
fastUsdcKit.resolve(harden({ ...kit, privateArgs }));
const { instance, creatorFacet } = kit;

// XXX: Read the policy from a config file somewhere?
await E(creatorFacet).writeFeedPolicy(
harden({
nobleAgoricChannelId: 'channel-21',
nobleDomainId: 4,
chainPolicies: {
42161: {
cctpTokenMessengerAddress:
'0x19330d10D9Cc8751218eaf51E8885D058642E08A',
chainName: 'Arbitrum',
confirmations: 1,
nobleContractAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A',
bridgeContractAddress: undefined,
eventFilter: undefined,
chainType: undefined,
isL2: undefined,
},
},
}),
);

const {
issuers: { PoolShares: shareIssuer },
brands: { PoolShares: shareBrand },
Expand Down
23 changes: 22 additions & 1 deletion packages/fast-usdc/src/type-guards.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { PendingTxStatus } from './constants.js';
* @import {TypedPattern} from '@agoric/internal';
* @import {FastUsdcTerms} from './fast-usdc.contract.js';
* @import {USDCProposalShapes} from './pool-share-math.js';
* @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics} from './types.js';
* @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy} from './types.js';
*/

/**
Expand Down Expand Up @@ -93,3 +93,24 @@ export const PoolMetricsShape = {
totalRepays: AmountShape,
};
harden(PoolMetricsShape);

/** @type {TypedPattern<ChainPolicy>} */
export const ChainPoliciesShape = {
nobleContractAddress: EvmHashShape,
cctpTokenMessengerAddress: EvmHashShape,
confirmations: M.number(),
chainName: M.string(),
bridgeContractAddress: M.opt(EvmHashShape),
eventFilter: M.opt(M.string()),
chainType: M.opt(M.number()),
isL2: M.opt(M.boolean()),
};
harden(ChainPoliciesShape);

/** @type {TypedPattern<FeedPolicy>} */
export const FeedPolicyShape = {
nobleDomainId: M.number(),
nobleAgoricChannelId: M.string(),
chainPolicies: M.recordOf(M.string(), ChainPoliciesShape),
};
harden(FeedPolicyShape);
17 changes: 17 additions & 0 deletions packages/fast-usdc/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,21 @@ export interface PoolMetrics extends PoolStats {
shareWorth: Ratio;
}

export interface ChainPolicy {
nobleContractAddress: EvmHash;
cctpTokenMessengerAddress: EvmHash;
confirmations: number;
chainName: string;
bridgeContractAddress?: EvmHash;
eventFilter?: string;
chainType?: number;
isL2?: boolean;
}

export interface FeedPolicy {
nobleDomainId: number;
nobleAgoricChannelId: string;
chainPolicies: Record<string, ChainPolicy>;
}

export type * from './constants.js';

0 comments on commit ae29bc2

Please sign in to comment.