From 212786adc9c5381f391ecd0d385920e4aa41824c Mon Sep 17 00:00:00 2001 From: padraic-X Date: Fri, 10 Jul 2020 15:44:38 +0100 Subject: [PATCH] pushing latest --- packages/dai-plugin-mcd/src/PsmType.js | 54 +++++- packages/dai-plugin-mcd/src/index.js | 3 +- .../dai-plugin-mcd/src/schemas/_constants.js | 9 + packages/dai-plugin-mcd/src/schemas/index.js | 4 +- packages/dai-plugin-mcd/src/schemas/psm.js | 159 ++++++++++++++++++ 5 files changed, 222 insertions(+), 7 deletions(-) create mode 100644 packages/dai-plugin-mcd/src/schemas/psm.js diff --git a/packages/dai-plugin-mcd/src/PsmType.js b/packages/dai-plugin-mcd/src/PsmType.js index 764c894c8..5866f9730 100644 --- a/packages/dai-plugin-mcd/src/PsmType.js +++ b/packages/dai-plugin-mcd/src/PsmType.js @@ -1,11 +1,14 @@ import assert from 'assert'; import CdpType from './CdpType'; import { ServiceRoles } from './constants'; +import tracksTransactions from './utils/tracksTransactions'; +import { DAI } from './index'; +import { castAsCurrency } from './utils'; export default class PsmType { constructor( psmTypeService, - { currency, ilk, decimals }, + { currency, ilk, decimals, pair }, options = { prefetch: true } ) { assert(currency && ilk, 'currency and ilk are required'); @@ -22,21 +25,58 @@ export default class PsmType { this.currency = currency; this.decimals = decimals; this.ilk = ilk; + this.pair = pair; this._cache = {}; if (options.prefetch) this.prefetch(); } get feeIn() { - return this.psm.feeIn(); + return this._getCached('psmInfo').feeIn; } get feeOut() { - return this.psm.feeOut(); + return this._getCached('psmInfo').feeOut; + } + + get debtCeiling() { + return this._cdpType.debtCeiling; + } + + get totalCollateral() { + return this._cdpType.totalCollateral; + } + + get totalDebt() { + return this._cdpType.totalDebt; + } + + @tracksTransactions + join(amount = this.currency(0), { promise }) { + amount = castAsCurrency(amount, this.currency); + return this.psm.join(amount.toFixed(this.decimals), { + promise, + metadata: { from: this.currency.symbol, to: this.pair.symbol } + }); + } + + @tracksTransactions + exit(amount = this.pair(0), { promise }) { + amount = castAsCurrency(amount, this.pair); + return this.psm.exit(amount.toFixed(this.decimals), { + promise, + metadata: { from: this.pair.symbol, to: this.currency.symbol } + }); } async prefetch() { if (!this._prefetchPromise) { - this._prefetchPromise = Promise.all([this._cdpType.prefetch()]); + this._prefetchPromise = Promise.all([ + this._cdpType.prefetch(), + Promise.all([ + this.psm.feeIn().then(x => (this._cache.feeIn = x)), + this.psm.feeOut().then(x => (this._cache.feeOut = x)) + ]) + ]); } return this._prefetchPromise; } @@ -48,7 +88,7 @@ export default class PsmType { cache() { return { - ...this._cache, + psmInfo: this._cache, ...this._cdpType.cache }; } @@ -61,4 +101,8 @@ export default class PsmType { get psm() { return this._smartContractService.getContract(this.ilk.replace(/-/g, '_')); } + + get address() { + return this.psm.address; + } } diff --git a/packages/dai-plugin-mcd/src/index.js b/packages/dai-plugin-mcd/src/index.js index 9ef72e6f5..180eb73e0 100644 --- a/packages/dai-plugin-mcd/src/index.js +++ b/packages/dai-plugin-mcd/src/index.js @@ -32,6 +32,7 @@ const { // if an exact match is not found, prefix-match against keys ending in *, e.g. // MCD_JOIN_ETH_B matches MCD_JOIN_* // this implementation assumes that all contracts in kovan.json are also in testnet.json + let addContracts = reduce( testnetAddresses, (result, testnetAddress, name) => { @@ -93,7 +94,7 @@ export const defaultCdpTypes = [ ]; export const defaultPsmTypes = [ - { currency: USDC, ilk: 'PSM-USDC-A', decimals: 6 } + { currency: USDC, ilk: 'PSM-USDC-A', decimals: 6, pair: DAI } ]; export const SAI = createCurrency('SAI'); diff --git a/packages/dai-plugin-mcd/src/schemas/_constants.js b/packages/dai-plugin-mcd/src/schemas/_constants.js index 983b5abd3..a66943a9a 100644 --- a/packages/dai-plugin-mcd/src/schemas/_constants.js +++ b/packages/dai-plugin-mcd/src/schemas/_constants.js @@ -97,3 +97,12 @@ export const TOKEN_PRICE_NEXT_UPDATE = 'tokenPriceNextUpdate'; export const TOKEN_PRICES_NEXT_UPDATES = 'tokenPricesNextUpdates'; export const TOKEN_PRICE_UPDATE_INTERVAL = 'tokenPriceUpdateInterval'; export const TOKEN_PRICE_LAST_UPDATE = 'tokenPriceLastUpdate'; + +// psm +export const PSM_FEE_IN = 'psmFeeIn'; +export const PSM_FEE_OUT = 'psmFeeOut'; +export const PSM_FEES = 'psmFees'; +export const PSM_ALLOWANCE = 'psmAllowance'; +export const PSM_ALLOWANCES = 'psmAllowances'; +export const PSM_TYPES_INFO = 'psmTypesInfo'; +export const PSM_TYPE_COLLATERAL_AMOUNT = 'psmTypeCollateralAmount'; diff --git a/packages/dai-plugin-mcd/src/schemas/index.js b/packages/dai-plugin-mcd/src/schemas/index.js index c48f98e70..dd7b3bf2b 100644 --- a/packages/dai-plugin-mcd/src/schemas/index.js +++ b/packages/dai-plugin-mcd/src/schemas/index.js @@ -10,6 +10,7 @@ import end from './end'; import osm from './osm'; import getCdps from './getCdps'; import computed from './computed'; +import psm from './psm'; export * from './_constants'; export default { @@ -24,7 +25,8 @@ export default { ...token, ...getCdps, ...end, - ...osm + ...osm, + ...psm }; /* diff --git a/packages/dai-plugin-mcd/src/schemas/psm.js b/packages/dai-plugin-mcd/src/schemas/psm.js new file mode 100644 index 000000000..26a23b2df --- /dev/null +++ b/packages/dai-plugin-mcd/src/schemas/psm.js @@ -0,0 +1,159 @@ +import { defaultPsmTypes } from '../'; +import { + PSM_FEE_IN, + PSM_FEE_OUT, + TOKEN_ALLOWANCE_BASE, + PSM_ALLOWANCE, + COLLATERAL_DEBT_AVAILABLE, + DEBT_CEILING, + ENCUMBERED_COLLATERAL, + PSM_TYPE_COLLATERAL_AMOUNT +} from './_constants'; +import { fromRay } from '../utils'; +import { ALLOWANCE_AMOUNT } from './token'; + +export const psmFeeIn = { + generate: psmIlkName => { + const contractName = `${psmIlkName.replace(/-/g, '_')}`; + return { + id: `${contractName}.feeIn`, + contract: contractName, + call: ['feeIn()(uint256)'] + }; + }, + returns: [[PSM_FEE_IN, fromRay]] +}; + +export const psmFeeOut = { + generate: psmIlkName => { + const contractName = `${psmIlkName.replace(/-/g, '_')}`; + return { + id: `${contractName}.feeIn`, + contract: contractName, + call: ['feeOut()(uint256)'] + }; + }, + returns: [[PSM_FEE_OUT, fromRay]] +}; + +export const psmFees = { + generate: () => ({ + dependencies: [ + ...defaultPsmTypes.map(({ ilk }) => [PSM_FEE_IN, ilk]), + ...defaultPsmTypes.map(({ ilk }) => [PSM_FEE_OUT, ilk]) + ], + computed: (...fees) => { + const feesIn = fees.slice(0, fees.length / 2); + const feesOut = fees.slice(fees.length / 2, fees.length); + return defaultPsmTypes.reduce( + (acc, { ilk }, idx) => ({ + ...acc, + [ilk]: { join: feesIn[idx], exit: feesOut[idx] } + }), + {} + ); + } + }) +}; + +export const psmAllowance = { + generate: (address, psmIlk, token) => ({ + dependencies: ({ get }) => { + const psmIlkAddress = get('smartContract').getContractAddress( + psmIlk.replace(/-/g, '_') + ); + return [ + token === 'ETH' + ? [[ALLOWANCE_AMOUNT]] + : [TOKEN_ALLOWANCE_BASE, address, psmIlkAddress, token] + ]; + }, + computed: v => v.isEqualTo(ALLOWANCE_AMOUNT) + }) +}; + +export const psmAllowances = { + generate: address => ({ + dependencies: [ + ...defaultPsmTypes.map(({ ilk, currency }) => [ + PSM_ALLOWANCE, + address, + ilk, + currency.symbol + ]), + ...defaultPsmTypes.map(({ ilk, pair }) => [ + PSM_ALLOWANCE, + address, + ilk, + pair.symbol + ]) + ], + computed: (...allowances) => { + const joinAllowance = allowances.slice(0, allowances.length / 2); + const exitAllowance = allowances.slice( + allowances.length / 2, + allowances.length + ); + return defaultPsmTypes.reduce( + (acc, { ilk }, idx) => ({ + ...acc, + [ilk]: { join: joinAllowance[idx], exit: exitAllowance[idx] } + }), + {} + ); + } + }) +}; + +export const psmTypeCollateralAmount = { + generate: psmIlk => ({ + dependencies: ({ get }) => { + const psmIlkAddress = get('smartContract').getContractAddress( + psmIlk.replace(/-/g, '_') + ); + return [[ENCUMBERED_COLLATERAL, psmIlk, psmIlkAddress]]; + }, + computed: v => { + const { currency } = defaultPsmTypes.find(types => types.ilk === psmIlk); + return currency(v); + } + }) +}; + +export const psmTypesInfo = { + generate: () => ({ + dependencies: [ + ...defaultPsmTypes.map(({ ilk }) => [PSM_TYPE_COLLATERAL_AMOUNT, ilk]), + ...defaultPsmTypes.map(({ ilk }) => [COLLATERAL_DEBT_AVAILABLE, ilk]), + ...defaultPsmTypes.map(({ ilk }) => [DEBT_CEILING, ilk]) + ], + computed: (...info) => { + const collateralAmounts = info.slice(0, info.length / 3); + const debtsAvailable = info.slice(info.length / 3, (info.length * 2) / 3); + const debtCeilings = info.slice((info.length * 2) / 3, info.length); + return defaultPsmTypes.reduce( + (acc, { ilk }, idx) => ({ + ...acc, + [ilk]: { + collateral: collateralAmounts[idx], + ceiling: debtCeilings[idx], + debtAvailable: debtsAvailable[idx] + } + }), + {} + ); + } + }) +}; + +export default { + psmFeeIn, + psmFeeOut, + + // computed + psmFees, + psmAllowance, + psmAllowances, + psmTypeCollateralAmount, + psmTypesInfo +};