polycopy 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +67 -96
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -843,7 +843,6 @@ class ClobClientWrapper {
|
|
|
843
843
|
}
|
|
844
844
|
const CTF_ADDRESS = viem.getAddress("0x4d97dcd97ec945f40cf65f87097ace5ea0476045");
|
|
845
845
|
const USDC_ADDRESS = viem.getAddress("0x2791bca1f2de4661ed88a30c99a7a9449aa84174");
|
|
846
|
-
const SUBMIT_ERROR_SYMBOL = "__SUBMIT_ERROR__";
|
|
847
846
|
class RelayClient extends EventEmitter__default.default {
|
|
848
847
|
lastPostTime;
|
|
849
848
|
resetsTime;
|
|
@@ -855,7 +854,6 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
855
854
|
this.options = {
|
|
856
855
|
batchSize: options.batchSize || 10,
|
|
857
856
|
postInterval: options.postInterval || 7.5 * 60 * 1e3,
|
|
858
|
-
maxRetry: 3,
|
|
859
857
|
...options
|
|
860
858
|
};
|
|
861
859
|
}
|
|
@@ -877,7 +875,7 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
877
875
|
merge: []
|
|
878
876
|
};
|
|
879
877
|
for (const { type, conditionId, execCount, transaction } of transactions) {
|
|
880
|
-
postEvent[type].push({ conditionId, execCount
|
|
878
|
+
postEvent[type].push({ conditionId, execCount });
|
|
881
879
|
postTransactions.push(transaction);
|
|
882
880
|
}
|
|
883
881
|
return {
|
|
@@ -888,11 +886,9 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
888
886
|
};
|
|
889
887
|
}
|
|
890
888
|
logPostedEvent(type, postedEvent) {
|
|
891
|
-
const
|
|
892
|
-
if (
|
|
893
|
-
logger.info(
|
|
894
|
-
` - ${type}: [success: ${success.length} failed: ${failed.length} nextRetry: ${failed.filter(({ done }) => !done).length}]`
|
|
895
|
-
);
|
|
889
|
+
const count = postedEvent[type].length;
|
|
890
|
+
if (count > 0) {
|
|
891
|
+
logger.info(` - ${type}: ${count}`);
|
|
896
892
|
}
|
|
897
893
|
}
|
|
898
894
|
exec() {
|
|
@@ -915,11 +911,7 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
915
911
|
return;
|
|
916
912
|
}
|
|
917
913
|
const { total, transactions, postTransactions, postEvent } = postData;
|
|
918
|
-
logger.info(
|
|
919
|
-
"RelayClient",
|
|
920
|
-
"post transactions:",
|
|
921
|
-
`${transactions.length}/${total}`
|
|
922
|
-
);
|
|
914
|
+
logger.info("RelayClient", "post:", `${transactions.length}/${total}`);
|
|
923
915
|
logger.info(` - pending: ${this.pendingTransactions.length}`);
|
|
924
916
|
this.emit("post", postEvent);
|
|
925
917
|
const onPosted = (txHash, error) => {
|
|
@@ -927,44 +919,23 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
927
919
|
const postedEvent = {
|
|
928
920
|
txHash,
|
|
929
921
|
error,
|
|
930
|
-
redeem:
|
|
931
|
-
|
|
932
|
-
failed: []
|
|
933
|
-
},
|
|
934
|
-
merge: {
|
|
935
|
-
success: [],
|
|
936
|
-
failed: []
|
|
937
|
-
}
|
|
922
|
+
redeem: [],
|
|
923
|
+
merge: []
|
|
938
924
|
};
|
|
939
925
|
const resolveTx = txHash ? (pt) => {
|
|
940
926
|
pt.resolve(txHash);
|
|
941
|
-
const success = postedEvent[pt.type].success;
|
|
942
|
-
success.push({
|
|
943
|
-
conditionId: pt.conditionId,
|
|
944
|
-
execCount: pt.execCount,
|
|
945
|
-
done: true
|
|
946
|
-
});
|
|
947
927
|
} : (pt) => {
|
|
948
|
-
|
|
949
|
-
if (pt.execCount >= this.options.maxRetry) {
|
|
950
|
-
pt.reject(error);
|
|
951
|
-
done = true;
|
|
952
|
-
} else {
|
|
953
|
-
this.pendingTransactions.push(pt);
|
|
954
|
-
done = false;
|
|
955
|
-
}
|
|
956
|
-
const failed = postedEvent[pt.type].failed;
|
|
957
|
-
failed.push({
|
|
958
|
-
conditionId: pt.conditionId,
|
|
959
|
-
execCount: pt.execCount,
|
|
960
|
-
done
|
|
961
|
-
});
|
|
928
|
+
this.pendingTransactions.push(pt);
|
|
962
929
|
};
|
|
963
930
|
for (const pt of transactions) {
|
|
964
931
|
pt.execCount++;
|
|
932
|
+
postedEvent[pt.type].push({
|
|
933
|
+
conditionId: pt.conditionId,
|
|
934
|
+
execCount: pt.execCount
|
|
935
|
+
});
|
|
965
936
|
resolveTx(pt);
|
|
966
937
|
}
|
|
967
|
-
logger.info("RelayClient", "
|
|
938
|
+
logger.info("RelayClient", "posted:", txHash || error);
|
|
968
939
|
this.logPostedEvent("redeem", postedEvent);
|
|
969
940
|
this.logPostedEvent("merge", postedEvent);
|
|
970
941
|
logger.info(` - pending: ${this.pendingTransactions.length}`);
|
|
@@ -1066,13 +1037,12 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
1066
1037
|
};
|
|
1067
1038
|
}
|
|
1068
1039
|
addTransaction(type, conditionId, transaction) {
|
|
1069
|
-
return new Promise((resolve
|
|
1040
|
+
return new Promise((resolve) => {
|
|
1070
1041
|
this.pendingTransactions.push({
|
|
1071
1042
|
type,
|
|
1072
1043
|
conditionId,
|
|
1073
1044
|
transaction,
|
|
1074
1045
|
execCount: 0,
|
|
1075
|
-
reject,
|
|
1076
1046
|
resolve
|
|
1077
1047
|
});
|
|
1078
1048
|
this.exec();
|
|
@@ -1091,6 +1061,7 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
1091
1061
|
logger.info(` - pending: ${this.pendingTransactions.length}`);
|
|
1092
1062
|
if (this.pendingTransactions.length === 0 && this.postTimeout) {
|
|
1093
1063
|
clearTimeout(this.postTimeout);
|
|
1064
|
+
this.postTimeout = null;
|
|
1094
1065
|
logger.info("检测到提交队列已清空,终止定时任务");
|
|
1095
1066
|
}
|
|
1096
1067
|
}
|
|
@@ -1098,17 +1069,13 @@ class RelayClient extends EventEmitter__default.default {
|
|
|
1098
1069
|
checkSubmit(conditionId) {
|
|
1099
1070
|
if (this.resetsTime) {
|
|
1100
1071
|
throw Error(
|
|
1101
|
-
`request limit before: ${new Date(this.resetsTime).toLocaleString()}
|
|
1102
|
-
{ cause: SUBMIT_ERROR_SYMBOL }
|
|
1072
|
+
`request limit before: ${new Date(this.resetsTime).toLocaleString()}`
|
|
1103
1073
|
);
|
|
1104
1074
|
}
|
|
1105
1075
|
if (this.pendingTransactions.some((pt) => pt.conditionId === conditionId)) {
|
|
1106
|
-
throw Error("duplicate conditionId"
|
|
1076
|
+
throw Error("duplicate conditionId");
|
|
1107
1077
|
}
|
|
1108
1078
|
}
|
|
1109
|
-
isSubmitError(error) {
|
|
1110
|
-
return error?.cause === SUBMIT_ERROR_SYMBOL;
|
|
1111
|
-
}
|
|
1112
1079
|
async submitRedeem(conditionId) {
|
|
1113
1080
|
this.checkSubmit(conditionId);
|
|
1114
1081
|
return this.addTransaction(
|
|
@@ -1296,7 +1263,7 @@ function listenEvent(e, eventName, callback) {
|
|
|
1296
1263
|
}
|
|
1297
1264
|
const DATA_API_HOST = "https://data-api.polymarket.com";
|
|
1298
1265
|
const AUTO_REDEEM_INTERVAL = 60 * 1e3;
|
|
1299
|
-
const TIMEOUT =
|
|
1266
|
+
const TIMEOUT = 30 * 60 * 1e3;
|
|
1300
1267
|
class Redeemer extends EventEmitter__default.default {
|
|
1301
1268
|
options;
|
|
1302
1269
|
running = false;
|
|
@@ -1313,32 +1280,14 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1313
1280
|
const unListenPosted = listenEvent(
|
|
1314
1281
|
relayClient,
|
|
1315
1282
|
"posted",
|
|
1316
|
-
({
|
|
1317
|
-
const
|
|
1318
|
-
|
|
1319
|
-
const pendingRecords = this.updateEventRecords(pendingEvents);
|
|
1320
|
-
if (pendingRecords.length > 0) {
|
|
1283
|
+
({ redeem }) => {
|
|
1284
|
+
const postedRecords = this.updatePostedRecords(redeem);
|
|
1285
|
+
if (postedRecords.length > 0) {
|
|
1321
1286
|
logger.lines(
|
|
1322
|
-
`🟡 redeem 待确认: ${
|
|
1323
|
-
...this.toMessages(
|
|
1287
|
+
`🟡 redeem 待确认: ${postedRecords.length} 个`,
|
|
1288
|
+
...this.toMessages(postedRecords)
|
|
1324
1289
|
);
|
|
1325
1290
|
}
|
|
1326
|
-
const failedRecords = this.updateEventRecords(
|
|
1327
|
-
redeem.failed.filter(({ done }) => done)
|
|
1328
|
-
);
|
|
1329
|
-
if (failedRecords.length > 0) {
|
|
1330
|
-
const messages = [
|
|
1331
|
-
`🔴 redeem 失败(重试超限): ${failedRecords.length} 个`,
|
|
1332
|
-
...this.toMessages(failedRecords)
|
|
1333
|
-
];
|
|
1334
|
-
logger.lines(...messages);
|
|
1335
|
-
telegramService.info(messages.join("\n"));
|
|
1336
|
-
}
|
|
1337
|
-
if (txHash) {
|
|
1338
|
-
logger.success("redeem 提交结果:", txHash);
|
|
1339
|
-
} else {
|
|
1340
|
-
logger.warning("redeem 提交结果:", error);
|
|
1341
|
-
}
|
|
1342
1291
|
}
|
|
1343
1292
|
);
|
|
1344
1293
|
const unListenRequestLimit = listenEvent(
|
|
@@ -1362,12 +1311,12 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1362
1311
|
unListenResets();
|
|
1363
1312
|
};
|
|
1364
1313
|
}
|
|
1365
|
-
|
|
1314
|
+
updatePostedRecords(events) {
|
|
1366
1315
|
const records = [];
|
|
1367
|
-
for (const { conditionId
|
|
1316
|
+
for (const { conditionId } of events) {
|
|
1368
1317
|
const record = this.getRecord(conditionId);
|
|
1369
1318
|
if (record) {
|
|
1370
|
-
record.execCount
|
|
1319
|
+
record.execCount++;
|
|
1371
1320
|
records.push(record);
|
|
1372
1321
|
}
|
|
1373
1322
|
}
|
|
@@ -1418,9 +1367,26 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1418
1367
|
}
|
|
1419
1368
|
toMessages(eventRecords) {
|
|
1420
1369
|
return eventRecords.map(
|
|
1421
|
-
({ position, execCount,
|
|
1370
|
+
({ position, execCount, createTime }) => ` - ${position.slug} ${position.outcome}: ${position.currentValue} USDC (执行次数: ${execCount} 确认时长: ${(Date.now() - createTime) / 1e3}s)`
|
|
1422
1371
|
);
|
|
1423
1372
|
}
|
|
1373
|
+
submitRedeem(record) {
|
|
1374
|
+
const conditionId = record.position.conditionId;
|
|
1375
|
+
this.options.relayClient.submitRedeem(conditionId).then(() => {
|
|
1376
|
+
record.postSuccess = true;
|
|
1377
|
+
}).catch((error) => {
|
|
1378
|
+
logger.error(
|
|
1379
|
+
"redeem 提交失败:",
|
|
1380
|
+
record.position.slug,
|
|
1381
|
+
record.position.outcome,
|
|
1382
|
+
error
|
|
1383
|
+
);
|
|
1384
|
+
telegramService.error(
|
|
1385
|
+
"redeem 提交失败",
|
|
1386
|
+
[record.position.slug, record.position.outcome].join(" ")
|
|
1387
|
+
);
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1424
1390
|
async autoRedeem() {
|
|
1425
1391
|
let redeemablePositions;
|
|
1426
1392
|
try {
|
|
@@ -1438,17 +1404,12 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1438
1404
|
record = {
|
|
1439
1405
|
position,
|
|
1440
1406
|
execCount: 0,
|
|
1407
|
+
createTime: Date.now(),
|
|
1408
|
+
postSuccess: false,
|
|
1441
1409
|
timeout: false
|
|
1442
1410
|
};
|
|
1443
1411
|
this.records.set(conditionId, record);
|
|
1444
|
-
|
|
1445
|
-
record.postSuccessTime = Date.now();
|
|
1446
|
-
}).catch((error) => {
|
|
1447
|
-
if (relayClient.isSubmitError(error)) {
|
|
1448
|
-
logger.error("Redeem 提交失败:", conditionId, error);
|
|
1449
|
-
telegramService.error(`Redeem 提交失败: ${conditionId}`);
|
|
1450
|
-
}
|
|
1451
|
-
});
|
|
1412
|
+
this.submitRedeem(record);
|
|
1452
1413
|
}
|
|
1453
1414
|
record.position = position;
|
|
1454
1415
|
}
|
|
@@ -1457,9 +1418,18 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1457
1418
|
const timeoutRecords = [];
|
|
1458
1419
|
for (const [conditionId, record] of this.records.entries()) {
|
|
1459
1420
|
if (redeemablePositions.some((p) => p.conditionId === conditionId)) {
|
|
1460
|
-
if (!record.timeout &&
|
|
1421
|
+
if (!record.timeout && now - record.createTime >= TIMEOUT) {
|
|
1461
1422
|
record.timeout = true;
|
|
1462
1423
|
timeoutRecords.push(record);
|
|
1424
|
+
if (record.postSuccess) {
|
|
1425
|
+
logger.info(
|
|
1426
|
+
"重新提交超时 redeem:",
|
|
1427
|
+
record.position.slug,
|
|
1428
|
+
record.position.outcome
|
|
1429
|
+
);
|
|
1430
|
+
record.postSuccess = false;
|
|
1431
|
+
this.submitRedeem(record);
|
|
1432
|
+
}
|
|
1463
1433
|
}
|
|
1464
1434
|
} else {
|
|
1465
1435
|
relayClient.removeTransaction(conditionId);
|
|
@@ -1467,24 +1437,25 @@ class Redeemer extends EventEmitter__default.default {
|
|
|
1467
1437
|
this.records.delete(conditionId);
|
|
1468
1438
|
}
|
|
1469
1439
|
}
|
|
1440
|
+
const messages = [];
|
|
1441
|
+
const curSize = this.records.size;
|
|
1470
1442
|
if (timeoutRecords.length > 0) {
|
|
1471
|
-
|
|
1443
|
+
messages.push(
|
|
1472
1444
|
`🔴 redeem 超时: ${timeoutRecords.length} 个`,
|
|
1473
1445
|
...this.toMessages(timeoutRecords)
|
|
1474
|
-
|
|
1475
|
-
logger.lines(...messages);
|
|
1476
|
-
telegramService.info(messages.join("\n"));
|
|
1446
|
+
);
|
|
1477
1447
|
}
|
|
1478
1448
|
if (successRecords.length > 0) {
|
|
1479
|
-
|
|
1449
|
+
messages.push(
|
|
1480
1450
|
`🟢 redeem 成功: ${successRecords.length} 个`,
|
|
1481
1451
|
...this.toMessages(successRecords)
|
|
1482
|
-
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
if (messages.length > 0) {
|
|
1455
|
+
messages.push(`待确认总数: ${curSize} 个`);
|
|
1483
1456
|
logger.lines(...messages);
|
|
1484
1457
|
telegramService.info(messages.join("\n"));
|
|
1485
|
-
}
|
|
1486
|
-
const curSize = this.records.size;
|
|
1487
|
-
if (curSize !== preSize) {
|
|
1458
|
+
} else if (curSize !== preSize) {
|
|
1488
1459
|
logger.info(`redeem 待确认总数: ${curSize} 个`);
|
|
1489
1460
|
}
|
|
1490
1461
|
if (successRecords.length > 0) this.emit("redeemed");
|