Re: Hyperledger Fabric 2.0, Can't Access Fabtokens of Users Using Node.js SDK

Nikhil Gupta


The token work was part of the 2.0 Alpha. However, the maintainers have decided not to move forward with tokens on the 2.0 release. As a result, tokens have been removed from the latest code in master. That may be why you are having problems.


-----fabric@... wrote: -----
To: hyperledger-fabric@...
From: "Sencer Burak Somuncuoğlu"
Sent by: fabric@...
Date: 09/23/2019 12:48PM
Subject: [EXTERNAL] [Hyperledger Fabric] Hyperledger Fabric 2.0, Can't Access Fabtokens of Users Using Node.js SDK


I'm trying to issue some Fabtokens to users and then use them in various scenarios such as transferring, redeeming, etc. I follow the Node SDK documentation here:

This is how they do the Fabtoken operations:

// create a TokenClient instance from client
const tokenclient = client.newTokenClient(mychannel);

// create a transaction ID for "issuer"
const txId = client.newTransactionID();

// create two parameters for issue, one for user1 and one for user2
const param1 = {
: user1.getIdentity().serialize(),
: 'USD',
: '500',
const param2 = {
: user2.getIdentity().serialize(),
: 'EURO',
: '300',

// create the token request for issue
const issueRequest = {
: [param1, param2],
: txId,

// issuer calls issue method to issue tokens to user1 and user2
const result = await tokenClient.issue(issueRequest);

And then use a different tokenClient to list the tokens of user 1:

const user1Tokenclient = client1.newTokenClient(mychannel);

// user1 lists tokens
const mytokens = await user1TokenClient.list();

// iterate the tokens to get token id, type, and quantity for each token
for (const token of tokens) {
// get, token.type, and token.quantity
// will be used for transfer and redeem

It's mentioned on the Node SDK's Client class page here: that switching userContexts with the same client instance is an anti-pattern and not recommended since client instances are stateful.

As they suggest, I create my client instances with different user contexts. This is how I create my clients, set their user context and create my tokenClient instances:

const adminClient = new Fabric_Client();
const admin = await adminClient.createUser(user_opts);
.setUserContext(admin, true);
let adminConfig = {
: admin,
: adminClient,
: adminClient.newTokenClient(channel)

const server = await serverClient.createUser(server_opts); 
.setUserContext(server, true);
let serverConfig = {
: server,
: serverClient,
: serverClient.newTokenClient(channel)
Later on, I'm using these config objects to issue some tokens to different users. How I issue tokens to my server account from my issuer (admin) account:
const txId = adminConfig.adminClient.newTransactionID();
let issueQuery = {
: adminConfig.adminTokenClient,
: txId,
: channel,
: []

for(let i=0; i < 3; ++i) {
let param = {
: serverConfig.server.getIdentity().serialize(),
: 'test',
: '1'
let issueTx = await waitForIssue(issueQuery);
This successfully issue three tokens to the server as expected. The problem is that when I try to access to the tokens of my server like the example they provide using a similar code:
let server_tokens = await serverConfig.serverTokenClient.list();
for (let server_token of server_tokens) {
Result is just empty and I don't get any error messages. However, when I check the transaction using queryTransaction(txId) for the token issue transaction I generate, I can see that owner of the issued tokens in that transaction is the server and that's how I can be sure that I can successfully issue the tokens to the server. Is there any other way to check the tokens of my server? Or shouldn't I use a different client and user context per each user as they suggest? Because, previously I was able to see the tokens of the server when I used a single client and single user context to issue and list tokens. But this approach caused me problems when I was trying to transfer my tokens asynchronously.


Join to automatically receive all group messages.