UNPKG

ndtr-dexter

Version:

Customizable Typescript SDK for interacting with Cardano DEXs

108 lines (107 loc) 4.33 kB
import { datumJsonToCbor } from 'lucid-cardano'; import { DatumParameterKey } from './constants'; export class DefinitionBuilder { /** * Load a DEX definition file as a template for this builder. */ async loadDefinition(definition) { this._definition = definition; return this; } /** * Push specified parameters to the definition template. */ pushParameters(parameters) { if (!this._definition) { throw new Error(`Definition file must be loaded before applying parameters`); } this._definition = this.applyParameters(this._definition, parameters); return this; } /** * Pull parameters of a datum using a definition template. */ pullParameters(definedDefinition) { if (!this._definition) { throw new Error(`Definition file must be loaded before pulling parameters`); } return this.extractParameters(definedDefinition, this._definition); } /** * Retrieve the CBOR for the builder. */ getCbor() { return datumJsonToCbor(JSON.parse(JSON.stringify(this._definition))); } /** * Recursively set specified parameters. */ applyParameters(field, mappedParameters) { if ('fields' in field) { if (typeof field.constructor === 'string') { const parameterValue = mappedParameters[field.constructor]; if (typeof parameterValue !== 'number') { throw new Error(`Invalid parameter value '${parameterValue}' for constructor value`); } field.constructor = parameterValue; } field.fields = field.fields.map((fieldParameter) => { return this.applyParameters(fieldParameter, mappedParameters); }); } if ('int' in field) { let parameterValue = mappedParameters[field.int]; if (typeof parameterValue === 'bigint') { parameterValue = Number(parameterValue); } if (typeof parameterValue !== 'number') { throw new Error(`Invalid parameter value '${parameterValue}' for type 'int'`); } field.int = parameterValue; } if ('bytes' in field) { const parameterValue = mappedParameters[field.bytes] ?? ''; if (typeof parameterValue !== 'string') { throw new Error(`Invalid parameter value '${parameterValue}' for type 'bytes'`); } field.bytes = parameterValue; } return field; } /** * Recursively pull parameters from datum using definition template. */ extractParameters(definedDefinition, templateDefinition, foundParameters = {}) { if ('fields' in definedDefinition) { if (!('fields' in templateDefinition)) { throw new Error("Template definition does not match with 'fields'"); } if (typeof templateDefinition.constructor !== 'number') { foundParameters[templateDefinition.constructor] = definedDefinition.constructor; } definedDefinition.fields.map((fieldParameter, index) => { return this.extractParameters(fieldParameter, templateDefinition.fields[index], foundParameters); }).forEach((parameters) => { foundParameters = { ...foundParameters, ...parameters }; }); } if ('int' in definedDefinition) { if (!('int' in templateDefinition)) { throw new Error("Template definition does not match with 'int'"); } if (typeof templateDefinition.int !== 'number') { foundParameters[templateDefinition.int] = definedDefinition.int; } } if ('bytes' in definedDefinition) { if (!('bytes' in templateDefinition)) { throw new Error("Template definition does not match with 'bytes'"); } const datumKeys = Object.values(DatumParameterKey); if (datumKeys.includes(templateDefinition.bytes)) { foundParameters[templateDefinition.bytes] = definedDefinition.bytes; } } return foundParameters; } }