@indigo-labs/indigo-sdk
Version:
Indigo SDK for interacting with Indigo endpoints via lucid-evolution
155 lines (138 loc) • 3.87 kB
text/typescript
import {
fromHex,
fromText,
LucidEvolution,
OutRef,
slotToUnixTime,
toUnit,
TxBuilder,
UTxO,
validatorToAddress,
} from '@lucid-evolution/lucid';
import { InterestOracleParams } from './types';
import { oneShotMintTx } from '../one-shot/transactions';
import { mkInterestOracleValidator } from './scripts';
import { findInterestOracle } from '../../../tests/queries/interest-oracle-queries';
import { ONE_SECOND } from '../../utils/time-helpers';
import { calculateUnitaryInterestSinceOracleLastUpdated } from '../interest-oracle/helpers';
import { getInlineDatumOrThrow } from '../../utils/lucid-utils';
import { AssetClass } from '@3rd-eye-labs/cardano-offchain-common';
import {
parseInterestOracleDatum,
serialiseFeedInterestOracleRedeemer,
serialiseInterestOracleDatum,
} from './types-new';
export async function startInterestOracle(
initialUnitaryInterest: bigint,
initialInterestRate: bigint,
initialLastInterestUpdate: bigint,
oracleParams: InterestOracleParams,
lucid: LucidEvolution,
interestTokenName?: string,
withScriptRef: boolean = false,
refOutRef?: OutRef,
): Promise<[TxBuilder, AssetClass]> {
const network = lucid.config().network!;
const tokenName = interestTokenName ?? 'INTEREST_ORACLE';
if (!refOutRef) {
refOutRef = (await lucid.wallet().getUtxos())[0];
}
const [tx, policyId] = await oneShotMintTx(lucid, {
referenceOutRef: {
txHash: refOutRef.txHash,
outputIdx: BigInt(refOutRef.outputIndex),
},
mintAmounts: [
{
tokenName: fromText(tokenName),
amount: 1n,
},
],
});
const validator = mkInterestOracleValidator(oracleParams);
tx.pay.ToContract(
validatorToAddress(network, validator),
{
kind: 'inline',
value: serialiseInterestOracleDatum({
unitaryInterest: initialUnitaryInterest,
interestRate: {
getOnChainInt: initialInterestRate,
},
lastUpdated: initialLastInterestUpdate,
}),
},
{
lovelace: 2_500_000n,
[toUnit(policyId, fromText(tokenName))]: 1n,
},
);
if (withScriptRef) {
tx.pay.ToAddressWithData(
validatorToAddress(network, validator),
undefined,
undefined,
validator,
);
}
return [
tx,
{
currencySymbol: fromHex(policyId),
tokenName: fromHex(fromText(tokenName)),
},
];
}
export async function feedInterestOracle(
params: InterestOracleParams,
newInterestRate: bigint,
lucid: LucidEvolution,
currentSlot: number,
assetClass?: AssetClass,
utxo?: UTxO,
scriptRef?: UTxO,
): Promise<TxBuilder> {
if (!assetClass && !utxo)
throw new Error('Either interest oracle nft or utxo must be provided');
if (assetClass && !utxo) {
utxo = await findInterestOracle(lucid, assetClass);
}
const network = lucid.config().network!;
const now = BigInt(slotToUnixTime(network, currentSlot));
const tx = lucid.newTx();
const datum = parseInterestOracleDatum(getInlineDatumOrThrow(utxo!));
if (scriptRef) {
tx.readFrom([scriptRef]);
} else {
tx.attach.Script(mkInterestOracleValidator(params));
}
tx.collectFrom(
[utxo!],
serialiseFeedInterestOracleRedeemer({
newInterestRate: {
getOnChainInt: newInterestRate,
},
currentTime: now,
}),
);
tx.pay.ToContract(
utxo!.address,
{
kind: 'inline',
value: serialiseInterestOracleDatum({
unitaryInterest:
datum.unitaryInterest +
calculateUnitaryInterestSinceOracleLastUpdated(now, datum),
interestRate: {
getOnChainInt: newInterestRate,
},
lastUpdated: now,
}),
},
utxo!.assets,
);
tx.validFrom(Number(now) - ONE_SECOND);
tx.validTo(Number(now + params.biasTime) - ONE_SECOND);
tx.addSignerKey(params.owner);
return tx;
}