balance.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import 'dotenv/config';
  2. import axios from "axios";
  3. import { HttpsProxyAgent } from "https-proxy-agent";
  4. import { AssetType, Chain, ClobClient, SignatureTypeV2 } from "@polymarket/clob-client-v2";
  5. import { deriveProxyWallet, RelayClient } from "@polymarket/builder-relayer-client";
  6. import { BuilderConfig } from "@polymarket/builder-signing-sdk";
  7. import {
  8. createPublicClient,
  9. createWalletClient,
  10. erc20Abi,
  11. formatUnits,
  12. http,
  13. } from "viem";
  14. import { privateKeyToAccount } from "viem/accounts";
  15. import { polygon } from "viem/chains";
  16. const CHAIN_ID = 137;
  17. const HOST = "https://clob.polymarket.com";
  18. const PUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
  19. const PUSD_DECIMALS = 6;
  20. const PROXY_FACTORY_ADDRESS = "0xaB45c5A4B0c941a2F231C04C3f49182e1A254052";
  21. const NODE_HTTP_PROXY = process.env.NODE_HTTP_PROXY;
  22. const proxyAgent = NODE_HTTP_PROXY ? new HttpsProxyAgent(NODE_HTTP_PROXY) : undefined;
  23. if (NODE_HTTP_PROXY) {
  24. axios.defaults.proxy = false;
  25. axios.defaults.httpAgent = proxyAgent;
  26. axios.defaults.httpsAgent = proxyAgent;
  27. }
  28. const getRequiredEnv = (key) => {
  29. const value = process.env[key];
  30. if (!value) {
  31. throw new Error(`${key} is required`);
  32. }
  33. return value;
  34. }
  35. const getOptionalEnv = (key) => {
  36. const value = process.env[key];
  37. return value && value.trim() ? value.trim() : undefined;
  38. }
  39. const normalizePrivateKey = (privateKey) => {
  40. return privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
  41. }
  42. const getArgValue = (name) => {
  43. const prefix = `${name}=`;
  44. const arg = process.argv.slice(2).find(item => item.startsWith(prefix));
  45. return arg ? arg.slice(prefix.length) : undefined;
  46. }
  47. const normalizeWalletMode = (wallet) => {
  48. const value = (wallet || "both").toLowerCase();
  49. if (!["deposit", "proxy", "both"].includes(value)) {
  50. throw new Error("wallet must be deposit, proxy, or both");
  51. }
  52. return value;
  53. }
  54. const makeClobClient = ({ signer, creds, funderAddress, signatureType }) => {
  55. return new ClobClient({
  56. host: HOST,
  57. chain: Chain.POLYGON,
  58. signer,
  59. creds,
  60. signatureType,
  61. funderAddress,
  62. throwOnError: true,
  63. });
  64. }
  65. const getChainBalance = async ({ publicClient, address }) => {
  66. const balance = await publicClient.readContract({
  67. address: PUSD_ADDRESS,
  68. abi: erc20Abi,
  69. functionName: "balanceOf",
  70. args: [address],
  71. });
  72. return formatUnits(balance, PUSD_DECIMALS);
  73. }
  74. const getClobBalanceAllowance = async ({ signer, creds, funderAddress, signatureType }) => {
  75. const client = makeClobClient({ signer, creds, funderAddress, signatureType });
  76. return client.getBalanceAllowance({ asset_type: AssetType.COLLATERAL });
  77. }
  78. const getDepositWalletAddress = async ({ account, signer, builderConfig }) => {
  79. const configuredAddress = getOptionalEnv("POLYMARKET_DEPOSIT_WALLET_ADDRESS");
  80. if (configuredAddress) {
  81. return configuredAddress;
  82. }
  83. const relayerUrl = getOptionalEnv("POLYMARKET_RELAYER_URL") || "https://relayer-v2.polymarket.com";
  84. const relayer = new RelayClient(relayerUrl, CHAIN_ID, signer, builderConfig);
  85. if (proxyAgent) {
  86. relayer.httpClient.instance.defaults.proxy = false;
  87. relayer.httpClient.instance.defaults.httpAgent = proxyAgent;
  88. relayer.httpClient.instance.defaults.httpsAgent = proxyAgent;
  89. }
  90. return relayer.deriveDepositWalletAddress();
  91. }
  92. const walletMode = normalizeWalletMode(getArgValue("--wallet") || process.env.BALANCE_WALLET);
  93. const rpcUrl = getOptionalEnv("POLYGON_RPC_URL");
  94. const transport = rpcUrl ? http(rpcUrl) : http();
  95. const account = privateKeyToAccount(normalizePrivateKey(getRequiredEnv("POLYMARKET_PRIVATE_KEY")));
  96. const signer = createWalletClient({ account, chain: polygon, transport });
  97. const publicClient = createPublicClient({ chain: polygon, transport });
  98. const creds = {
  99. key: getRequiredEnv("POLYMARKET_API_KEY"),
  100. secret: getRequiredEnv("POLYMARKET_API_SECRET"),
  101. passphrase: getRequiredEnv("POLYMARKET_API_PASSPHRASE"),
  102. };
  103. const builderConfig = new BuilderConfig({
  104. localBuilderCreds: {
  105. key: getRequiredEnv("POLYMARKET_BUILDER_API_KEY"),
  106. secret: getRequiredEnv("POLYMARKET_BUILDER_SECRET"),
  107. passphrase: getRequiredEnv("POLYMARKET_BUILDER_PASS_PHRASE"),
  108. },
  109. });
  110. const wallets = [];
  111. if (walletMode === "proxy" || walletMode === "both") {
  112. wallets.push({
  113. type: "proxy",
  114. address: getOptionalEnv("POLYMARKET_PROXY_WALLET_ADDRESS")
  115. || deriveProxyWallet(account.address, PROXY_FACTORY_ADDRESS),
  116. signatureType: SignatureTypeV2.POLY_PROXY,
  117. });
  118. }
  119. if (walletMode === "deposit" || walletMode === "both") {
  120. wallets.push({
  121. type: "deposit",
  122. address: await getDepositWalletAddress({ account, signer, builderConfig }),
  123. signatureType: SignatureTypeV2.POLY_1271,
  124. });
  125. }
  126. const results = [];
  127. for (const wallet of wallets) {
  128. const [chainPusdBalance, clobBalanceAllowance] = await Promise.all([
  129. getChainBalance({ publicClient, address: wallet.address }),
  130. getClobBalanceAllowance({
  131. signer,
  132. creds,
  133. funderAddress: wallet.address,
  134. signatureType: wallet.signatureType,
  135. }),
  136. ]);
  137. results.push({
  138. type: wallet.type,
  139. owner: account.address,
  140. address: wallet.address,
  141. signatureType: SignatureTypeV2[wallet.signatureType],
  142. chainPusdBalance,
  143. clobBalanceAllowance,
  144. });
  145. }
  146. console.log(JSON.stringify(results, null, 2));