mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
first steps for send coins
This commit is contained in:
parent
bf8bd24abf
commit
41afaa0e01
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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'
|
||||
}
|
||||
}
|
||||
|
||||
6
backend/src/graphql/resolvers/createTransaction.ts
Normal file
6
backend/src/graphql/resolvers/createTransaction.ts
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
export default function createTransaction()
|
||||
{
|
||||
|
||||
}
|
||||
32
backend/src/graphql/resolvers/getPublicKey.ts
Normal file
32
backend/src/graphql/resolvers/getPublicKey.ts
Normal 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
|
||||
|
||||
}
|
||||
53
backend/src/graphql/resolvers/sendCoins.ts
Normal file
53
backend/src/graphql/resolvers/sendCoins.ts
Normal 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
1
backend/src/proto
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cc9acbb212201a560d86fc87a47665497f11f27d
|
||||
21
backend/src/util/validate.ts
Normal file
21
backend/src/util/validate.ts
Normal 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 }
|
||||
Loading…
x
Reference in New Issue
Block a user