Skip to content

refactor: added a "common" package to share code between packages #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c316924
chore: added common package
andreabadesso Mar 28, 2024
5a1d21d
chore: using wallet-lib from daemon resolution
andreabadesso Mar 28, 2024
09a51d7
chore: installed shared dependencies on root project, using peerDepen…
andreabadesso Mar 31, 2024
b175d1a
refactor: using addAlert method from common utils
andreabadesso Mar 31, 2024
9ba4b63
chore: updated package.json with missing deps
andreabadesso Mar 31, 2024
23acb9e
refactor: using types from commons on wallet-service
andreabadesso Mar 31, 2024
02ed3b7
chore: re-added sequelize to root
andreabadesso Mar 31, 2024
18f7fe5
refactor: removed isNftAutoReviewEnabled from services
andreabadesso Mar 31, 2024
da614c6
tests: mocked assertEnv
andreabadesso Mar 31, 2024
b49cf75
tests: mocked assertEnv on integration tests
andreabadesso Mar 31, 2024
cd0c540
chore: removed nft utils
andreabadesso Apr 1, 2024
1f00aa2
refactor: removed old addAlerts from the wallet-service package
andreabadesso Apr 1, 2024
2ff158c
chore: wallet-lib is now a peerDependency in wallet-service package
andreabadesso Apr 1, 2024
f48f3be
refactor: logger is now a required param in addAlert, refactored all …
andreabadesso Apr 3, 2024
d74c702
docs: added missing hathor header
andreabadesso Apr 3, 2024
c6ab0f7
refactor: invalid type for metadata on addAlert
andreabadesso Apr 3, 2024
572aba9
tests: passing mocked logger
andreabadesso Apr 3, 2024
3968f84
chore: updated gitignore to ignore env files
andreabadesso Apr 5, 2024
525f04b
chore: revert eslint package updates
andreabadesso Apr 5, 2024
e386ec6
refactor: using types from commons on wallet-service
andreabadesso Apr 5, 2024
9b3623c
refactor: removed unused commented line
andreabadesso Apr 5, 2024
86ad635
chore: missing package in daemon
andreabadesso Apr 5, 2024
4c4b08d
refactor: using transaction type from common
andreabadesso Apr 5, 2024
8c22af7
refactor: bitcoinjs is not a shared dep
andreabadesso Apr 5, 2024
6af96eb
chore: added a comment explaining that logger is a param temporarily
andreabadesso Apr 5, 2024
7fb0971
refactor: removed default from metadata
andreabadesso Apr 9, 2024
5881f32
chore: lint fixes and package ordering
andreabadesso Apr 11, 2024
25261a1
feat: call onNewNftEvent when a new NFT tx is received (#150)
andreabadesso Apr 19, 2024
856b5cc
tests: fixed failing test
andreabadesso May 29, 2024
fab1c25
fix: serverless failing (#162)
andreabadesso May 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .codebuild/buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ env:
CONFIRM_FIRST_ADDRESS: true
VOIDED_TX_OFFSET: 20
TX_HISTORY_MAX_COUNT: 50
CREATE_NFT_MAX_RETRIES: 3
dev_DEFAULT_SERVER: "https://wallet-service.private-nodes.testnet.hathor.network/v1a/"
dev_WS_DOMAIN: "ws.dev.wallet-service.testnet.hathor.network"
dev_NETWORK: "testnet"
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
experimental-features = nix-command flakes

- name: Cache Nix
uses: DeterminateSystems/magic-nix-cache-action@v2

Expand All @@ -59,6 +59,10 @@ jobs:
CI_DB_HOST: 127.0.0.1
CI_DB_PORT: 3306

- name: Run tests on the common modules project
run: |
nix develop . -c yarn workspace @wallet-service/common run test

- name: Run tests on the daemon
run: |
nix develop . -c yarn workspace sync-daemon run test
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ dist
coverage/
packages/daemon/dist
packages/daemon/node_modules
packages/common/node_modules
packages/wallet-service/node_modules
packages/wallet-service/.serverless
packages/wallet-service/.webpack
packages/wallet-service/.env*
packages/wallet-service/.warmup
.yarn/
.env.*
3 changes: 2 additions & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ compressionLevel: mixed

enableGlobalCache: false

nmHoistingLimits: dependencies
# Without this setting, the common package is hoisted in the root node_modules, causing the serverless-monorepo plugin to fail
nmHoistingLimits: workspaces

nodeLinker: node-modules
33 changes: 27 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "hathor-wallet-service",
"version": "1.5.0",
"workspaces": [
"packages/common",
"packages/daemon",
"packages/wallet-service"
],
Expand All @@ -11,14 +12,34 @@
"nohoist": [
"**"
],
"repository": "[email protected]:HathorNetwork/hathor-wallet-service-sync_daemon.git",
"repository": "[email protected]:HathorNetwork/hathor-wallet-service.git",
"author": "André Abadesso <[email protected]>",
"private": true,
"devDependencies": {
"dotenv": "^16.3.1",
"mysql2": "^3.6.1",
"sequelize": "^6.33.0",
"sequelize-cli": "^6.6.1"
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "^7.4.0",
"@typescript-eslint/parser": "^7.4.0",
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.9.0",
"mysql2": "^3.9.3",
"sequelize": "^6.37.2",
"sequelize-cli": "^6.6.2"
},
"packageManager": "[email protected]"
"packageManager": "[email protected]",
"dependencies": {
"@aws-sdk/client-apigatewaymanagementapi": "3.540.0",
"@aws-sdk/client-lambda": "3.540.0",
"@aws-sdk/client-sqs": "3.540.0",
"@hathor/wallet-lib": "0.39.0",
"@wallet-service/common": "1.5.0",
"bip32": "^4.0.0",
"bitcoinjs-lib": "^6.1.5",
"bitcoinjs-message": "^2.2.0",
"jest": "^29.7.0",
"tiny-secp256k1": "^2.2.3",
"winston": "3.13.0"
}
}
1 change: 1 addition & 0 deletions packages/common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Common utils for the wallet-service
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/* eslint-disable @typescript-eslint/no-empty-function */

import { Context } from 'aws-lambda';
import { Transaction } from '@src/types';
import { Transaction, TxOutput } from '../../src/types';

/**
* A sample transaction for a NFT creation, as obtained by a wallet's history methods
Expand Down Expand Up @@ -149,11 +149,12 @@ export function getTransaction(): Transaction {
spent_by: o.spent_by,
token_data: o.token_data,
locked: false,
})),
})) as TxOutput[],
height: 8,
token_name: nftCreationTx.token_name,
token_symbol: nftCreationTx.token_symbol,
};

return result;
}

Expand Down
4 changes: 4 additions & 0 deletions packages/common/__tests__/utils/alerting.utils.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const mockedAddAlert = jest.fn();
export default jest.mock('@src/utils/alerting.utils', () => ({
addAlert: mockedAddAlert.mockReturnValue(Promise.resolve()),
}));
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
// @ts-ignore: Using old wallet-lib version, no types exported
import hathorLib from '@hathor/wallet-lib';
import { mockedAddAlert } from '@tests/utils/alerting.utils.mock';
import { mockedAddAlert } from './alerting.utils.mock';
import { Severity } from '@src/types';
import { MAX_METADATA_UPDATE_RETRIES, NftUtils } from '@src/utils/nft.utils';
import { getHandlerContext, getTransaction } from '@events/nftCreationTx';
import { NftUtils } from '@src/utils/nft.utils';
import { getHandlerContext, getTransaction } from '../events/nftCreationTx';
import {
LambdaClient as LambdaClientMock,
InvokeCommandOutput,
} from '@aws-sdk/client-lambda';
import { Logger } from 'winston';

jest.mock('winston', () => {
class FakeLogger {
warn() {
return jest.fn();
}
error() {
return jest.fn();
}
info() {
return jest.fn();
}
};

return {
Logger: FakeLogger,
}
});

jest.mock('@aws-sdk/client-lambda', () => {
const mLambda = { send: jest.fn() };
Expand All @@ -17,19 +37,23 @@ jest.mock('@aws-sdk/client-lambda', () => {
};
});

const network = new hathorLib.Network('testnet');
const logger = new Logger();

describe('shouldInvokeNftHandlerForTx', () => {
it('should return false for a NFT transaction if the feature is disabled', () => {
expect.hasAssertions();

// Preparation
const tx = getTransaction();
const isNftTransaction = NftUtils.isTransactionNFTCreation(tx);
const isNftTransaction = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(isNftTransaction).toStrictEqual(true);

expect(process.env.NFT_AUTO_REVIEW_ENABLED).not.toStrictEqual('true');

// Execution
const result = NftUtils.shouldInvokeNftHandlerForTx(tx);
// @ts-ignore
const result = NftUtils.shouldInvokeNftHandlerForTx(tx, network, logger);

// Assertion
expect(result).toBe(false);
Expand All @@ -40,14 +64,14 @@ describe('shouldInvokeNftHandlerForTx', () => {

// Preparation
const tx = getTransaction();
const isNftTransaction = NftUtils.isTransactionNFTCreation(tx);
const isNftTransaction = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(isNftTransaction).toStrictEqual(true);

const oldValue = process.env.NFT_AUTO_REVIEW_ENABLED;
process.env.NFT_AUTO_REVIEW_ENABLED = 'true';

// Execution
const result = NftUtils.shouldInvokeNftHandlerForTx(tx);
const result = NftUtils.shouldInvokeNftHandlerForTx(tx, network, logger);

// Assertion
expect(result).toBe(true);
Expand All @@ -70,21 +94,21 @@ describe('isTransactionNFTCreation', () => {
// Incorrect version
tx = getTransaction();
tx.version = hathorLib.constants.DEFAULT_TX_VERSION;
result = NftUtils.isTransactionNFTCreation(tx);
result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(false);
expect(spyCreateTx).not.toHaveBeenCalled();

// Missing name
tx = getTransaction();
tx.token_name = undefined;
result = NftUtils.isTransactionNFTCreation(tx);
result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(false);
expect(spyCreateTx).not.toHaveBeenCalled();

// Missing symbol
tx = getTransaction();
tx.token_symbol = undefined;
result = NftUtils.isTransactionNFTCreation(tx);
result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(false);
expect(spyCreateTx).not.toHaveBeenCalled();

Expand All @@ -101,7 +125,7 @@ describe('isTransactionNFTCreation', () => {

// Validation
const tx = getTransaction();
const result = NftUtils.isTransactionNFTCreation(tx);
const result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(true);

// Reverting mocks
Expand All @@ -113,7 +137,7 @@ describe('isTransactionNFTCreation', () => {

// Validation
const tx = getTransaction();
const result = NftUtils.isTransactionNFTCreation(tx);
const result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(true);
});

Expand All @@ -128,7 +152,7 @@ describe('isTransactionNFTCreation', () => {

// Validation
const tx = getTransaction();
const result = NftUtils.isTransactionNFTCreation(tx);
const result = NftUtils.isTransactionNFTCreation(tx, network, logger);
expect(result).toBe(false);

// Reverting mocks
Expand All @@ -154,11 +178,11 @@ describe('createOrUpdateNftMetadata', () => {
const expectedUpdateResponse = { updated: 'ok' };

spyUpdateMetadata.mockImplementation(async () => expectedUpdateResponse);
const result = await NftUtils.createOrUpdateNftMetadata('sampleUid');
const result = await NftUtils.createOrUpdateNftMetadata('sampleUid', 5, logger);

expect(spyUpdateMetadata).toHaveBeenCalledTimes(1);

expect(spyUpdateMetadata).toHaveBeenCalledWith('sampleUid', expectedUpdateRequest);
expect(spyUpdateMetadata).toHaveBeenCalledWith('sampleUid', expectedUpdateRequest, 5, logger);
expect(result).toBeUndefined(); // The method returns void
});
});
Expand All @@ -181,7 +205,7 @@ describe('_updateMetadata', () => {
const oldStage = process.env.STAGE;
process.env.STAGE = 'dev'; // Testing all code branches, including the developer ones, for increased coverage

const result = await NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' });
const result = await NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' }, 5, logger);
expect(result).toStrictEqual(expectedLambdaResponse);
process.env.STAGE = oldStage;
});
Expand All @@ -197,7 +221,7 @@ describe('_updateMetadata', () => {
};
const mLambdaClient = new LambdaClientMock({});
(mLambdaClient.send as jest.Mocked<any>).mockImplementation(async () => {
if (failureCount < MAX_METADATA_UPDATE_RETRIES - 1) {
if (failureCount < 4) {
++failureCount;
return {
StatusCode: 500,
Expand All @@ -207,7 +231,7 @@ describe('_updateMetadata', () => {
return expectedLambdaResponse;
});

const result = await NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' });
const result = await NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' }, 5, logger);
expect(result).toStrictEqual(expectedLambdaResponse);
});

Expand All @@ -218,7 +242,7 @@ describe('_updateMetadata', () => {
let failureCount = 0;
const mLambdaClient = new LambdaClientMock({});
(mLambdaClient.send as jest.Mocked<any>).mockImplementation(() => {
if (failureCount < MAX_METADATA_UPDATE_RETRIES) {
if (failureCount < 5) {
++failureCount;
return {
StatusCode: 500,
Expand All @@ -232,7 +256,7 @@ describe('_updateMetadata', () => {
});

// eslint-disable-next-line jest/valid-expect
expect(NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' }))
expect(NftUtils._updateMetadata('sampleUid', { sampleData: 'fake' }, network, logger))
.rejects.toThrow(new Error('Metadata update failed for tx_id: sampleUid.'));
});
});
Expand All @@ -249,7 +273,7 @@ describe('invokeNftHandlerLambda', () => {
const mLambdaClient = new LambdaClientMock({});
(mLambdaClient.send as jest.Mocked<any>).mockImplementationOnce(async () => expectedLambdaResponse);

await expect(NftUtils.invokeNftHandlerLambda('sampleUid')).resolves.toBeUndefined();
await expect(NftUtils.invokeNftHandlerLambda('sampleUid', 'local', logger)).resolves.toBeUndefined();
});

it('should throw when payload response status is invalid', async () => {
Expand All @@ -263,14 +287,15 @@ describe('invokeNftHandlerLambda', () => {
};
(mLambdaClient.send as jest.Mocked<any>).mockImplementation(() => expectedLambdaResponse);

await expect(NftUtils.invokeNftHandlerLambda('sampleUid'))
await expect(NftUtils.invokeNftHandlerLambda('sampleUid', 'local', logger))
.rejects.toThrow(new Error('onNewNftEvent lambda invoke failed for tx: sampleUid'));

expect(mockedAddAlert).toHaveBeenCalledWith(
'Error on NFTHandler lambda',
'Erroed on invokeNftHandlerLambda invocation',
Severity.MINOR,
{ TxId: 'sampleUid' },
logger,
);
});
});
Expand Down
18 changes: 18 additions & 0 deletions packages/common/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
roots: ["<rootDir>/__tests__"],
testRegex: ".*\\.test\\.ts$",
moduleNameMapper: {
'^@src/(.*)$': '<rootDir>/src/$1',
'^@tests/(.*)$': '<rootDir>/__tests__/$1',
'^@events/(.*)$': '<rootDir>/__tests__/events/$1',
},
transform: {
"^.+\\.ts$": ["ts-jest", {
tsconfig: "./tsconfig.json",
babelConfig: {
sourceMaps: true,
}
}]
},
moduleFileExtensions: ["ts", "js", "json", "node"]
};
20 changes: 20 additions & 0 deletions packages/common/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@wallet-service/common",
"version": "1.5.0",
"packageManager": "[email protected]",
"scripts": {
"test": "jest --runInBand --collectCoverage --detectOpenHandles --forceExit"
},
"peerDependencies": {
"@aws-sdk/client-lambda": "3.540.0",
"@hathor/wallet-lib": "0.39.0",
"winston": "^3.13.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(non-blocking): Here we have a mix of version definitions. Some are pinned to an exact value and some are with a flexible caret range.

Should we decide for one approach or another? Or can we leave this mixed as it currently is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix all versions in a future PR

},
"devDependencies": {
"@types/aws-lambda": "^8.10.136",
"@types/node": "^20.11.30",
"jest": "^29.6.4",
"ts-jest": "^29.1.2",
"typescript": "^5.4.3"
}
}
Loading
Loading