-
Notifications
You must be signed in to change notification settings - Fork 13
[node-rewards-program] task: add service to communicate with API #679
[node-rewards-program] task: add service to communicate with API #679
Conversation
add methods: prepareEnrollTransaction, checkEnrollmentAddress, checkEnrollmentStatus and getEnrollmentHash
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 { |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, thanks!
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why square brackets? [multisigAccountAddress]
There was a problem hiding this comment.
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.
I think we should also add some unit tests as well. |
})); | ||
} | ||
|
||
describe('NodeRewardsProgram service tests', function() { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
.
…ion test, register service, cleanup
I think I missed it this time, looks okay 👍 |
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); | ||
} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
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; |
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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
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() | ||
}); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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 | ||
}); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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; | ||
} |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
* 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]>
What was the issue?
What's the fix?
prepareEnrollTransaction()
which returns transfer transaction filled with an enrollment data.checkEnrollmentAddress()
which calls/enrollment/check/address/<address_str>
and maps result toboolean
.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.getEnrollmentHash()
which fetches codeword dependent hash from/codeword/<public_key_str>
.getNodePayouts()
which fetches payout information for a single node from/node/<int:node_id>/payouts
.getNodeInfo()
which fetches detailed information about a single node from/node/<node_id>
.