Explorar o código

Merge pull request #14 from Al366io/master

Update wallet configuration and dependencies
Filip Dunđer hai 1 ano
pai
achega
fe71335cef
Modificáronse 7 ficheiros con 91 adicións e 25 borrados
  1. 4 0
      .env.copy
  2. 1 4
      README.md
  3. 22 13
      buy.ts
  4. 49 7
      package-lock.json
  5. 2 0
      package.json
  6. 13 0
      utils/utils.ts
  7. 0 1
      wallet.json

+ 4 - 0
.env.copy

@@ -0,0 +1,4 @@
+PRIVATE_KEY=
+RPC_ENDPOINT=
+RPC_WEBSOCKET_ENDPOINT=
+```

+ 1 - 4
README.md

@@ -12,9 +12,6 @@ In order to run the script you need to:
 - Transfer some SOL to it.
 - Convert some SOL to USDC.
   - We need USDC because the script is buying USDC pairs.
-- Export wallet private key and paste it into: `wallet.json`
-- Modify the buy.ts file and enter your RPC endpoint
-  - Find line where it says: `ENTER RPC ENDPOINT HERE` and `ENTER RPC WEBSOCKET ENDPOINT HERE`
-    and replace it with your endpoint
+- Set your PRIVATE_KEY, RPC_ENDPOINT and RPC_WEBSOCKET_ENDPOINT in the .env file (remove the .copy from the file name when done)
 - Install dependencies by typing: `npm install`
 - Run the script by typing: `npm run buy` in terminal

+ 22 - 13
buy.ts

@@ -14,7 +14,6 @@ import {
   TransactionMessage,
   VersionedTransaction,
 } from '@solana/web3.js';
-import secret from './wallet.json';
 import {
   getAllAccountsV4,
   getTokenAccounts,
@@ -22,10 +21,11 @@ import {
   RAYDIUM_LIQUIDITY_PROGRAM_ID_V4,
   OPENBOOK_PROGRAM_ID,
 } from './liquidity';
-import { retry } from './utils';
+import { retry, retrieveEnvVariable } from './utils';
 import { USDC_AMOUNT, USDC_TOKEN_ID } from './common';
 import { getAllMarketsV3 } from './market';
 import pino from 'pino';
+import bs58 from 'bs58';
 
 const transport = pino.transport({
   targets: [
@@ -50,7 +50,7 @@ export const logger = pino(
   {
     redact: ['poolKeys'],
     serializers: {
-      error: pino.stdSerializers.err
+      error: pino.stdSerializers.err,
     },
     base: undefined,
   },
@@ -58,14 +58,16 @@ export const logger = pino(
 );
 
 const network = 'mainnet-beta';
-const solanaConnection = new Connection(
-  'ENTER RPC ENDPOINT HERE',
-  {
-    wsEndpoint:
-     'ENTER RPC WEBSOCKET ENDPOINT HERE',
-  },
+const RPC_ENDPOINT = retrieveEnvVariable('RPC_ENDPOINT', logger);
+const RPC_WEBSOCKET_ENDPOINT = retrieveEnvVariable(
+  'RPC_WEBSOCKET_ENDPOINT',
+  logger,
 );
 
+const solanaConnection = new Connection(RPC_ENDPOINT, {
+  wsEndpoint: RPC_WEBSOCKET_ENDPOINT,
+});
+
 export type MinimalTokenAccountData = {
   mint: PublicKey;
   address: PublicKey;
@@ -80,9 +82,10 @@ let existingTokenAccounts: Map<string, MinimalTokenAccountData> = new Map<
 
 let wallet: Keypair;
 let usdcTokenKey: PublicKey;
+const PRIVATE_KEY = retrieveEnvVariable('PRIVATE_KEY', logger);
 
 async function init(): Promise<void> {
-  wallet = Keypair.fromSecretKey(new Uint8Array(secret));
+  wallet = Keypair.fromSecretKey(bs58.decode(PRIVATE_KEY));
   logger.info(`Wallet Address: ${wallet.publicKey.toString()}`);
   const allLiquidityPools = await getAllAccountsV4(solanaConnection);
   existingLiquidityPools = new Set(
@@ -167,14 +170,20 @@ async function buy(accountId: PublicKey, accountData: any): Promise<void> {
     solanaConnection.getLatestBlockhash({ commitment: 'processed' }),
   ]);
 
+  const baseMint = poolKeys.baseMint.toString();
+  const tokenAccountOut =
+    existingTokenAccounts && existingTokenAccounts.get(baseMint)?.address;
+
+  if (!tokenAccountOut) {
+    logger.info(`No token account for ${baseMint}`);
+    return;
+  }
   const { innerTransaction, address } = Liquidity.makeSwapFixedInInstruction(
     {
       poolKeys,
       userKeys: {
         tokenAccountIn: usdcTokenKey,
-        tokenAccountOut: existingTokenAccounts.get(
-          poolKeys.baseMint.toString(),
-        )!.address,
+        tokenAccountOut: tokenAccountOut,
         owner: wallet.publicKey,
       },
       amountIn: USDC_AMOUNT * 1000000,

+ 49 - 7
package-lock.json

@@ -10,6 +10,8 @@
         "@solana/spl-token": "^0.3.11",
         "bigint-buffer": "^1.1.5",
         "bn.js": "^5.2.1",
+        "bs58": "^5.0.0",
+        "dotenv": "^16.3.2",
         "pino": "^8.17.2",
         "pino-pretty": "^10.3.1",
         "pino-std-serializers": "^6.2.2"
@@ -248,6 +250,22 @@
         "superstruct": "^0.14.2"
       }
     },
+    "node_modules/@solana/web3.js/node_modules/base-x": {
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
+      "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
+      "dependencies": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/@solana/web3.js/node_modules/bs58": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+      "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
+      "dependencies": {
+        "base-x": "^3.0.2"
+      }
+    },
     "node_modules/@tsconfig/node10": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
@@ -375,12 +393,9 @@
       }
     },
     "node_modules/base-x": {
-      "version": "3.0.9",
-      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
-      "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
-      "dependencies": {
-        "safe-buffer": "^5.0.1"
-      }
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
+      "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw=="
     },
     "node_modules/base64-js": {
       "version": "1.5.1",
@@ -456,7 +471,15 @@
         "text-encoding-utf-8": "^1.0.2"
       }
     },
-    "node_modules/bs58": {
+    "node_modules/borsh/node_modules/base-x": {
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
+      "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
+      "dependencies": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "node_modules/borsh/node_modules/bs58": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
       "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
@@ -464,6 +487,14 @@
         "base-x": "^3.0.2"
       }
     },
+    "node_modules/bs58": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
+      "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
+      "dependencies": {
+        "base-x": "^4.0.0"
+      }
+    },
     "node_modules/buffer": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
@@ -573,6 +604,17 @@
         "node": ">=0.3.1"
       }
     },
+    "node_modules/dotenv": {
+      "version": "16.3.2",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz",
+      "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/motdotla/dotenv?sponsor=1"
+      }
+    },
     "node_modules/end-of-stream": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",

+ 2 - 0
package.json

@@ -9,6 +9,8 @@
     "@solana/spl-token": "^0.3.11",
     "bigint-buffer": "^1.1.5",
     "bn.js": "^5.2.1",
+    "bs58": "^5.0.0",
+    "dotenv": "^16.3.2",
     "pino": "^8.17.2",
     "pino-pretty": "^10.3.1",
     "pino-std-serializers": "^6.2.2"

+ 13 - 0
utils/utils.ts

@@ -1,3 +1,7 @@
+import { Logger } from "pino";
+import dotenv from 'dotenv';
+dotenv.config();
+
 /**
  * Runs the function `fn`
  * and retries automatically if it fails.
@@ -23,3 +27,12 @@ export const retry = async <T>(
 };
 
 export const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));
+
+export const retrieveEnvVariable = (variableName: string, logger: Logger) => {
+    const variable = process.env[variableName] || '';
+    if (!variable) {
+      logger.error(`${variableName} is not set`);
+      process.exit(1);
+    }
+    return variable;
+}

+ 0 - 1
wallet.json

@@ -1 +0,0 @@
-[]