first steps for send coins

This commit is contained in:
einhorn_b 2021-09-29 18:47:10 +02:00
parent bf8bd24abf
commit 41afaa0e01
8 changed files with 136 additions and 0 deletions

3
.gitmodules vendored
View File

@ -34,3 +34,6 @@
[submodule "login_server/dependencies/protobuf"]
path = login_server/dependencies/protobuf
url = https://github.com/protocolbuffers/protobuf.git
[submodule "backend/src/proto"]
path = backend/src/proto
url = git@github.com:gradido/gradido_protocol.git

View File

@ -15,6 +15,7 @@
"lint": "eslint . --ext .js,.ts"
},
"dependencies": {
"@apollo/protobufjs": "^1.2.2",
"apollo-server-express": "^2.25.2",
"axios": "^0.21.1",
"class-validator": "^0.13.1",
@ -23,6 +24,7 @@
"express": "^4.17.1",
"graphql": "^15.5.1",
"jsonwebtoken": "^8.5.1",
"libsodium-wrappers": "^0.7.9",
"mysql2": "^2.3.0",
"reflect-metadata": "^0.1.13",
"type-graphql": "^1.1.1",
@ -31,6 +33,7 @@
"devDependencies": {
"@types/express": "^4.17.12",
"@types/jsonwebtoken": "^8.5.2",
"@types/libsodium-wrappers": "^0.7.9",
"@typescript-eslint/eslint-plugin": "^4.28.0",
"@typescript-eslint/parser": "^4.28.0",
"eslint": "^7.29.0",

View File

@ -11,6 +11,8 @@ import { Balance as dbBalance } from '../../typeorm/entity/Balance'
import listTransactions from './listTransactions'
import { roundFloorFrom4 } from '../../util/round'
import { calculateDecay } from '../../util/decay'
import sendCoins from './sendCoins'
import getPublicKey from './getPublicKey'
@Resolver()
export class TransactionResolver {
@ -69,6 +71,21 @@ export class TransactionResolver {
if (!result.success) {
throw new Error(result.data)
}
const recipiantPublicKey = await getPublicKey(email, context.sessionId)
if(!recipiantPublicKey) {
throw new Error('recipiant not known')
}
// get public key for current logged in user
const loginResult = await apiGet(CONFIG.LOGIN_API_URL + 'login?session_id=' + context.sessionId)
if (!loginResult.success) throw new Error(result.data)
// load user and balance
const userEntity = await dbUser.findByPubkeyHex(result.data.user.public_hex)
const transaction = sendCoins(userEntity, recipiantPublicKey, amount, memo)
return 'success'
}
}

View File

@ -0,0 +1,6 @@
export default function createTransaction()
{
}

View File

@ -0,0 +1,32 @@
import { apiPost } from '../../apis/HttpRequest'
import CONFIG from '../../config'
import { isHexPublicKey } from '../../util/validate'
// target can be email, username or public_key
// groupId if not null and another community, try to get public key from there
export default async function getPublicKey(target: string, sessionId:number, groupId: number = 0): Promise<string | undefined>
{
// if it is already a public key, return it
if(isHexPublicKey(target)) {
return target
}
// assume it is a email address if it's contain a @
if(/@/i.test(target)) {
const result = await apiPost(CONFIG.LOGIN_API_URL + 'getUserInfos', {
session_id: sessionId,
email: target,
ask: ['user.pubkeyhex']
})
if (result.success) {
return result.data.userData.pubkeyhex
}
}
// if username is used add code here
// if we have multiple communities add code here
return undefined
}

View File

@ -0,0 +1,53 @@
import protobuf from '@apollo/protobufjs'
import { from_hex } from 'libsodium-wrappers'
import { isHexPublicKey, hasUserAmount } from '../../util/validate'
import { User as dbUser } from '../../typeorm/entity/User'
/**
*
* @param senderPublicKey as hex string
* @param recipiantPublicKey as hex string
* @param amount as float
* @param memo
* @param groupId
*/
export default async function sendCoins(
senderUser: dbUser,
recipiantPublicKey:string,
amount:number,
memo:string,
groupId:number = 0)
{
if(senderUser.pubkey.length != 32) {
throw new Error('invalid sender public key')
}
if(!isHexPublicKey(recipiantPublicKey)) {
throw new Error('invalid recipiant public key')
}
if(amount <= 0) {
throw new Error('invalid amount')
}
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 transferAmount = TransferAmount.create({
pubkey: senderUser.pubkey,
amount: amount / 10000
})
// 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({
sender: transferAmount,
recipiant: from_hex(recipiantPublicKey)
})
return GradidoTransfer.create({local: localTransfer})
}
}

1
backend/src/proto Submodule

@ -0,0 +1 @@
Subproject commit cc9acbb212201a560d86fc87a47665497f11f27d

View File

@ -0,0 +1,21 @@
import { User as dbUser } from '../typeorm/entity/User'
import { Balance as dbBalance } from '../typeorm/entity/Balance'
import { getRepository } from 'typeorm'
import { calculateDecay } from './decay'
import { UserResolver } from '../graphql/resolvers'
function isHexPublicKey(publicKey:string): boolean {
return /^[0-9A-Fa-f]{64}$/i.test(publicKey)
}
async function hasUserAmount(user:dbUser, amount:number): Promise<boolean> {
if(amount < 0) return false
const balanceRepository = getRepository(dbBalance)
const balance = await balanceRepository.findOne({ userId: user.id })
if(!balance) return false
const decay = await calculateDecay(balance.amount, balance.recordDate, new Date())
return decay > amount
}
export { isHexPublicKey, hasUserAmount }