UNPKG

@indigo-labs/indigo-sdk

Version:

Indigo SDK for interacting with Indigo endpoints via lucid-evolution

169 lines (142 loc) 4.12 kB
import { negateAssets, noAdaValue, } from '@3rd-eye-labs/cardano-offchain-common'; import { addAssets, Assets, credentialToAddress, getAddressDetails, LucidEvolution, paymentCredentialOf, UTxO, } from '@lucid-evolution/lucid'; import { array as A, function as F } from 'fp-ts'; import { zipWith } from 'fp-ts/lib/Array'; import { runAndAwaitTxBuilder } from '../test-helpers'; /** * In case passing in address with stake credential, the non stake credential address * is used as well for collecting inputs but cannot increase its value. */ export async function getValueChangeAtAddressAfterAction<T>( lucid: LucidEvolution, address: string, action: () => Promise<T>, ): Promise<[T, Assets]> { const hasStakeCred = getAddressDetails(address).stakeCredential != null; const valBefore = A.reduce<UTxO, Assets>({}, (acc, utxo) => addAssets(acc, utxo.assets), )(await lucid.utxosAt(address)); const [res, nonStakeCredValChange] = hasStakeCred ? await getValueChangeAtAddressAfterAction( lucid, credentialToAddress( lucid.config().network!, paymentCredentialOf(address), ), action, ) : [await action(), {}]; if ( hasStakeCred && !Object.entries(nonStakeCredValChange).every(([_, amt]) => amt <= 0n) ) { throw new Error("Can't add value to the address without stake credential"); } const valAfter = A.reduce<UTxO, Assets>({}, (acc, utxo) => addAssets(acc, utxo.assets), )(await lucid.utxosAt(address)); return [ res, addAssets(valAfter, negateAssets(valBefore), nonStakeCredValChange), ]; } export async function getValueChangeAtAddressesAfterAction<T>( lucid: LucidEvolution, addresses: string[], action: () => Promise<T>, ): Promise<[T, Assets[]]> { const valsBefore = []; for (const address of addresses) { const utxos = await lucid.utxosAt(address); valsBefore.push( F.pipe( utxos, A.reduce<UTxO, Assets>({}, (acc, utxo) => addAssets(acc, utxo.assets)), ), ); } const res = await action(); const valsAfter = []; for (const address of addresses) { const utxos = await lucid.utxosAt(address); valsAfter.push( F.pipe( utxos, A.reduce<UTxO, Assets>({}, (acc, utxo) => addAssets(acc, utxo.assets)), ), ); } return [ res, zipWith(valsBefore, valsAfter, (valBefore, valAfter) => addAssets(valAfter, negateAssets(valBefore)), ), ]; } export async function getNewUtxosAtAddressAfterAction<T>( lucid: LucidEvolution, address: string, action: () => Promise<T>, ): Promise<[T, UTxO[]]> { const utxosBefore = await lucid.utxosAt(address); const res = await action(); const utxosAfter = await lucid.utxosAt(address); return [ res, utxosAfter.filter( (utxo) => utxosBefore.filter( (oldUtxo) => utxo.txHash === oldUtxo.txHash && utxo.outputIndex === oldUtxo.outputIndex, ).length === 0, ), ]; } export async function totalValueAtAddress( lucid: LucidEvolution, addr: string, ): Promise<Assets> { const utxos = await lucid.utxosAt(addr); return F.pipe( utxos, A.reduce<UTxO, Assets>({}, (acc, utxo) => addAssets(acc, utxo.assets)), ); } export async function sendValueTo( destinationAddr: string, value: Assets, lucid: LucidEvolution, ): Promise<void> { await runAndAwaitTxBuilder( lucid, lucid.newTx().pay.ToAddress(destinationAddr, value), ); } /** * For all the non-ADA assets in current wallet, create a separate UTXo with each of them. */ export async function fragmentWallet(lucid: LucidEvolution): Promise<void> { const currentAddr = await lucid.wallet().address(); const totalVal = await totalValueAtAddress(lucid, currentAddr); const otherAssets = Object.keys(noAdaValue(totalVal)); if (otherAssets.length === 0) return; const tx = lucid.newTx(); for (const asset of otherAssets) { tx.pay.ToAddress(currentAddr, { [asset]: totalVal[asset], }); } await runAndAwaitTxBuilder(lucid, tx); }