From 89e3c726b2f9e404c343d150f8f6255e264a6274 Mon Sep 17 00:00:00 2001 From: WrBug Date: Sun, 7 Dec 2025 14:45:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96UI=E5=92=8C=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=9B=BE=E6=A0=87=E7=94=9F?= =?UTF-8?q?=E6=88=90=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复未匹配订单更新逻辑,添加去重机制避免重复赎回 - 优化跟单配置列表,移除订单菜单中的编辑选项 - 限制账户编辑功能,只允许编辑账户名称 - 优化Layout布局,将PC端图标移至标题下方,添加Telegram群链接 - 添加图标生成脚本到polymarket-demo目录 - 添加多个尺寸的favicon图标文件 --- .../service/PositionCheckService.kt | 46 +- frontend/public/apple-touch-icon.png | Bin 0 -> 3998 bytes frontend/public/favicon-16x16.png | Bin 0 -> 320 bytes frontend/public/favicon-32x32.png | Bin 0 -> 693 bytes frontend/public/icon-512x512.png | Bin 0 -> 11284 bytes frontend/src/components/Layout.tsx | 64 ++- frontend/src/pages/AccountDetail.tsx | 45 +- frontend/src/pages/AccountList.tsx | 45 +- frontend/src/pages/CopyTradingList.tsx | 9 - polymarket-demo/icon-512x512.png | Bin 0 -> 9978 bytes polymarket-demo/package-lock.json | 437 ++++++++++++++++++ polymarket-demo/package.json | 5 +- polymarket-demo/scripts/generate-icon.js | 107 +++++ 13 files changed, 644 insertions(+), 114 deletions(-) create mode 100644 frontend/public/apple-touch-icon.png create mode 100644 frontend/public/favicon-16x16.png create mode 100644 frontend/public/favicon-32x32.png create mode 100644 frontend/public/icon-512x512.png create mode 100644 polymarket-demo/icon-512x512.png create mode 100644 polymarket-demo/scripts/generate-icon.js diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/PositionCheckService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/PositionCheckService.kt index f170dbe..63cb6eb 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/PositionCheckService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/PositionCheckService.kt @@ -51,6 +51,9 @@ class PositionCheckService( // 记录已发送通知的仓位(避免重复推送) private val notifiedRedeemablePositions = ConcurrentHashMap() // "accountId_marketId_outcomeIndex" -> lastNotificationTime + // 记录已处理的赎回仓位(避免重复赎回) + private val processedRedeemablePositions = ConcurrentHashMap() // "accountId_marketId_outcomeIndex" -> lastProcessTime + // 记录已发送提示的配置(避免重复推送) private val notifiedConfigs = ConcurrentHashMap() // accountId/copyTradingId -> lastNotificationTime @@ -139,6 +142,14 @@ class PositionCheckService( notifiedRedeemablePositions.remove(key) } + // 清理过期的已处理赎回仓位记录 + val expiredProcessed = processedRedeemablePositions.entries.filter { (_, timestamp) -> + (now - timestamp) > expireTime + } + expiredProcessed.forEach { (key, _) -> + processedRedeemablePositions.remove(key) + } + // 清理过期的配置通知记录 val expiredConfigs = notifiedConfigs.entries.filter { (_, timestamp) -> (now - timestamp) > expireTime @@ -147,8 +158,8 @@ class PositionCheckService( notifiedConfigs.remove(key) } - if (expiredPositions.isNotEmpty() || expiredConfigs.isNotEmpty()) { - logger.debug("清理过期缓存: positions=${expiredPositions.size}, configs=${expiredConfigs.size}") + if (expiredPositions.isNotEmpty() || expiredProcessed.isNotEmpty() || expiredConfigs.isNotEmpty()) { + logger.debug("清理过期缓存: positions=${expiredPositions.size}, processed=${expiredProcessed.size}, configs=${expiredConfigs.size}") } } @@ -235,9 +246,28 @@ class PositionCheckService( continue } + // 过滤掉已经处理过的仓位(去重,避免重复赎回) + val now = System.currentTimeMillis() + val positionsToRedeem = positions.filter { position -> + val positionKey = "${accountId}_${position.marketId}_${position.outcomeIndex ?: 0}" + val lastProcessed = processedRedeemablePositions[positionKey] + // 如果最近30分钟内已经处理过,跳过(避免重复赎回) + if (lastProcessed != null && (now - lastProcessed) < 1800000) { // 30分钟 + logger.debug("跳过已处理的赎回仓位: $positionKey (上次处理时间: ${lastProcessed})") + false + } else { + true + } + } + + if (positionsToRedeem.isEmpty()) { + logger.debug("所有仓位都已处理过,跳过赎回: accountId=$accountId") + continue + } + // 先执行赎回(不查找订单) val redeemRequest = com.wrbug.polymarketbot.dto.PositionRedeemRequest( - positions = positions.map { position -> + positions = positionsToRedeem.map { position -> com.wrbug.polymarketbot.dto.AccountRedeemPositionItem( accountId = accountId, marketId = position.marketId, @@ -250,10 +280,16 @@ class PositionCheckService( val redeemResult = accountService.redeemPositions(redeemRequest) redeemResult.fold( onSuccess = { response -> - logger.info("自动赎回成功: accountId=$accountId, redeemedCount=${positions.size}, totalValue=${response.totalRedeemedValue}") + logger.info("自动赎回成功: accountId=$accountId, redeemedCount=${positionsToRedeem.size}, totalValue=${response.totalRedeemedValue}") + + // 记录已处理的仓位(避免重复赎回) + for (position in positionsToRedeem) { + val positionKey = "${accountId}_${position.marketId}_${position.outcomeIndex ?: 0}" + processedRedeemablePositions[positionKey] = now + } // 赎回成功后,再查找订单并更新订单状态 - for (position in positions) { + for (position in positionsToRedeem) { // 查找相同仓位的未卖出订单(remaining_quantity > 0) val unmatchedOrders = mutableListOf() for (copyTrading in copyTradings) { diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..784ef0a15100030d9e5dd5d0b2da832b2db64441 GIT binary patch literal 3998 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 S25S8P0000$!eEbRKJ{_+5w9erHvDi7hb zyXZQ3h3*rVaoSy$!g~q;Z2AinQ_|gj16xiq@@lYPF_)_G;QC`cYCSd+dRlt9^Xw+E z)xx*GSa=Ztu$hwcXL?ag2)rJov-K*iM>-HD*d%xy-h8-XN_2;Z`!&@@IiQ`Y|_IE4VF7CvwI{{Ic4LUOA* zeytH9L|Ly80>9RXrs|deENw#p9P>5P(s-Kh;W>gU3q(^9GTHTIR8wWgt!nt32l4Ao zB#i_g=O-)yY^eqAS~m^aA@(_axYYG^3}EC8VyOs=D?xrl=7|;=NdFA56Wa9`Q3ap^ bPyzS@>p0;LF&aKq00000NkvXXu0mjf?@KQu literal 0 HcmV?d00001 diff --git a/frontend/public/icon-512x512.png b/frontend/public/icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..a2b4a9e07040f2449443d152877372d8030f1f31 GIT binary patch literal 11284 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 = ({ children }) => { size="normal" darkMode={true} /> -
+
@@ -210,14 +212,24 @@ const Layout: React.FC = ({ children }) => { href="https://x.com/quant_tr" target="_blank" rel="noopener noreferrer" - style={{ color: '#fff', fontSize: '18px' }} + style={{ color: '#fff', fontSize: '16px', display: 'flex', alignItems: 'center' }} + title="Twitter" > + + +
@@ -265,23 +277,30 @@ const Layout: React.FC = ({ children }) => { }} >
- PolyHermes - = ({ children }) => { items={menuItems} onClick={handleMenuClick} style={{ - height: 'calc(100vh - 64px)', + height: 'calc(100vh - 100px)', borderRight: 0, overflowY: 'auto' }} diff --git a/frontend/src/pages/AccountDetail.tsx b/frontend/src/pages/AccountDetail.tsx index e3b3273..69f72ca 100644 --- a/frontend/src/pages/AccountDetail.tsx +++ b/frontend/src/pages/AccountDetail.tsx @@ -72,23 +72,12 @@ const AccountDetail: React.FC = () => { setEditLoading(true) try { - // 构建更新请求,空字符串转换为 undefined(不修改) + // 构建更新请求,只支持编辑账户名称 const updateData: any = { accountId: account.id, accountName: values.accountName || undefined, } - // 只有非空字符串才更新 API 凭证 - if (values.apiKey && values.apiKey.trim()) { - updateData.apiKey = values.apiKey.trim() - } - if (values.apiSecret && values.apiSecret.trim()) { - updateData.apiSecret = values.apiSecret.trim() - } - if (values.apiPassphrase && values.apiPassphrase.trim()) { - updateData.apiPassphrase = values.apiPassphrase.trim() - } - await updateAccount(updateData) message.success(t('account.updateSuccess')) @@ -335,42 +324,18 @@ const AccountDetail: React.FC = () => { size={isMobile ? 'middle' : 'large'} > - - - - - - - - - - - - - + diff --git a/frontend/src/pages/AccountList.tsx b/frontend/src/pages/AccountList.tsx index 2e08c6a..c7b9bbd 100644 --- a/frontend/src/pages/AccountList.tsx +++ b/frontend/src/pages/AccountList.tsx @@ -171,23 +171,12 @@ const AccountList: React.FC = () => { setEditLoading(true) try { - // 构建更新请求,空字符串转换为 undefined(不修改) + // 构建更新请求,只支持编辑账户名称 const updateData: any = { accountId: editAccount.id, accountName: values.accountName || undefined } - // 只有非空字符串才更新 API 凭证 - if (values.apiKey && values.apiKey.trim()) { - updateData.apiKey = values.apiKey.trim() - } - if (values.apiSecret && values.apiSecret.trim()) { - updateData.apiSecret = values.apiSecret.trim() - } - if (values.apiPassphrase && values.apiPassphrase.trim()) { - updateData.apiPassphrase = values.apiPassphrase.trim() - } - await updateAccount(updateData) message.success(t('accountList.updateSuccess')) @@ -778,42 +767,18 @@ const AccountList: React.FC = () => { size={isMobile ? 'middle' : 'large'} > - - - - - - - - - - - - - + diff --git a/frontend/src/pages/CopyTradingList.tsx b/frontend/src/pages/CopyTradingList.tsx index a36917a..458aab7 100644 --- a/frontend/src/pages/CopyTradingList.tsx +++ b/frontend/src/pages/CopyTradingList.tsx @@ -265,15 +265,6 @@ const CopyTradingList: React.FC = () => { fixed: 'right' as const, render: (_: any, record: CopyTrading) => { const menuItems: MenuProps['items'] = [ - { - key: 'edit', - label: t('common.edit') || '编辑', - icon: , - onClick: () => navigate(`/copy-trading/edit/${record.id}`) - }, - { - type: 'divider' - }, { key: 'buyOrders', label: t('copyTradingList.buyOrders') || '买入订单', diff --git a/polymarket-demo/icon-512x512.png b/polymarket-demo/icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..32ddf7dab5caddfbb6db6d6f7356ebdb1b52b203 GIT binary patch literal 9978 zcmeHti8s{$_y5aKrev!uDTFqAMI{=vnUH;#EwU3TVJ2oIR6>c-Vhvd{lF4qABwG|B zWNbsmGK^&mW9Ivu_viCF=leV7_Xm7_=X{QHUNiG_pU>yL_j&Jq-ut+(N2bO|{+$v# zAqe8vzjDbOf?(h)41#Y5A1k4~8{lKRt0D3d#OC~E)#pElpo5V9rSq1dY4d-=0@EJZ zO)oi1Q!e@tdf&Cz_%XztCt7z&#k8J~*|DSW(2bLP+2%q?MyFr9M!Nf^zA+d2n1$VY zw$|t{&d%ar#sZv9xM&GB?|sd>igJhUfgF+qKxR=XvLXG z{@H5y(?z#9m7;HGt%F0L8n)Jk0?@r71qu-4^0iyL=izYw z-@*SXmkZQ!Q0QEmfwhR3ca2tJom zl5la&1XVLDtMN^J2(PvZQ7@e3sTz-69P_Nzb-B!pDqUQLP50zq7 zrC6$4u=O$XnpH5_YbGK|$E_%^kXm59Ok?P`h&M6a?T{buJYbD2t7!QGqozZtpZd>_u$)awIo(G|$~KlPM{tHpA^@E={)ab4}6Qz<+&Ui`tH;>?r_2Iwwk?xQSpmwx4Z_Y zMByP0ago}W$DoaE20U%gP0q-$ z+@L%V^*92|SMrr;pbiYG(!X}Rq*PL?525k4^i%q5My6BP1B|=-r>iDD@~0+7bK!b# zC=_Wc8}`GR4J5gC>|UIKyWPth7nUCdbs9OEo_HN})3h-f4(XbsLlVcEHhU3OhCnm3 z+8rOJtbf54itnz z9?>}`nvqnCu5S&&N2yl0cKa9AC5*zL&ZA$$oT~L1+%lIpV?_23z8e@_2o}>)xS?iX z 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 0.4" } }, + "node_modules/canvas": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.2.0.tgz", + "integrity": "sha512-jk0GxrLtUEmW/TmFsk2WghvgHe8B0pxGilqCL21y8lHkPUGa6FTsnCNtHPOzT8O3y+N+m3espawV80bbBlgfTA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": "^18.12.0 || >= 20.9.0" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1006,6 +1082,30 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1014,6 +1114,15 @@ "node": ">=0.4.0" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -1050,6 +1159,15 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1162,6 +1280,15 @@ "npm": ">=3" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -1196,6 +1323,12 @@ "node": ">= 6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1239,6 +1372,12 @@ "node": ">= 0.4" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -1305,11 +1444,37 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/is-hex-prefixed": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", @@ -1362,6 +1527,18 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -1372,16 +1549,215 @@ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true + }, + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -1394,6 +1770,43 @@ "npm": ">=3" } }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -1442,6 +1855,18 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -1470,12 +1895,24 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", diff --git a/polymarket-demo/package.json b/polymarket-demo/package.json index b064a0a..37a6114 100644 --- a/polymarket-demo/package.json +++ b/polymarket-demo/package.json @@ -6,7 +6,8 @@ "scripts": { "test": "ts-node src/createOrder.ts", "build": "tsc", - "start": "node dist/createOrder.js" + "start": "node dist/createOrder.js", + "generate-icon": "node scripts/generate-icon.js" }, "keywords": [ "polymarket", @@ -21,8 +22,8 @@ }, "devDependencies": { "@types/node": "^18.7.18", + "canvas": "^3.2.0", "ts-node": "^10.9.1", "typescript": "^4.8.3" } } - diff --git a/polymarket-demo/scripts/generate-icon.js b/polymarket-demo/scripts/generate-icon.js new file mode 100644 index 0000000..17fc66b --- /dev/null +++ b/polymarket-demo/scripts/generate-icon.js @@ -0,0 +1,107 @@ +const { createCanvas } = require('canvas'); +const fs = require('fs'); +const path = require('path'); + +// 创建 512x512 的画布 +const canvas = createCanvas(512, 512); +const ctx = canvas.getContext('2d'); + +// 设置背景色(标题背景色 #001529) +ctx.fillStyle = '#001529'; +ctx.fillRect(0, 0, 512, 512); + +// 设置图标颜色(深色背景使用较亮的颜色) +const gradientColors = { + start: '#69c0ff', + end: '#b37feb' +}; + +// 创建渐变 +const gradient = ctx.createLinearGradient(0, 0, 512, 512); +gradient.addColorStop(0, gradientColors.start); +gradient.addColorStop(1, gradientColors.end); + +// 计算缩放比例(原始 viewBox 是 64x64,需要缩放到 512x512) +const scale = 512 / 64; +const centerX = 256; +const centerY = 256; + +// 保存当前状态 +ctx.save(); + +// 移动到中心并缩放 +ctx.translate(centerX, centerY); +ctx.scale(scale, scale); +ctx.translate(-32, -32); // 偏移到原点 + +// 绘制左侧箭头(指向中心) +ctx.beginPath(); +ctx.moveTo(16, 32); +ctx.lineTo(8, 24); +ctx.lineTo(8, 40); +ctx.closePath(); +ctx.fillStyle = gradient; +ctx.fill(); + +// 绘制中心连接线 +ctx.beginPath(); +ctx.moveTo(20, 32); +ctx.lineTo(44, 32); +ctx.strokeStyle = gradient; +ctx.lineWidth = 3 / scale; // 调整线宽 +ctx.lineCap = 'round'; +ctx.stroke(); + +// 绘制右侧箭头(指向中心) +ctx.beginPath(); +ctx.moveTo(48, 32); +ctx.lineTo(56, 24); +ctx.lineTo(56, 40); +ctx.closePath(); +ctx.fillStyle = gradient; +ctx.fill(); + +// 绘制中心圆点 +ctx.beginPath(); +ctx.arc(32, 32, 5, 0, Math.PI * 2); +ctx.fillStyle = gradient; +ctx.fill(); + +// 绘制装饰性数据流弧线(上方) +ctx.beginPath(); +ctx.moveTo(20, 20); +ctx.quadraticCurveTo(32, 14, 44, 20); +ctx.strokeStyle = gradient; +ctx.lineWidth = 2 / scale; +ctx.globalAlpha = 0.5; +ctx.lineCap = 'round'; +ctx.stroke(); + +// 绘制装饰性数据流弧线(下方) +ctx.beginPath(); +ctx.moveTo(20, 44); +ctx.quadraticCurveTo(32, 50, 44, 44); +ctx.strokeStyle = gradient; +ctx.lineWidth = 2 / scale; +ctx.globalAlpha = 0.5; +ctx.lineCap = 'round'; +ctx.stroke(); + +// 恢复状态 +ctx.restore(); + +// 保存为 PNG(输出到当前目录) +const outputPath = path.join(__dirname, '../icon-512x512.png'); +// 确保输出目录存在 +const outputDir = path.dirname(outputPath); +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +const buffer = canvas.toBuffer('image/png'); +fs.writeFileSync(outputPath, buffer); + +console.log(`✅ 图标已生成: ${outputPath}`); +console.log(` 尺寸: 512x512 像素`); +console.log(` 背景色: #001529`); +