@rhinestone/deposit-modal 0.3.0-alpha.9 → 0.3.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.
Files changed (47) hide show
  1. package/README.md +76 -0
  2. package/dist/{DepositModalReown-I7I3KLD2.mjs → DepositModalReown-G7UX4IBZ.mjs} +6 -4
  3. package/dist/{DepositModalReown-XUA47RYZ.cjs → DepositModalReown-MECHBE6P.cjs} +9 -7
  4. package/dist/{QRCode-KG47KTGX.cjs → QRCode-5DXFNKI2.cjs} +1 -1
  5. package/dist/{QRCode-YJ3EGWQS.mjs → QRCode-WUC652SH.mjs} +1 -1
  6. package/dist/{WithdrawModalReown-KN2DGOXR.mjs → WithdrawModalReown-CUJAFUQM.mjs} +5 -4
  7. package/dist/{WithdrawModalReown-JATYMQYP.cjs → WithdrawModalReown-WJ6VBZKK.cjs} +8 -7
  8. package/dist/{constants-DqVn968d.d.ts → caip-CsslyHGL.d.cts} +11 -1
  9. package/dist/{constants-DqVn968d.d.cts → caip-CsslyHGL.d.ts} +11 -1
  10. package/dist/{chunk-TJG2AFPS.mjs → chunk-3C35DVPE.mjs} +1048 -829
  11. package/dist/{chunk-SZIYS42B.mjs → chunk-6YRDD462.mjs} +63 -3
  12. package/dist/chunk-AJHFNHG3.cjs +295 -0
  13. package/dist/chunk-BAEB5AFZ.mjs +212 -0
  14. package/dist/{chunk-KE4MRCFN.mjs → chunk-DZQD3DAV.mjs} +26 -17
  15. package/dist/{chunk-G5Q4QBWX.cjs → chunk-LEL6GMEQ.cjs} +111 -102
  16. package/dist/{chunk-7JIDIX27.cjs → chunk-MILJQWPT.cjs} +73 -13
  17. package/dist/{chunk-MMXUBBGK.cjs → chunk-MQIJZNTP.cjs} +1026 -807
  18. package/dist/{chunk-4BUMVXPS.mjs → chunk-QYSCCX4K.mjs} +2237 -871
  19. package/dist/chunk-R5CPOBCF.cjs +212 -0
  20. package/dist/{chunk-OISMGA2L.mjs → chunk-R5WDHHVM.mjs} +2 -12
  21. package/dist/{chunk-ZVG4JDKZ.cjs → chunk-SPUZLWQS.cjs} +2285 -919
  22. package/dist/chunk-TQ2AYMWS.mjs +295 -0
  23. package/dist/{chunk-KIPKYPNF.cjs → chunk-ULEAK63T.cjs} +6 -16
  24. package/dist/constants.cjs +6 -2
  25. package/dist/constants.d.cts +1 -1
  26. package/dist/constants.d.ts +1 -1
  27. package/dist/constants.mjs +5 -1
  28. package/dist/deposit.cjs +6 -4
  29. package/dist/deposit.d.cts +4 -4
  30. package/dist/deposit.d.ts +4 -4
  31. package/dist/deposit.mjs +5 -3
  32. package/dist/index.cjs +21 -6
  33. package/dist/index.d.cts +4 -3
  34. package/dist/index.d.ts +4 -3
  35. package/dist/index.mjs +22 -7
  36. package/dist/polymarket.cjs +64 -0
  37. package/dist/polymarket.d.cts +57 -0
  38. package/dist/polymarket.d.ts +57 -0
  39. package/dist/polymarket.mjs +64 -0
  40. package/dist/styles.css +719 -75
  41. package/dist/{types-D8Q4TMk7.d.cts → types-RzfAD14B.d.cts} +65 -2
  42. package/dist/{types-D8Q4TMk7.d.ts → types-RzfAD14B.d.ts} +65 -2
  43. package/dist/withdraw.cjs +5 -4
  44. package/dist/withdraw.d.cts +4 -4
  45. package/dist/withdraw.d.ts +4 -4
  46. package/dist/withdraw.mjs +4 -3
  47. package/package.json +55 -18
@@ -1,3 +1,37 @@
1
+ // src/core/caip.ts
2
+ var SOLANA_MAINNET_GENESIS = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
3
+ var SOLANA_MAINNET_CAIP2 = `solana:${SOLANA_MAINNET_GENESIS}`;
4
+ function toEvmCaip2(chainId) {
5
+ return `eip155:${chainId}`;
6
+ }
7
+ function targetChainToCaip2(targetChain) {
8
+ return targetChain === "solana" ? SOLANA_MAINNET_CAIP2 : toEvmCaip2(targetChain);
9
+ }
10
+ function parseEvmChainId(value) {
11
+ if (typeof value === "number" && Number.isFinite(value)) {
12
+ return value;
13
+ }
14
+ if (typeof value !== "string") return null;
15
+ const match = value.match(/^eip155:(\d+)$/);
16
+ if (!match?.[1]) return null;
17
+ const parsed = Number.parseInt(match[1], 10);
18
+ return Number.isFinite(parsed) ? parsed : null;
19
+ }
20
+ function isSolanaCaip2(value) {
21
+ return typeof value === "string" && value.startsWith("solana:");
22
+ }
23
+ var HYPERCORE_CHAIN_ID = 1337;
24
+ var HYPERCORE_USDC_ADDRESS = "0xb88339CB7199b77E23DB6E890353E22632Ba630f";
25
+ var HYPERCORE_MIN_DEPOSIT_USD = 1;
26
+ function isVirtualDestination(targetChain) {
27
+ return targetChain === "solana" || targetChain === HYPERCORE_CHAIN_ID;
28
+ }
29
+ function isContractBytecode(code) {
30
+ if (!code || code === "0x") return false;
31
+ if (code.toLowerCase().startsWith("0xef0100")) return false;
32
+ return true;
33
+ }
34
+
1
35
  // src/core/solana-tokens.ts
2
36
  var SOLANA_TOKENS = [
3
37
  { symbol: "SOL", mint: "native", decimals: 9 },
@@ -67,6 +101,7 @@ var SOLANA_CHAIN_ICON = SOL_BADGE_SVG;
67
101
  var SOLANA_TOKEN_ICON = SOL_BADGE_SVG;
68
102
  function getChainIcon(chainId) {
69
103
  if (chainId === "solana") return SOLANA_CHAIN_ICON;
104
+ if (chainId === HYPERCORE_CHAIN_ID) return CHAIN_ICONS[hyperliquid.id];
70
105
  return CHAIN_ICONS[chainId];
71
106
  }
72
107
  function getTokenIcon(symbol) {
@@ -303,6 +338,13 @@ var chainRegistry = {
303
338
  decimals: 6
304
339
  }
305
340
  ]
341
+ },
342
+ // HyperCore (virtual chain 1337) is a USDC-only deposit *destination*. It has
343
+ // no viem chain / RPC, so it lives only here for name + token resolution —
344
+ // deliberately absent from the source-chain matrices above.
345
+ [HYPERCORE_CHAIN_ID]: {
346
+ name: "HyperCore",
347
+ tokens: [{ symbol: "USDC", address: HYPERCORE_USDC_ADDRESS, decimals: 6 }]
306
348
  }
307
349
  };
308
350
  function getChainId(chain) {
@@ -403,7 +445,7 @@ function getSupportedTargetTokens(chainId) {
403
445
  }
404
446
  return options;
405
447
  }
406
- function getTokenDecimalsByAddress(token, chainId) {
448
+ function findTokenDecimals(token, chainId) {
407
449
  const normalized = token.toLowerCase();
408
450
  if (normalized === NATIVE_TOKEN_ADDRESS) {
409
451
  return 18;
@@ -423,7 +465,10 @@ function getTokenDecimalsByAddress(token, chainId) {
423
465
  );
424
466
  if (found) return found.decimals;
425
467
  }
426
- return 18;
468
+ return void 0;
469
+ }
470
+ function getTokenDecimalsByAddress(token, chainId) {
471
+ return findTokenDecimals(token, chainId) ?? 18;
427
472
  }
428
473
  function findChainIdForToken(address) {
429
474
  const normalized = address.toLowerCase();
@@ -479,7 +524,12 @@ var CHAIN_BADGES = {
479
524
  [sonic2.id]: { shortLabel: "Sonic", color: "#5B6DEF", bg: "#EDEFFE" },
480
525
  [gnosis2.id]: { shortLabel: "Gnosis", color: "#3E6957", bg: "#E5F0EB" },
481
526
  [hyperliquid2.id]: { shortLabel: "Hyper", color: "#5BE7C4", bg: "#E5FFF8" },
482
- [monad2.id]: { shortLabel: "Monad", color: "#6E54FF", bg: "#EEEBFF" }
527
+ [monad2.id]: { shortLabel: "Monad", color: "#6E54FF", bg: "#EEEBFF" },
528
+ [HYPERCORE_CHAIN_ID]: {
529
+ shortLabel: "HyperCore",
530
+ color: "#5BE7C4",
531
+ bg: "#E5FFF8"
532
+ }
483
533
  };
484
534
  function getChainName(chainId) {
485
535
  if (chainId === "solana") return "Solana";
@@ -517,6 +567,15 @@ function getExplorerName(chainId) {
517
567
  }
518
568
 
519
569
  export {
570
+ toEvmCaip2,
571
+ targetChainToCaip2,
572
+ parseEvmChainId,
573
+ isSolanaCaip2,
574
+ HYPERCORE_CHAIN_ID,
575
+ HYPERCORE_USDC_ADDRESS,
576
+ HYPERCORE_MIN_DEPOSIT_USD,
577
+ isVirtualDestination,
578
+ isContractBytecode,
520
579
  SOLANA_TOKENS,
521
580
  getSolanaTokenBySymbol,
522
581
  getSolanaTokenByMint,
@@ -541,6 +600,7 @@ export {
541
600
  getSupportedChainIds,
542
601
  isSupportedTokenAddressForChain,
543
602
  getSupportedTargetTokens,
603
+ findTokenDecimals,
544
604
  getTokenDecimalsByAddress,
545
605
  findChainIdForToken,
546
606
  getTokenSymbol,
@@ -0,0 +1,295 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkMILJQWPTcjs = require('./chunk-MILJQWPT.cjs');
4
+
5
+ // src/core/safe.ts
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+ var _viem = require('viem');
16
+ var SAFE_ABI = [
17
+ {
18
+ type: "function",
19
+ name: "isOwner",
20
+ stateMutability: "view",
21
+ inputs: [{ name: "owner", type: "address" }],
22
+ outputs: [{ name: "", type: "bool" }]
23
+ },
24
+ {
25
+ type: "function",
26
+ name: "nonce",
27
+ stateMutability: "view",
28
+ inputs: [],
29
+ outputs: [{ type: "uint256" }]
30
+ },
31
+ {
32
+ type: "function",
33
+ name: "execTransaction",
34
+ stateMutability: "payable",
35
+ inputs: [
36
+ { name: "to", type: "address" },
37
+ { name: "value", type: "uint256" },
38
+ { name: "data", type: "bytes" },
39
+ { name: "operation", type: "uint8" },
40
+ { name: "safeTxGas", type: "uint256" },
41
+ { name: "baseGas", type: "uint256" },
42
+ { name: "gasPrice", type: "uint256" },
43
+ { name: "gasToken", type: "address" },
44
+ { name: "refundReceiver", type: "address" },
45
+ { name: "signatures", type: "bytes" }
46
+ ],
47
+ outputs: [{ name: "success", type: "bool" }]
48
+ },
49
+ {
50
+ type: "event",
51
+ name: "ExecutionSuccess",
52
+ inputs: [
53
+ { name: "txHash", type: "bytes32", indexed: true },
54
+ { name: "payment", type: "uint256", indexed: false }
55
+ ],
56
+ anonymous: false
57
+ },
58
+ {
59
+ type: "event",
60
+ name: "ExecutionFailure",
61
+ inputs: [
62
+ { name: "txHash", type: "bytes32", indexed: true },
63
+ { name: "payment", type: "uint256", indexed: false }
64
+ ],
65
+ anonymous: false
66
+ }
67
+ ];
68
+ async function executeSafeEthTransfer(params) {
69
+ const {
70
+ walletClient,
71
+ publicClient,
72
+ safeAddress,
73
+ recipient,
74
+ amount,
75
+ chainId
76
+ } = params;
77
+ const account = walletClient.account;
78
+ const chain = walletClient.chain;
79
+ if (!account || !chain) {
80
+ throw new Error("Wallet not connected");
81
+ }
82
+ if (chain.id !== chainId) {
83
+ throw new Error(`Switch to ${_chunkMILJQWPTcjs.getChainName.call(void 0, chainId)} to sign`);
84
+ }
85
+ const isOwner = await publicClient.readContract({
86
+ address: safeAddress,
87
+ abi: SAFE_ABI,
88
+ functionName: "isOwner",
89
+ args: [account.address]
90
+ });
91
+ if (!isOwner) {
92
+ throw new Error("Connected wallet is not a Safe owner");
93
+ }
94
+ const safeTx = {
95
+ to: recipient,
96
+ value: amount,
97
+ data: "0x",
98
+ operation: 0,
99
+ safeTxGas: 0n,
100
+ baseGas: 0n,
101
+ gasPrice: 0n,
102
+ gasToken: _viem.zeroAddress,
103
+ refundReceiver: _viem.zeroAddress
104
+ };
105
+ const signature = _viem.concat.call(void 0, [
106
+ _viem.pad.call(void 0, account.address, { size: 32 }),
107
+ _viem.pad.call(void 0, _viem.toHex.call(void 0, 0), { size: 32 }),
108
+ _viem.toHex.call(void 0, 1, { size: 1 })
109
+ ]);
110
+ const txHash = await walletClient.writeContract({
111
+ account,
112
+ chain,
113
+ address: safeAddress,
114
+ abi: SAFE_ABI,
115
+ functionName: "execTransaction",
116
+ args: [
117
+ safeTx.to,
118
+ safeTx.value,
119
+ safeTx.data,
120
+ safeTx.operation,
121
+ safeTx.safeTxGas,
122
+ safeTx.baseGas,
123
+ safeTx.gasPrice,
124
+ safeTx.gasToken,
125
+ safeTx.refundReceiver,
126
+ signature
127
+ ]
128
+ });
129
+ const receipt = await publicClient.waitForTransactionReceipt({
130
+ hash: txHash
131
+ });
132
+ const safeLogs = receipt.logs.filter(
133
+ (log) => log.address.toLowerCase() === safeAddress.toLowerCase()
134
+ );
135
+ const parsed = _viem.parseEventLogs.call(void 0, {
136
+ abi: SAFE_ABI,
137
+ logs: safeLogs,
138
+ strict: false
139
+ });
140
+ const failed = parsed.find((log) => log.eventName === "ExecutionFailure");
141
+ if (failed) {
142
+ throw new Error("Safe transaction failed");
143
+ }
144
+ const succeeded = parsed.find((log) => log.eventName === "ExecutionSuccess");
145
+ if (!succeeded) {
146
+ throw new Error("Safe transaction status unavailable");
147
+ }
148
+ return { txHash };
149
+ }
150
+ async function executeSafeErc20Transfer(params) {
151
+ const {
152
+ walletClient,
153
+ publicClient,
154
+ safeAddress,
155
+ tokenAddress,
156
+ recipient,
157
+ amount,
158
+ chainId
159
+ } = params;
160
+ const account = walletClient.account;
161
+ const chain = walletClient.chain;
162
+ if (!account || !chain) {
163
+ throw new Error("Wallet not connected");
164
+ }
165
+ if (chain.id !== chainId) {
166
+ throw new Error(`Switch to ${_chunkMILJQWPTcjs.getChainName.call(void 0, chainId)} to sign`);
167
+ }
168
+ const isOwner = await publicClient.readContract({
169
+ address: safeAddress,
170
+ abi: SAFE_ABI,
171
+ functionName: "isOwner",
172
+ args: [account.address]
173
+ });
174
+ if (!isOwner) {
175
+ throw new Error("Connected wallet is not a Safe owner");
176
+ }
177
+ const data = _viem.encodeFunctionData.call(void 0, {
178
+ abi: _viem.erc20Abi,
179
+ functionName: "transfer",
180
+ args: [recipient, amount]
181
+ });
182
+ const safeTx = {
183
+ to: tokenAddress,
184
+ value: 0n,
185
+ data,
186
+ operation: 0,
187
+ safeTxGas: 0n,
188
+ baseGas: 0n,
189
+ gasPrice: 0n,
190
+ gasToken: _viem.zeroAddress,
191
+ refundReceiver: _viem.zeroAddress
192
+ };
193
+ const signature = _viem.concat.call(void 0, [
194
+ _viem.pad.call(void 0, account.address, { size: 32 }),
195
+ _viem.pad.call(void 0, _viem.toHex.call(void 0, 0), { size: 32 }),
196
+ _viem.toHex.call(void 0, 1, { size: 1 })
197
+ ]);
198
+ const txHash = await walletClient.writeContract({
199
+ account,
200
+ chain,
201
+ address: safeAddress,
202
+ abi: SAFE_ABI,
203
+ functionName: "execTransaction",
204
+ args: [
205
+ safeTx.to,
206
+ safeTx.value,
207
+ safeTx.data,
208
+ safeTx.operation,
209
+ safeTx.safeTxGas,
210
+ safeTx.baseGas,
211
+ safeTx.gasPrice,
212
+ safeTx.gasToken,
213
+ safeTx.refundReceiver,
214
+ signature
215
+ ]
216
+ });
217
+ const receipt = await publicClient.waitForTransactionReceipt({
218
+ hash: txHash
219
+ });
220
+ const safeLogs = receipt.logs.filter(
221
+ (log) => log.address.toLowerCase() === safeAddress.toLowerCase()
222
+ );
223
+ const parsed = _viem.parseEventLogs.call(void 0, {
224
+ abi: SAFE_ABI,
225
+ logs: safeLogs,
226
+ strict: false
227
+ });
228
+ const failed = parsed.find((log) => log.eventName === "ExecutionFailure");
229
+ if (failed) {
230
+ throw new Error("Safe transaction failed");
231
+ }
232
+ const succeeded = parsed.find((log) => log.eventName === "ExecutionSuccess");
233
+ if (!succeeded) {
234
+ throw new Error("Safe transaction status unavailable");
235
+ }
236
+ return { txHash };
237
+ }
238
+ var SAFE_TX_TYPES = {
239
+ SafeTx: [
240
+ { name: "to", type: "address" },
241
+ { name: "value", type: "uint256" },
242
+ { name: "data", type: "bytes" },
243
+ { name: "operation", type: "uint8" },
244
+ { name: "safeTxGas", type: "uint256" },
245
+ { name: "baseGas", type: "uint256" },
246
+ { name: "gasPrice", type: "uint256" },
247
+ { name: "gasToken", type: "address" },
248
+ { name: "refundReceiver", type: "address" },
249
+ { name: "nonce", type: "uint256" }
250
+ ]
251
+ };
252
+ async function buildSafeTransaction(params) {
253
+ const { publicClient, safeAddress, to, value, data, chainId } = params;
254
+ const nonce = await publicClient.readContract({
255
+ address: safeAddress,
256
+ abi: SAFE_ABI,
257
+ functionName: "nonce"
258
+ });
259
+ const message = {
260
+ to,
261
+ value,
262
+ data,
263
+ operation: 0,
264
+ safeTxGas: 0n,
265
+ baseGas: 0n,
266
+ gasPrice: 0n,
267
+ gasToken: _viem.zeroAddress,
268
+ refundReceiver: _viem.zeroAddress,
269
+ nonce
270
+ };
271
+ const safeTxHash = _viem.hashTypedData.call(void 0, {
272
+ domain: { chainId, verifyingContract: safeAddress },
273
+ types: SAFE_TX_TYPES,
274
+ primaryType: "SafeTx",
275
+ message
276
+ });
277
+ return {
278
+ chainId,
279
+ safeAddress,
280
+ safeTxHash,
281
+ typedData: {
282
+ domain: { chainId, verifyingContract: safeAddress },
283
+ types: SAFE_TX_TYPES,
284
+ primaryType: "SafeTx",
285
+ message
286
+ }
287
+ };
288
+ }
289
+
290
+
291
+
292
+
293
+
294
+
295
+ exports.SAFE_ABI = SAFE_ABI; exports.executeSafeEthTransfer = executeSafeEthTransfer; exports.executeSafeErc20Transfer = executeSafeErc20Transfer; exports.buildSafeTransaction = buildSafeTransaction;
@@ -0,0 +1,212 @@
1
+ import {
2
+ SAFE_ABI
3
+ } from "./chunk-TQ2AYMWS.mjs";
4
+
5
+ // src/core/dapp-imports/polymarket/constants.ts
6
+ var POLYMARKET_POLYGON_CHAIN_ID = 137;
7
+ var POLYMARKET_PUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
8
+ var POLYMARKET_USDCE_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
9
+ var POLYMARKET_COLLATERAL_OFFRAMP_ADDRESS = "0x2957922Eb93258b93368531d39fAcCA3B4dC5854";
10
+ var SAFE_MULTI_SEND_CALL_ONLY_ADDRESS = "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D";
11
+ var GAMMA_API_PUBLIC_PROFILE = "https://gamma-api.polymarket.com/public-profile";
12
+ var POLYMARKET_ICON_URL = "data:image/svg+xml,%3Csvg width='512' height='512' viewBox='0 0 512 512' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='512' height='512' fill='%232E5CFF'/%3E%3Cpath d='M375.84 389.422C375.84 403.572 375.84 410.647 371.212 414.154C366.585 417.662 359.773 415.75 346.15 411.927L127.22 350.493C119.012 348.19 114.907 347.038 112.534 343.907C110.161 340.776 110.161 336.513 110.161 327.988V184.012C110.161 175.487 110.161 171.224 112.534 168.093C114.907 164.962 119.012 163.81 127.22 161.507L346.15 100.072C359.773 96.2495 366.585 94.338 371.212 97.8455C375.84 101.353 375.84 108.428 375.84 122.578V389.422ZM164.761 330.463L346.035 381.337V279.595L164.761 330.463ZM139.963 306.862L321.201 256L139.963 205.138V306.862ZM164.759 181.537L346.035 232.406V130.663L164.759 181.537Z' fill='white'/%3E%3C/svg%3E";
13
+
14
+ // src/core/dapp-imports/polymarket/gamma-api.ts
15
+ import { getAddress, isAddress, zeroAddress } from "viem";
16
+ async function fetchPolymarketProxyWallet(eoa, signal) {
17
+ const url = `${GAMMA_API_PUBLIC_PROFILE}?address=${eoa}`;
18
+ const response = await fetch(url, { signal });
19
+ if (response.status === 404) {
20
+ return null;
21
+ }
22
+ if (!response.ok) {
23
+ throw new Error(
24
+ `Polymarket profile request failed: ${response.status}`
25
+ );
26
+ }
27
+ let payload;
28
+ try {
29
+ payload = await response.json();
30
+ } catch {
31
+ return null;
32
+ }
33
+ const raw = payload.proxyWallet;
34
+ if (!raw || !isAddress(raw)) {
35
+ return null;
36
+ }
37
+ const checksummed = getAddress(raw);
38
+ if (checksummed === zeroAddress) {
39
+ return null;
40
+ }
41
+ return checksummed;
42
+ }
43
+
44
+ // src/core/dapp-imports/polymarket/safe.ts
45
+ import {
46
+ concat,
47
+ encodeFunctionData,
48
+ encodePacked,
49
+ erc20Abi,
50
+ pad,
51
+ parseAbi,
52
+ parseEventLogs,
53
+ toHex,
54
+ zeroAddress as zeroAddress2
55
+ } from "viem";
56
+ var COLLATERAL_OFFRAMP_ABI = parseAbi([
57
+ "function unwrap(address _asset, address _to, uint256 _amount)"
58
+ ]);
59
+ var MULTI_SEND_ABI = parseAbi(["function multiSend(bytes transactions)"]);
60
+ async function readPolymarketBalances(params) {
61
+ const { publicClient, proxyWallet } = params;
62
+ const results = await publicClient.multicall({
63
+ allowFailure: true,
64
+ contracts: [
65
+ {
66
+ address: POLYMARKET_PUSD_ADDRESS,
67
+ abi: erc20Abi,
68
+ functionName: "balanceOf",
69
+ args: [proxyWallet]
70
+ },
71
+ {
72
+ address: POLYMARKET_USDCE_ADDRESS,
73
+ abi: erc20Abi,
74
+ functionName: "balanceOf",
75
+ args: [proxyWallet]
76
+ }
77
+ ]
78
+ });
79
+ return {
80
+ pusd: results[0].status === "success" ? results[0].result : 0n,
81
+ usdce: results[1].status === "success" ? results[1].result : 0n
82
+ };
83
+ }
84
+ async function executePolymarketSafeTransfer(params) {
85
+ const {
86
+ walletClient,
87
+ publicClient,
88
+ safeAddress,
89
+ recipient,
90
+ amount,
91
+ tokenKind
92
+ } = params;
93
+ const account = walletClient.account;
94
+ const chain = walletClient.chain;
95
+ if (!account || !chain) {
96
+ throw new Error("Wallet not connected");
97
+ }
98
+ if (chain.id !== POLYMARKET_POLYGON_CHAIN_ID) {
99
+ throw new Error("Switch to Polygon to sign");
100
+ }
101
+ const isOwner = await publicClient.readContract({
102
+ address: safeAddress,
103
+ abi: SAFE_ABI,
104
+ functionName: "isOwner",
105
+ args: [account.address]
106
+ });
107
+ if (!isOwner) {
108
+ throw new Error("Connected wallet is not a Polymarket Safe owner");
109
+ }
110
+ const safeTx = tokenKind === "pusd" ? buildPusdUnwrapSafeTx(recipient, amount) : buildUsdceTransferSafeTx(recipient, amount);
111
+ const signature = concat([
112
+ pad(account.address, { size: 32 }),
113
+ pad(toHex(0), { size: 32 }),
114
+ toHex(1, { size: 1 })
115
+ ]);
116
+ const txHash = await walletClient.writeContract({
117
+ account,
118
+ chain,
119
+ address: safeAddress,
120
+ abi: SAFE_ABI,
121
+ functionName: "execTransaction",
122
+ args: [
123
+ safeTx.to,
124
+ 0n,
125
+ safeTx.data,
126
+ safeTx.operation,
127
+ 0n,
128
+ 0n,
129
+ 0n,
130
+ zeroAddress2,
131
+ zeroAddress2,
132
+ signature
133
+ ]
134
+ });
135
+ const receipt = await publicClient.waitForTransactionReceipt({
136
+ hash: txHash
137
+ });
138
+ const parsed = parseEventLogs({
139
+ abi: SAFE_ABI,
140
+ logs: receipt.logs.filter(
141
+ (log) => log.address.toLowerCase() === safeAddress.toLowerCase()
142
+ ),
143
+ strict: false
144
+ });
145
+ if (parsed.some((log) => log.eventName === "ExecutionFailure")) {
146
+ throw new Error("Polymarket Safe transaction failed");
147
+ }
148
+ if (!parsed.some((log) => log.eventName === "ExecutionSuccess")) {
149
+ throw new Error("Polymarket Safe transaction status unavailable");
150
+ }
151
+ return {
152
+ txHash,
153
+ // The smart account always receives USDC.e — pUSD is unwrapped to USDC.e
154
+ // before it lands at `recipient`.
155
+ sourceToken: POLYMARKET_USDCE_ADDRESS,
156
+ sourceSymbol: tokenKind === "pusd" ? "pUSD" : "USDC.e"
157
+ };
158
+ }
159
+ function buildUsdceTransferSafeTx(recipient, amount) {
160
+ return {
161
+ to: POLYMARKET_USDCE_ADDRESS,
162
+ data: encodeFunctionData({
163
+ abi: erc20Abi,
164
+ functionName: "transfer",
165
+ args: [recipient, amount]
166
+ }),
167
+ operation: 0
168
+ };
169
+ }
170
+ function buildPusdUnwrapSafeTx(recipient, amount) {
171
+ const approveData = encodeFunctionData({
172
+ abi: erc20Abi,
173
+ functionName: "approve",
174
+ args: [POLYMARKET_COLLATERAL_OFFRAMP_ADDRESS, amount]
175
+ });
176
+ const unwrapData = encodeFunctionData({
177
+ abi: COLLATERAL_OFFRAMP_ABI,
178
+ functionName: "unwrap",
179
+ args: [POLYMARKET_USDCE_ADDRESS, recipient, amount]
180
+ });
181
+ return {
182
+ to: SAFE_MULTI_SEND_CALL_ONLY_ADDRESS,
183
+ data: encodeFunctionData({
184
+ abi: MULTI_SEND_ABI,
185
+ functionName: "multiSend",
186
+ args: [
187
+ concat([
188
+ encodeMultiSendCall(POLYMARKET_PUSD_ADDRESS, approveData),
189
+ encodeMultiSendCall(POLYMARKET_COLLATERAL_OFFRAMP_ADDRESS, unwrapData)
190
+ ])
191
+ ]
192
+ }),
193
+ operation: 1
194
+ };
195
+ }
196
+ function encodeMultiSendCall(to, data) {
197
+ return encodePacked(
198
+ ["uint8", "address", "uint256", "uint256", "bytes"],
199
+ [0, to, 0n, BigInt((data.length - 2) / 2), data]
200
+ );
201
+ }
202
+
203
+ export {
204
+ POLYMARKET_POLYGON_CHAIN_ID,
205
+ POLYMARKET_PUSD_ADDRESS,
206
+ POLYMARKET_USDCE_ADDRESS,
207
+ POLYMARKET_COLLATERAL_OFFRAMP_ADDRESS,
208
+ POLYMARKET_ICON_URL,
209
+ fetchPolymarketProxyWallet,
210
+ readPolymarketBalances,
211
+ executePolymarketSafeTransfer
212
+ };