@node-dlc/core
Version:
224 lines (188 loc) • 5.88 kB
text/typescript
import {
ContractDescriptorV1,
ContractInfoV0,
DigitDecompositionEventDescriptorV0,
DlcOfferV0,
HyperbolaPayoutCurvePiece,
OracleAnnouncementV0,
OracleEventV0,
OracleInfoV0,
PayoutFunctionV0,
} from '@node-dlc/messaging';
import { expect } from 'chai';
import { CoveredCall } from '../../../lib/dlc/finance/CoveredCall';
import {
getOptionInfoFromContractInfo,
getOptionInfoFromOffer,
} from '../../../lib/dlc/finance/OptionInfo';
import { ShortPut } from '../../../lib/dlc/finance/ShortPut';
describe('OptionInfo', () => {
describe('OptionInfo from covered call messages', () => {
const strikePrice = BigInt(50000);
const contractSize = BigInt(10) ** BigInt(8);
const premium = BigInt(50000);
const expiry = new Date(1620014750000);
const oracleBase = 2;
const oracleDigits = 17;
const { totalCollateral, payoutFunction } = CoveredCall.buildPayoutFunction(
strikePrice,
contractSize,
oracleBase,
oracleDigits,
);
const dlcOffer = buildDlcOfferFixture(
oracleDigits,
expiry,
payoutFunction,
totalCollateral,
premium,
);
const contractInfo = dlcOffer.contractInfo;
it('should get correct OptionInfo from ContractInfo', () => {
const optionInfo = getOptionInfoFromContractInfo(contractInfo);
expect(optionInfo).to.deep.equal({
contractSize,
strikePrice,
expiry,
type: 'call',
});
});
it('should get correct OptionInfoWithPremium from DlcOffer', () => {
const optionInfo = getOptionInfoFromOffer(dlcOffer);
expect(optionInfo).to.deep.equal({
contractSize,
strikePrice,
expiry,
premium,
type: 'call',
});
});
it('should throw on an invalid curve', () => {
const {
totalCollateral,
payoutFunction,
} = CoveredCall.buildPayoutFunction(
strikePrice,
contractSize,
oracleBase,
oracleDigits,
);
const invalidDlcOffer = buildDlcOfferFixture(
oracleDigits,
expiry,
payoutFunction,
totalCollateral,
premium,
);
((((invalidDlcOffer.contractInfo as ContractInfoV0)
.contractDescriptor as ContractDescriptorV1)
.payoutFunction as PayoutFunctionV0).pieces[0]
.payoutCurvePiece as HyperbolaPayoutCurvePiece).translateOutcome = BigInt(
4,
);
expect(() => {
getOptionInfoFromOffer(invalidDlcOffer);
}).to.throw();
});
});
describe('OptionInfo from short call messages', () => {
const strikePrice = BigInt(50000);
const contractSize = BigInt(10) ** BigInt(8);
const totalCollateral = BigInt(9) ** BigInt(8);
const premium = BigInt(50000);
const expiry = new Date(1620014750000);
const oracleBase = 2;
const oracleDigits = 17;
const { payoutFunction } = ShortPut.buildPayoutFunction(
strikePrice,
contractSize,
totalCollateral,
oracleBase,
oracleDigits,
);
const dlcOffer = buildDlcOfferFixture(
oracleDigits,
expiry,
payoutFunction,
totalCollateral,
premium,
);
const contractInfo = dlcOffer.contractInfo;
it('should get correct OptionInfo from ContractInfo', () => {
const optionInfo = getOptionInfoFromContractInfo(contractInfo);
expect(optionInfo).to.deep.equal({
contractSize,
strikePrice,
expiry,
type: 'put',
});
});
it('should get correct OptionInfoWithPremium from DlcOffer', () => {
const optionInfo = getOptionInfoFromOffer(dlcOffer);
expect(optionInfo).to.deep.equal({
contractSize,
strikePrice,
expiry,
premium,
type: 'put',
});
});
it('should throw on an invalid curve', () => {
const { payoutFunction } = ShortPut.buildPayoutFunction(
strikePrice,
contractSize,
totalCollateral,
oracleBase,
oracleDigits,
);
const invalidDlcOffer = buildDlcOfferFixture(
oracleDigits,
expiry,
payoutFunction,
totalCollateral,
premium,
);
((((invalidDlcOffer.contractInfo as ContractInfoV0)
.contractDescriptor as ContractDescriptorV1)
.payoutFunction as PayoutFunctionV0).pieces[0]
.payoutCurvePiece as HyperbolaPayoutCurvePiece).translateOutcome = BigInt(
4,
);
expect(() => {
getOptionInfoFromOffer(invalidDlcOffer);
}).to.throw();
});
});
});
function buildDlcOfferFixture(
oracleDigits: number,
expiry: Date,
payoutFunction: PayoutFunctionV0,
totalCollateral: bigint,
premium: bigint,
) {
const eventDescriptor = new DigitDecompositionEventDescriptorV0();
eventDescriptor.base = 2;
eventDescriptor.isSigned = false;
eventDescriptor.unit = 'BTC-USD';
eventDescriptor.precision = 0;
eventDescriptor.nbDigits = oracleDigits;
const oracleEvent = new OracleEventV0();
oracleEvent.eventMaturityEpoch = Math.floor(expiry.getTime() / 1000);
oracleEvent.eventDescriptor = eventDescriptor;
const oracleAnnouncement = new OracleAnnouncementV0();
oracleAnnouncement.oracleEvent = oracleEvent;
const oracleInfo = new OracleInfoV0();
oracleInfo.announcement = oracleAnnouncement;
const contractDescriptor = new ContractDescriptorV1();
contractDescriptor.numDigits = oracleDigits;
contractDescriptor.payoutFunction = payoutFunction;
const contractInfo = new ContractInfoV0();
contractInfo.totalCollateral = totalCollateral;
contractInfo.contractDescriptor = contractDescriptor;
contractInfo.oracleInfo = oracleInfo;
const dlcOffer = new DlcOfferV0();
dlcOffer.contractInfo = contractInfo;
dlcOffer.offerCollateralSatoshis = totalCollateral - premium;
return dlcOffer;
}