Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion models/Award.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export type Award = Record<
| 'reason'
| 'nominator'
| 'createdAt'
| 'votes',
| 'votes'
| 'walletAddress'
| 'transactionHash'
| 'tokenId',
TableCellValue
>;

Expand Down
40 changes: 40 additions & 0 deletions pages/api/Lark/award/issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Context } from 'koa';
import { createKoaRouter, withKoaRouter } from 'next-ssr-middleware';
import { AwardModel } from '../../../../models/Award';
import { safeAPI, verifyJWT } from '../../core';

export const config = { api: { bodyParser: true } };

const router = createKoaRouter(import.meta.url);

const EthereumAddressPattern = /^0x[a-fA-F0-9]{40}$/;

router.post('/issue', safeAPI, verifyJWT, async (context: Context) => {
const { recordId, walletAddress } = (context.request as any).body;

if (!recordId || !walletAddress) {
context.throw(400, 'recordId and walletAddress are required');
}

if (typeof walletAddress !== 'string' || !EthereumAddressPattern.test(walletAddress)) {
context.throw(400, 'walletAddress must be a valid Ethereum address');
}

// Issue OCToken NFT logic
const transactionHash = `0x${Math.random().toString(16).slice(2)}`;
const tokenId = Math.floor(Math.random() * 10000).toString();
Comment on lines +24 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

当前实现没有真正执行 NFT 颁发流程。

这里仅生成本地随机 transactionHash/tokenId 并写库,然后直接返回 success: true。这会产生“已颁发”假记录,且无法保证与链上状态一致。建议先调用真实铸造/发放服务,使用其返回值落库,并在失败时返回错误状态。

🔧 建议改造方向(示意)
-  // Issue OCToken NFT logic
-  const transactionHash = `0x${Math.random().toString(16).slice(2)}`;
-  const tokenId = Math.floor(Math.random() * 10000).toString();
+  // 1) 调用真实发放服务(链上或签名服务)
+  const { transactionHash, tokenId } = await issueOCTokenNFT({ walletAddress, recordId });
+  if (!transactionHash || !tokenId) {
+    context.throw(502, 'NFT issuance failed');
+  }

   const awardModel = new AwardModel();
   await awardModel.updateOne({
     transactionHash,
     tokenId,
     walletAddress
   }, recordId);

-  context.body = { success: true, transactionHash, tokenId };
+  context.body = { success: true, transactionHash, tokenId };

As per coding guidelines **/*.{ts,tsx}: "Import from established sources ... rather than reimplementing" and "Use minimal exports and avoid unnecessary custom implementations".

Also applies to: 22-28

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/api/Lark/award/issue.ts` around lines 18 - 19, The current code
fabricates transactionHash and tokenId locally instead of calling the real
minting/issuance service; replace the Math.random-based generation
(transactionHash and tokenId) with a call to the actual NFT mint/issue API or
internal service (e.g., call mintService.mint(...) or nftIssuer.issue(...)),
await its response, extract the real transaction hash and token id from that
response, persist those returned values to the DB only on success, and propagate
failures (return error status and do not write a false "issued" record); also
update any import to use the established minting/issuer module rather than a
custom reimplementation as noted (this applies to the code around the token/tx
creation and the DB write logic).


const awardModel = new AwardModel();
await awardModel.updateOne(
{
transactionHash,
tokenId,
walletAddress,
},
recordId,
);

context.body = { success: true, transactionHash, tokenId };
});

export default withKoaRouter(router);