@polymarbot/shared 0.5.4 → 0.6.1

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.
@@ -0,0 +1,73 @@
1
+ // src/utils/wallet.ts
2
+ import { createPublicClient, http, formatUnits, parseAbi } from "viem";
3
+ import { polygon } from "viem/chains";
4
+ var USDC_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
5
+ var USDC_DECIMALS = 6;
6
+ var USDC_ABI = parseAbi(["function balanceOf(address) view returns (uint256)"]);
7
+ var getPublicClient = /* @__PURE__ */ (() => {
8
+ let client = null;
9
+ let batchClient = null;
10
+ return (options) => {
11
+ const rpcUrl = process.env.POLYGON_RPC || polygon.rpcUrls.default.http[0];
12
+ if (options?.batch) {
13
+ if (!batchClient) {
14
+ batchClient = createPublicClient({
15
+ chain: polygon,
16
+ transport: http(rpcUrl, { batch: { batchSize: 100, wait: 0 } })
17
+ });
18
+ }
19
+ return batchClient;
20
+ }
21
+ if (!client) {
22
+ client = createPublicClient({
23
+ chain: polygon,
24
+ transport: http(rpcUrl)
25
+ });
26
+ }
27
+ return client;
28
+ };
29
+ })();
30
+ function formatBalance(rawBalance, decimals = USDC_DECIMALS) {
31
+ const num = parseFloat(formatUnits(BigInt(rawBalance), decimals));
32
+ return (Math.floor(num * 100) / 100).toFixed(2);
33
+ }
34
+ async function getUSDCBalance(address) {
35
+ const publicClient = getPublicClient();
36
+ return await publicClient.readContract({
37
+ address: USDC_ADDRESS,
38
+ abi: USDC_ABI,
39
+ functionName: "balanceOf",
40
+ args: [address]
41
+ });
42
+ }
43
+ async function getUSDCBalancesBatch(addresses) {
44
+ if (addresses.length === 0) {
45
+ return [];
46
+ }
47
+ const publicClient = getPublicClient();
48
+ return await publicClient.multicall({
49
+ contracts: addresses.map((address) => ({
50
+ address: USDC_ADDRESS,
51
+ abi: USDC_ABI,
52
+ functionName: "balanceOf",
53
+ args: [address]
54
+ })),
55
+ allowFailure: true
56
+ });
57
+ }
58
+ function isAddressEqual(a, b) {
59
+ if (!a) return false;
60
+ if (!b) return false;
61
+ return a.toLowerCase() === b.toLowerCase();
62
+ }
63
+
64
+ export {
65
+ USDC_ADDRESS,
66
+ USDC_DECIMALS,
67
+ USDC_ABI,
68
+ getPublicClient,
69
+ formatBalance,
70
+ getUSDCBalance,
71
+ getUSDCBalancesBatch,
72
+ isAddressEqual
73
+ };
package/index.cjs CHANGED
@@ -7,6 +7,7 @@ module.exports = {
7
7
  ...require('./markets/types.cjs'),
8
8
  ...require('./markets/utils.cjs'),
9
9
  ...require('./relayer-client.cjs'),
10
+ ...require('./safe-executor.cjs'),
10
11
  ...require('./trade-strategy/normalize.cjs'),
11
12
  ...require('./trade-strategy/types.cjs'),
12
13
  ...require('./wallet.cjs')
package/index.d.cts CHANGED
@@ -6,6 +6,7 @@ export * from './load-env.js'
6
6
  export * from './markets/types.js'
7
7
  export * from './markets/utils.js'
8
8
  export * from './relayer-client.js'
9
+ export * from './safe-executor.js'
9
10
  export * from './trade-strategy/normalize.js'
10
11
  export * from './trade-strategy/types.js'
11
12
  export * from './wallet.js'
package/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export * from './load-env.js'
6
6
  export * from './markets/types.js'
7
7
  export * from './markets/utils.js'
8
8
  export * from './relayer-client.js'
9
+ export * from './safe-executor.js'
9
10
  export * from './trade-strategy/normalize.js'
10
11
  export * from './trade-strategy/types.js'
11
12
  export * from './wallet.js'
package/index.js CHANGED
@@ -6,6 +6,7 @@ export * from './load-env.js'
6
6
  export * from './markets/types.js'
7
7
  export * from './markets/utils.js'
8
8
  export * from './relayer-client.js'
9
+ export * from './safe-executor.js'
9
10
  export * from './trade-strategy/normalize.js'
10
11
  export * from './trade-strategy/types.js'
11
12
  export * from './wallet.js'
package/markets/utils.cjs CHANGED
@@ -679,7 +679,12 @@ function generate1dSlug(timestamp, symbol) {
679
679
  const date = new Date(timestamp * 1e3);
680
680
  const month = MONTH_NAMES[date.getUTCMonth()];
681
681
  const day = date.getUTCDate();
682
- return `${prefix}-up-or-down-on-${month}-${day}`;
682
+ const YEAR_SLUG_CUTOFF = 1773532800;
683
+ if (timestamp < YEAR_SLUG_CUTOFF) {
684
+ return `${prefix}-up-or-down-on-${month}-${day}`;
685
+ }
686
+ const year = date.getUTCFullYear();
687
+ return `${prefix}-up-or-down-on-${month}-${day}-${year}`;
683
688
  }
684
689
  function calculatePeriodStartInET(intervalSeconds) {
685
690
  const now = Math.floor(Date.now() / 1e3);
@@ -724,7 +729,7 @@ function parseIntervalFromSlug(slug) {
724
729
  if (lowerSlug.match(/-up-or-down-\w+-\d+-\d+(am|pm)-et$/)) {
725
730
  return "1h" /* H1 */;
726
731
  }
727
- if (lowerSlug.match(/-up-or-down-on-\w+-\d+$/)) {
732
+ if (lowerSlug.match(/-up-or-down-on-\w+-\d+(-\d{4})?$/)) {
728
733
  return "1d" /* D1 */;
729
734
  }
730
735
  return null;
@@ -778,12 +783,12 @@ function parseTimeRangeFromSlug(slug, referenceYear) {
778
783
  }
779
784
  }
780
785
  } else if (interval === "1d" /* D1 */) {
781
- const match = lowerSlug.match(/-up-or-down-on-(\w+)-(\d+)$/);
786
+ const match = lowerSlug.match(/-up-or-down-on-(\w+)-(\d+)(?:-(\d{4}))?$/);
782
787
  if (match) {
783
- const [, monthName, day] = match;
788
+ const [, monthName, day, slugYear] = match;
784
789
  const monthIndex = MONTH_NAMES.indexOf(monthName);
785
790
  if (monthIndex !== -1) {
786
- const year = referenceYear ?? (/* @__PURE__ */ new Date()).getFullYear();
791
+ const year = slugYear ? parseInt(slugYear, 10) : referenceYear ?? (/* @__PURE__ */ new Date()).getFullYear();
787
792
  const utcTime = dayjs_default.utc(
788
793
  `${year}-${String(monthIndex + 1).padStart(2, "0")}-${String(day).padStart(2, "0")} 00:00:00`
789
794
  );
package/markets/utils.js CHANGED
@@ -626,7 +626,12 @@ function generate1dSlug(timestamp, symbol) {
626
626
  const date = new Date(timestamp * 1e3);
627
627
  const month = MONTH_NAMES[date.getUTCMonth()];
628
628
  const day = date.getUTCDate();
629
- return `${prefix}-up-or-down-on-${month}-${day}`;
629
+ const YEAR_SLUG_CUTOFF = 1773532800;
630
+ if (timestamp < YEAR_SLUG_CUTOFF) {
631
+ return `${prefix}-up-or-down-on-${month}-${day}`;
632
+ }
633
+ const year = date.getUTCFullYear();
634
+ return `${prefix}-up-or-down-on-${month}-${day}-${year}`;
630
635
  }
631
636
  function calculatePeriodStartInET(intervalSeconds) {
632
637
  const now = Math.floor(Date.now() / 1e3);
@@ -671,7 +676,7 @@ function parseIntervalFromSlug(slug) {
671
676
  if (lowerSlug.match(/-up-or-down-\w+-\d+-\d+(am|pm)-et$/)) {
672
677
  return "1h" /* H1 */;
673
678
  }
674
- if (lowerSlug.match(/-up-or-down-on-\w+-\d+$/)) {
679
+ if (lowerSlug.match(/-up-or-down-on-\w+-\d+(-\d{4})?$/)) {
675
680
  return "1d" /* D1 */;
676
681
  }
677
682
  return null;
@@ -725,12 +730,12 @@ function parseTimeRangeFromSlug(slug, referenceYear) {
725
730
  }
726
731
  }
727
732
  } else if (interval === "1d" /* D1 */) {
728
- const match = lowerSlug.match(/-up-or-down-on-(\w+)-(\d+)$/);
733
+ const match = lowerSlug.match(/-up-or-down-on-(\w+)-(\d+)(?:-(\d{4}))?$/);
729
734
  if (match) {
730
- const [, monthName, day] = match;
735
+ const [, monthName, day, slugYear] = match;
731
736
  const monthIndex = MONTH_NAMES.indexOf(monthName);
732
737
  if (monthIndex !== -1) {
733
- const year = referenceYear ?? (/* @__PURE__ */ new Date()).getFullYear();
738
+ const year = slugYear ? parseInt(slugYear, 10) : referenceYear ?? (/* @__PURE__ */ new Date()).getFullYear();
734
739
  const utcTime = dayjs_default.utc(
735
740
  `${year}-${String(monthIndex + 1).padStart(2, "0")}-${String(day).padStart(2, "0")} 00:00:00`
736
741
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polymarbot/shared",
3
- "version": "0.5.4",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
@@ -96,6 +96,16 @@
96
96
  "default": "./relayer-client.cjs"
97
97
  }
98
98
  },
99
+ "./safe-executor": {
100
+ "import": {
101
+ "types": "./safe-executor.d.ts",
102
+ "default": "./safe-executor.js"
103
+ },
104
+ "require": {
105
+ "types": "./safe-executor.d.cts",
106
+ "default": "./safe-executor.cjs"
107
+ }
108
+ },
99
109
  "./trade-strategy/normalize": {
100
110
  "import": {
101
111
  "types": "./trade-strategy/normalize.d.ts",
@@ -134,9 +144,10 @@
134
144
  "**/*.d.cts"
135
145
  ],
136
146
  "dependencies": {
137
- "dotenv": "^17.3.1",
138
147
  "viem": "^2.46.2",
148
+ "dotenv": "^17.3.1",
139
149
  "@polymarket/builder-relayer-client": "^0.0.8",
140
- "@polymarket/builder-signing-sdk": "^0.0.8"
150
+ "@polymarket/builder-signing-sdk": "^0.0.8",
151
+ "p-limit": "^7.3.0"
141
152
  }
142
153
  }
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/utils/safe-executor.ts
31
+ var safe_executor_exports = {};
32
+ __export(safe_executor_exports, {
33
+ execSafeTransaction: () => execSafeTransaction
34
+ });
35
+ module.exports = __toCommonJS(safe_executor_exports);
36
+ var import_viem2 = require("viem");
37
+ var import_accounts = require("viem/accounts");
38
+ var import_chains2 = require("viem/chains");
39
+ var import_builder_relayer_client = require("@polymarket/builder-relayer-client");
40
+
41
+ // src/utils/wallet.ts
42
+ var import_viem = require("viem");
43
+ var import_chains = require("viem/chains");
44
+ var USDC_ABI = (0, import_viem.parseAbi)(["function balanceOf(address) view returns (uint256)"]);
45
+ var getPublicClient = /* @__PURE__ */ (() => {
46
+ let client = null;
47
+ let batchClient = null;
48
+ return (options) => {
49
+ const rpcUrl = process.env.POLYGON_RPC || import_chains.polygon.rpcUrls.default.http[0];
50
+ if (options?.batch) {
51
+ if (!batchClient) {
52
+ batchClient = (0, import_viem.createPublicClient)({
53
+ chain: import_chains.polygon,
54
+ transport: (0, import_viem.http)(rpcUrl, { batch: { batchSize: 100, wait: 0 } })
55
+ });
56
+ }
57
+ return batchClient;
58
+ }
59
+ if (!client) {
60
+ client = (0, import_viem.createPublicClient)({
61
+ chain: import_chains.polygon,
62
+ transport: (0, import_viem.http)(rpcUrl)
63
+ });
64
+ }
65
+ return client;
66
+ };
67
+ })();
68
+
69
+ // src/utils/safe-executor.ts
70
+ var import_p_limit = __toESM(require("p-limit"), 1);
71
+ var SAFE_MULTISEND = "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761";
72
+ var SAFE_ABI = (0, import_viem2.parseAbi)([
73
+ "function execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) payable returns (bool success)",
74
+ "function nonce() view returns (uint256)"
75
+ ]);
76
+ var SAFE_TX_TYPES = {
77
+ SafeTx: [
78
+ { name: "to", type: "address" },
79
+ { name: "value", type: "uint256" },
80
+ { name: "data", type: "bytes" },
81
+ { name: "operation", type: "uint8" },
82
+ { name: "safeTxGas", type: "uint256" },
83
+ { name: "baseGas", type: "uint256" },
84
+ { name: "gasPrice", type: "uint256" },
85
+ { name: "gasToken", type: "address" },
86
+ { name: "refundReceiver", type: "address" },
87
+ { name: "nonce", type: "uint256" }
88
+ ]
89
+ };
90
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
91
+ var gasPayerLimit = (0, import_p_limit.default)(1);
92
+ function aggregateTransaction(txns) {
93
+ if (txns.length === 0) {
94
+ throw new Error("No transactions to aggregate");
95
+ }
96
+ if (txns.length === 1) {
97
+ return txns[0];
98
+ }
99
+ return (0, import_builder_relayer_client.createSafeMultisendTransaction)(txns, SAFE_MULTISEND);
100
+ }
101
+ function createSafeTxHash(chainId, safeAddress, tx, nonce) {
102
+ return (0, import_viem2.hashTypedData)({
103
+ domain: {
104
+ chainId,
105
+ verifyingContract: safeAddress
106
+ },
107
+ types: SAFE_TX_TYPES,
108
+ primaryType: "SafeTx",
109
+ message: {
110
+ to: tx.to,
111
+ value: BigInt(tx.value),
112
+ data: tx.data,
113
+ operation: tx.operation,
114
+ safeTxGas: 0n,
115
+ baseGas: 0n,
116
+ gasPrice: 0n,
117
+ gasToken: ZERO_ADDRESS,
118
+ refundReceiver: ZERO_ADDRESS,
119
+ nonce
120
+ }
121
+ });
122
+ }
123
+ async function signSafeTransaction(ownerPrivateKey, structHash) {
124
+ const account = (0, import_accounts.privateKeyToAccount)(ownerPrivateKey);
125
+ const signature = await account.signMessage({
126
+ message: { raw: (0, import_viem2.toBytes)(structHash) }
127
+ });
128
+ const r = signature.slice(0, 66);
129
+ const s = "0x" + signature.slice(66, 130);
130
+ const v = parseInt(signature.slice(130, 132), 16);
131
+ const adjustedV = v + 4;
132
+ return (0, import_viem2.encodePacked)(
133
+ ["bytes32", "bytes32", "uint8"],
134
+ [r, s, adjustedV]
135
+ );
136
+ }
137
+ async function execSafeTransaction(params) {
138
+ const {
139
+ safeAddress,
140
+ ownerPrivateKey,
141
+ gasPayerPrivateKey,
142
+ transactions,
143
+ chainId = import_chains2.polygon.id
144
+ } = params;
145
+ const aggregatedTx = aggregateTransaction(transactions);
146
+ const publicClient = getPublicClient();
147
+ const safeNonce = await publicClient.readContract({
148
+ address: safeAddress,
149
+ abi: SAFE_ABI,
150
+ functionName: "nonce"
151
+ });
152
+ const safeTxHash = createSafeTxHash(chainId, safeAddress, aggregatedTx, safeNonce);
153
+ const signature = await signSafeTransaction(ownerPrivateKey, safeTxHash);
154
+ const txHash = await gasPayerLimit(async () => {
155
+ const rpcUrl = process.env.POLYGON_RPC || import_chains2.polygon.rpcUrls.default.http[0];
156
+ const gasPayerAccount = (0, import_accounts.privateKeyToAccount)(gasPayerPrivateKey);
157
+ const gasPayerWallet = (0, import_viem2.createWalletClient)({
158
+ account: gasPayerAccount,
159
+ chain: import_chains2.polygon,
160
+ transport: (0, import_viem2.http)(rpcUrl)
161
+ });
162
+ const hash = await gasPayerWallet.writeContract({
163
+ address: safeAddress,
164
+ abi: SAFE_ABI,
165
+ functionName: "execTransaction",
166
+ args: [
167
+ aggregatedTx.to,
168
+ BigInt(aggregatedTx.value),
169
+ aggregatedTx.data,
170
+ aggregatedTx.operation,
171
+ 0n,
172
+ // safeTxGas
173
+ 0n,
174
+ // baseGas
175
+ 0n,
176
+ // gasPrice
177
+ ZERO_ADDRESS,
178
+ // gasToken
179
+ ZERO_ADDRESS,
180
+ // refundReceiver
181
+ signature
182
+ ]
183
+ });
184
+ return hash;
185
+ });
186
+ return txHash;
187
+ }
188
+ // Annotate the CommonJS export names for ESM import in node:
189
+ 0 && (module.exports = {
190
+ execSafeTransaction
191
+ });
@@ -0,0 +1,19 @@
1
+ import { Address, Hex, Hash } from 'viem';
2
+ import { SafeTransaction } from '@polymarket/builder-relayer-client';
3
+
4
+ interface ExecSafeTransactionParams {
5
+
6
+ safeAddress: Address;
7
+
8
+ ownerPrivateKey: Hex;
9
+
10
+ gasPayerPrivateKey: Hex;
11
+
12
+ transactions: SafeTransaction[];
13
+
14
+ chainId?: number;
15
+ }
16
+
17
+ declare function execSafeTransaction(params: ExecSafeTransactionParams): Promise<Hash>;
18
+
19
+ export { type ExecSafeTransactionParams, execSafeTransaction };
@@ -0,0 +1,19 @@
1
+ import { Address, Hex, Hash } from 'viem';
2
+ import { SafeTransaction } from '@polymarket/builder-relayer-client';
3
+
4
+ interface ExecSafeTransactionParams {
5
+
6
+ safeAddress: Address;
7
+
8
+ ownerPrivateKey: Hex;
9
+
10
+ gasPayerPrivateKey: Hex;
11
+
12
+ transactions: SafeTransaction[];
13
+
14
+ chainId?: number;
15
+ }
16
+
17
+ declare function execSafeTransaction(params: ExecSafeTransactionParams): Promise<Hash>;
18
+
19
+ export { type ExecSafeTransactionParams, execSafeTransaction };
@@ -0,0 +1,138 @@
1
+ import {
2
+ getPublicClient
3
+ } from "./chunk-LHBGF66E.js";
4
+ import "./chunk-JSBRDJBE.js";
5
+
6
+ // src/utils/safe-executor.ts
7
+ import {
8
+ createWalletClient,
9
+ encodePacked,
10
+ hashTypedData,
11
+ http,
12
+ parseAbi,
13
+ toBytes
14
+ } from "viem";
15
+ import { privateKeyToAccount } from "viem/accounts";
16
+ import { polygon } from "viem/chains";
17
+ import { createSafeMultisendTransaction } from "@polymarket/builder-relayer-client";
18
+ import pLimit from "p-limit";
19
+ var SAFE_MULTISEND = "0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761";
20
+ var SAFE_ABI = parseAbi([
21
+ "function execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 baseGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) payable returns (bool success)",
22
+ "function nonce() view returns (uint256)"
23
+ ]);
24
+ var SAFE_TX_TYPES = {
25
+ SafeTx: [
26
+ { name: "to", type: "address" },
27
+ { name: "value", type: "uint256" },
28
+ { name: "data", type: "bytes" },
29
+ { name: "operation", type: "uint8" },
30
+ { name: "safeTxGas", type: "uint256" },
31
+ { name: "baseGas", type: "uint256" },
32
+ { name: "gasPrice", type: "uint256" },
33
+ { name: "gasToken", type: "address" },
34
+ { name: "refundReceiver", type: "address" },
35
+ { name: "nonce", type: "uint256" }
36
+ ]
37
+ };
38
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
39
+ var gasPayerLimit = pLimit(1);
40
+ function aggregateTransaction(txns) {
41
+ if (txns.length === 0) {
42
+ throw new Error("No transactions to aggregate");
43
+ }
44
+ if (txns.length === 1) {
45
+ return txns[0];
46
+ }
47
+ return createSafeMultisendTransaction(txns, SAFE_MULTISEND);
48
+ }
49
+ function createSafeTxHash(chainId, safeAddress, tx, nonce) {
50
+ return hashTypedData({
51
+ domain: {
52
+ chainId,
53
+ verifyingContract: safeAddress
54
+ },
55
+ types: SAFE_TX_TYPES,
56
+ primaryType: "SafeTx",
57
+ message: {
58
+ to: tx.to,
59
+ value: BigInt(tx.value),
60
+ data: tx.data,
61
+ operation: tx.operation,
62
+ safeTxGas: 0n,
63
+ baseGas: 0n,
64
+ gasPrice: 0n,
65
+ gasToken: ZERO_ADDRESS,
66
+ refundReceiver: ZERO_ADDRESS,
67
+ nonce
68
+ }
69
+ });
70
+ }
71
+ async function signSafeTransaction(ownerPrivateKey, structHash) {
72
+ const account = privateKeyToAccount(ownerPrivateKey);
73
+ const signature = await account.signMessage({
74
+ message: { raw: toBytes(structHash) }
75
+ });
76
+ const r = signature.slice(0, 66);
77
+ const s = "0x" + signature.slice(66, 130);
78
+ const v = parseInt(signature.slice(130, 132), 16);
79
+ const adjustedV = v + 4;
80
+ return encodePacked(
81
+ ["bytes32", "bytes32", "uint8"],
82
+ [r, s, adjustedV]
83
+ );
84
+ }
85
+ async function execSafeTransaction(params) {
86
+ const {
87
+ safeAddress,
88
+ ownerPrivateKey,
89
+ gasPayerPrivateKey,
90
+ transactions,
91
+ chainId = polygon.id
92
+ } = params;
93
+ const aggregatedTx = aggregateTransaction(transactions);
94
+ const publicClient = getPublicClient();
95
+ const safeNonce = await publicClient.readContract({
96
+ address: safeAddress,
97
+ abi: SAFE_ABI,
98
+ functionName: "nonce"
99
+ });
100
+ const safeTxHash = createSafeTxHash(chainId, safeAddress, aggregatedTx, safeNonce);
101
+ const signature = await signSafeTransaction(ownerPrivateKey, safeTxHash);
102
+ const txHash = await gasPayerLimit(async () => {
103
+ const rpcUrl = process.env.POLYGON_RPC || polygon.rpcUrls.default.http[0];
104
+ const gasPayerAccount = privateKeyToAccount(gasPayerPrivateKey);
105
+ const gasPayerWallet = createWalletClient({
106
+ account: gasPayerAccount,
107
+ chain: polygon,
108
+ transport: http(rpcUrl)
109
+ });
110
+ const hash = await gasPayerWallet.writeContract({
111
+ address: safeAddress,
112
+ abi: SAFE_ABI,
113
+ functionName: "execTransaction",
114
+ args: [
115
+ aggregatedTx.to,
116
+ BigInt(aggregatedTx.value),
117
+ aggregatedTx.data,
118
+ aggregatedTx.operation,
119
+ 0n,
120
+ // safeTxGas
121
+ 0n,
122
+ // baseGas
123
+ 0n,
124
+ // gasPrice
125
+ ZERO_ADDRESS,
126
+ // gasToken
127
+ ZERO_ADDRESS,
128
+ // refundReceiver
129
+ signature
130
+ ]
131
+ });
132
+ return hash;
133
+ });
134
+ return txHash;
135
+ }
136
+ export {
137
+ execSafeTransaction
138
+ };
@@ -80,6 +80,7 @@ interface TokenTradeStepOrder {
80
80
  size: number;
81
81
  status: string;
82
82
  updatedAt: number;
83
+ expiresAt?: number;
83
84
  keep?: boolean;
84
85
  }
85
86
 
@@ -80,6 +80,7 @@ interface TokenTradeStepOrder {
80
80
  size: number;
81
81
  status: string;
82
82
  updatedAt: number;
83
+ expiresAt?: number;
83
84
  keep?: boolean;
84
85
  }
85
86
 
package/wallet.js CHANGED
@@ -1,67 +1,14 @@
1
+ import {
2
+ USDC_ABI,
3
+ USDC_ADDRESS,
4
+ USDC_DECIMALS,
5
+ formatBalance,
6
+ getPublicClient,
7
+ getUSDCBalance,
8
+ getUSDCBalancesBatch,
9
+ isAddressEqual
10
+ } from "./chunk-LHBGF66E.js";
1
11
  import "./chunk-JSBRDJBE.js";
2
-
3
- // src/utils/wallet.ts
4
- import { createPublicClient, http, formatUnits, parseAbi } from "viem";
5
- import { polygon } from "viem/chains";
6
- var USDC_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
7
- var USDC_DECIMALS = 6;
8
- var USDC_ABI = parseAbi(["function balanceOf(address) view returns (uint256)"]);
9
- var getPublicClient = /* @__PURE__ */ (() => {
10
- let client = null;
11
- let batchClient = null;
12
- return (options) => {
13
- const rpcUrl = process.env.POLYGON_RPC || polygon.rpcUrls.default.http[0];
14
- if (options?.batch) {
15
- if (!batchClient) {
16
- batchClient = createPublicClient({
17
- chain: polygon,
18
- transport: http(rpcUrl, { batch: { batchSize: 100, wait: 0 } })
19
- });
20
- }
21
- return batchClient;
22
- }
23
- if (!client) {
24
- client = createPublicClient({
25
- chain: polygon,
26
- transport: http(rpcUrl)
27
- });
28
- }
29
- return client;
30
- };
31
- })();
32
- function formatBalance(rawBalance, decimals = USDC_DECIMALS) {
33
- const num = parseFloat(formatUnits(BigInt(rawBalance), decimals));
34
- return (Math.floor(num * 100) / 100).toFixed(2);
35
- }
36
- async function getUSDCBalance(address) {
37
- const publicClient = getPublicClient();
38
- return await publicClient.readContract({
39
- address: USDC_ADDRESS,
40
- abi: USDC_ABI,
41
- functionName: "balanceOf",
42
- args: [address]
43
- });
44
- }
45
- async function getUSDCBalancesBatch(addresses) {
46
- if (addresses.length === 0) {
47
- return [];
48
- }
49
- const publicClient = getPublicClient();
50
- return await publicClient.multicall({
51
- contracts: addresses.map((address) => ({
52
- address: USDC_ADDRESS,
53
- abi: USDC_ABI,
54
- functionName: "balanceOf",
55
- args: [address]
56
- })),
57
- allowFailure: true
58
- });
59
- }
60
- function isAddressEqual(a, b) {
61
- if (!a) return false;
62
- if (!b) return false;
63
- return a.toLowerCase() === b.toLowerCase();
64
- }
65
12
  export {
66
13
  USDC_ABI,
67
14
  USDC_ADDRESS,