diff --git a/database/migrations/20210401005831-AddClaimBoolean.js b/database/migrations/20210401005831-AddClaimBoolean.js new file mode 100644 index 00000000..85af9ca8 --- /dev/null +++ b/database/migrations/20210401005831-AddClaimBoolean.js @@ -0,0 +1,27 @@ +'use strict'; + +var dbm; +var type; +var seed; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function(options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; +}; + +exports.up = function(db) { + return db.addColumn('token', 'claim', { type: 'boolean', notNull: true, defaultValue: false }) +}; + +exports.down = function(db) { + return db.removeColumn('token', 'claim'); +}; + +exports._meta = { + "version": 1 +}; diff --git a/database/migrations/20210401015411-AddColClaimBooleanTransferTable.js b/database/migrations/20210401015411-AddColClaimBooleanTransferTable.js new file mode 100644 index 00000000..8c9468bd --- /dev/null +++ b/database/migrations/20210401015411-AddColClaimBooleanTransferTable.js @@ -0,0 +1,27 @@ +'use strict'; + +var dbm; +var type; +var seed; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function(options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; +}; + +exports.up = function(db) { + return db.addColumn('transfer', 'claim', { type: 'boolean' }) +}; + +exports.down = function(db) { + return db.removeColumn('transfer', 'claim'); +}; + +exports._meta = { + "version": 1 +}; diff --git a/scripts/demo/create-demo-wallet-simple.js b/scripts/demo/create-demo-wallet-simple.js new file mode 100644 index 00000000..0a1c302b --- /dev/null +++ b/scripts/demo/create-demo-wallet-simple.js @@ -0,0 +1,87 @@ + +function getRandomArbitrary(min, max) { + return Math.random() * (max - min) + min; +} + +(async () => { + + const Knex = require('knex') + const faker = require('faker'); + const { v4: uuidv4 } = require('uuid'); + + + const Config = require('./config/config'); + const knex = Knex({ + client: 'pg', + connection: Config.connectionString[process.env.NODE_ENV] + }) + + const Crypto = require('crypto'); + const sha512 = function(password, salt){ + var hash = Crypto.createHmac('sha512', salt); /** Hashing algorithm sha512 */ + hash.update(password); + var value = hash.digest('hex'); + return value; + }; + + const username = faker.internet.userName() + const password = faker.internet.password() // not a secure password + const apiKey = faker.internet.password() + + const salt = faker.internet.password() // not a secure salt + const passwordHash = sha512(password, salt) + + const trx = await knex.transaction(); + + try { + + + // create API key + const apiKeyData = { + key: apiKey, + tree_token_api_access: true, + name: username + } + const result0 = await trx('wallet.api_key').insert(apiKeyData).returning('*') + console.log(result0) + + // create wallet and password, salt + + const result = await trx('wallet.wallet').insert({ + name: username, + password: passwordHash, + salt: salt + }).returning('*') + const wallet = result[0] + console.log(wallet) + + + // create fake tokens + for(i=0; i<5000; i++){ + const tokenData = { + capture_id: uuidv4(), + wallet_id: wallet.id, + } + const result4 = await trx('wallet.token').insert(tokenData).returning('*') + const token = result4[0] + console.log(token.id) + } + + await trx.commit(); + + knex.destroy() + + console.log('wallet ' + username); + console.log('password ' + password); + console.log('apiKey ' + apiKey); + + } catch (error) { + + console.log(error) + await trx.rollback() + knex.destroy() + + } + + +})().catch(e => console.error(e.stack)); diff --git a/server/models/Session.js b/server/models/Session.js index 0ae16fbc..f8c9ebb2 100644 --- a/server/models/Session.js +++ b/server/models/Session.js @@ -21,7 +21,6 @@ class Session{ throw new Error("Can not start transaction in transaction"); } this.thx = await knex.transaction(); - console.log('HEREbbba'); } async commitTransaction(){ diff --git a/server/models/Wallet.js b/server/models/Wallet.js index f7643fef..7e1ce5f3 100644 --- a/server/models/Wallet.js +++ b/server/models/Wallet.js @@ -454,14 +454,6 @@ class Wallet{ */ async transfer(sender, receiver, tokens, claimBoolean){ // await this.checkDeduct(sender, receiver); - // check if the tokens you want to transfer is claimed, i.e. not trasfferable - for (const token of tokens) { - if (token.claim == true) { - console.log("token is claimed, cannot be transfered"); - throw new HttpError(403, `The token ${uuid} is claimed, cannot be transfered`); - } - } - //check tokens belong to sender for(const token of tokens){ if(!await token.belongsTo(sender)){ @@ -473,6 +465,14 @@ class Wallet{ throw new HttpError(403, `The token ${uuid} can not be transfer for some reason, for example, it's been pending for another transfer`); } } + // check if the tokens you want to transfer is claimed, i.e. not trasfferable + for (const token of tokens) { + if (token['_JSON']['claim'] == true) { + console.log("token is claimed, cannot be transfered"); + let uuid = token['_id']; + throw new HttpError(403, `The token ${uuid} is claimed, cannot be transfered`); + } + } const isDeduct = await this.isDeduct(sender,receiver); const hasTrust = await this.hasTrust(TrustRelationship.ENTITY_TRUST_REQUEST_TYPE.send, sender, receiver); @@ -555,6 +555,7 @@ class Wallet{ // if(tokenCount < bundleSize){ // throw new HttpError(403, `Do not have enough tokens to send`); // } + // console.log(notClaimedTokenCount); if(notClaimedTokenCount < bundleSize){ throw new HttpError(403, `Do not have enough tokens to send`); } @@ -582,9 +583,9 @@ class Wallet{ claim: claimBoolean, }); log.debug("now, deal with tokens"); - const tokens = await this.tokenService.getTokensByBundle(sender, bundleSize) + const tokens = await this.tokenService.getTokensByBundle(sender, bundleSize, claimBoolean) // need to check if tokens are not claim - await this.tokenService.completeTransfer(tokens, transfer); + await this.tokenService.completeTransfer(tokens, transfer, claimBoolean); return transfer; }else{ if(hasControlOverSender){ @@ -598,7 +599,9 @@ class Wallet{ bundle: { bundleSize: bundleSize, } - } + }, + //TODO: boolean for claim + claim: claimBoolean, }); return transfer; }else if(hasControlOverReceiver){ diff --git a/server/routes/transferRouter.js b/server/routes/transferRouter.js index 96dd4aff..c3f925b7 100644 --- a/server/routes/transferRouter.js +++ b/server/routes/transferRouter.js @@ -42,21 +42,17 @@ transferRouter.post( .required(), receiver_wallet: Joi.string() .required(), + claim: Joi.boolean(), }), }) ); - console.log('HERE0'); const session = new Session(); //begin transaction try{ - console.log('HERE00'); await session.beginTransaction(); - console.log('HERE000'); const walletService = new WalletService(session); const walletLogin = await walletService.getById(res.locals.wallet_id); - - console.log('HERE001'); const walletSender = await walletService.getByIdOrName(req.body.sender_wallet); const walletReceiver = await walletService.getByIdOrName(req.body.receiver_wallet); // check if this transfer is a claim (claim == not transferrrable tokens) @@ -72,15 +68,12 @@ transferRouter.post( tokens.push(token); } //Case 1: with trust, token transfer - console.log('HERE1'); result = await walletLogin.transfer(walletSender, walletReceiver, tokens, claim); }else{ //Case 2: with trust, bundle transfer // TODO: get only transferrable tokens - console.log('HERE2'); result = await walletLogin.transferBundle(walletSender, walletReceiver, req.body.bundle.bundle_size, claim); } - // console.log('HERE3'); const transferService = new TransferService(session); result = await transferService.convertToResponse(result); if(result.state === Transfer.STATE.completed){ diff --git a/server/services/TokenService.js b/server/services/TokenService.js index 5825cff9..84d7ccae 100644 --- a/server/services/TokenService.js +++ b/server/services/TokenService.js @@ -40,7 +40,8 @@ class TokenService{ /* * Get n tokens from a wallet */ - async getTokensByBundle(wallet, bundleSize){ + async getTokensByBundle(wallet, bundleSize, claimBoolean){ + console.log(claimBoolean); //TODO: getByFilter should be able to handle claim boolean const result = await this.tokenRepository.getByFilter({ wallet_id: wallet.getId(), @@ -48,7 +49,7 @@ class TokenService{ },{ limit: bundleSize, // add claim - claim: false, + claim: claimBoolean, }); return result.map(json => new Token(json, this._session)); } @@ -115,12 +116,13 @@ class TokenService{ /* * To replace token.completeTransfer, as a bulk operaction */ - async completeTransfer(tokens, transfer){ + async completeTransfer(tokens, transfer, claimBoolean){ log.debug("Token complete transfer batch"); await this.tokenRepository.updateByIds({ transfer_pending: false, transfer_pending_id: null, wallet_id: transfer.destination_wallet_id, + claim: claimBoolean, }, tokens.map(token => token.getId()), );