From ffa998a4afa8a89c3be665f4f91221d927ce28bd Mon Sep 17 00:00:00 2001 From: Wenjian Qiao Date: Fri, 5 Apr 2019 11:14:56 -0400 Subject: [PATCH] [FABN-1199] Simplify token owner parameter Simplify token owner to be a flat field for usability. In the future, if new owner type is supported, we can add another field. Change-Id: I996c73b8e82b6d9bddd50f530fe272a7aea2ca8b Signed-off-by: Wenjian Qiao --- docs/tutorials/fabtoken.md | 8 ++++---- fabric-client/lib/TokenClient.js | 13 +++---------- fabric-client/lib/token-utils.js | 6 ++++-- fabric-client/test/TokenClient.js | 2 +- fabric-client/test/token-utils.js | 18 ++++++++++-------- test/integration/token.js | 23 ++++++++++++----------- 6 files changed, 34 insertions(+), 36 deletions(-) diff --git a/docs/tutorials/fabtoken.md b/docs/tutorials/fabtoken.md index 2bf92188c7..35f8309291 100755 --- a/docs/tutorials/fabtoken.md +++ b/docs/tutorials/fabtoken.md @@ -70,12 +70,12 @@ const txId = client.newTransactionID(); // create two parameters for issue, one for user1 and one for user2 const param1 = { - owner: {raw: user1.getIdentity().serialize(), type: 0}, + owner: user1.getIdentity().serialize(), type: 'USD', quantity: '500', }; const param2 = { - owner: {raw: user2.getIdentity().serialize(), type: 0}, + owner: user2.getIdentity().serialize(), type: 'EURO', quantity: '300', }; @@ -124,11 +124,11 @@ const txId = client1.newTransactionID(); // create two parameters, where param1 is to transfer 300 to user2 and param2 is to transfer the remaining 200 to user1. const param1 = { - owner: {raw: user2.getIdentity().serialize(), type:0}, + owner: user2.getIdentity().serialize(), quantity: '300', }; const param2 = { - owner: {raw: user1.getIdentity().serialize(), type:0}, + owner: user1.getIdentity().serialize(), quantity: '200', }; diff --git a/fabric-client/lib/TokenClient.js b/fabric-client/lib/TokenClient.js index 09d5d1b52e..85ea5354d7 100644 --- a/fabric-client/lib/TokenClient.js +++ b/fabric-client/lib/TokenClient.js @@ -63,7 +63,7 @@ const {HashPrimitives} = require('fabric-common'); * // create request to issue tokens to user2 * // owner type is optional; default is 0 (i.e., TokenOwner_MSP_IDENTIFIER type) * const txId = tokenClient1.newTransactionID(); - * const owner = {raw: user2.getIdentity().serialize(), type: 0}; + * const owner = user2.getIdentity().serialize(); * const tokenType = 'myTokenType'; * let param = {owner: owner, type: tokenType, quantity: '200'}; * let request = {params: [param], txId: txId}; @@ -94,7 +94,7 @@ const {HashPrimitives} = require('fabric-common'); * * // user2 calls transfer method to transfer the token to user1 * // owner type is optional; default is 0 (i.e., TokenOwner_MSP_IDENTIFIER type) - * const newOwner = {raw: user1.getIdentity().serialize(), type: 0}; + * const newOwner = user1.getIdentity().serialize(); * param = {owner: newOwner, quantity: '150'}; * request = {params: [param], tokenId: token.id, txId: txId}; * result = await tokenClient1.transfer(request); @@ -164,18 +164,11 @@ const TokenClient = class { this._targets = targets; } - /** - * @typedef {Object} TokenOwner - * This object contains the bytes and type for the owner. - * @property {byte[]} raw - Required. The serialized bytes for the owner. - * @property {int} type - Optional. Default is 0 (i.e., TokenOwner_MSP_IDENTIFIER type). - */ - /** * @typedef {Object} TokenParam * This object contains properties that specify the owner, type, * and quantity of a token kind. - * @property {TokenOwner} owner - Required for issue and transfer. The recipient of the token. + * @property {byte[]} owner - Required for issue and transfer. The serialized bytes for the recipient. * @property {string} type - Required for issue. The type of the token. * @property {string} quantity - Required. The quantity of the token in decimal string format. * For example, use '200' for 200. diff --git a/fabric-client/lib/token-utils.js b/fabric-client/lib/token-utils.js index c042577155..ced0b4fe3c 100644 --- a/fabric-client/lib/token-utils.js +++ b/fabric-client/lib/token-utils.js @@ -36,7 +36,8 @@ module.exports.buildIssueCommand = (request) => { // iterate params to populate tokensToIssue const tokensToIssue = []; params.forEach((param) => { - const token = {owner: param.owner, type: param.type, quantity: param.quantity}; + const owner = {raw: param.owner, type: fabprotos.token.TokenOwner_MSP_IDENTIFIER}; + const token = {owner: owner, type: param.type, quantity: param.quantity}; tokensToIssue.push(token); }); @@ -62,7 +63,8 @@ module.exports.buildTransferCommand = (request) => { // iterate params to populate transfer shares const shares = []; params.forEach((param) => { - const share = {recipient: param.owner, quantity: param.quantity}; + const owner = {raw: param.owner, type: fabprotos.token.TokenOwner_MSP_IDENTIFIER}; + const share = {recipient: owner, quantity: param.quantity}; shares.push(share); }); diff --git a/fabric-client/test/TokenClient.js b/fabric-client/test/TokenClient.js index 1d6bd1efd1..a9942e1f22 100644 --- a/fabric-client/test/TokenClient.js +++ b/fabric-client/test/TokenClient.js @@ -46,7 +46,7 @@ describe('TokenClient', () => { let client; let tokenClient; - const testowner = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('testowner')}; + const testowner = Buffer.from('testowner'); const txId = sinon.createStubInstance(TransactionID); const channelId = 'mychannel'; diff --git a/fabric-client/test/token-utils.js b/fabric-client/test/token-utils.js index 6cbd88687e..dede5de9bf 100644 --- a/fabric-client/test/token-utils.js +++ b/fabric-client/test/token-utils.js @@ -47,7 +47,7 @@ describe('token-utils', () => { beforeEach(() => { // prepare token request - const owner = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('test-owner')}; + const owner = Buffer.from('test-owner'); param = {owner: owner, type: 'abc123', quantity: '210'}; request = {params: [param], txId: txId, tokenIds: tokenIds}; }); @@ -239,8 +239,8 @@ describe('token-utils', () => { describe('#buildIssueCommand', () => { beforeEach(() => { // prepare token request for issue - const owner1 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner1')}; - const owner2 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner2')}; + const owner1 = Buffer.from('owner1'); + const owner2 = Buffer.from('owner2'); param1 = {owner: owner1, type: 'abc123', quantity: '210'}; param2 = {owner: owner2, type: 'horizon', quantity: '300'}; request = { @@ -249,8 +249,10 @@ describe('token-utils', () => { }; // create expected command based on request + const token1 = {owner: {raw: owner1, type:0}, type: 'abc123', quantity: '210'}; + const token2 = {owner: {raw: owner2, type:0}, type: 'horizon', quantity: '300'}; const issueRequest = new fabprotos.token.IssueRequest(); - issueRequest.setTokensToIssue([param1, param2]); + issueRequest.setTokensToIssue([token1, token2]); expectedCommand = new fabprotos.token.Command(); expectedCommand.set('issue_request', issueRequest); }); @@ -265,8 +267,8 @@ describe('token-utils', () => { beforeEach(() => { // prepare token request for transfer const tokenId = {tx_id: 'mock_tx_id', index: 0}; - const owner1 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner1')}; - const owner2 = {type: fabprotos.token.TokenOwner_MSP_IDENTIFIER, raw: Buffer.from('owner2')}; + const owner1 = Buffer.from('owner1'); + const owner2 = Buffer.from('owner2'); param1 = {owner: owner1, quantity: '100'}; param2 = {owner: owner2, quantity: '200'}; @@ -279,8 +281,8 @@ describe('token-utils', () => { // create expected command based on request const transferRequest = new fabprotos.token.TransferRequest(); transferRequest.setTokenIds([tokenId]); - const share1 = {recipient: param1.owner, quantity: param1.quantity}; - const share2 = {recipient: param2.owner, quantity: param2.quantity}; + const share1 = {recipient: {raw: owner1, type: 0}, quantity: param1.quantity}; + const share2 = {recipient: {raw: owner2, type:0}, quantity: param2.quantity}; transferRequest.setShares([share1, share2]); expectedCommand = new fabprotos.token.Command(); expectedCommand.set('transfer_request', transferRequest); diff --git a/test/integration/token.js b/test/integration/token.js index fac54681c3..f8d9d226e5 100644 --- a/test/integration/token.js +++ b/test/integration/token.js @@ -90,12 +90,12 @@ test('\n\n***** Token end-to-end flow (green path): issue, transfer, redeem and // build the request for user2 to issue tokens to user1 let txId = user2TokenClient.getClient().newTransactionID(); let param = { - owner: {type: 0, raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'abc123', quantity: '200' }; const param2 = { - owner: {type: 0, raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'ibm', quantity: '200' }; @@ -125,7 +125,7 @@ test('\n\n***** Token end-to-end flow (green path): issue, transfer, redeem and // build request for user1 to transfer transfer token to user2 txId = user1TokenClient.getClient().newTransactionID(); param = { - owner: {type: 0, raw: user2Identity.serialize()}, + owner: user2Identity.serialize(), quantity: transferToken.quantity, }; request = { @@ -213,7 +213,7 @@ test('\n\n***** Token end-to-end flow: double spending fails *****\n\n', async ( // build request for user2 to issue a token to user1 let txId = user2TokenClient.getClient().newTransactionID(); let param = { - owner: {raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'abc123', quantity: '210' }; @@ -238,7 +238,7 @@ test('\n\n***** Token end-to-end flow: double spending fails *****\n\n', async ( // build request for user1 to transfer transfer token to user2 txId = user1TokenClient.getClient().newTransactionID(); param = { - owner: {raw: user2Identity.serialize()}, + owner: user2Identity.serialize(), quantity: transferToken.quantity }; request = { @@ -303,7 +303,7 @@ test('\n\n***** Token end-to-end flow: non owner transfer fails *****\n\n', asyn // build request for user2 to issue a token to user1 let txId = user2TokenClient.getClient().newTransactionID(); let param = { - owner: {raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'abc123', quantity: '210' }; @@ -328,7 +328,7 @@ test('\n\n***** Token end-to-end flow: non owner transfer fails *****\n\n', asyn // token is owned by user1, but user2 attempts to transfer the token, should fail txId = user2TokenClient.getClient().newTransactionID(); param = { - owner: {raw: user2Identity.serialize()}, + owner: user2Identity.serialize(), quantity: '10' }; request = { @@ -372,7 +372,7 @@ test('\n\n***** Token end-to-end flow: transfer with remaining balance succeeds // build request for user2 to issue a token to user1 let txId = user2TokenClient.getClient().newTransactionID(); let param = { - owner: {raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'abc123', quantity: '210' }; @@ -397,7 +397,7 @@ test('\n\n***** Token end-to-end flow: transfer with remaining balance succeeds // build request for user1 to transfer transfer token to user2 txId = user1TokenClient.getClient().newTransactionID(); param = { - owner: {raw: user2Identity.serialize()}, + owner: user2Identity.serialize(), quantity: '10' }; request = { @@ -451,7 +451,7 @@ test('\n\n***** Token end-to-end flow: invalid redeem amount fails *****\n\n', a // build request for user2 to issue a token to user1 let txId = user2TokenClient.getClient().newTransactionID(); let param = { - owner: {raw: user1Identity.serialize()}, + owner: user1Identity.serialize(), type: 'abc123', quantity: '100' }; @@ -562,8 +562,9 @@ function validateTransactionEnvelope(txEnvelope, commandName, expectedInputs, ex for (let i = 0; i < expectedOutputs.length; i++) { // fabtoken uses hex string in token transaction, so convert expectedQuantity to hex string const expectedQuantityToHex = tokenUtils.toHex(parseInt(expectedOutputs[i].quantity)); + // list tokens returns owner in TokenOwner format {raw: xxx}, so get raw field. + t.deepEqual(action_data.outputs[i].owner.raw, expectedOutputs[i].owner, 'Validationing owner in token transaction'); t.deepEqual(action_data.outputs[i].quantity, expectedQuantityToHex, 'Validationing quantity in token transaction'); - t.deepEqual(action_data.outputs[i].owner, expectedOutputs[i].owner, 'Validationing owner in token transaction'); t.deepEqual(action_data.outputs[i].type, expectedOutputs[i].type, 'Validationing type in token transaction'); } if (expectedInputs) {