UNPKG

ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges

215 lines (212 loc) • 9.2 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD import { CairoUint256 } from '../cairoDataTypes/uint256.js'; import { CairoUint512 } from '../cairoDataTypes/uint512.js'; import { addHexPrefix, removeHexPrefix } from '../encode.js'; import { toHex } from '../num.js'; import { decodeShortString } from '../shortString.js'; import { stringFromByteArray } from './byteArray.js'; import { getArrayType, isCairo1Type, isLen, isTypeArray, isTypeBool, isTypeByteArray, isTypeEnum, isTypeSecp256k1Point, isTypeTuple, } from './cairo.js'; import { CairoCustomEnum, CairoOption, CairoOptionVariant, CairoResult, CairoResultVariant, } from './enum/index.js'; import extractTupleMemberTypes from './tuple.js'; /** * Parse base types * @param type type of element * @param it iterator * @returns bigint | boolean */ function parseBaseTypes(type, it) { let temp; switch (true) { case isTypeBool(type): temp = it.next().value; return Boolean(BigInt(temp)); case CairoUint256.isAbiType(type): const low = it.next().value; const high = it.next().value; return new CairoUint256(low, high).toBigInt(); case CairoUint512.isAbiType(type): const limb0 = it.next().value; const limb1 = it.next().value; const limb2 = it.next().value; const limb3 = it.next().value; return new CairoUint512(limb0, limb1, limb2, limb3).toBigInt(); case type === 'core::starknet::eth_address::EthAddress': temp = it.next().value; return BigInt(temp); case type === 'core::bytes_31::bytes31': temp = it.next().value; return decodeShortString(temp); case isTypeSecp256k1Point(type): const xLow = removeHexPrefix(it.next().value).padStart(32, '0'); const xHigh = removeHexPrefix(it.next().value).padStart(32, '0'); const yLow = removeHexPrefix(it.next().value).padStart(32, '0'); const yHigh = removeHexPrefix(it.next().value).padStart(32, '0'); const pubK = BigInt(addHexPrefix(xHigh + xLow + yHigh + yLow)); return pubK; default: temp = it.next().value; return BigInt(temp); } } /** * Parse of the response elements that are converted to Object (Struct) by using the abi * * @param responseIterator - iterator of the response * @param element - element of the field {name: string, type: string} * @param structs - structs from abi * @param enums * @return {any} - parsed arguments in format that contract is expecting */ function parseResponseValue(responseIterator, element, structs, enums) { if (element.type === '()') { return {}; } // type uint256 struct (c1v2) if (CairoUint256.isAbiType(element.type)) { const low = responseIterator.next().value; const high = responseIterator.next().value; return new CairoUint256(low, high).toBigInt(); } // type uint512 struct if (CairoUint512.isAbiType(element.type)) { const limb0 = responseIterator.next().value; const limb1 = responseIterator.next().value; const limb2 = responseIterator.next().value; const limb3 = responseIterator.next().value; return new CairoUint512(limb0, limb1, limb2, limb3).toBigInt(); } // type C1 ByteArray struct, representing a LongString if (isTypeByteArray(element.type)) { const parsedBytes31Arr = []; const bytes31ArrLen = BigInt(responseIterator.next().value); while (parsedBytes31Arr.length < bytes31ArrLen) { parsedBytes31Arr.push(toHex(responseIterator.next().value)); } const pending_word = toHex(responseIterator.next().value); const pending_word_len = BigInt(responseIterator.next().value); const myByteArray = { data: parsedBytes31Arr, pending_word, pending_word_len, }; return stringFromByteArray(myByteArray); } // type c1 array if (isTypeArray(element.type)) { // eslint-disable-next-line no-case-declarations const parsedDataArr = []; const el = { name: '', type: getArrayType(element.type) }; const len = BigInt(responseIterator.next().value); // get length while (parsedDataArr.length < len) { parsedDataArr.push(parseResponseValue(responseIterator, el, structs, enums)); } return parsedDataArr; } // type struct if (structs && element.type in structs && structs[element.type]) { if (element.type === 'core::starknet::eth_address::EthAddress') { return parseBaseTypes(element.type, responseIterator); } return structs[element.type].members.reduce((acc, el) => { acc[el.name] = parseResponseValue(responseIterator, el, structs, enums); return acc; }, {}); } // type Enum (only CustomEnum) if (enums && element.type in enums && enums[element.type]) { const variantNum = Number(responseIterator.next().value); // get variant number const rawEnum = enums[element.type].variants.reduce((acc, variant, num) => { if (num === variantNum) { acc[variant.name] = parseResponseValue(responseIterator, { name: '', type: variant.type }, structs, enums); return acc; } acc[variant.name] = undefined; return acc; }, {}); // Option if (element.type.startsWith('core::option::Option')) { const content = variantNum === CairoOptionVariant.Some ? rawEnum.Some : undefined; return new CairoOption(variantNum, content); } // Result if (element.type.startsWith('core::result::Result')) { let content; if (variantNum === CairoResultVariant.Ok) { content = rawEnum.Ok; } else { content = rawEnum.Err; } return new CairoResult(variantNum, content); } // Cairo custom Enum const customEnum = new CairoCustomEnum(rawEnum); return customEnum; } // type tuple if (isTypeTuple(element.type)) { const memberTypes = extractTupleMemberTypes(element.type); return memberTypes.reduce((acc, it, idx) => { const name = it?.name ? it.name : idx; const type = it?.type ? it.type : it; const el = { name, type }; acc[name] = parseResponseValue(responseIterator, el, structs, enums); return acc; }, {}); } // type c1 array if (isTypeArray(element.type)) { // eslint-disable-next-line no-case-declarations const parsedDataArr = []; const el = { name: '', type: getArrayType(element.type) }; const len = BigInt(responseIterator.next().value); // get length while (parsedDataArr.length < len) { parsedDataArr.push(parseResponseValue(responseIterator, el, structs, enums)); } return parsedDataArr; } // base type return parseBaseTypes(element.type, responseIterator); } /** * Parse elements of the response and structuring them into one field by using output property from the abi for that method * * @param responseIterator - iterator of the response * @param output - output(field) information from the abi that will be used to parse the data * @param structs - structs from abi * @param parsedResult * @return - parsed response corresponding to the abi structure of the field */ export default function responseParser(responseIterator, output, structs, enums, parsedResult) { const { name, type } = output; let temp; switch (true) { case isLen(name): temp = responseIterator.next().value; return BigInt(temp); case (structs && type in structs) || isTypeTuple(type): return parseResponseValue(responseIterator, output, structs, enums); case enums && isTypeEnum(type, enums): return parseResponseValue(responseIterator, output, structs, enums); case isTypeArray(type): // C1 Array if (isCairo1Type(type)) { return parseResponseValue(responseIterator, output, structs, enums); } // C0 Array // eslint-disable-next-line no-case-declarations const parsedDataArr = []; if (parsedResult && parsedResult[`${name}_len`]) { const arrLen = parsedResult[`${name}_len`]; while (parsedDataArr.length < arrLen) { parsedDataArr.push(parseResponseValue(responseIterator, { name, type: output.type.replace('*', '') }, structs, enums)); } } return parsedDataArr; default: return parseBaseTypes(type, responseIterator); } }