diff --git a/backend/package.json b/backend/package.json index 451a5a86d..85a0e4aed 100644 --- a/backend/package.json +++ b/backend/package.json @@ -8,9 +8,11 @@ "license": "MIT", "private": false, "scripts": { + "prebuild": "pbjs -t static-module -w commonjs -o src/proto/bundle.js src/proto/gradido/*.proto && pbts -o src/proto/bundle.d.ts src/proto/bundle.js", "build": "tsc --build", "clean": "tsc --build --clean", "start": "node build/index.js", + "predev": "pbjs -t static-module -w commonjs -o src/proto/bundle.js src/proto/gradido/*.proto && pbts -o src/proto/bundle.d.ts src/proto/bundle.js", "dev": "nodemon -w src --ext ts --exec ts-node src/index.ts", "lint": "eslint . --ext .js,.ts", "test": "jest --coverage" @@ -51,6 +53,7 @@ "eslint-plugin-promise": "^5.1.0", "nodemon": "^2.0.7", "prettier": "^2.3.1", + "protobufjs": "^6.11.2", "ts-node": "^10.0.0", "typescript": "^4.3.4" } diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 063ad69d7..47f65f9c9 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql' +import { Resolver, Query, Args, Authorized, Ctx, Mutation, Root } from 'type-graphql' import { getCustomRepository, getConnection, getRepository } from 'typeorm' import { createTransport } from 'nodemailer' @@ -33,7 +33,6 @@ import { calculateDecay, calculateDecayWithInterval } from '../../util/decay' import { TransactionTypeId } from '../enum/TransactionTypeId' import { TransactionType } from '../enum/TransactionType' import { hasUserAmount, isHexPublicKey } from '../../util/validate' -import protobuf from '@apollo/protobufjs' import { from_hex as fromHex, to_base64 as toBase64, @@ -46,6 +45,9 @@ import { crypto_generichash_BYTES as cryptoGenericHashBytes, } from 'libsodium-wrappers' +import { proto } from '../../proto/bundle' +import context from '../../server/context' + // Helper function async function calculateAndAddDecayTransactions( userTransactions: DbUserTransaction[], @@ -239,7 +241,7 @@ async function updateStateBalance( balance.amount = centAmount } else { balance.amount = - (await calculateDecay(balance.amount, balance.recordDate, received)) + centAmount + Number(await calculateDecay(balance.amount, balance.recordDate, received)) + centAmount } if (balance.amount <= 0) { throw new Error('error new balance <= 0') @@ -254,16 +256,16 @@ async function updateStateBalance( // helper helper function async function addUserTransaction(user: dbUser, transaction: DbTransaction, centAmount: number) { let newBalance = centAmount - const userTransactionRepository = getCustomRepository(UserTransactionRepository) const lastUserTransaction = await userTransactionRepository.findLastForUser(user.id) if (lastUserTransaction) { - newBalance += await calculateDecay( - lastUserTransaction.balance, + newBalance += Number(await calculateDecay( + Number(lastUserTransaction.balance), lastUserTransaction.balanceDate, transaction.received, - ) + )) } + if (newBalance <= 0) { throw new Error('error new balance <= 0') } @@ -295,6 +297,7 @@ async function sendCoins( recipiantPublicKey: string, amount: number, memo: string, + sessionId: number, groupId = 0, ): Promise { if (senderUser.pubkey.length !== 32) { @@ -309,37 +312,32 @@ async function sendCoins( if (!hasUserAmount(senderUser, amount)) { throw new Error("user hasn't enough GDD") } - const protoRoot = await protobuf.load('../../proto/gradido/GradidoTransfer.proto') - const GradidoTransfer = protoRoot.lookupType('proto.gradido.GradidoTransfer') - const TransferAmount = protoRoot.lookupType('proto.gradido.TransferAmount') const centAmount = Math.trunc(amount * 10000) - const transferAmount = TransferAmount.create({ + const transferAmount = new proto.gradido.TransferAmount({ pubkey: senderUser.pubkey, amount: centAmount, }) // no group id is given so we assume it is a local transfer if (!groupId) { - const LocalTransfer = protoRoot.lookupType('proto.gradido.LocalTransfer') - const localTransfer = LocalTransfer.create({ + const localTransfer = new proto.gradido.LocalTransfer({ sender: transferAmount, recipiant: fromHex(recipiantPublicKey), }) - const createTransaction = GradidoTransfer.create({ local: localTransfer }) - const TransactionBody = protoRoot.lookupType('proto.gradido.TransactionBody') - - const transactionBody = TransactionBody.create({ + const transferTransaction = new proto.gradido.GradidoTransfer({ local: localTransfer }) + const transactionBody = new proto.gradido.TransactionBody({ memo: memo, - created: new Date(), - data: createTransaction, + created: { seconds: new Date().getTime() / 1000 }, + transfer: transferTransaction, }) - const bodyBytes = TransactionBody.encode(transactionBody).finish() + const bodyBytes = proto.gradido.TransactionBody.encode(transactionBody).finish() const bodyBytesBase64 = toBase64(bodyBytes, base64Variants.ORIGINAL) // let Login-Server sign transaction const result = await apiPost(CONFIG.LOGIN_API_URL + 'signTransaction', { + session_id: sessionId, bodyBytes: bodyBytesBase64, }) if (!result.success) throw new Error(result.data) @@ -348,13 +346,12 @@ async function sendCoins( if (!cryptoSignVerifyDetached(sign, bodyBytesBase64, senderUser.pubkey)) { throw new Error('Could not verify signature') } - const SignatureMap = protoRoot.lookupType('proto.gradido.SignatureMap') - const SignaturePair = protoRoot.lookupType('proto.gradido.SignaturePair') - const sigPair = SignaturePair.create({ + + const sigPair = new proto.gradido.SignaturePair({ pubKey: senderUser.pubkey, - signature: { ed25519: sign }, + ed25519: sign, }) - const sigMap = SignatureMap.create({ sigPair: [sigPair] }) + const sigMap = new proto.gradido.SignatureMap({ sigPair: [sigPair] }) const userRepository = getCustomRepository(UserRepository) const recipiantUser = await userRepository.findByPubkeyHex(recipiantPublicKey) @@ -424,7 +421,7 @@ async function sendCoins( // should match previous used format: yyyy-MM-dd HH:mm:ss const receivedString = transaction.received.toISOString().slice(0, 19).replace('T', ' ') cryptoGenerichashUpdate(state, receivedString) - cryptoGenerichashUpdate(state, SignatureMap.encode(sigMap).finish()) + cryptoGenerichashUpdate(state, proto.gradido.SignatureMap.encode(sigMap).finish()) transaction.txHash = Buffer.from(cryptoGenerichashFinal(state, cryptoGenericHashBytes)) transactionRepository.save(transaction).catch(() => { throw new Error('error saving transaction with tx hash') @@ -589,7 +586,7 @@ export class TransactionResolver { const userRepository = getCustomRepository(UserRepository) const userEntity = await userRepository.findByPubkeyHex(context.pubKey) - const transaction = sendCoins(userEntity, recipiantPublicKey, amount, memo) + const transaction = sendCoins(userEntity, recipiantPublicKey, amount, memo, context.sessionId) if (!transaction) { throw new Error('error sending coins') } diff --git a/backend/yarn.lock b/backend/yarn.lock index 3ad3e65d1..ff596c957 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -893,7 +893,7 @@ resolved "https://registry.yarnpkg.com/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.9.tgz#89c3ad2156d5143e64bce86cfeb0045a983aeccc" integrity sha512-LisgKLlYQk19baQwjkBZZXdJL0KbeTpdEnrAfz5hQACbklCY0gVFnsKUyjfNWF1UQsCSjw93Sj5jSbiO8RPfdw== -"@types/long@^4.0.0": +"@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.1" resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== @@ -913,6 +913,11 @@ resolved "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz" integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA== +"@types/node@>=13.7.0": + version "16.10.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5" + integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ== + "@types/node@^10.1.0": version "10.17.60" resolved "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz" @@ -4589,6 +4594,25 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +protobufjs@^6.11.2: + version "6.11.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" + integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + proxy-addr@~2.0.5: version "2.0.7" resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz"