Skip to content

Commit

Permalink
feat: move oracle and priceAggregator contracts from dapp-oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Nov 5, 2020
1 parent 259c08f commit 035603b
Show file tree
Hide file tree
Showing 5 changed files with 1,472 additions and 0 deletions.
79 changes: 79 additions & 0 deletions packages/zoe/src/contracts/exported.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,82 @@
* @property {() => Promise<Invitation>} makeInvitation
* @property {() => Notifier<any>} getNotifier
*/

/**
* @typedef {Object} OracleAdmin
* @property {() => Promise<void>} delete Remove the oracle from the aggregator
* @property {(result: any) => Promise<void>} pushResult rather than waiting for
* the polling query, push a result directly from this oracle
*/

/**
* @typedef {Object} PriceAggregatorCreatorFacet
* @property {(quoteMint: Mint) => Promise<void>} initializeQuoteMint
* @property {(oracleInstance: Instance, query: any=) => Promise<OracleAdmin>} initOracle
*/

/**
* @typedef {Object} PriceAggregatorPublicFacet
* @property {() => PriceAuthority} getPriceAuthority
*/

/**
* @typedef {Object} PriceAggregatorKit
* @property {PriceAggregatorPublicFacet} publicFacet
* @property {PriceAggregatorCreatorFacet} creatorFacet
*/

/**
* @typedef {Object} OraclePublicFacet the public methods accessible from the
* contract instance
* @property {(query: any) => ERef<Invitation>} makeQueryInvitation create an
* invitation for a paid oracle query
* @property {(query: any) => ERef<any>} query make an unpaid query
* @property {() => string} getDescription describe this oracle
*/

/**
* @typedef {Object} OracleCreatorFacet the private methods accessible from the
* contract instance
* @property {(issuerP: ERef<Issuer>) => Promise<void>} addFeeIssuer add an
* issuer to collect fees for the oracle
* @property {() => AmountKeywordRecord} getCurrentFees get the current
* fee amounts
* @property {(total: boolean=) => ERef<Invitation>}
* makeWithdrawInvitation create an invitation to withdraw fees
*/

/**
* @typedef {Object} OraclePrivateParameters
* @property {OracleHandler} oracleHandler
*/

/**
* @typedef {Object} OracleInitializationFacet
* @property {(privateParams: OraclePrivateParameters) => OracleCreatorFacet} initialize
*/

/**
* @typedef {Object} OracleStartFnResult
* @property {OracleInitializationFacet} creatorFacet
* @property {OraclePublicFacet} publicFacet
* @property {Instance} instance
* @property {Invitation} creatorInvitation
*/

/**
* @typedef {Object} OracleKit
* @property {OracleCreatorFacet} creatorFacet
* @property {OraclePublicFacet} publicFacet
* @property {Instance} instance
* @property {Invitation} creatorInvitation
*/

/**
* @typedef {Object} OracleHandler
* @property {(query: any, fee: Amount) => Promise<{ reply:
* any, requiredFee: Amount }>} onQuery callback to reply to a query
* @property {(query: any, reason: any) => void} onError notice an error
* @property {(query: any, reply: any, requiredFee: Amount) => void} onReply
* notice a successful reply
*/
145 changes: 145 additions & 0 deletions packages/zoe/src/contracts/oracle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// @ts-check
import { assert, details } from '@agoric/assert';
import { E } from '@agoric/eventual-send';
import { trade } from '../contractSupport';

import '../../exported';

/**
* This contract provides oracle queries for a fee or for pay.
*
* @type {ContractStartFn}
*
*/
const start = async zcf => {
const { oracleDescription } = zcf.getTerms();

const {
brands: { Fee: feeBrand },
maths: { Fee: feeMath },
} = zcf.getTerms();

/** @type {OracleHandler} */
let handler;
/** @type {string} */
const description = oracleDescription;

const { zcfSeat: feeSeat } = zcf.makeEmptySeatKit();

let lastIssuerNonce = 0;
/** @type {string} */
let revoked;

/** @type {OracleCreatorFacet} */
const realCreatorFacet = {
async addFeeIssuer(issuerP) {
lastIssuerNonce += 1;
const keyword = `OracleFee${lastIssuerNonce}`;
await zcf.saveIssuer(issuerP, keyword);
},
makeWithdrawInvitation(total = false) {
return zcf.makeInvitation(seat => {
const gains = total
? feeSeat.getCurrentAllocation()
: seat.getProposal().want;
trade(zcf, { seat: feeSeat, gains: {} }, { seat, gains });
seat.exit();
return 'liquidated';
}, 'oracle liquidation');
},
getCurrentFees() {
return feeSeat.getCurrentAllocation();
},
};

const creatorFacet = harden({
initialize(privateParams) {
const { oracleHandler } = privateParams;
handler = oracleHandler;
return realCreatorFacet;
},
});

/** @type {OraclePublicFacet} */
const publicFacet = harden({
getDescription() {
return description;
},
async query(query) {
try {
if (revoked) {
throw Error(revoked);
}
const noFee = feeMath.getEmpty();
const { requiredFee, reply } = await E(handler).onQuery(query, noFee);
if (revoked) {
throw Error(revoked);
}
assert(
!requiredFee || feeMath.isGTE(noFee, requiredFee),
details`Oracle required a fee but the query had none`,
);
return reply;
} catch (e) {
E(handler).onError(query, e);
throw e;
}
},
async makeQueryInvitation(query) {
/** @type {OfferHandler} */
const offerHandler = async seat => {
try {
if (revoked) {
throw Error(revoked);
}

const fee = await seat.getAmountAllocated('Fee', feeBrand);
if (revoked) {
throw Error(revoked);
}

const { requiredFee, reply } = await E(handler).onQuery(query, fee);
if (requiredFee) {
trade(
zcf,
{ seat, gains: {} },
{ seat: feeSeat, gains: { Fee: requiredFee } },
);
}

seat.exit();
E(handler).onReply(query, reply, requiredFee);
return reply;
} catch (e) {
seat.kickOut(e);
E(handler).onError(query, e);
throw e;
}
};
return zcf.makeInvitation(offerHandler, 'oracle query', { query });
},
});

const creatorInvitation = zcf.makeInvitation(
async seat =>
harden({
exit() {
trade(
zcf,
{ seat: feeSeat, gains: {} },
{ seat, gains: feeSeat.getCurrentAllocation() },
);
seat.exit();
feeSeat.exit();
revoked = `Oracle ${description} revoked`;
return 'liquidated';
},
}),
'oracle total liquidation',
);

return { creatorFacet, publicFacet, creatorInvitation };
};

harden(start);
export { start };
Loading

0 comments on commit 035603b

Please sign in to comment.