@indigo-labs/indigo-sdk
Version:
Indigo SDK for interacting with Indigo endpoints via lucid-evolution
121 lines (108 loc) • 3.44 kB
text/typescript
import {
addAssets,
Data,
fromHex,
fromText,
LucidEvolution,
OutRef,
slotToUnixTime,
TxBuilder,
validatorToAddress,
} from '@lucid-evolution/lucid';
import { PriceOracleParams } from './types';
import { mkPriceOracleValidator } from './scripts';
import { oneShotMintTx } from '../one-shot/transactions';
import { AssetClass, mkAssetsOf } from '@3rd-eye-labs/cardano-offchain-common';
import { matchSingle } from '../../utils/utils';
import { ONE_SECOND } from '../../utils/time-helpers';
import {
PriceOracleDatum,
serialisePriceOracleDatum,
serialisePriceOracleRedeemer,
} from './types-new';
import * as Core from '@evolution-sdk/evolution';
import { Rational } from '../../types/rational';
export async function startPriceOracleTx(
lucid: LucidEvolution,
assetName: string,
startPrice: Rational,
oracleParams: PriceOracleParams,
currentSlot: number,
refOutRef?: OutRef,
auxiliaryData?: Core.Data.Data,
): Promise<[TxBuilder, AssetClass]> {
const network = lucid.config().network!;
const now = BigInt(slotToUnixTime(network, currentSlot));
if (!refOutRef) {
refOutRef = (await lucid.wallet().getUtxos())[0];
}
const [tx, oracleNftPolicyId] = await oneShotMintTx(lucid, {
referenceOutRef: {
txHash: refOutRef.txHash,
outputIdx: BigInt(refOutRef.outputIndex),
},
mintAmounts: [
{
tokenName: fromText(assetName),
amount: 1n,
},
],
});
const priceOracleNft: AssetClass = {
currencySymbol: fromHex(oracleNftPolicyId),
tokenName: fromHex(fromText(assetName)),
};
const oracleValidator = mkPriceOracleValidator(oracleParams);
const oracleDatum: PriceOracleDatum = {
price: startPrice,
expirationTime: BigInt(now) + oracleParams.expirationPeriod,
auxiliaryData: auxiliaryData ?? Core.Data.fromCBORHex(Data.void()),
};
tx.pay.ToContract(
validatorToAddress(lucid.config().network!, oracleValidator),
{ kind: 'inline', value: serialisePriceOracleDatum(oracleDatum) },
addAssets(mkAssetsOf(priceOracleNft, 1n)),
);
return [tx, priceOracleNft];
}
export async function feedPriceOracleTx(
lucid: LucidEvolution,
oracleOref: OutRef,
newPrice: Rational,
oracleParams: PriceOracleParams,
currentSlot: number,
auxiliaryData?: Core.Data.Data,
): Promise<TxBuilder> {
const network = lucid.config().network!;
const currentTime = BigInt(slotToUnixTime(network, currentSlot));
const priceOracleUtxo = matchSingle(
await lucid.utxosByOutRef([oracleOref]),
(_) => new Error('Expected a single price oracle UTXO'),
);
const oracleValidator = mkPriceOracleValidator(oracleParams);
return lucid
.newTx()
.validFrom(Number(currentTime - oracleParams.biasTime) + ONE_SECOND)
.validTo(Number(currentTime + oracleParams.biasTime) - ONE_SECOND)
.attach.SpendingValidator(oracleValidator)
.collectFrom(
[priceOracleUtxo],
serialisePriceOracleRedeemer({
currentTime: currentTime,
newPrice: newPrice,
}),
)
.pay.ToContract(
priceOracleUtxo.address,
{
kind: 'inline',
value: serialisePriceOracleDatum({
price: newPrice,
expirationTime: currentTime + oracleParams.expirationPeriod,
auxiliaryData: auxiliaryData ?? Core.Data.fromCBORHex(Data.void()),
}),
},
priceOracleUtxo.assets,
)
.addSignerKey(oracleParams.owner);
}