Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

[node-rewards-program] task: add service to communicate with API #679

Merged

Conversation

OlegMakarenko
Copy link

@OlegMakarenko OlegMakarenko commented Jun 10, 2022

What was the issue?

  • Node Rewards Program module doesn't have service to communicate with API.

What's the fix?

  • Added Node Rewards Program service.
  • Added prepareEnrollTransaction() which returns transfer transaction filled with an enrollment data.
  • Added checkEnrollmentAddress() which calls /enrollment/check/address/<address_str> and maps result to boolean.
  • Added checkEnrollmentStatus() which checks if a signer public key is enrolled in the current period. It fetches latest successful enrollments from /enrollment/successes/<public_key_str> and check wheter a recipient address is the current enrollment address.
  • Added getEnrollmentHash() which fetches codeword dependent hash from /codeword/<public_key_str>.
  • Added getNodePayouts() which fetches payout information for a single node from /node/<int:node_id>/payouts.
  • Added getNodeInfo() which fetches detailed information about a single node from /node/<node_id>.

add methods: prepareEnrollTransaction, checkEnrollmentAddress, checkEnrollmentStatus and getEnrollmentHash
@OlegMakarenko OlegMakarenko linked an issue Jun 10, 2022 that may be closed by this pull request
const NODE_REWARDS_PROGRAM_API_BASE_URL = 'https://supernodesapi.nem.io';

/** Service to enroll in the Node Rewards Program and to get the status related information */
class nodeRewardsProgram {

Choose a reason for hiding this comment

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

should we apply a PascalCase since it's a class? (Capitalize the first letter)

Copy link
Author

Choose a reason for hiding this comment

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

Oops, thanks!

Copy link
Author

Choose a reason for hiding this comment

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

Fixed.

* @param {string} mainPublicKey - Delegated harvesting public key.
* @param {string} host - IP or domain of the node.
* @param {string} enrollmentAddress - Node Rewards Program enrollment address.
* @param {string} [multisigAccountAddress] - Multisig account address. For multisig enrollment only.

Choose a reason for hiding this comment

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

why square brackets? [multisigAccountAddress]

Copy link
Author

Choose a reason for hiding this comment

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

This is an optional parameter, according to the JSDoc syntax.

@yilmazbahadir
Copy link

I think we should also add some unit tests as well.

}));
}

describe('NodeRewardsProgram service tests', function() {

Choose a reason for hiding this comment

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

Have you run this test in the browser?

Hint: Open the file build/tests/start.html in the browser.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks. Tests updated.

expect(transaction.mosaics).toBe(null);
expect(transaction.message).toBe(expectedMessage);
expect(transaction.isMultisig).toBe(false);
done();

Choose a reason for hiding this comment

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

I think the function needs to take the done as a parameter? (in all of the tests)

Choose a reason for hiding this comment

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

And perhaps it's not mandatory to call done?

Copy link
Author

@OlegMakarenko OlegMakarenko Jun 14, 2022

Choose a reason for hiding this comment

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

Seems like here the async tests doesn't work correctly without calling done().
Without done(), I got this warning: SPEC HAS NO EXPECTATIONS.

@yilmazbahadir
Copy link

Are the tests passing in your local?

image

@OlegMakarenko
Copy link
Author

Works fine on my local.
image

Did you try npm run build?

@yilmazbahadir
Copy link

I think I missed it this time, looks okay 👍

Comment on lines 44 to 65
async prepareEnrollTransaction(mainPublicKey, host, enrollmentAddress, multisigAccountAddress) {
// Create a new transaction object
const transferTransaction = nem.model.objects.get('transferTransaction');

// Set enrollment address as recipient
transferTransaction.recipient = enrollmentAddress.toUpperCase().replace(/-/g, '');

// Set multisig, if selected
if (multisigAccountAddress) {
transferTransaction.isMultisig = true;
transferTransaction.multisigAccount = multisigAccountAddress.toUpperCase().replace(/-/g, '');
}

// Set the message
const hash = await this.getCodewordHash(mainPublicKey);
transferTransaction.message = `enroll ${host} ${hash}`;

// Set no mosaics
transferTransaction.mosaics = null;

return nem.model.transactions.prepare('transferTransaction')(this.common, transferTransaction, this._Wallet.network);
}

Choose a reason for hiding this comment

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

I think we can keep this in the controller.
since this method didn't require fetch

what do you think?

Choose a reason for hiding this comment

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

@AnthonyLaw Can you elaborate on this? (Which class are you referring to and why?)

Choose a reason for hiding this comment

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

@AnthonyLaw Can you elaborate on this? (Which class are you referring to and why?)

sure, I mean prepareEnrollTransaction method, not class.

for my understanding, *.service.js should just make a request to the endpoint NODE_REWARDS_PROGRAM_API_BASE_URL.

but prepareEnrollTransaction just prepares the transaction object, it does not have any interaction with another endpoint.

so I think preparing transaction object should happen in nodeRewardsProgram.controller.

Choose a reason for hiding this comment

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

I think this is not the case.

for my understanding, *.service.js should just make a request to the endpoint NODE_REWARDS_PROGRAM_API_BASE_URL

Please see this answer => https://stackoverflow.com/a/27398868/3190131

And this => https://docs.angularjs.org/guide/services

Comment on lines +31 to +35
const mainPublicKey = '00a30788dc1f042da959309639a884d8f6a87086cda10300d2a7c3a0e0891a4d';
const host = 'http://108.61.168.86:7890';
const enrollmentAddress = 'NCHESTYVD2P6P646AMY7WSNG73PCPZDUQNSD6JAK';
const expectedMessage = nem.utils.convert.utf8ToHex(`enroll ${host} hash`);
const transferTransactionType = 257;

Choose a reason for hiding this comment

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

this was duplicated in a few tests, I think we can create it as an object to share with other tests.

done();
});

it('should return valid multisig enroll transaction', async (done) => {

Choose a reason for hiding this comment

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

For all unit tests, I drop should (action => verb)

should returns

@AnthonyLaw AnthonyLaw requested a review from Jaguar0625 June 17, 2022 17:00
src/app/services/nodeRewardsProgram.service.js Outdated Show resolved Hide resolved
src/app/services/nodeRewardsProgram.service.js Outdated Show resolved Hide resolved
src/app/services/nodeRewardsProgram.service.js Outdated Show resolved Hide resolved
src/app/services/nodeRewardsProgram.service.js Outdated Show resolved Hide resolved
src/app/services/nodeRewardsProgram.service.js Outdated Show resolved Hide resolved
tests/specs/nodeRewardsProgram.spec.js Show resolved Hide resolved
tests/specs/nodeRewardsProgram.spec.js Show resolved Hide resolved
tests/specs/nodeRewardsProgram.spec.js Show resolved Hide resolved
Comment on lines 193 to 206
it('should fetch to be called with valid endpoint url when publicKey passed', async (done) => {
// Arrange:
const mockedFetch = mockFetch(null);
const baseUrl = NODE_REWARDS_PROGRAM_API_BASE_URL;
const publicKey = '00a30788dc1f042da959309639a884d8f6a87086cda10300d2a7c3a0e0891a4d';
const expectedEndpoint = `${baseUrl}/codeword/${publicKey}`;

// Act:
await NodeRewardsProgram.getCodewordHash(publicKey);

// Assert:
expect(mockedFetch).toHaveBeenCalledWith(expectedEndpoint);
done()
});

Choose a reason for hiding this comment

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

i don't think this test make much sense as standalone.
instead, check that fetch was called in following two tests.

Copy link
Author

Choose a reason for hiding this comment

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

These three tests have different "object" of test. This test checks how the function cunstructs the request URL, but two other - a pass through and - the error to be thrown. Not sure, but it seems to me that if I remove 1st and add a fetch test to the 2nd and 3rd, it might be a "mixed" test. What do you think?

Choose a reason for hiding this comment

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

it depends how you define a unit. if you define a unit as something like "constructs url properly", "forwards object on success", then the separate tests make sense.

however, if you define a unit as a branch, like "handles successful fetch", "handles failed fetch", then combining makes sense. one benefit of this approach is that you will validate (in error cases) that the fetch was initiated (and that something previous didn't trigger the error).

defining units is more of an art than a science, so you can leave current cases if you prefer.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the explanation, that makes sense.

Comment on lines +279 to +286
const expectedDTO = new Array(15).fill({
amount: 0,
fromRoundId: 844,
isPaid: false,
timestamp: '2022-06-16T12:15:27.427749+00:00',
toRoundId: 844,
transactionHash: null
});

Choose a reason for hiding this comment

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

probably better to return 15 unique objects vs 15 copies of same object

Choose a reason for hiding this comment

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

also, fyi - since function being tested is simply a pass through it's not required to match "real" shape from server, although that's find and there's nothing wrong with it (so you can leave it).

// Act:
try {
await promiseToTest;
}

Choose a reason for hiding this comment

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

you should add assert here too to make sure test fails if exception isn't thrown

Copy link
Author

Choose a reason for hiding this comment

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

Updated. Moved assert from the catch section.

@AnthonyLaw AnthonyLaw merged commit a63f24b into node-rewards-program Jun 28, 2022
@AnthonyLaw AnthonyLaw deleted the feat/init-node-rewards-program-service branch June 28, 2022 07:52
AnthonyLaw added a commit that referenced this pull request Jul 28, 2022
* feat: init node rewards modules (#678)

* feat: init node rewards modules

* fix: clean up comment

* [node-rewards-program] task: add service to communicate with API #679

* [node-rewards-program] task: add service

add methods: prepareEnrollTransaction, checkEnrollmentAddress, checkEnrollmentStatus and getEnrollmentHash

* [node-rewards-program] fix: typo in error message

* [node-rewards-program] fix: typo in class name

* [node-rewards-program] task: add tests

* [node-rewards-program] fix: fetch mock, improve prepareEnrollTransaction test, register service, cleanup

* [node-rewards-program] feat: add getNodePayouts() and getNodeInfo() methods, add unit tests

* [node-rewards-program] fix: typo in jsdoc

* [node-rewards-program] fix: test comments

* [node-rewards-program] fix: remove whitespaces

* [node-rewards-program] task: refactor fetch requests

* [node-rewards-program] task: refactor the enrollment and error tests, remove unused variable

* [node-rewards-program] task: update codeword test, fix runPromiseErrorTest helper

* [node-rewards-program] task: add enrollment tab component (#681)

* feat: add account selection section

* build: add object-rest-spread plugins

* feat: add node reward program alert message

* [node-rewards-program] feat: add UI Tab component

* [node-rewards-program] task: refactor UI and typo

* [node-rewards-program] task: node reward controller

* [node-rewards-program] task: add unit test

* [node-rewards-program] task: fix typo

* [node-rewards-program] task: fix send enrollment logic

* [node-rewards-program] task: refactor on assign selected account

* [node-rewards-program] task: refactor on tab and rename

* [node-rewards-program] task: fix typo and lint

* [node-rewards-program] task: change from toFixed to ceil

* [node-rewards-program] task: minor refactor on unit test

* Enhancement and feedback (#682)

* [node-rewards-program] task: fix send enrollment logic

* [node-rewards-program] task: fix typo and lint

* [node-rewards-program] fix: change payout table width

* [node-rewards-program] fix: format endpoint url to display only hostname

* [node-rewards-program] feat: add last round payout property into Status tab

* [node-rewards-program] fix: replace money bag icon

* [node-rewards-program] perf: add check required params before calling API services

* [node-rewards-program] feat: add validation for codeword hash

* [node-rewards-program] fix: assign public key for new created account

* [node-rewards-program] fix: allow update domain name when account enrolled

* [node-rewards-program] task: enable hardware wallet enrollment

* [node-rewards-program] task: fix typo

* [node-rewards-program] task: rename module to superNode program (#683)

* [node-rewards-program] bug: fix minor bug and refactor. (#684)

* [node-rewards-program] task: add count params in getNodePayouts

* [node-rewards-program] bug: fix unable send enrollement tx to update domain name

* [node-rewards-program] task: removed unused method

* [node-rewards-program] task: rename enroll in program and form data node host

* [node-rewards-program] task: refactor on the logic

* [node-rewards-program] task: new validation alert for node host

* [node-rewards-program] task: update invalid node host message

* [node-rewards-program] task: duplicated lastPayoutRound in unit test

* [node-rewards-program] task: patch fix handle lastPayoutRound in null

* [node-rewards-program] task: add translation (#685)

* [node-rewards-program] task: add chinese translation

* [node-rewards-program] task: add spanish translation

* [node-rewards-program] task: add italian translation

* [node-rewards-program] task: add japanese translation

* [node-rewards-program] task: add polish translation

* [node-rewards-program] task: add russian translation

* [node-rewards-program] task: patch spanish translation

* [node-rewards-program] task: add ukrainian translation

* [node-rewards-program] task: patch italian translation

* [node-rewards-program] task: add default translation in German, Nederlands and Portuguese

* [node-rewards-program] task: patch Polish translation

* [node-rewards-program] task: patch latest supernode program url and api endpoint

* [node-rewards-program] task: patch minor fix

Co-authored-by: OlegMakarenko <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NEM node rewards program support
4 participants