Skip to content

Commit

Permalink
fully replace old command (#325)
Browse files Browse the repository at this point in the history
  • Loading branch information
bergarces authored Sep 24, 2024
1 parent 87bf0ef commit d3f55a6
Show file tree
Hide file tree
Showing 25 changed files with 481 additions and 2,937 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
"build-metadata": "npm run adapters-cli build-metadata --",
"build-metadata-db": "npm run adapters-cli build-metadata-db --",
"build-types": "npm run adapters-cli build-types --",
"new-adapter": "npm run adapters-cli new-adapter2 --",
"new-adapter2": "npm run adapters-cli new-adapter2 --",
"new-adapter": "npm run adapters-cli new-adapter --",
"build-snapshots": "npm run adapters-cli build-snapshots --",
"positions": "npm run adapters-cli positions --",
"profits": "npm run adapters-cli profits --",
Expand Down Expand Up @@ -50,4 +49,4 @@
"nodemon": "^3.1.0",
"typescript": "^5.4.5"
}
}
}
4 changes: 2 additions & 2 deletions packages/adapters-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"test": "jest src --testPathIgnorePatterns='src/adapters/integration.test.ts' --testPathIgnorePatterns='src/tests/detect-errors.test.ts'",
"test:file": "if [ -z \"$TEST_FILE\" ]; then echo 'No test file specified'; exit 1; else jest $TEST_FILE; fi",
"test:detect-errors": "jest src/tests/detect-errors.test.ts",
"test:update:adapter-snapshot": "jest src/scripts/newAdapter2Command.test.ts -u",
"test:update:adapter-snapshot": "jest src/scripts/adapterBuilder/newAdapterCommand.test.ts -u",
"test:tsc": "tsc --noEmit -p tsconfig.json",
"test:integration": "DEFI_ADAPTERS_TEST_FILTER_PROTOCOL=$npm_config_protocol jest --coverage --coverageDirectory='coverage/e2e/' src/adapters/integration.test.ts",
"test:cov": "jest src --ci --coverage --coverageDirectory='coverage/unit/' --testPathIgnorePatterns='src/adapters/integration.test.ts' --testPathIgnorePatterns='src/tests/detect-errors.test.ts'",
Expand Down Expand Up @@ -70,4 +70,4 @@
"pino": "^8.15.0",
"zod": "^3.22.4"
}
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { parse, print, types, visit } from 'recast'
import { writeAndLintFile } from '../../core/utils/writeAndLintFile'
import { sortEntries } from '../utils/sortEntries'
import n = types.namedTypes
import b = types.builders

/**
* @description Writes changes to include new adapter in src/adapters/protocols.ts file
*/
export async function addProtocol({
protocolKey,
protocolId,
}: {
protocolKey: string
protocolId: string
}) {
const protocolsFile = path.resolve(
'./packages/adapters-library/src/adapters/protocols.ts',
)
const contents = await fs.readFile(protocolsFile, 'utf-8')
const ast = parse(contents, {
parser: require('recast/parsers/typescript'),
})

visit(ast, {
visitVariableDeclarator(path) {
const node = path.node
if (!n.Identifier.check(node.id)) {
// Skips any other declaration
return false
}

if (node.id.name === 'Protocol') {
addProtocolEntry(node, protocolKey, protocolId)
}

this.traverse(path)
},
})

await writeAndLintFile(protocolsFile, print(ast).code)
}

/**
* @description Adds a new entry to the Protocol constant if it does not exist.
*
* @param protocolListDeclaratorNode AST node for the Protocol declarator
*/
function addProtocolEntry(
protocolListDeclaratorNode: n.VariableDeclarator,
protocolKey: string,
protocolId: string,
) {
const protocolListObjectNode = protocolListDeclaratorNode.init
if (
!n.TSAsExpression.check(protocolListObjectNode) ||
!n.ObjectExpression.check(protocolListObjectNode.expression)
) {
throw new Error('Incorrectly typed Protocol object')
}

const protocolEntryObjectNode =
protocolListObjectNode.expression.properties.find((property) => {
if (
!n.ObjectProperty.check(property) ||
!n.Identifier.check(property.key)
) {
throw new Error('Incorrectly typed Protocol object')
}

return property.key.name === protocolKey
})

if (!protocolEntryObjectNode) {
protocolListObjectNode.expression.properties.push(
buildProtocolEntry(protocolKey, protocolId),
)

sortEntries(
protocolListObjectNode.expression.properties,
(entry) => ((entry as n.ObjectProperty).key as n.Identifier).name,
)
}
}

/*
<ProtocolKey>: 'protocol-id'
*/
function buildProtocolEntry(protocolKey: string, protocolId: string) {
const key = b.identifier(protocolKey)
const value = b.stringLiteral(protocolId)

return b.objectProperty(key, value)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { promises as fs } from 'node:fs'
import path from 'node:path'
import partition from 'lodash/partition'
import { parse, print, types, visit } from 'recast'
import { lowerFirst } from '../../core/utils/caseConversion'
import { writeAndLintFile } from '../../core/utils/writeAndLintFile'
import { fileExists } from '../utils/fileExists'
import { sortEntries } from '../utils/sortEntries'
import { testCases } from './templates/testCases'
import n = types.namedTypes
import b = types.builders

/**
* @description Creates a new file for integration tests if it doesn't exist
*/
export async function buildIntegrationTests({
protocolId,
protocolKey,
productId,
}: {
protocolId: string
protocolKey: string
productId: string
}) {
const testCasesFilePath = `./packages/adapters-library/src/adapters/${protocolId}/tests/testCases.ts`

if (await fileExists(testCasesFilePath)) {
return
}

await writeAndLintFile(testCasesFilePath, testCases(productId))

const testsFile = path.resolve(
'./packages/adapters-library/src/adapters/integration.test.ts',
)
const contents = await fs.readFile(testsFile, 'utf-8')
const ast = parse(contents, {
parser: require('recast/parsers/typescript'),
})

visit(ast, {
visitProgram(path) {
const programNode = path.value as n.Program

addTestCasesImport(programNode, protocolId, protocolKey)

this.traverse(path)
},
visitVariableDeclarator(path) {
const node = path.node
if (!n.Identifier.check(node.id)) {
return false
}

if (
node.id.name === 'protocolTestCases' &&
n.ObjectExpression.check(node.init)
) {
if (
node.init.properties.some(
(property) =>
n.ObjectProperty.check(property) &&
n.MemberExpression.check(property.key) &&
n.Identifier.check(property.key.property) &&
property.key.property.name === protocolKey,
)
) {
return false
}

const newEntry = b.objectProperty(
b.memberExpression(
b.identifier('Protocol'),
b.identifier(protocolKey),
),
b.identifier(`${lowerFirst(protocolKey)}TestCases`),
)
newEntry.computed = true

node.init.properties.push(newEntry)

sortEntries(
node.init.properties,
(entry) => ((entry as n.ObjectProperty).value as n.Identifier).name,
)
}

this.traverse(path)
},
})

await writeAndLintFile(testsFile, print(ast).code)
}

/**
* @description Adds a new entry to the imports for the test cases
*
* @param programNode AST node for the Protocol program
*/
function addTestCasesImport(
programNode: n.Program,
protocolId: string,
protocolKey: string,
) {
const [importNodes, codeAfterImports] = partition(programNode.body, (node) =>
n.ImportDeclaration.check(node),
)

const newImportEntry = buildImportTestCasesEntry(protocolId, protocolKey)

programNode.body = [...importNodes, newImportEntry, ...codeAfterImports]
}

/*
import { testCases as <protocolId>TestCases } from './<protocolId>/tests/testCases'
*/
function buildImportTestCasesEntry(protocolId: string, protocolKey: string) {
return b.importDeclaration(
[
b.importSpecifier(
b.identifier('testCases'),
b.identifier(`${lowerFirst(protocolKey)}TestCases`),
),
],
b.literal(`./${protocolId}/tests/testCases`),
)
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { Protocol } from '../adapters/protocols'
import { Chain } from '../core/constants/chains'
import { lowerFirst, pascalCase } from '../core/utils/caseConversion'
import { writeAndLintFile } from '../core/utils/writeAndLintFile'
import { DefiProvider } from '../defiProvider'
import {
addProtocol,
buildIntegrationTests,
exportAdapter,
} from './newAdapterCommand'
import { Protocol } from '../../adapters/protocols'
import { Chain } from '../../core/constants/chains'
import { lowerFirst, pascalCase } from '../../core/utils/caseConversion'
import { writeAndLintFile } from '../../core/utils/writeAndLintFile'
import { DefiProvider } from '../../defiProvider'
import { addProtocol } from './addProtocol'
import { buildIntegrationTests } from './buildIntegrationTests'
import { exportAdapter } from './exportAdapter'

const defiProvider = new DefiProvider()

Expand Down
Loading

0 comments on commit d3f55a6

Please sign in to comment.