🏗️」 wip: seems to be working

This commit is contained in:
2025-07-30 16:04:18 +02:00
parent 0449ad7ad2
commit 041bb2deb5
10 changed files with 252 additions and 12 deletions

View File

@ -0,0 +1,26 @@
import { ContractTransactionResponse } from "ethers";
import scoreDB from "../../utils/scoreDB.js";
import { callAddScore, callLastId } from "../../utils/scoreStore_contract.js";
/**
* @async
* @param {import("fastify").FastifyRequest} request
* @param {import("fastify").FastifyReply} reply
* @param {import("fastify").FastifyInstance} fastify
*/
export async function addTx(request, reply, fastify) {
try {
const id = await callLastId();
/** @type ContractTransactionResponse */
const tx = await callAddScore(request.body.p1, request.body.p2, request.body.p1Score, request.body.p2Score);
scoreDB.addTx(id, tx.hash);
return reply.code(200).send({
tx: tx.hash
});
} catch (err) {
fastify.log.error(err);
return reply.code(500).send({ error: "Internal server error" });
}
}

View File

@ -1,6 +1,8 @@
import { evm } from '@avalabs/avalanchejs';
import scoreDB from '../../utils/scoreDB.js';
import { getTx } from './getTx.js';
import { addTx } from './addTx.js';
import scoreDB from '../../utils/scoreDB.js';
scoreDB.prepareDB();
/**
* @param {import('fastify').FastifyInstance} fastify
@ -10,4 +12,21 @@ export default async function(fastify, options) {
fastify.get("/:id", async (request, reply) => {
return getTx(request, reply, fastify);
});
fastify.post("/", {
schema: {
body: {
type: 'object',
required: ['p1', 'p2', 'p1Score', 'p2Score'],
properties: {
p1: { type: 'string', minLength: 1 },
p2: { type: 'string', minLength: 1 },
p1Score: { type: 'integer', minimum: 0 },
p2Score: { type: 'integer', minimum: 0 },
}
}
}
}, async (request, reply) => {
return addTx(request, reply, fastify);
});
}

View File

@ -1,4 +1,5 @@
import scoreDB from "../../utils/scoreDB.js";
import { callGetScore } from "../../utils/scoreStore_contract.js";
/**
* @async
@ -10,10 +11,16 @@ import scoreDB from "../../utils/scoreDB.js";
*/
export async function getTx(request, reply, fastify) {
try {
const tx = scoreDB.getTx(request.params.id);
const score = callGetScore(request.params.id);
return reply.code(200).send({
score: score,
tx: tx
});
} catch (err) {
fastify.log.error(err);
return reply.code(500).send({ error: "Internal server error" });
}
}

View File

@ -0,0 +1 @@
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"p1","type":"string"},{"internalType":"string","name":"p2","type":"string"},{"internalType":"uint128","name":"p1Score","type":"uint128"},{"internalType":"uint128","name":"p2Score","type":"uint128"}],"name":"addScore","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getScore","outputs":[{"components":[{"internalType":"string","name":"p1","type":"string"},{"internalType":"string","name":"p2","type":"string"},{"internalType":"uint128","name":"p1Score","type":"uint128"},{"internalType":"uint128","name":"p2Score","type":"uint128"}],"internalType":"struct score","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"scores","outputs":[{"internalType":"string","name":"p1","type":"string"},{"internalType":"string","name":"p2","type":"string"},{"internalType":"uint128","name":"p1Score","type":"uint128"},{"internalType":"uint128","name":"p2Score","type":"uint128"}],"stateMutability":"view","type":"function"}]

View File

@ -1,6 +1,7 @@
import Fastify from 'fastify';
import authApi from './api/auth/default.js';
import userApi from './api/user/default.js';
import scoreApi from './api/scoreStore/default.js';
const loggerOption = {
transport: {
@ -47,6 +48,19 @@ async function start() {
console.log('User API listening on http://localhost:3002');
}
}
if (target === 'scoreStore' || target === 'all') {
const scoreStore = Fastify({ logger: loggerOption });
scoreStore.register(scoreApi);
if (target !== 'all') {
await scoreStore.listen({ port: 3000, host: '0.0.0.0' });
console.log('scoreStore API listening on http://0.0.0.0:3000');
}
else {
await scoreStore.listen({ port: 3002, host: '127.0.0.1'});
console.log('scoreStore API listening on http://localhost:3002');
}
}
}
start().catch(console.error);

View File

@ -17,7 +17,7 @@ if (!env || env === 'development') {
function prepareDB() {
database.exec(`
CREATE TABLE IF NOT EXISTS scoresTx (
id INTEGER PRIMARY KEY,
id INT PRIMARY KEY,
txHash TEXT
) STRICT
`);
@ -25,7 +25,7 @@ function prepareDB() {
/**
* @description Can be used to add a score hash to the DB
* @param {Int} The id of the score
* @param {Number} The id of the score
* @param {String} The hash of the score
*/
function addTx(id, txHash) {
@ -39,7 +39,7 @@ function addTx(id, txHash) {
* @returns {String} The tx hash
*/
function getTx(id) {
const txGet = database.prepare('SELECT txHash FROM credentials WHERE id = ?;')
const txGet = database.prepare('SELECT txHash FROM scoresTx WHERE id = ?;')
return txGet.get(id);
}

View File

@ -0,0 +1,88 @@
import { ethers } from "ethers";
import { readFile } from "fs/promises";
export const rpc_url = process.env.AVAX_RPC_URL;
export const contract_addr = process.env.AVAX_CONTRACT_ADDR;
export const owner_priv_key = process.env.AVAX_PRIVATE_KEY;
const provider = new ethers.JsonRpcProvider(rpc_url);
const wallet = new ethers.Wallet(owner_priv_key, provider);
async function loadContract() {
try {
const contractABI = JSON.parse(await readFile(new URL('../contract/scoreStore.json', import.meta.url)));
const contract = new ethers.Contract(contract_addr, contractABI, wallet);
return contract;
} catch (error) {
console.error('Error loading contract ABI:', error);
throw error;
}
}
/**
* @param {int} id
* @returns {Promise<Object>} A promise that resolves to the score details if successful.
* @throws {Error} Throws an error if the function call fails.
*/
async function callGetScore(id) {
try {
const contract = await loadContract();
const result = await contract.getScore(id);
return result;
} catch (error) {
console.error('Error calling view function:', error);
throw error;
}
}
/**
* Adds a new score to the smart contract.
*
* @async
* @param {string} p1 - The name of the first player.
* @param {string} p2 - The name of the second player.
* @param {number} p1Score - The score of the first player.
* @param {number} p2Score - The score of the second player.
* @returns {Promise<ethers.ContractTransactionResponse>} A promise that resolves to the transaction response if successful.
* @throws {Error} Throws an error if the function call fails.
*/
async function callAddScore(p1, p2, p1Score, p2Score) {
try {
const contract = await loadContract();
const tx = await contract.addScore(p1, p2, p1Score, p2Score);
console.log('Transaction sent:', tx.hash);
await tx.wait(); // Wait for the transaction to be mined
console.log('Transaction confirmed');
return tx;
} catch (error) {
console.error('Error calling addScore function:', error);
throw error;
}
}
/**
* Fetches the last ID from the smart contract.
*
* @async
* @returns {Promise<number>} A promise that resolves to the last ID.
* @throws {Error} Throws an error if the function call fails.
*/
async function callLastId() {
try {
const contract = await loadContract();
const lastId = await contract.lastId();
console.log('Last ID:', lastId.toString());
return lastId;
} catch (error) {
console.error('Error calling lastId function:', error);
throw error;
}
}
export {
callAddScore,
callGetScore,
callLastId
};