├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── .gitmodules ├── .npmignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── package.json ├── scripts ├── gen-block-engine-protos └── gen-geyser-protos ├── src ├── examples │ ├── geyser │ │ └── index.ts │ └── simple_bundle │ │ ├── index.ts │ │ └── utils.ts ├── gen │ ├── block-engine │ │ ├── auth.ts │ │ ├── block.ts │ │ ├── block_engine.ts │ │ ├── bundle.ts │ │ ├── google │ │ │ └── protobuf │ │ │ │ └── timestamp.ts │ │ ├── packet.ts │ │ ├── relayer.ts │ │ ├── searcher.ts │ │ ├── shared.ts │ │ └── shredstream.ts │ └── geyser │ │ ├── confirmed_block.ts │ │ ├── geyser.ts │ │ ├── google │ │ └── protobuf │ │ │ └── timestamp.ts │ │ └── transaction_by_addr.ts ├── index.ts └── sdk │ ├── block-engine │ ├── auth.ts │ ├── index.ts │ ├── searcher.ts │ ├── types.ts │ └── utils.ts │ ├── geyser │ ├── auth.ts │ ├── geyser.ts │ └── index.ts │ ├── index.ts │ └── rpc │ ├── connection.ts │ ├── errors.ts │ ├── fetch-impl.ts │ ├── index.ts │ └── utils.ts ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | src/gen 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/" 3 | } 4 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npm 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-latest 11 | environment: NPM_TOKEN 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: '20' 17 | registry-url: 'https://registry.npmjs.org' 18 | - name: Install Yarn 19 | run: npm install -g yarn 20 | - name: Install Dependencies 21 | run: yarn install --frozen-lockfile 22 | - name: Build 23 | run: yarn compile 24 | - name: Publish 25 | run: yarn publish --non-interactive 26 | env: 27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | 3 | build 4 | 5 | lib-cov 6 | *.seed 7 | *.log 8 | *.csv 9 | *.dat 10 | *.out 11 | *.pid 12 | *.gz 13 | *.swp 14 | 15 | pids 16 | logs 17 | results 18 | tmp 19 | 20 | # Build 21 | public/css/main.css 22 | 23 | # Coverage reports 24 | coverage 25 | 26 | # API keys and secrets 27 | .env 28 | 29 | # Dependency directory 30 | node_modules 31 | bower_components 32 | 33 | # Editors 34 | .idea 35 | *.iml 36 | 37 | # OS metadata 38 | .DS_Store 39 | Thumbs.db 40 | 41 | # Ignore built ts files 42 | dist/**/* 43 | 44 | # ignore yarn cache 45 | .yarn 46 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submods/mev-protos"] 2 | path = submods/mev-protos 3 | url = https://github.com/jito-labs/mev-protos.git 4 | [submodule "submods/geyser-grpc-plugin"] 5 | path = submods/geyser-grpc-plugin 6 | url = https://github.com/jito-foundation/geyser-grpc-plugin.git 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .env 2 | 3 | *.tgz 4 | 5 | #tests 6 | test 7 | coverage 8 | 9 | #build tools 10 | .travis.yml 11 | .jenkins.yml 12 | .codeclimate.yml 13 | 14 | #linters 15 | .jscsrc 16 | .jshintrc 17 | .eslintrc* 18 | 19 | #editor settings 20 | .idea 21 | .editorconfig 22 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('gts/.prettierrc.json') 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright (c) 2025 Jito Labs 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jito-ts 2 | 3 | [![Discord](https://img.shields.io/discord/938287290806042626?label=Discord&logo=discord&style=flat&color=7289DA)](https://discord.gg/jTSmEzaR) 4 | [![NPM Version](https://img.shields.io/npm/v/jito-ts)](https://www.npmjs.com/package/jito-ts) 5 | 6 | Welcome to the Jito Typescript SDK repository! Use this to interact with the block-engine, relayer and future Jito APIs. 7 | 8 | ## Setup 9 | Use with yarn `1.22`+ and Node 20. 10 | ```bash 11 | yarn 12 | ``` 13 | 14 | ### Building Protos 15 | The generated proto files have been committed for convenience, but if there's ever a change you'll need to re-generate. 16 | Steps to regenerate: 17 | * Make sure you have protoc installed on your system 18 | * If any new `.proto` files were added, update the appropriate `./scripts/gen-*-protos` script to include it. 19 | * Run the appropriate `yarn gen-* ${PATH_TO_PROTOS}` and commit! 20 | 21 | ### Geyser 22 | 23 | **Note:** Mac users may run into an error to the effect of "protoc-gen-js: program not found or is not executable"; 24 | if this is thrown, run: 25 | * `brew install protobuf@3` 26 | * `brew link --overwrite protobuf@3` 27 | * `yarn gen-block-engine ${PATH_TO_BLOCK_ENGINE_PROTOS}` 28 | * `yarn gen-geyser ${PATH_TO_GEYSER_PROTOS}` 29 | 30 | ## Usage 31 | 32 | ```bash 33 | export RPC_URL="https://MY_RPC_URL" 34 | export BLOCK_ENGINE_URL=mainnet.block-engine.jito.wtf 35 | export AUTH_KEYPAIR_PATH=MY_AUTH_KEYPAIR.json 36 | export BUNDLE_TRANSACTION_LIMIT=5 37 | 38 | yarn run:simple_bundle 39 | ``` 40 | 41 | See other commands in `package.json` 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Jito Team ", 3 | "license": "Apache-2.0", 4 | "name": "jito-ts", 5 | "version": "4.2.0", 6 | "main": "dist/index.js", 7 | "types": "dist/index.d.ts", 8 | "prepublish": "tsc", 9 | "dependencies": { 10 | "@grpc/grpc-js": "^1.8.13", 11 | "@noble/ed25519": "^1.7.1", 12 | "@solana/web3.js": "~1.77.3", 13 | "@types/bs58": "^4.0.4", 14 | "agentkeepalive": "^4.3.0", 15 | "bs58": "^6.0.0", 16 | "dotenv": "^16.0.3", 17 | "jayson": "^4.0.0", 18 | "node-fetch": "^2.6.7", 19 | "rpc-websockets": "7.10.0", 20 | "superstruct": "^1.0.3" 21 | }, 22 | "devDependencies": { 23 | "@types/google-protobuf": "^3.15.6", 24 | "@types/node": "^22.9.1", 25 | "@types/node-fetch": "^2.6", 26 | "@types/uuid": "^10.0.0", 27 | "grpc-tools": "^1.12.3", 28 | "gts": "^3.1.1", 29 | "protoc-gen-ts": "^0.8.5", 30 | "ts-proto": "~1.138.0", 31 | "ts-protoc-gen": "~0.15.0", 32 | "typescript": "^5.6.3" 33 | }, 34 | "scripts": { 35 | "gen-block-engine": "./scripts/gen-block-engine-protos submods/mev-protos", 36 | "gen-geyser": "./scripts/gen-geyser-protos submods/geyser-grpc-plugin/proto/proto", 37 | "lint": "gts lint", 38 | "clean": "gts clean", 39 | "compile": "tsc", 40 | "fix": "gts fix", 41 | "prepare": "yarn run compile", 42 | "pretest": "yarn run compile", 43 | "posttest": "yarn run lint", 44 | "run:geyser": "yarn tsc && node dist/examples/geyser/index", 45 | "run:simple_bundle": "yarn tsc && node dist/examples/simple_bundle/index" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/gen-block-engine-protos: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Path to these plugins 4 | PROTOC_GEN_TS_PATH="./node_modules/.bin/protoc-gen-ts_proto" 5 | 6 | PROTOS_PATH=$1 7 | 8 | 9 | # Directory to write generated code to 10 | OUT_DIR="./src/gen/block-engine" 11 | 12 | protoc \ 13 | --plugin=${PROTOC_GEN_TS_PATH} \ 14 | --proto_path="${PROTOS_PATH}" \ 15 | --ts_proto_out=${OUT_DIR} \ 16 | --ts_proto_opt=outputServices=grpc-js \ 17 | --ts_proto_opt=esModuleInterop=true \ 18 | auth.proto block.proto block_engine.proto bundle.proto packet.proto relayer.proto searcher.proto shared.proto shredstream.proto 19 | -------------------------------------------------------------------------------- /scripts/gen-geyser-protos: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Path to these plugins 4 | PROTOC_GEN_TS_PATH="./node_modules/.bin/protoc-gen-ts_proto" 5 | 6 | PROTOS_PATH=$1 7 | 8 | 9 | # Directory to write generated code to 10 | OUT_DIR="./src/gen/geyser" 11 | 12 | protoc \ 13 | --plugin=${PROTOC_GEN_TS_PATH} \ 14 | --proto_path="${PROTOS_PATH}" \ 15 | --ts_proto_out=${OUT_DIR} \ 16 | --ts_proto_opt=outputServices=grpc-js \ 17 | --ts_proto_opt=esModuleInterop=true \ 18 | confirmed_block.proto geyser.proto transaction_by_addr.proto 19 | -------------------------------------------------------------------------------- /src/examples/geyser/index.ts: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | import {PublicKey} from '@solana/web3.js'; 4 | 5 | import {geyserClient} from '../../sdk'; 6 | 7 | const main = async () => { 8 | const geyserUrl = process.env.GEYSER_URL || ''; 9 | const geyserAccessToken = process.env.GEYSER_ACCESS_TOKEN || ''; 10 | console.log(`GEYSER_URL: ${geyserUrl}`); 11 | 12 | const _accounts = (process.env.ACCOUNTS_OF_INTEREST || '').split(','); 13 | console.log(`ACCOUNTS_OF_INTEREST: ${_accounts}`); 14 | const accounts = _accounts.map(a => new PublicKey(a)); 15 | 16 | const _programs = (process.env.PROGRAMS_OF_INTEREST || '').split(','); 17 | console.log(`PROGRAMS_OF_INTEREST: ${_programs}`); 18 | const programs = _programs.map(p => new PublicKey(p)); 19 | 20 | const c = geyserClient(geyserUrl, geyserAccessToken); 21 | 22 | const heartbeatMs = await c.getHeartbeatIntervalMillis(); 23 | console.log(`Heartbeat Millis: ${heartbeatMs}`); 24 | 25 | c.onAccountUpdate( 26 | accounts, 27 | resp => { 28 | console.log(`received account update: ${resp.accountUpdate?.seq}`); 29 | }, 30 | e => { 31 | console.error(`received account update error: ${e}`); 32 | throw e; 33 | } 34 | ); 35 | 36 | c.onProgramUpdate( 37 | programs, 38 | resp => { 39 | console.log(`received program update: ${resp.accountUpdate?.seq}`); 40 | }, 41 | e => { 42 | console.error(`received program update error: ${e}`); 43 | throw e; 44 | } 45 | ); 46 | 47 | c.onProcessedBlock( 48 | resp => { 49 | console.log(`received processed block: ${resp.blockUpdate?.slot}`); 50 | }, 51 | e => { 52 | console.error(`block update stream error: ${e}`); 53 | throw e; 54 | } 55 | ); 56 | }; 57 | 58 | main() 59 | .then(() => console.log('running geyser example')) 60 | .catch(e => { 61 | console.error(`error: ${e}`); 62 | }); 63 | -------------------------------------------------------------------------------- /src/examples/simple_bundle/index.ts: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | import * as Fs from 'fs'; 4 | import {Keypair, Connection} from '@solana/web3.js'; 5 | 6 | import {searcherClient} from '../../sdk/block-engine/searcher'; 7 | import {onBundleResult, sendBundles} from './utils'; 8 | 9 | const main = async () => { 10 | const blockEngineUrl = process.env.BLOCK_ENGINE_URL || ''; 11 | console.log('BLOCK_ENGINE_URL:', blockEngineUrl); 12 | 13 | const authKeypairPath = process.env.AUTH_KEYPAIR_PATH || ''; 14 | console.log('AUTH_KEYPAIR_PATH:', authKeypairPath); 15 | const decodedKey = new Uint8Array( 16 | JSON.parse(Fs.readFileSync(authKeypairPath).toString()) as number[] 17 | ); 18 | const keypair = Keypair.fromSecretKey(decodedKey); 19 | 20 | const _accounts = (process.env.ACCOUNTS_OF_INTEREST || '').split(','); 21 | console.log('ACCOUNTS_OF_INTEREST:', _accounts); 22 | // const accounts = _accounts.map(a => new PublicKey(a)); 23 | 24 | const bundleTransactionLimit = parseInt( 25 | process.env.BUNDLE_TRANSACTION_LIMIT || '0' 26 | ); 27 | 28 | const c = searcherClient(blockEngineUrl, keypair); 29 | 30 | const rpcUrl = process.env.RPC_URL || ''; 31 | console.log('RPC_URL:', rpcUrl); 32 | const conn = new Connection(rpcUrl, 'confirmed'); 33 | 34 | const result = await sendBundles(c, bundleTransactionLimit, keypair, conn); 35 | if (!result.ok) { 36 | console.error('Failed to send bundles:', result.error); 37 | return; 38 | } 39 | console.log('Successfully sent bundles:', result.value); 40 | onBundleResult(c); 41 | }; 42 | 43 | main() 44 | .then(() => { 45 | console.log('Sending bundle'); 46 | }) 47 | .catch(e => { 48 | throw e; 49 | }); -------------------------------------------------------------------------------- /src/examples/simple_bundle/utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Connection, 3 | Keypair, 4 | PublicKey, 5 | TransactionInstruction, 6 | TransactionMessage, 7 | VersionedTransaction, 8 | } from '@solana/web3.js'; 9 | import bs58 from 'bs58'; 10 | 11 | import {SearcherClient, SearcherClientError} from '../../sdk/block-engine/searcher'; 12 | import {Bundle} from '../../sdk/block-engine/types'; 13 | import {isError, Result} from '../../sdk/block-engine/utils'; 14 | 15 | const MEMO_PROGRAM_ID = 'Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo'; 16 | 17 | export const sendBundles = async ( 18 | c: SearcherClient, 19 | bundleTransactionLimit: number, 20 | keypair: Keypair, 21 | conn: Connection 22 | ): Promise> => { 23 | try { 24 | const tipAccountResult = await c.getTipAccounts(); 25 | if (!tipAccountResult.ok) { 26 | return tipAccountResult; 27 | } 28 | const _tipAccount = tipAccountResult.value[0]; 29 | console.log('tip account:', _tipAccount); 30 | const tipAccount = new PublicKey(_tipAccount); 31 | 32 | const balance = await conn.getBalance(keypair.publicKey); 33 | console.log('current account has balance: ', balance); 34 | 35 | let isLeaderSlot = false; 36 | while (!isLeaderSlot) { 37 | const next_leader = await c.getNextScheduledLeader(); 38 | if (!next_leader.ok) { 39 | return next_leader; 40 | } 41 | const num_slots = next_leader.value.nextLeaderSlot - next_leader.value.currentSlot; 42 | isLeaderSlot = num_slots <= 2; 43 | console.log(`next jito leader slot in ${num_slots} slots`); 44 | await new Promise(r => setTimeout(r, 500)); 45 | } 46 | 47 | const blockHash = await conn.getLatestBlockhash(); 48 | const b = new Bundle([], bundleTransactionLimit); 49 | 50 | console.log(blockHash.blockhash); 51 | 52 | const bundles = [b]; 53 | 54 | let maybeBundle = b.addTransactions( 55 | buildMemoTransaction(keypair, 'jito test 1', blockHash.blockhash), 56 | buildMemoTransaction(keypair, 'jito test 2', blockHash.blockhash) 57 | ); 58 | if (isError(maybeBundle)) { 59 | return { 60 | ok: false, 61 | error: new SearcherClientError( 62 | 3, // INVALID_ARGUMENT 63 | 'Failed to add transactions to bundle', 64 | maybeBundle.message 65 | ) 66 | }; 67 | } 68 | 69 | maybeBundle = maybeBundle.addTipTx( 70 | keypair, 71 | 100_000, 72 | tipAccount, 73 | blockHash.blockhash 74 | ); 75 | 76 | if (isError(maybeBundle)) { 77 | return { 78 | ok: false, 79 | error: new SearcherClientError( 80 | 3, // INVALID_ARGUMENT 81 | 'Failed to add tip transaction to bundle', 82 | maybeBundle.message 83 | ) 84 | }; 85 | } 86 | 87 | type BundleResponse = Result; 88 | const results: BundleResponse[] = await Promise.all( 89 | bundles.map(async b => { 90 | try { 91 | const resp = await c.sendBundle(b); 92 | if (!resp.ok) { 93 | return resp; 94 | } 95 | console.log('resp:', resp.value); 96 | return resp; 97 | } catch (e) { 98 | console.error('error sending bundle:', e); 99 | return { 100 | ok: false, 101 | error: e as SearcherClientError 102 | }; 103 | } 104 | }) 105 | ); 106 | 107 | // Check if any bundle sends failed 108 | const error = results.find(r => !r.ok); 109 | if (error && !error.ok) { 110 | return { ok: false, error: error.error }; 111 | } 112 | 113 | // At this point we know all results are successful 114 | const successResults = results.filter((r): r is { ok: true; value: string } => r.ok); 115 | return { ok: true, value: successResults.map(r => r.value) }; 116 | 117 | } catch (e) { 118 | return { 119 | ok: false, 120 | error: e as SearcherClientError 121 | }; 122 | } 123 | }; 124 | 125 | export const onBundleResult = (c: SearcherClient) => { 126 | return c.onBundleResult( 127 | result => { 128 | console.log('received bundle result:', result); 129 | }, 130 | e => { 131 | console.error('Bundle result error:', e); 132 | throw e; 133 | } 134 | ); 135 | }; 136 | 137 | const buildMemoTransaction = ( 138 | keypair: Keypair, 139 | message: string, 140 | recentBlockhash: string 141 | ): VersionedTransaction => { 142 | const ix = new TransactionInstruction({ 143 | keys: [ 144 | { 145 | pubkey: keypair.publicKey, 146 | isSigner: true, 147 | isWritable: true, 148 | }, 149 | ], 150 | programId: new PublicKey(MEMO_PROGRAM_ID), 151 | data: Buffer.from(message), 152 | }); 153 | 154 | const instructions = [ix]; 155 | 156 | const messageV0 = new TransactionMessage({ 157 | payerKey: keypair.publicKey, 158 | recentBlockhash: recentBlockhash, 159 | instructions, 160 | }).compileToV0Message(); 161 | 162 | const tx = new VersionedTransaction(messageV0); 163 | 164 | tx.sign([keypair]); 165 | 166 | console.log('txn signature is: ', bs58.encode(tx.signatures[0])); 167 | return tx; 168 | }; -------------------------------------------------------------------------------- /src/gen/block-engine/auth.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { 3 | CallOptions, 4 | ChannelCredentials, 5 | Client, 6 | ClientOptions, 7 | ClientUnaryCall, 8 | handleUnaryCall, 9 | makeGenericClientConstructor, 10 | Metadata, 11 | ServiceError, 12 | UntypedServiceImplementation, 13 | } from "@grpc/grpc-js"; 14 | import _m0 from "protobufjs/minimal"; 15 | import { Timestamp } from "./google/protobuf/timestamp"; 16 | 17 | export const protobufPackage = "auth"; 18 | 19 | export enum Role { 20 | RELAYER = 0, 21 | SEARCHER = 1, 22 | VALIDATOR = 2, 23 | SHREDSTREAM_SUBSCRIBER = 3, 24 | UNRECOGNIZED = -1, 25 | } 26 | 27 | export function roleFromJSON(object: any): Role { 28 | switch (object) { 29 | case 0: 30 | case "RELAYER": 31 | return Role.RELAYER; 32 | case 1: 33 | case "SEARCHER": 34 | return Role.SEARCHER; 35 | case 2: 36 | case "VALIDATOR": 37 | return Role.VALIDATOR; 38 | case 3: 39 | case "SHREDSTREAM_SUBSCRIBER": 40 | return Role.SHREDSTREAM_SUBSCRIBER; 41 | case -1: 42 | case "UNRECOGNIZED": 43 | default: 44 | return Role.UNRECOGNIZED; 45 | } 46 | } 47 | 48 | export function roleToJSON(object: Role): string { 49 | switch (object) { 50 | case Role.RELAYER: 51 | return "RELAYER"; 52 | case Role.SEARCHER: 53 | return "SEARCHER"; 54 | case Role.VALIDATOR: 55 | return "VALIDATOR"; 56 | case Role.SHREDSTREAM_SUBSCRIBER: 57 | return "SHREDSTREAM_SUBSCRIBER"; 58 | case Role.UNRECOGNIZED: 59 | default: 60 | return "UNRECOGNIZED"; 61 | } 62 | } 63 | 64 | export interface GenerateAuthChallengeRequest { 65 | /** / Role the client is attempting to generate tokens for. */ 66 | role: Role; 67 | /** / Client's 32 byte pubkey. */ 68 | pubkey: Uint8Array; 69 | } 70 | 71 | export interface GenerateAuthChallengeResponse { 72 | challenge: string; 73 | } 74 | 75 | export interface GenerateAuthTokensRequest { 76 | /** / The pre-signed challenge. */ 77 | challenge: string; 78 | /** / The signing keypair's corresponding 32 byte pubkey. */ 79 | clientPubkey: Uint8Array; 80 | /** 81 | * / The 64 byte signature of the challenge signed by the client's private key. The private key must correspond to 82 | * the pubkey passed in the [GenerateAuthChallenge] method. The client is expected to sign the challenge token 83 | * prepended with their pubkey. For example sign(pubkey, challenge). 84 | */ 85 | signedChallenge: Uint8Array; 86 | } 87 | 88 | export interface Token { 89 | /** / The token. */ 90 | value: string; 91 | /** / When the token will expire. */ 92 | expiresAtUtc: Date | undefined; 93 | } 94 | 95 | export interface GenerateAuthTokensResponse { 96 | /** / The token granting access to resources. */ 97 | accessToken: 98 | | Token 99 | | undefined; 100 | /** / The token used to refresh the access_token. This has a longer TTL than the access_token. */ 101 | refreshToken: Token | undefined; 102 | } 103 | 104 | export interface RefreshAccessTokenRequest { 105 | /** / Non-expired refresh token obtained from the [GenerateAuthTokens] method. */ 106 | refreshToken: string; 107 | } 108 | 109 | export interface RefreshAccessTokenResponse { 110 | /** / Fresh access_token. */ 111 | accessToken: Token | undefined; 112 | } 113 | 114 | function createBaseGenerateAuthChallengeRequest(): GenerateAuthChallengeRequest { 115 | return { role: 0, pubkey: new Uint8Array() }; 116 | } 117 | 118 | export const GenerateAuthChallengeRequest = { 119 | encode(message: GenerateAuthChallengeRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 120 | if (message.role !== 0) { 121 | writer.uint32(8).int32(message.role); 122 | } 123 | if (message.pubkey.length !== 0) { 124 | writer.uint32(18).bytes(message.pubkey); 125 | } 126 | return writer; 127 | }, 128 | 129 | decode(input: _m0.Reader | Uint8Array, length?: number): GenerateAuthChallengeRequest { 130 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 131 | let end = length === undefined ? reader.len : reader.pos + length; 132 | const message = createBaseGenerateAuthChallengeRequest(); 133 | while (reader.pos < end) { 134 | const tag = reader.uint32(); 135 | switch (tag >>> 3) { 136 | case 1: 137 | message.role = reader.int32() as any; 138 | break; 139 | case 2: 140 | message.pubkey = reader.bytes(); 141 | break; 142 | default: 143 | reader.skipType(tag & 7); 144 | break; 145 | } 146 | } 147 | return message; 148 | }, 149 | 150 | fromJSON(object: any): GenerateAuthChallengeRequest { 151 | return { 152 | role: isSet(object.role) ? roleFromJSON(object.role) : 0, 153 | pubkey: isSet(object.pubkey) ? bytesFromBase64(object.pubkey) : new Uint8Array(), 154 | }; 155 | }, 156 | 157 | toJSON(message: GenerateAuthChallengeRequest): unknown { 158 | const obj: any = {}; 159 | message.role !== undefined && (obj.role = roleToJSON(message.role)); 160 | message.pubkey !== undefined && 161 | (obj.pubkey = base64FromBytes(message.pubkey !== undefined ? message.pubkey : new Uint8Array())); 162 | return obj; 163 | }, 164 | 165 | create, I>>(base?: I): GenerateAuthChallengeRequest { 166 | return GenerateAuthChallengeRequest.fromPartial(base ?? {}); 167 | }, 168 | 169 | fromPartial, I>>(object: I): GenerateAuthChallengeRequest { 170 | const message = createBaseGenerateAuthChallengeRequest(); 171 | message.role = object.role ?? 0; 172 | message.pubkey = object.pubkey ?? new Uint8Array(); 173 | return message; 174 | }, 175 | }; 176 | 177 | function createBaseGenerateAuthChallengeResponse(): GenerateAuthChallengeResponse { 178 | return { challenge: "" }; 179 | } 180 | 181 | export const GenerateAuthChallengeResponse = { 182 | encode(message: GenerateAuthChallengeResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 183 | if (message.challenge !== "") { 184 | writer.uint32(10).string(message.challenge); 185 | } 186 | return writer; 187 | }, 188 | 189 | decode(input: _m0.Reader | Uint8Array, length?: number): GenerateAuthChallengeResponse { 190 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 191 | let end = length === undefined ? reader.len : reader.pos + length; 192 | const message = createBaseGenerateAuthChallengeResponse(); 193 | while (reader.pos < end) { 194 | const tag = reader.uint32(); 195 | switch (tag >>> 3) { 196 | case 1: 197 | message.challenge = reader.string(); 198 | break; 199 | default: 200 | reader.skipType(tag & 7); 201 | break; 202 | } 203 | } 204 | return message; 205 | }, 206 | 207 | fromJSON(object: any): GenerateAuthChallengeResponse { 208 | return { challenge: isSet(object.challenge) ? String(object.challenge) : "" }; 209 | }, 210 | 211 | toJSON(message: GenerateAuthChallengeResponse): unknown { 212 | const obj: any = {}; 213 | message.challenge !== undefined && (obj.challenge = message.challenge); 214 | return obj; 215 | }, 216 | 217 | create, I>>(base?: I): GenerateAuthChallengeResponse { 218 | return GenerateAuthChallengeResponse.fromPartial(base ?? {}); 219 | }, 220 | 221 | fromPartial, I>>( 222 | object: I, 223 | ): GenerateAuthChallengeResponse { 224 | const message = createBaseGenerateAuthChallengeResponse(); 225 | message.challenge = object.challenge ?? ""; 226 | return message; 227 | }, 228 | }; 229 | 230 | function createBaseGenerateAuthTokensRequest(): GenerateAuthTokensRequest { 231 | return { challenge: "", clientPubkey: new Uint8Array(), signedChallenge: new Uint8Array() }; 232 | } 233 | 234 | export const GenerateAuthTokensRequest = { 235 | encode(message: GenerateAuthTokensRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 236 | if (message.challenge !== "") { 237 | writer.uint32(10).string(message.challenge); 238 | } 239 | if (message.clientPubkey.length !== 0) { 240 | writer.uint32(18).bytes(message.clientPubkey); 241 | } 242 | if (message.signedChallenge.length !== 0) { 243 | writer.uint32(26).bytes(message.signedChallenge); 244 | } 245 | return writer; 246 | }, 247 | 248 | decode(input: _m0.Reader | Uint8Array, length?: number): GenerateAuthTokensRequest { 249 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 250 | let end = length === undefined ? reader.len : reader.pos + length; 251 | const message = createBaseGenerateAuthTokensRequest(); 252 | while (reader.pos < end) { 253 | const tag = reader.uint32(); 254 | switch (tag >>> 3) { 255 | case 1: 256 | message.challenge = reader.string(); 257 | break; 258 | case 2: 259 | message.clientPubkey = reader.bytes(); 260 | break; 261 | case 3: 262 | message.signedChallenge = reader.bytes(); 263 | break; 264 | default: 265 | reader.skipType(tag & 7); 266 | break; 267 | } 268 | } 269 | return message; 270 | }, 271 | 272 | fromJSON(object: any): GenerateAuthTokensRequest { 273 | return { 274 | challenge: isSet(object.challenge) ? String(object.challenge) : "", 275 | clientPubkey: isSet(object.clientPubkey) ? bytesFromBase64(object.clientPubkey) : new Uint8Array(), 276 | signedChallenge: isSet(object.signedChallenge) ? bytesFromBase64(object.signedChallenge) : new Uint8Array(), 277 | }; 278 | }, 279 | 280 | toJSON(message: GenerateAuthTokensRequest): unknown { 281 | const obj: any = {}; 282 | message.challenge !== undefined && (obj.challenge = message.challenge); 283 | message.clientPubkey !== undefined && 284 | (obj.clientPubkey = base64FromBytes( 285 | message.clientPubkey !== undefined ? message.clientPubkey : new Uint8Array(), 286 | )); 287 | message.signedChallenge !== undefined && 288 | (obj.signedChallenge = base64FromBytes( 289 | message.signedChallenge !== undefined ? message.signedChallenge : new Uint8Array(), 290 | )); 291 | return obj; 292 | }, 293 | 294 | create, I>>(base?: I): GenerateAuthTokensRequest { 295 | return GenerateAuthTokensRequest.fromPartial(base ?? {}); 296 | }, 297 | 298 | fromPartial, I>>(object: I): GenerateAuthTokensRequest { 299 | const message = createBaseGenerateAuthTokensRequest(); 300 | message.challenge = object.challenge ?? ""; 301 | message.clientPubkey = object.clientPubkey ?? new Uint8Array(); 302 | message.signedChallenge = object.signedChallenge ?? new Uint8Array(); 303 | return message; 304 | }, 305 | }; 306 | 307 | function createBaseToken(): Token { 308 | return { value: "", expiresAtUtc: undefined }; 309 | } 310 | 311 | export const Token = { 312 | encode(message: Token, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 313 | if (message.value !== "") { 314 | writer.uint32(10).string(message.value); 315 | } 316 | if (message.expiresAtUtc !== undefined) { 317 | Timestamp.encode(toTimestamp(message.expiresAtUtc), writer.uint32(18).fork()).ldelim(); 318 | } 319 | return writer; 320 | }, 321 | 322 | decode(input: _m0.Reader | Uint8Array, length?: number): Token { 323 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 324 | let end = length === undefined ? reader.len : reader.pos + length; 325 | const message = createBaseToken(); 326 | while (reader.pos < end) { 327 | const tag = reader.uint32(); 328 | switch (tag >>> 3) { 329 | case 1: 330 | message.value = reader.string(); 331 | break; 332 | case 2: 333 | message.expiresAtUtc = fromTimestamp(Timestamp.decode(reader, reader.uint32())); 334 | break; 335 | default: 336 | reader.skipType(tag & 7); 337 | break; 338 | } 339 | } 340 | return message; 341 | }, 342 | 343 | fromJSON(object: any): Token { 344 | return { 345 | value: isSet(object.value) ? String(object.value) : "", 346 | expiresAtUtc: isSet(object.expiresAtUtc) ? fromJsonTimestamp(object.expiresAtUtc) : undefined, 347 | }; 348 | }, 349 | 350 | toJSON(message: Token): unknown { 351 | const obj: any = {}; 352 | message.value !== undefined && (obj.value = message.value); 353 | message.expiresAtUtc !== undefined && (obj.expiresAtUtc = message.expiresAtUtc.toISOString()); 354 | return obj; 355 | }, 356 | 357 | create, I>>(base?: I): Token { 358 | return Token.fromPartial(base ?? {}); 359 | }, 360 | 361 | fromPartial, I>>(object: I): Token { 362 | const message = createBaseToken(); 363 | message.value = object.value ?? ""; 364 | message.expiresAtUtc = object.expiresAtUtc ?? undefined; 365 | return message; 366 | }, 367 | }; 368 | 369 | function createBaseGenerateAuthTokensResponse(): GenerateAuthTokensResponse { 370 | return { accessToken: undefined, refreshToken: undefined }; 371 | } 372 | 373 | export const GenerateAuthTokensResponse = { 374 | encode(message: GenerateAuthTokensResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 375 | if (message.accessToken !== undefined) { 376 | Token.encode(message.accessToken, writer.uint32(10).fork()).ldelim(); 377 | } 378 | if (message.refreshToken !== undefined) { 379 | Token.encode(message.refreshToken, writer.uint32(18).fork()).ldelim(); 380 | } 381 | return writer; 382 | }, 383 | 384 | decode(input: _m0.Reader | Uint8Array, length?: number): GenerateAuthTokensResponse { 385 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 386 | let end = length === undefined ? reader.len : reader.pos + length; 387 | const message = createBaseGenerateAuthTokensResponse(); 388 | while (reader.pos < end) { 389 | const tag = reader.uint32(); 390 | switch (tag >>> 3) { 391 | case 1: 392 | message.accessToken = Token.decode(reader, reader.uint32()); 393 | break; 394 | case 2: 395 | message.refreshToken = Token.decode(reader, reader.uint32()); 396 | break; 397 | default: 398 | reader.skipType(tag & 7); 399 | break; 400 | } 401 | } 402 | return message; 403 | }, 404 | 405 | fromJSON(object: any): GenerateAuthTokensResponse { 406 | return { 407 | accessToken: isSet(object.accessToken) ? Token.fromJSON(object.accessToken) : undefined, 408 | refreshToken: isSet(object.refreshToken) ? Token.fromJSON(object.refreshToken) : undefined, 409 | }; 410 | }, 411 | 412 | toJSON(message: GenerateAuthTokensResponse): unknown { 413 | const obj: any = {}; 414 | message.accessToken !== undefined && 415 | (obj.accessToken = message.accessToken ? Token.toJSON(message.accessToken) : undefined); 416 | message.refreshToken !== undefined && 417 | (obj.refreshToken = message.refreshToken ? Token.toJSON(message.refreshToken) : undefined); 418 | return obj; 419 | }, 420 | 421 | create, I>>(base?: I): GenerateAuthTokensResponse { 422 | return GenerateAuthTokensResponse.fromPartial(base ?? {}); 423 | }, 424 | 425 | fromPartial, I>>(object: I): GenerateAuthTokensResponse { 426 | const message = createBaseGenerateAuthTokensResponse(); 427 | message.accessToken = (object.accessToken !== undefined && object.accessToken !== null) 428 | ? Token.fromPartial(object.accessToken) 429 | : undefined; 430 | message.refreshToken = (object.refreshToken !== undefined && object.refreshToken !== null) 431 | ? Token.fromPartial(object.refreshToken) 432 | : undefined; 433 | return message; 434 | }, 435 | }; 436 | 437 | function createBaseRefreshAccessTokenRequest(): RefreshAccessTokenRequest { 438 | return { refreshToken: "" }; 439 | } 440 | 441 | export const RefreshAccessTokenRequest = { 442 | encode(message: RefreshAccessTokenRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 443 | if (message.refreshToken !== "") { 444 | writer.uint32(10).string(message.refreshToken); 445 | } 446 | return writer; 447 | }, 448 | 449 | decode(input: _m0.Reader | Uint8Array, length?: number): RefreshAccessTokenRequest { 450 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 451 | let end = length === undefined ? reader.len : reader.pos + length; 452 | const message = createBaseRefreshAccessTokenRequest(); 453 | while (reader.pos < end) { 454 | const tag = reader.uint32(); 455 | switch (tag >>> 3) { 456 | case 1: 457 | message.refreshToken = reader.string(); 458 | break; 459 | default: 460 | reader.skipType(tag & 7); 461 | break; 462 | } 463 | } 464 | return message; 465 | }, 466 | 467 | fromJSON(object: any): RefreshAccessTokenRequest { 468 | return { refreshToken: isSet(object.refreshToken) ? String(object.refreshToken) : "" }; 469 | }, 470 | 471 | toJSON(message: RefreshAccessTokenRequest): unknown { 472 | const obj: any = {}; 473 | message.refreshToken !== undefined && (obj.refreshToken = message.refreshToken); 474 | return obj; 475 | }, 476 | 477 | create, I>>(base?: I): RefreshAccessTokenRequest { 478 | return RefreshAccessTokenRequest.fromPartial(base ?? {}); 479 | }, 480 | 481 | fromPartial, I>>(object: I): RefreshAccessTokenRequest { 482 | const message = createBaseRefreshAccessTokenRequest(); 483 | message.refreshToken = object.refreshToken ?? ""; 484 | return message; 485 | }, 486 | }; 487 | 488 | function createBaseRefreshAccessTokenResponse(): RefreshAccessTokenResponse { 489 | return { accessToken: undefined }; 490 | } 491 | 492 | export const RefreshAccessTokenResponse = { 493 | encode(message: RefreshAccessTokenResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 494 | if (message.accessToken !== undefined) { 495 | Token.encode(message.accessToken, writer.uint32(10).fork()).ldelim(); 496 | } 497 | return writer; 498 | }, 499 | 500 | decode(input: _m0.Reader | Uint8Array, length?: number): RefreshAccessTokenResponse { 501 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 502 | let end = length === undefined ? reader.len : reader.pos + length; 503 | const message = createBaseRefreshAccessTokenResponse(); 504 | while (reader.pos < end) { 505 | const tag = reader.uint32(); 506 | switch (tag >>> 3) { 507 | case 1: 508 | message.accessToken = Token.decode(reader, reader.uint32()); 509 | break; 510 | default: 511 | reader.skipType(tag & 7); 512 | break; 513 | } 514 | } 515 | return message; 516 | }, 517 | 518 | fromJSON(object: any): RefreshAccessTokenResponse { 519 | return { accessToken: isSet(object.accessToken) ? Token.fromJSON(object.accessToken) : undefined }; 520 | }, 521 | 522 | toJSON(message: RefreshAccessTokenResponse): unknown { 523 | const obj: any = {}; 524 | message.accessToken !== undefined && 525 | (obj.accessToken = message.accessToken ? Token.toJSON(message.accessToken) : undefined); 526 | return obj; 527 | }, 528 | 529 | create, I>>(base?: I): RefreshAccessTokenResponse { 530 | return RefreshAccessTokenResponse.fromPartial(base ?? {}); 531 | }, 532 | 533 | fromPartial, I>>(object: I): RefreshAccessTokenResponse { 534 | const message = createBaseRefreshAccessTokenResponse(); 535 | message.accessToken = (object.accessToken !== undefined && object.accessToken !== null) 536 | ? Token.fromPartial(object.accessToken) 537 | : undefined; 538 | return message; 539 | }, 540 | }; 541 | 542 | /** / This service is responsible for issuing auth tokens to clients for API access. */ 543 | export type AuthServiceService = typeof AuthServiceService; 544 | export const AuthServiceService = { 545 | /** / Returns a challenge, client is expected to sign this challenge with an appropriate keypair in order to obtain access tokens. */ 546 | generateAuthChallenge: { 547 | path: "/auth.AuthService/GenerateAuthChallenge", 548 | requestStream: false, 549 | responseStream: false, 550 | requestSerialize: (value: GenerateAuthChallengeRequest) => 551 | Buffer.from(GenerateAuthChallengeRequest.encode(value).finish()), 552 | requestDeserialize: (value: Buffer) => GenerateAuthChallengeRequest.decode(value), 553 | responseSerialize: (value: GenerateAuthChallengeResponse) => 554 | Buffer.from(GenerateAuthChallengeResponse.encode(value).finish()), 555 | responseDeserialize: (value: Buffer) => GenerateAuthChallengeResponse.decode(value), 556 | }, 557 | /** / Provides the client with the initial pair of auth tokens for API access. */ 558 | generateAuthTokens: { 559 | path: "/auth.AuthService/GenerateAuthTokens", 560 | requestStream: false, 561 | responseStream: false, 562 | requestSerialize: (value: GenerateAuthTokensRequest) => 563 | Buffer.from(GenerateAuthTokensRequest.encode(value).finish()), 564 | requestDeserialize: (value: Buffer) => GenerateAuthTokensRequest.decode(value), 565 | responseSerialize: (value: GenerateAuthTokensResponse) => 566 | Buffer.from(GenerateAuthTokensResponse.encode(value).finish()), 567 | responseDeserialize: (value: Buffer) => GenerateAuthTokensResponse.decode(value), 568 | }, 569 | /** / Call this method with a non-expired refresh token to obtain a new access token. */ 570 | refreshAccessToken: { 571 | path: "/auth.AuthService/RefreshAccessToken", 572 | requestStream: false, 573 | responseStream: false, 574 | requestSerialize: (value: RefreshAccessTokenRequest) => 575 | Buffer.from(RefreshAccessTokenRequest.encode(value).finish()), 576 | requestDeserialize: (value: Buffer) => RefreshAccessTokenRequest.decode(value), 577 | responseSerialize: (value: RefreshAccessTokenResponse) => 578 | Buffer.from(RefreshAccessTokenResponse.encode(value).finish()), 579 | responseDeserialize: (value: Buffer) => RefreshAccessTokenResponse.decode(value), 580 | }, 581 | } as const; 582 | 583 | export interface AuthServiceServer extends UntypedServiceImplementation { 584 | /** / Returns a challenge, client is expected to sign this challenge with an appropriate keypair in order to obtain access tokens. */ 585 | generateAuthChallenge: handleUnaryCall; 586 | /** / Provides the client with the initial pair of auth tokens for API access. */ 587 | generateAuthTokens: handleUnaryCall; 588 | /** / Call this method with a non-expired refresh token to obtain a new access token. */ 589 | refreshAccessToken: handleUnaryCall; 590 | } 591 | 592 | export interface AuthServiceClient extends Client { 593 | /** / Returns a challenge, client is expected to sign this challenge with an appropriate keypair in order to obtain access tokens. */ 594 | generateAuthChallenge( 595 | request: GenerateAuthChallengeRequest, 596 | callback: (error: ServiceError | null, response: GenerateAuthChallengeResponse) => void, 597 | ): ClientUnaryCall; 598 | generateAuthChallenge( 599 | request: GenerateAuthChallengeRequest, 600 | metadata: Metadata, 601 | callback: (error: ServiceError | null, response: GenerateAuthChallengeResponse) => void, 602 | ): ClientUnaryCall; 603 | generateAuthChallenge( 604 | request: GenerateAuthChallengeRequest, 605 | metadata: Metadata, 606 | options: Partial, 607 | callback: (error: ServiceError | null, response: GenerateAuthChallengeResponse) => void, 608 | ): ClientUnaryCall; 609 | /** / Provides the client with the initial pair of auth tokens for API access. */ 610 | generateAuthTokens( 611 | request: GenerateAuthTokensRequest, 612 | callback: (error: ServiceError | null, response: GenerateAuthTokensResponse) => void, 613 | ): ClientUnaryCall; 614 | generateAuthTokens( 615 | request: GenerateAuthTokensRequest, 616 | metadata: Metadata, 617 | callback: (error: ServiceError | null, response: GenerateAuthTokensResponse) => void, 618 | ): ClientUnaryCall; 619 | generateAuthTokens( 620 | request: GenerateAuthTokensRequest, 621 | metadata: Metadata, 622 | options: Partial, 623 | callback: (error: ServiceError | null, response: GenerateAuthTokensResponse) => void, 624 | ): ClientUnaryCall; 625 | /** / Call this method with a non-expired refresh token to obtain a new access token. */ 626 | refreshAccessToken( 627 | request: RefreshAccessTokenRequest, 628 | callback: (error: ServiceError | null, response: RefreshAccessTokenResponse) => void, 629 | ): ClientUnaryCall; 630 | refreshAccessToken( 631 | request: RefreshAccessTokenRequest, 632 | metadata: Metadata, 633 | callback: (error: ServiceError | null, response: RefreshAccessTokenResponse) => void, 634 | ): ClientUnaryCall; 635 | refreshAccessToken( 636 | request: RefreshAccessTokenRequest, 637 | metadata: Metadata, 638 | options: Partial, 639 | callback: (error: ServiceError | null, response: RefreshAccessTokenResponse) => void, 640 | ): ClientUnaryCall; 641 | } 642 | 643 | export const AuthServiceClient = makeGenericClientConstructor(AuthServiceService, "auth.AuthService") as unknown as { 644 | new (address: string, credentials: ChannelCredentials, options?: Partial): AuthServiceClient; 645 | service: typeof AuthServiceService; 646 | }; 647 | 648 | declare var self: any | undefined; 649 | declare var window: any | undefined; 650 | declare var global: any | undefined; 651 | var tsProtoGlobalThis: any = (() => { 652 | if (typeof globalThis !== "undefined") { 653 | return globalThis; 654 | } 655 | if (typeof self !== "undefined") { 656 | return self; 657 | } 658 | if (typeof window !== "undefined") { 659 | return window; 660 | } 661 | if (typeof global !== "undefined") { 662 | return global; 663 | } 664 | throw "Unable to locate global object"; 665 | })(); 666 | 667 | function bytesFromBase64(b64: string): Uint8Array { 668 | if (tsProtoGlobalThis.Buffer) { 669 | return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, "base64")); 670 | } else { 671 | const bin = tsProtoGlobalThis.atob(b64); 672 | const arr = new Uint8Array(bin.length); 673 | for (let i = 0; i < bin.length; ++i) { 674 | arr[i] = bin.charCodeAt(i); 675 | } 676 | return arr; 677 | } 678 | } 679 | 680 | function base64FromBytes(arr: Uint8Array): string { 681 | if (tsProtoGlobalThis.Buffer) { 682 | return tsProtoGlobalThis.Buffer.from(arr).toString("base64"); 683 | } else { 684 | const bin: string[] = []; 685 | arr.forEach((byte) => { 686 | bin.push(String.fromCharCode(byte)); 687 | }); 688 | return tsProtoGlobalThis.btoa(bin.join("")); 689 | } 690 | } 691 | 692 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 693 | 694 | export type DeepPartial = T extends Builtin ? T 695 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 696 | : T extends {} ? { [K in keyof T]?: DeepPartial } 697 | : Partial; 698 | 699 | type KeysOfUnion = T extends T ? keyof T : never; 700 | export type Exact = P extends Builtin ? P 701 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 702 | 703 | function toTimestamp(date: Date): Timestamp { 704 | const seconds = date.getTime() / 1_000; 705 | const nanos = (date.getTime() % 1_000) * 1_000_000; 706 | return { seconds, nanos }; 707 | } 708 | 709 | function fromTimestamp(t: Timestamp): Date { 710 | let millis = t.seconds * 1_000; 711 | millis += t.nanos / 1_000_000; 712 | return new Date(millis); 713 | } 714 | 715 | function fromJsonTimestamp(o: any): Date { 716 | if (o instanceof Date) { 717 | return o; 718 | } else if (typeof o === "string") { 719 | return new Date(o); 720 | } else { 721 | return fromTimestamp(Timestamp.fromJSON(o)); 722 | } 723 | } 724 | 725 | function isSet(value: any): boolean { 726 | return value !== null && value !== undefined; 727 | } 728 | -------------------------------------------------------------------------------- /src/gen/block-engine/block.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | import { Header } from "./shared"; 5 | 6 | export const protobufPackage = "block"; 7 | 8 | /** Condensed block helpful for getting data around efficiently internal to our system. */ 9 | export interface CondensedBlock { 10 | header: Header | undefined; 11 | previousBlockhash: string; 12 | blockhash: string; 13 | parentSlot: number; 14 | versionedTransactions: Uint8Array[]; 15 | slot: number; 16 | commitment: string; 17 | } 18 | 19 | function createBaseCondensedBlock(): CondensedBlock { 20 | return { 21 | header: undefined, 22 | previousBlockhash: "", 23 | blockhash: "", 24 | parentSlot: 0, 25 | versionedTransactions: [], 26 | slot: 0, 27 | commitment: "", 28 | }; 29 | } 30 | 31 | export const CondensedBlock = { 32 | encode(message: CondensedBlock, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 33 | if (message.header !== undefined) { 34 | Header.encode(message.header, writer.uint32(10).fork()).ldelim(); 35 | } 36 | if (message.previousBlockhash !== "") { 37 | writer.uint32(18).string(message.previousBlockhash); 38 | } 39 | if (message.blockhash !== "") { 40 | writer.uint32(26).string(message.blockhash); 41 | } 42 | if (message.parentSlot !== 0) { 43 | writer.uint32(32).uint64(message.parentSlot); 44 | } 45 | for (const v of message.versionedTransactions) { 46 | writer.uint32(42).bytes(v!); 47 | } 48 | if (message.slot !== 0) { 49 | writer.uint32(48).uint64(message.slot); 50 | } 51 | if (message.commitment !== "") { 52 | writer.uint32(58).string(message.commitment); 53 | } 54 | return writer; 55 | }, 56 | 57 | decode(input: _m0.Reader | Uint8Array, length?: number): CondensedBlock { 58 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 59 | let end = length === undefined ? reader.len : reader.pos + length; 60 | const message = createBaseCondensedBlock(); 61 | while (reader.pos < end) { 62 | const tag = reader.uint32(); 63 | switch (tag >>> 3) { 64 | case 1: 65 | message.header = Header.decode(reader, reader.uint32()); 66 | break; 67 | case 2: 68 | message.previousBlockhash = reader.string(); 69 | break; 70 | case 3: 71 | message.blockhash = reader.string(); 72 | break; 73 | case 4: 74 | message.parentSlot = longToNumber(reader.uint64() as Long); 75 | break; 76 | case 5: 77 | message.versionedTransactions.push(reader.bytes()); 78 | break; 79 | case 6: 80 | message.slot = longToNumber(reader.uint64() as Long); 81 | break; 82 | case 7: 83 | message.commitment = reader.string(); 84 | break; 85 | default: 86 | reader.skipType(tag & 7); 87 | break; 88 | } 89 | } 90 | return message; 91 | }, 92 | 93 | fromJSON(object: any): CondensedBlock { 94 | return { 95 | header: isSet(object.header) ? Header.fromJSON(object.header) : undefined, 96 | previousBlockhash: isSet(object.previousBlockhash) ? String(object.previousBlockhash) : "", 97 | blockhash: isSet(object.blockhash) ? String(object.blockhash) : "", 98 | parentSlot: isSet(object.parentSlot) ? Number(object.parentSlot) : 0, 99 | versionedTransactions: Array.isArray(object?.versionedTransactions) 100 | ? object.versionedTransactions.map((e: any) => bytesFromBase64(e)) 101 | : [], 102 | slot: isSet(object.slot) ? Number(object.slot) : 0, 103 | commitment: isSet(object.commitment) ? String(object.commitment) : "", 104 | }; 105 | }, 106 | 107 | toJSON(message: CondensedBlock): unknown { 108 | const obj: any = {}; 109 | message.header !== undefined && (obj.header = message.header ? Header.toJSON(message.header) : undefined); 110 | message.previousBlockhash !== undefined && (obj.previousBlockhash = message.previousBlockhash); 111 | message.blockhash !== undefined && (obj.blockhash = message.blockhash); 112 | message.parentSlot !== undefined && (obj.parentSlot = Math.round(message.parentSlot)); 113 | if (message.versionedTransactions) { 114 | obj.versionedTransactions = message.versionedTransactions.map((e) => 115 | base64FromBytes(e !== undefined ? e : new Uint8Array()) 116 | ); 117 | } else { 118 | obj.versionedTransactions = []; 119 | } 120 | message.slot !== undefined && (obj.slot = Math.round(message.slot)); 121 | message.commitment !== undefined && (obj.commitment = message.commitment); 122 | return obj; 123 | }, 124 | 125 | create, I>>(base?: I): CondensedBlock { 126 | return CondensedBlock.fromPartial(base ?? {}); 127 | }, 128 | 129 | fromPartial, I>>(object: I): CondensedBlock { 130 | const message = createBaseCondensedBlock(); 131 | message.header = (object.header !== undefined && object.header !== null) 132 | ? Header.fromPartial(object.header) 133 | : undefined; 134 | message.previousBlockhash = object.previousBlockhash ?? ""; 135 | message.blockhash = object.blockhash ?? ""; 136 | message.parentSlot = object.parentSlot ?? 0; 137 | message.versionedTransactions = object.versionedTransactions?.map((e) => e) || []; 138 | message.slot = object.slot ?? 0; 139 | message.commitment = object.commitment ?? ""; 140 | return message; 141 | }, 142 | }; 143 | 144 | declare var self: any | undefined; 145 | declare var window: any | undefined; 146 | declare var global: any | undefined; 147 | var tsProtoGlobalThis: any = (() => { 148 | if (typeof globalThis !== "undefined") { 149 | return globalThis; 150 | } 151 | if (typeof self !== "undefined") { 152 | return self; 153 | } 154 | if (typeof window !== "undefined") { 155 | return window; 156 | } 157 | if (typeof global !== "undefined") { 158 | return global; 159 | } 160 | throw "Unable to locate global object"; 161 | })(); 162 | 163 | function bytesFromBase64(b64: string): Uint8Array { 164 | if (tsProtoGlobalThis.Buffer) { 165 | return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, "base64")); 166 | } else { 167 | const bin = tsProtoGlobalThis.atob(b64); 168 | const arr = new Uint8Array(bin.length); 169 | for (let i = 0; i < bin.length; ++i) { 170 | arr[i] = bin.charCodeAt(i); 171 | } 172 | return arr; 173 | } 174 | } 175 | 176 | function base64FromBytes(arr: Uint8Array): string { 177 | if (tsProtoGlobalThis.Buffer) { 178 | return tsProtoGlobalThis.Buffer.from(arr).toString("base64"); 179 | } else { 180 | const bin: string[] = []; 181 | arr.forEach((byte) => { 182 | bin.push(String.fromCharCode(byte)); 183 | }); 184 | return tsProtoGlobalThis.btoa(bin.join("")); 185 | } 186 | } 187 | 188 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 189 | 190 | export type DeepPartial = T extends Builtin ? T 191 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 192 | : T extends {} ? { [K in keyof T]?: DeepPartial } 193 | : Partial; 194 | 195 | type KeysOfUnion = T extends T ? keyof T : never; 196 | export type Exact = P extends Builtin ? P 197 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 198 | 199 | function longToNumber(long: Long): number { 200 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 201 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 202 | } 203 | return long.toNumber(); 204 | } 205 | 206 | if (_m0.util.Long !== Long) { 207 | _m0.util.Long = Long as any; 208 | _m0.configure(); 209 | } 210 | 211 | function isSet(value: any): boolean { 212 | return value !== null && value !== undefined; 213 | } 214 | -------------------------------------------------------------------------------- /src/gen/block-engine/bundle.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | import { Packet } from "./packet"; 5 | import { Header } from "./shared"; 6 | 7 | export const protobufPackage = "bundle"; 8 | 9 | export enum DroppedReason { 10 | BlockhashExpired = 0, 11 | /** PartiallyProcessed - One or more transactions in the bundle landed on-chain, invalidating the bundle. */ 12 | PartiallyProcessed = 1, 13 | /** NotFinalized - This indicates bundle was processed but not finalized. This could occur during forks. */ 14 | NotFinalized = 2, 15 | UNRECOGNIZED = -1, 16 | } 17 | 18 | export function droppedReasonFromJSON(object: any): DroppedReason { 19 | switch (object) { 20 | case 0: 21 | case "BlockhashExpired": 22 | return DroppedReason.BlockhashExpired; 23 | case 1: 24 | case "PartiallyProcessed": 25 | return DroppedReason.PartiallyProcessed; 26 | case 2: 27 | case "NotFinalized": 28 | return DroppedReason.NotFinalized; 29 | case -1: 30 | case "UNRECOGNIZED": 31 | default: 32 | return DroppedReason.UNRECOGNIZED; 33 | } 34 | } 35 | 36 | export function droppedReasonToJSON(object: DroppedReason): string { 37 | switch (object) { 38 | case DroppedReason.BlockhashExpired: 39 | return "BlockhashExpired"; 40 | case DroppedReason.PartiallyProcessed: 41 | return "PartiallyProcessed"; 42 | case DroppedReason.NotFinalized: 43 | return "NotFinalized"; 44 | case DroppedReason.UNRECOGNIZED: 45 | default: 46 | return "UNRECOGNIZED"; 47 | } 48 | } 49 | 50 | export interface Bundle { 51 | header: Header | undefined; 52 | packets: Packet[]; 53 | } 54 | 55 | export interface BundleUuid { 56 | bundle: Bundle | undefined; 57 | uuid: string; 58 | } 59 | 60 | /** 61 | * Indicates the bundle was accepted and forwarded to a validator. 62 | * NOTE: A single bundle may have multiple events emitted if forwarded to many validators. 63 | */ 64 | export interface Accepted { 65 | /** Slot at which bundle was forwarded. */ 66 | slot: number; 67 | /** Validator identity bundle was forwarded to. */ 68 | validatorIdentity: string; 69 | } 70 | 71 | /** Indicates the bundle was dropped and therefore not forwarded to any validator. */ 72 | export interface Rejected { 73 | stateAuctionBidRejected?: StateAuctionBidRejected | undefined; 74 | winningBatchBidRejected?: WinningBatchBidRejected | undefined; 75 | simulationFailure?: SimulationFailure | undefined; 76 | internalError?: InternalError | undefined; 77 | droppedBundle?: DroppedBundle | undefined; 78 | } 79 | 80 | /** 81 | * Indicates the bundle's bid was high enough to win its state auction. 82 | * However, not high enough relative to other state auction winners and therefore excluded from being forwarded. 83 | */ 84 | export interface WinningBatchBidRejected { 85 | /** Auction's unique identifier. */ 86 | auctionId: string; 87 | /** Bundle's simulated bid. */ 88 | simulatedBidLamports: number; 89 | msg?: string | undefined; 90 | } 91 | 92 | /** Indicates the bundle's bid was __not__ high enough to be included in its state auction's set of winners. */ 93 | export interface StateAuctionBidRejected { 94 | /** Auction's unique identifier. */ 95 | auctionId: string; 96 | /** Bundle's simulated bid. */ 97 | simulatedBidLamports: number; 98 | msg?: string | undefined; 99 | } 100 | 101 | /** Bundle dropped due to simulation failure. */ 102 | export interface SimulationFailure { 103 | /** Signature of the offending transaction. */ 104 | txSignature: string; 105 | msg?: string | undefined; 106 | } 107 | 108 | /** Bundle dropped due to an internal error. */ 109 | export interface InternalError { 110 | msg: string; 111 | } 112 | 113 | /** Bundle dropped (e.g. because no leader upcoming) */ 114 | export interface DroppedBundle { 115 | msg: string; 116 | } 117 | 118 | export interface Finalized { 119 | } 120 | 121 | export interface Processed { 122 | validatorIdentity: string; 123 | slot: number; 124 | /** / Index within the block. */ 125 | bundleIndex: number; 126 | } 127 | 128 | export interface Dropped { 129 | reason: DroppedReason; 130 | } 131 | 132 | export interface BundleResult { 133 | /** Bundle's Uuid. */ 134 | bundleId: string; 135 | /** Indicated accepted by the block-engine and forwarded to a jito-solana validator. */ 136 | accepted?: 137 | | Accepted 138 | | undefined; 139 | /** Rejected by the block-engine. */ 140 | rejected?: 141 | | Rejected 142 | | undefined; 143 | /** Reached finalized commitment level. */ 144 | finalized?: 145 | | Finalized 146 | | undefined; 147 | /** Reached a processed commitment level. */ 148 | processed?: 149 | | Processed 150 | | undefined; 151 | /** Was accepted and forwarded by the block-engine but never landed on-chain. */ 152 | dropped?: Dropped | undefined; 153 | } 154 | 155 | function createBaseBundle(): Bundle { 156 | return { header: undefined, packets: [] }; 157 | } 158 | 159 | export const Bundle = { 160 | encode(message: Bundle, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 161 | if (message.header !== undefined) { 162 | Header.encode(message.header, writer.uint32(18).fork()).ldelim(); 163 | } 164 | for (const v of message.packets) { 165 | Packet.encode(v!, writer.uint32(26).fork()).ldelim(); 166 | } 167 | return writer; 168 | }, 169 | 170 | decode(input: _m0.Reader | Uint8Array, length?: number): Bundle { 171 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 172 | let end = length === undefined ? reader.len : reader.pos + length; 173 | const message = createBaseBundle(); 174 | while (reader.pos < end) { 175 | const tag = reader.uint32(); 176 | switch (tag >>> 3) { 177 | case 2: 178 | message.header = Header.decode(reader, reader.uint32()); 179 | break; 180 | case 3: 181 | message.packets.push(Packet.decode(reader, reader.uint32())); 182 | break; 183 | default: 184 | reader.skipType(tag & 7); 185 | break; 186 | } 187 | } 188 | return message; 189 | }, 190 | 191 | fromJSON(object: any): Bundle { 192 | return { 193 | header: isSet(object.header) ? Header.fromJSON(object.header) : undefined, 194 | packets: Array.isArray(object?.packets) ? object.packets.map((e: any) => Packet.fromJSON(e)) : [], 195 | }; 196 | }, 197 | 198 | toJSON(message: Bundle): unknown { 199 | const obj: any = {}; 200 | message.header !== undefined && (obj.header = message.header ? Header.toJSON(message.header) : undefined); 201 | if (message.packets) { 202 | obj.packets = message.packets.map((e) => e ? Packet.toJSON(e) : undefined); 203 | } else { 204 | obj.packets = []; 205 | } 206 | return obj; 207 | }, 208 | 209 | create, I>>(base?: I): Bundle { 210 | return Bundle.fromPartial(base ?? {}); 211 | }, 212 | 213 | fromPartial, I>>(object: I): Bundle { 214 | const message = createBaseBundle(); 215 | message.header = (object.header !== undefined && object.header !== null) 216 | ? Header.fromPartial(object.header) 217 | : undefined; 218 | message.packets = object.packets?.map((e) => Packet.fromPartial(e)) || []; 219 | return message; 220 | }, 221 | }; 222 | 223 | function createBaseBundleUuid(): BundleUuid { 224 | return { bundle: undefined, uuid: "" }; 225 | } 226 | 227 | export const BundleUuid = { 228 | encode(message: BundleUuid, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 229 | if (message.bundle !== undefined) { 230 | Bundle.encode(message.bundle, writer.uint32(10).fork()).ldelim(); 231 | } 232 | if (message.uuid !== "") { 233 | writer.uint32(18).string(message.uuid); 234 | } 235 | return writer; 236 | }, 237 | 238 | decode(input: _m0.Reader | Uint8Array, length?: number): BundleUuid { 239 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 240 | let end = length === undefined ? reader.len : reader.pos + length; 241 | const message = createBaseBundleUuid(); 242 | while (reader.pos < end) { 243 | const tag = reader.uint32(); 244 | switch (tag >>> 3) { 245 | case 1: 246 | message.bundle = Bundle.decode(reader, reader.uint32()); 247 | break; 248 | case 2: 249 | message.uuid = reader.string(); 250 | break; 251 | default: 252 | reader.skipType(tag & 7); 253 | break; 254 | } 255 | } 256 | return message; 257 | }, 258 | 259 | fromJSON(object: any): BundleUuid { 260 | return { 261 | bundle: isSet(object.bundle) ? Bundle.fromJSON(object.bundle) : undefined, 262 | uuid: isSet(object.uuid) ? String(object.uuid) : "", 263 | }; 264 | }, 265 | 266 | toJSON(message: BundleUuid): unknown { 267 | const obj: any = {}; 268 | message.bundle !== undefined && (obj.bundle = message.bundle ? Bundle.toJSON(message.bundle) : undefined); 269 | message.uuid !== undefined && (obj.uuid = message.uuid); 270 | return obj; 271 | }, 272 | 273 | create, I>>(base?: I): BundleUuid { 274 | return BundleUuid.fromPartial(base ?? {}); 275 | }, 276 | 277 | fromPartial, I>>(object: I): BundleUuid { 278 | const message = createBaseBundleUuid(); 279 | message.bundle = (object.bundle !== undefined && object.bundle !== null) 280 | ? Bundle.fromPartial(object.bundle) 281 | : undefined; 282 | message.uuid = object.uuid ?? ""; 283 | return message; 284 | }, 285 | }; 286 | 287 | function createBaseAccepted(): Accepted { 288 | return { slot: 0, validatorIdentity: "" }; 289 | } 290 | 291 | export const Accepted = { 292 | encode(message: Accepted, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 293 | if (message.slot !== 0) { 294 | writer.uint32(8).uint64(message.slot); 295 | } 296 | if (message.validatorIdentity !== "") { 297 | writer.uint32(18).string(message.validatorIdentity); 298 | } 299 | return writer; 300 | }, 301 | 302 | decode(input: _m0.Reader | Uint8Array, length?: number): Accepted { 303 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 304 | let end = length === undefined ? reader.len : reader.pos + length; 305 | const message = createBaseAccepted(); 306 | while (reader.pos < end) { 307 | const tag = reader.uint32(); 308 | switch (tag >>> 3) { 309 | case 1: 310 | message.slot = longToNumber(reader.uint64() as Long); 311 | break; 312 | case 2: 313 | message.validatorIdentity = reader.string(); 314 | break; 315 | default: 316 | reader.skipType(tag & 7); 317 | break; 318 | } 319 | } 320 | return message; 321 | }, 322 | 323 | fromJSON(object: any): Accepted { 324 | return { 325 | slot: isSet(object.slot) ? Number(object.slot) : 0, 326 | validatorIdentity: isSet(object.validatorIdentity) ? String(object.validatorIdentity) : "", 327 | }; 328 | }, 329 | 330 | toJSON(message: Accepted): unknown { 331 | const obj: any = {}; 332 | message.slot !== undefined && (obj.slot = Math.round(message.slot)); 333 | message.validatorIdentity !== undefined && (obj.validatorIdentity = message.validatorIdentity); 334 | return obj; 335 | }, 336 | 337 | create, I>>(base?: I): Accepted { 338 | return Accepted.fromPartial(base ?? {}); 339 | }, 340 | 341 | fromPartial, I>>(object: I): Accepted { 342 | const message = createBaseAccepted(); 343 | message.slot = object.slot ?? 0; 344 | message.validatorIdentity = object.validatorIdentity ?? ""; 345 | return message; 346 | }, 347 | }; 348 | 349 | function createBaseRejected(): Rejected { 350 | return { 351 | stateAuctionBidRejected: undefined, 352 | winningBatchBidRejected: undefined, 353 | simulationFailure: undefined, 354 | internalError: undefined, 355 | droppedBundle: undefined, 356 | }; 357 | } 358 | 359 | export const Rejected = { 360 | encode(message: Rejected, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 361 | if (message.stateAuctionBidRejected !== undefined) { 362 | StateAuctionBidRejected.encode(message.stateAuctionBidRejected, writer.uint32(10).fork()).ldelim(); 363 | } 364 | if (message.winningBatchBidRejected !== undefined) { 365 | WinningBatchBidRejected.encode(message.winningBatchBidRejected, writer.uint32(18).fork()).ldelim(); 366 | } 367 | if (message.simulationFailure !== undefined) { 368 | SimulationFailure.encode(message.simulationFailure, writer.uint32(26).fork()).ldelim(); 369 | } 370 | if (message.internalError !== undefined) { 371 | InternalError.encode(message.internalError, writer.uint32(34).fork()).ldelim(); 372 | } 373 | if (message.droppedBundle !== undefined) { 374 | DroppedBundle.encode(message.droppedBundle, writer.uint32(42).fork()).ldelim(); 375 | } 376 | return writer; 377 | }, 378 | 379 | decode(input: _m0.Reader | Uint8Array, length?: number): Rejected { 380 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 381 | let end = length === undefined ? reader.len : reader.pos + length; 382 | const message = createBaseRejected(); 383 | while (reader.pos < end) { 384 | const tag = reader.uint32(); 385 | switch (tag >>> 3) { 386 | case 1: 387 | message.stateAuctionBidRejected = StateAuctionBidRejected.decode(reader, reader.uint32()); 388 | break; 389 | case 2: 390 | message.winningBatchBidRejected = WinningBatchBidRejected.decode(reader, reader.uint32()); 391 | break; 392 | case 3: 393 | message.simulationFailure = SimulationFailure.decode(reader, reader.uint32()); 394 | break; 395 | case 4: 396 | message.internalError = InternalError.decode(reader, reader.uint32()); 397 | break; 398 | case 5: 399 | message.droppedBundle = DroppedBundle.decode(reader, reader.uint32()); 400 | break; 401 | default: 402 | reader.skipType(tag & 7); 403 | break; 404 | } 405 | } 406 | return message; 407 | }, 408 | 409 | fromJSON(object: any): Rejected { 410 | return { 411 | stateAuctionBidRejected: isSet(object.stateAuctionBidRejected) 412 | ? StateAuctionBidRejected.fromJSON(object.stateAuctionBidRejected) 413 | : undefined, 414 | winningBatchBidRejected: isSet(object.winningBatchBidRejected) 415 | ? WinningBatchBidRejected.fromJSON(object.winningBatchBidRejected) 416 | : undefined, 417 | simulationFailure: isSet(object.simulationFailure) 418 | ? SimulationFailure.fromJSON(object.simulationFailure) 419 | : undefined, 420 | internalError: isSet(object.internalError) ? InternalError.fromJSON(object.internalError) : undefined, 421 | droppedBundle: isSet(object.droppedBundle) ? DroppedBundle.fromJSON(object.droppedBundle) : undefined, 422 | }; 423 | }, 424 | 425 | toJSON(message: Rejected): unknown { 426 | const obj: any = {}; 427 | message.stateAuctionBidRejected !== undefined && (obj.stateAuctionBidRejected = message.stateAuctionBidRejected 428 | ? StateAuctionBidRejected.toJSON(message.stateAuctionBidRejected) 429 | : undefined); 430 | message.winningBatchBidRejected !== undefined && (obj.winningBatchBidRejected = message.winningBatchBidRejected 431 | ? WinningBatchBidRejected.toJSON(message.winningBatchBidRejected) 432 | : undefined); 433 | message.simulationFailure !== undefined && (obj.simulationFailure = message.simulationFailure 434 | ? SimulationFailure.toJSON(message.simulationFailure) 435 | : undefined); 436 | message.internalError !== undefined && 437 | (obj.internalError = message.internalError ? InternalError.toJSON(message.internalError) : undefined); 438 | message.droppedBundle !== undefined && 439 | (obj.droppedBundle = message.droppedBundle ? DroppedBundle.toJSON(message.droppedBundle) : undefined); 440 | return obj; 441 | }, 442 | 443 | create, I>>(base?: I): Rejected { 444 | return Rejected.fromPartial(base ?? {}); 445 | }, 446 | 447 | fromPartial, I>>(object: I): Rejected { 448 | const message = createBaseRejected(); 449 | message.stateAuctionBidRejected = 450 | (object.stateAuctionBidRejected !== undefined && object.stateAuctionBidRejected !== null) 451 | ? StateAuctionBidRejected.fromPartial(object.stateAuctionBidRejected) 452 | : undefined; 453 | message.winningBatchBidRejected = 454 | (object.winningBatchBidRejected !== undefined && object.winningBatchBidRejected !== null) 455 | ? WinningBatchBidRejected.fromPartial(object.winningBatchBidRejected) 456 | : undefined; 457 | message.simulationFailure = (object.simulationFailure !== undefined && object.simulationFailure !== null) 458 | ? SimulationFailure.fromPartial(object.simulationFailure) 459 | : undefined; 460 | message.internalError = (object.internalError !== undefined && object.internalError !== null) 461 | ? InternalError.fromPartial(object.internalError) 462 | : undefined; 463 | message.droppedBundle = (object.droppedBundle !== undefined && object.droppedBundle !== null) 464 | ? DroppedBundle.fromPartial(object.droppedBundle) 465 | : undefined; 466 | return message; 467 | }, 468 | }; 469 | 470 | function createBaseWinningBatchBidRejected(): WinningBatchBidRejected { 471 | return { auctionId: "", simulatedBidLamports: 0, msg: undefined }; 472 | } 473 | 474 | export const WinningBatchBidRejected = { 475 | encode(message: WinningBatchBidRejected, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 476 | if (message.auctionId !== "") { 477 | writer.uint32(10).string(message.auctionId); 478 | } 479 | if (message.simulatedBidLamports !== 0) { 480 | writer.uint32(16).uint64(message.simulatedBidLamports); 481 | } 482 | if (message.msg !== undefined) { 483 | writer.uint32(26).string(message.msg); 484 | } 485 | return writer; 486 | }, 487 | 488 | decode(input: _m0.Reader | Uint8Array, length?: number): WinningBatchBidRejected { 489 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 490 | let end = length === undefined ? reader.len : reader.pos + length; 491 | const message = createBaseWinningBatchBidRejected(); 492 | while (reader.pos < end) { 493 | const tag = reader.uint32(); 494 | switch (tag >>> 3) { 495 | case 1: 496 | message.auctionId = reader.string(); 497 | break; 498 | case 2: 499 | message.simulatedBidLamports = longToNumber(reader.uint64() as Long); 500 | break; 501 | case 3: 502 | message.msg = reader.string(); 503 | break; 504 | default: 505 | reader.skipType(tag & 7); 506 | break; 507 | } 508 | } 509 | return message; 510 | }, 511 | 512 | fromJSON(object: any): WinningBatchBidRejected { 513 | return { 514 | auctionId: isSet(object.auctionId) ? String(object.auctionId) : "", 515 | simulatedBidLamports: isSet(object.simulatedBidLamports) ? Number(object.simulatedBidLamports) : 0, 516 | msg: isSet(object.msg) ? String(object.msg) : undefined, 517 | }; 518 | }, 519 | 520 | toJSON(message: WinningBatchBidRejected): unknown { 521 | const obj: any = {}; 522 | message.auctionId !== undefined && (obj.auctionId = message.auctionId); 523 | message.simulatedBidLamports !== undefined && (obj.simulatedBidLamports = Math.round(message.simulatedBidLamports)); 524 | message.msg !== undefined && (obj.msg = message.msg); 525 | return obj; 526 | }, 527 | 528 | create, I>>(base?: I): WinningBatchBidRejected { 529 | return WinningBatchBidRejected.fromPartial(base ?? {}); 530 | }, 531 | 532 | fromPartial, I>>(object: I): WinningBatchBidRejected { 533 | const message = createBaseWinningBatchBidRejected(); 534 | message.auctionId = object.auctionId ?? ""; 535 | message.simulatedBidLamports = object.simulatedBidLamports ?? 0; 536 | message.msg = object.msg ?? undefined; 537 | return message; 538 | }, 539 | }; 540 | 541 | function createBaseStateAuctionBidRejected(): StateAuctionBidRejected { 542 | return { auctionId: "", simulatedBidLamports: 0, msg: undefined }; 543 | } 544 | 545 | export const StateAuctionBidRejected = { 546 | encode(message: StateAuctionBidRejected, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 547 | if (message.auctionId !== "") { 548 | writer.uint32(10).string(message.auctionId); 549 | } 550 | if (message.simulatedBidLamports !== 0) { 551 | writer.uint32(16).uint64(message.simulatedBidLamports); 552 | } 553 | if (message.msg !== undefined) { 554 | writer.uint32(26).string(message.msg); 555 | } 556 | return writer; 557 | }, 558 | 559 | decode(input: _m0.Reader | Uint8Array, length?: number): StateAuctionBidRejected { 560 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 561 | let end = length === undefined ? reader.len : reader.pos + length; 562 | const message = createBaseStateAuctionBidRejected(); 563 | while (reader.pos < end) { 564 | const tag = reader.uint32(); 565 | switch (tag >>> 3) { 566 | case 1: 567 | message.auctionId = reader.string(); 568 | break; 569 | case 2: 570 | message.simulatedBidLamports = longToNumber(reader.uint64() as Long); 571 | break; 572 | case 3: 573 | message.msg = reader.string(); 574 | break; 575 | default: 576 | reader.skipType(tag & 7); 577 | break; 578 | } 579 | } 580 | return message; 581 | }, 582 | 583 | fromJSON(object: any): StateAuctionBidRejected { 584 | return { 585 | auctionId: isSet(object.auctionId) ? String(object.auctionId) : "", 586 | simulatedBidLamports: isSet(object.simulatedBidLamports) ? Number(object.simulatedBidLamports) : 0, 587 | msg: isSet(object.msg) ? String(object.msg) : undefined, 588 | }; 589 | }, 590 | 591 | toJSON(message: StateAuctionBidRejected): unknown { 592 | const obj: any = {}; 593 | message.auctionId !== undefined && (obj.auctionId = message.auctionId); 594 | message.simulatedBidLamports !== undefined && (obj.simulatedBidLamports = Math.round(message.simulatedBidLamports)); 595 | message.msg !== undefined && (obj.msg = message.msg); 596 | return obj; 597 | }, 598 | 599 | create, I>>(base?: I): StateAuctionBidRejected { 600 | return StateAuctionBidRejected.fromPartial(base ?? {}); 601 | }, 602 | 603 | fromPartial, I>>(object: I): StateAuctionBidRejected { 604 | const message = createBaseStateAuctionBidRejected(); 605 | message.auctionId = object.auctionId ?? ""; 606 | message.simulatedBidLamports = object.simulatedBidLamports ?? 0; 607 | message.msg = object.msg ?? undefined; 608 | return message; 609 | }, 610 | }; 611 | 612 | function createBaseSimulationFailure(): SimulationFailure { 613 | return { txSignature: "", msg: undefined }; 614 | } 615 | 616 | export const SimulationFailure = { 617 | encode(message: SimulationFailure, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 618 | if (message.txSignature !== "") { 619 | writer.uint32(10).string(message.txSignature); 620 | } 621 | if (message.msg !== undefined) { 622 | writer.uint32(18).string(message.msg); 623 | } 624 | return writer; 625 | }, 626 | 627 | decode(input: _m0.Reader | Uint8Array, length?: number): SimulationFailure { 628 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 629 | let end = length === undefined ? reader.len : reader.pos + length; 630 | const message = createBaseSimulationFailure(); 631 | while (reader.pos < end) { 632 | const tag = reader.uint32(); 633 | switch (tag >>> 3) { 634 | case 1: 635 | message.txSignature = reader.string(); 636 | break; 637 | case 2: 638 | message.msg = reader.string(); 639 | break; 640 | default: 641 | reader.skipType(tag & 7); 642 | break; 643 | } 644 | } 645 | return message; 646 | }, 647 | 648 | fromJSON(object: any): SimulationFailure { 649 | return { 650 | txSignature: isSet(object.txSignature) ? String(object.txSignature) : "", 651 | msg: isSet(object.msg) ? String(object.msg) : undefined, 652 | }; 653 | }, 654 | 655 | toJSON(message: SimulationFailure): unknown { 656 | const obj: any = {}; 657 | message.txSignature !== undefined && (obj.txSignature = message.txSignature); 658 | message.msg !== undefined && (obj.msg = message.msg); 659 | return obj; 660 | }, 661 | 662 | create, I>>(base?: I): SimulationFailure { 663 | return SimulationFailure.fromPartial(base ?? {}); 664 | }, 665 | 666 | fromPartial, I>>(object: I): SimulationFailure { 667 | const message = createBaseSimulationFailure(); 668 | message.txSignature = object.txSignature ?? ""; 669 | message.msg = object.msg ?? undefined; 670 | return message; 671 | }, 672 | }; 673 | 674 | function createBaseInternalError(): InternalError { 675 | return { msg: "" }; 676 | } 677 | 678 | export const InternalError = { 679 | encode(message: InternalError, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 680 | if (message.msg !== "") { 681 | writer.uint32(10).string(message.msg); 682 | } 683 | return writer; 684 | }, 685 | 686 | decode(input: _m0.Reader | Uint8Array, length?: number): InternalError { 687 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 688 | let end = length === undefined ? reader.len : reader.pos + length; 689 | const message = createBaseInternalError(); 690 | while (reader.pos < end) { 691 | const tag = reader.uint32(); 692 | switch (tag >>> 3) { 693 | case 1: 694 | message.msg = reader.string(); 695 | break; 696 | default: 697 | reader.skipType(tag & 7); 698 | break; 699 | } 700 | } 701 | return message; 702 | }, 703 | 704 | fromJSON(object: any): InternalError { 705 | return { msg: isSet(object.msg) ? String(object.msg) : "" }; 706 | }, 707 | 708 | toJSON(message: InternalError): unknown { 709 | const obj: any = {}; 710 | message.msg !== undefined && (obj.msg = message.msg); 711 | return obj; 712 | }, 713 | 714 | create, I>>(base?: I): InternalError { 715 | return InternalError.fromPartial(base ?? {}); 716 | }, 717 | 718 | fromPartial, I>>(object: I): InternalError { 719 | const message = createBaseInternalError(); 720 | message.msg = object.msg ?? ""; 721 | return message; 722 | }, 723 | }; 724 | 725 | function createBaseDroppedBundle(): DroppedBundle { 726 | return { msg: "" }; 727 | } 728 | 729 | export const DroppedBundle = { 730 | encode(message: DroppedBundle, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 731 | if (message.msg !== "") { 732 | writer.uint32(10).string(message.msg); 733 | } 734 | return writer; 735 | }, 736 | 737 | decode(input: _m0.Reader | Uint8Array, length?: number): DroppedBundle { 738 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 739 | let end = length === undefined ? reader.len : reader.pos + length; 740 | const message = createBaseDroppedBundle(); 741 | while (reader.pos < end) { 742 | const tag = reader.uint32(); 743 | switch (tag >>> 3) { 744 | case 1: 745 | message.msg = reader.string(); 746 | break; 747 | default: 748 | reader.skipType(tag & 7); 749 | break; 750 | } 751 | } 752 | return message; 753 | }, 754 | 755 | fromJSON(object: any): DroppedBundle { 756 | return { msg: isSet(object.msg) ? String(object.msg) : "" }; 757 | }, 758 | 759 | toJSON(message: DroppedBundle): unknown { 760 | const obj: any = {}; 761 | message.msg !== undefined && (obj.msg = message.msg); 762 | return obj; 763 | }, 764 | 765 | create, I>>(base?: I): DroppedBundle { 766 | return DroppedBundle.fromPartial(base ?? {}); 767 | }, 768 | 769 | fromPartial, I>>(object: I): DroppedBundle { 770 | const message = createBaseDroppedBundle(); 771 | message.msg = object.msg ?? ""; 772 | return message; 773 | }, 774 | }; 775 | 776 | function createBaseFinalized(): Finalized { 777 | return {}; 778 | } 779 | 780 | export const Finalized = { 781 | encode(_: Finalized, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 782 | return writer; 783 | }, 784 | 785 | decode(input: _m0.Reader | Uint8Array, length?: number): Finalized { 786 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 787 | let end = length === undefined ? reader.len : reader.pos + length; 788 | const message = createBaseFinalized(); 789 | while (reader.pos < end) { 790 | const tag = reader.uint32(); 791 | switch (tag >>> 3) { 792 | default: 793 | reader.skipType(tag & 7); 794 | break; 795 | } 796 | } 797 | return message; 798 | }, 799 | 800 | fromJSON(_: any): Finalized { 801 | return {}; 802 | }, 803 | 804 | toJSON(_: Finalized): unknown { 805 | const obj: any = {}; 806 | return obj; 807 | }, 808 | 809 | create, I>>(base?: I): Finalized { 810 | return Finalized.fromPartial(base ?? {}); 811 | }, 812 | 813 | fromPartial, I>>(_: I): Finalized { 814 | const message = createBaseFinalized(); 815 | return message; 816 | }, 817 | }; 818 | 819 | function createBaseProcessed(): Processed { 820 | return { validatorIdentity: "", slot: 0, bundleIndex: 0 }; 821 | } 822 | 823 | export const Processed = { 824 | encode(message: Processed, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 825 | if (message.validatorIdentity !== "") { 826 | writer.uint32(10).string(message.validatorIdentity); 827 | } 828 | if (message.slot !== 0) { 829 | writer.uint32(16).uint64(message.slot); 830 | } 831 | if (message.bundleIndex !== 0) { 832 | writer.uint32(24).uint64(message.bundleIndex); 833 | } 834 | return writer; 835 | }, 836 | 837 | decode(input: _m0.Reader | Uint8Array, length?: number): Processed { 838 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 839 | let end = length === undefined ? reader.len : reader.pos + length; 840 | const message = createBaseProcessed(); 841 | while (reader.pos < end) { 842 | const tag = reader.uint32(); 843 | switch (tag >>> 3) { 844 | case 1: 845 | message.validatorIdentity = reader.string(); 846 | break; 847 | case 2: 848 | message.slot = longToNumber(reader.uint64() as Long); 849 | break; 850 | case 3: 851 | message.bundleIndex = longToNumber(reader.uint64() as Long); 852 | break; 853 | default: 854 | reader.skipType(tag & 7); 855 | break; 856 | } 857 | } 858 | return message; 859 | }, 860 | 861 | fromJSON(object: any): Processed { 862 | return { 863 | validatorIdentity: isSet(object.validatorIdentity) ? String(object.validatorIdentity) : "", 864 | slot: isSet(object.slot) ? Number(object.slot) : 0, 865 | bundleIndex: isSet(object.bundleIndex) ? Number(object.bundleIndex) : 0, 866 | }; 867 | }, 868 | 869 | toJSON(message: Processed): unknown { 870 | const obj: any = {}; 871 | message.validatorIdentity !== undefined && (obj.validatorIdentity = message.validatorIdentity); 872 | message.slot !== undefined && (obj.slot = Math.round(message.slot)); 873 | message.bundleIndex !== undefined && (obj.bundleIndex = Math.round(message.bundleIndex)); 874 | return obj; 875 | }, 876 | 877 | create, I>>(base?: I): Processed { 878 | return Processed.fromPartial(base ?? {}); 879 | }, 880 | 881 | fromPartial, I>>(object: I): Processed { 882 | const message = createBaseProcessed(); 883 | message.validatorIdentity = object.validatorIdentity ?? ""; 884 | message.slot = object.slot ?? 0; 885 | message.bundleIndex = object.bundleIndex ?? 0; 886 | return message; 887 | }, 888 | }; 889 | 890 | function createBaseDropped(): Dropped { 891 | return { reason: 0 }; 892 | } 893 | 894 | export const Dropped = { 895 | encode(message: Dropped, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 896 | if (message.reason !== 0) { 897 | writer.uint32(8).int32(message.reason); 898 | } 899 | return writer; 900 | }, 901 | 902 | decode(input: _m0.Reader | Uint8Array, length?: number): Dropped { 903 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 904 | let end = length === undefined ? reader.len : reader.pos + length; 905 | const message = createBaseDropped(); 906 | while (reader.pos < end) { 907 | const tag = reader.uint32(); 908 | switch (tag >>> 3) { 909 | case 1: 910 | message.reason = reader.int32() as any; 911 | break; 912 | default: 913 | reader.skipType(tag & 7); 914 | break; 915 | } 916 | } 917 | return message; 918 | }, 919 | 920 | fromJSON(object: any): Dropped { 921 | return { reason: isSet(object.reason) ? droppedReasonFromJSON(object.reason) : 0 }; 922 | }, 923 | 924 | toJSON(message: Dropped): unknown { 925 | const obj: any = {}; 926 | message.reason !== undefined && (obj.reason = droppedReasonToJSON(message.reason)); 927 | return obj; 928 | }, 929 | 930 | create, I>>(base?: I): Dropped { 931 | return Dropped.fromPartial(base ?? {}); 932 | }, 933 | 934 | fromPartial, I>>(object: I): Dropped { 935 | const message = createBaseDropped(); 936 | message.reason = object.reason ?? 0; 937 | return message; 938 | }, 939 | }; 940 | 941 | function createBaseBundleResult(): BundleResult { 942 | return { 943 | bundleId: "", 944 | accepted: undefined, 945 | rejected: undefined, 946 | finalized: undefined, 947 | processed: undefined, 948 | dropped: undefined, 949 | }; 950 | } 951 | 952 | export const BundleResult = { 953 | encode(message: BundleResult, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 954 | if (message.bundleId !== "") { 955 | writer.uint32(10).string(message.bundleId); 956 | } 957 | if (message.accepted !== undefined) { 958 | Accepted.encode(message.accepted, writer.uint32(18).fork()).ldelim(); 959 | } 960 | if (message.rejected !== undefined) { 961 | Rejected.encode(message.rejected, writer.uint32(26).fork()).ldelim(); 962 | } 963 | if (message.finalized !== undefined) { 964 | Finalized.encode(message.finalized, writer.uint32(34).fork()).ldelim(); 965 | } 966 | if (message.processed !== undefined) { 967 | Processed.encode(message.processed, writer.uint32(42).fork()).ldelim(); 968 | } 969 | if (message.dropped !== undefined) { 970 | Dropped.encode(message.dropped, writer.uint32(50).fork()).ldelim(); 971 | } 972 | return writer; 973 | }, 974 | 975 | decode(input: _m0.Reader | Uint8Array, length?: number): BundleResult { 976 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 977 | let end = length === undefined ? reader.len : reader.pos + length; 978 | const message = createBaseBundleResult(); 979 | while (reader.pos < end) { 980 | const tag = reader.uint32(); 981 | switch (tag >>> 3) { 982 | case 1: 983 | message.bundleId = reader.string(); 984 | break; 985 | case 2: 986 | message.accepted = Accepted.decode(reader, reader.uint32()); 987 | break; 988 | case 3: 989 | message.rejected = Rejected.decode(reader, reader.uint32()); 990 | break; 991 | case 4: 992 | message.finalized = Finalized.decode(reader, reader.uint32()); 993 | break; 994 | case 5: 995 | message.processed = Processed.decode(reader, reader.uint32()); 996 | break; 997 | case 6: 998 | message.dropped = Dropped.decode(reader, reader.uint32()); 999 | break; 1000 | default: 1001 | reader.skipType(tag & 7); 1002 | break; 1003 | } 1004 | } 1005 | return message; 1006 | }, 1007 | 1008 | fromJSON(object: any): BundleResult { 1009 | return { 1010 | bundleId: isSet(object.bundleId) ? String(object.bundleId) : "", 1011 | accepted: isSet(object.accepted) ? Accepted.fromJSON(object.accepted) : undefined, 1012 | rejected: isSet(object.rejected) ? Rejected.fromJSON(object.rejected) : undefined, 1013 | finalized: isSet(object.finalized) ? Finalized.fromJSON(object.finalized) : undefined, 1014 | processed: isSet(object.processed) ? Processed.fromJSON(object.processed) : undefined, 1015 | dropped: isSet(object.dropped) ? Dropped.fromJSON(object.dropped) : undefined, 1016 | }; 1017 | }, 1018 | 1019 | toJSON(message: BundleResult): unknown { 1020 | const obj: any = {}; 1021 | message.bundleId !== undefined && (obj.bundleId = message.bundleId); 1022 | message.accepted !== undefined && (obj.accepted = message.accepted ? Accepted.toJSON(message.accepted) : undefined); 1023 | message.rejected !== undefined && (obj.rejected = message.rejected ? Rejected.toJSON(message.rejected) : undefined); 1024 | message.finalized !== undefined && 1025 | (obj.finalized = message.finalized ? Finalized.toJSON(message.finalized) : undefined); 1026 | message.processed !== undefined && 1027 | (obj.processed = message.processed ? Processed.toJSON(message.processed) : undefined); 1028 | message.dropped !== undefined && (obj.dropped = message.dropped ? Dropped.toJSON(message.dropped) : undefined); 1029 | return obj; 1030 | }, 1031 | 1032 | create, I>>(base?: I): BundleResult { 1033 | return BundleResult.fromPartial(base ?? {}); 1034 | }, 1035 | 1036 | fromPartial, I>>(object: I): BundleResult { 1037 | const message = createBaseBundleResult(); 1038 | message.bundleId = object.bundleId ?? ""; 1039 | message.accepted = (object.accepted !== undefined && object.accepted !== null) 1040 | ? Accepted.fromPartial(object.accepted) 1041 | : undefined; 1042 | message.rejected = (object.rejected !== undefined && object.rejected !== null) 1043 | ? Rejected.fromPartial(object.rejected) 1044 | : undefined; 1045 | message.finalized = (object.finalized !== undefined && object.finalized !== null) 1046 | ? Finalized.fromPartial(object.finalized) 1047 | : undefined; 1048 | message.processed = (object.processed !== undefined && object.processed !== null) 1049 | ? Processed.fromPartial(object.processed) 1050 | : undefined; 1051 | message.dropped = (object.dropped !== undefined && object.dropped !== null) 1052 | ? Dropped.fromPartial(object.dropped) 1053 | : undefined; 1054 | return message; 1055 | }, 1056 | }; 1057 | 1058 | declare var self: any | undefined; 1059 | declare var window: any | undefined; 1060 | declare var global: any | undefined; 1061 | var tsProtoGlobalThis: any = (() => { 1062 | if (typeof globalThis !== "undefined") { 1063 | return globalThis; 1064 | } 1065 | if (typeof self !== "undefined") { 1066 | return self; 1067 | } 1068 | if (typeof window !== "undefined") { 1069 | return window; 1070 | } 1071 | if (typeof global !== "undefined") { 1072 | return global; 1073 | } 1074 | throw "Unable to locate global object"; 1075 | })(); 1076 | 1077 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 1078 | 1079 | export type DeepPartial = T extends Builtin ? T 1080 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 1081 | : T extends {} ? { [K in keyof T]?: DeepPartial } 1082 | : Partial; 1083 | 1084 | type KeysOfUnion = T extends T ? keyof T : never; 1085 | export type Exact = P extends Builtin ? P 1086 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 1087 | 1088 | function longToNumber(long: Long): number { 1089 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 1090 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 1091 | } 1092 | return long.toNumber(); 1093 | } 1094 | 1095 | if (_m0.util.Long !== Long) { 1096 | _m0.util.Long = Long as any; 1097 | _m0.configure(); 1098 | } 1099 | 1100 | function isSet(value: any): boolean { 1101 | return value !== null && value !== undefined; 1102 | } 1103 | -------------------------------------------------------------------------------- /src/gen/block-engine/google/protobuf/timestamp.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | 5 | export const protobufPackage = "google.protobuf"; 6 | 7 | /** 8 | * A Timestamp represents a point in time independent of any time zone or local 9 | * calendar, encoded as a count of seconds and fractions of seconds at 10 | * nanosecond resolution. The count is relative to an epoch at UTC midnight on 11 | * January 1, 1970, in the proleptic Gregorian calendar which extends the 12 | * Gregorian calendar backwards to year one. 13 | * 14 | * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap 15 | * second table is needed for interpretation, using a [24-hour linear 16 | * smear](https://developers.google.com/time/smear). 17 | * 18 | * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By 19 | * restricting to that range, we ensure that we can convert to and from [RFC 20 | * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. 21 | * 22 | * # Examples 23 | * 24 | * Example 1: Compute Timestamp from POSIX `time()`. 25 | * 26 | * Timestamp timestamp; 27 | * timestamp.set_seconds(time(NULL)); 28 | * timestamp.set_nanos(0); 29 | * 30 | * Example 2: Compute Timestamp from POSIX `gettimeofday()`. 31 | * 32 | * struct timeval tv; 33 | * gettimeofday(&tv, NULL); 34 | * 35 | * Timestamp timestamp; 36 | * timestamp.set_seconds(tv.tv_sec); 37 | * timestamp.set_nanos(tv.tv_usec * 1000); 38 | * 39 | * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 40 | * 41 | * FILETIME ft; 42 | * GetSystemTimeAsFileTime(&ft); 43 | * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 44 | * 45 | * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 46 | * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 47 | * Timestamp timestamp; 48 | * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 49 | * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 50 | * 51 | * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 52 | * 53 | * long millis = System.currentTimeMillis(); 54 | * 55 | * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 56 | * .setNanos((int) ((millis % 1000) * 1000000)).build(); 57 | * 58 | * Example 5: Compute Timestamp from Java `Instant.now()`. 59 | * 60 | * Instant now = Instant.now(); 61 | * 62 | * Timestamp timestamp = 63 | * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) 64 | * .setNanos(now.getNano()).build(); 65 | * 66 | * Example 6: Compute Timestamp from current time in Python. 67 | * 68 | * timestamp = Timestamp() 69 | * timestamp.GetCurrentTime() 70 | * 71 | * # JSON Mapping 72 | * 73 | * In JSON format, the Timestamp type is encoded as a string in the 74 | * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 75 | * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 76 | * where {year} is always expressed using four digits while {month}, {day}, 77 | * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 78 | * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 79 | * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 80 | * is required. A proto3 JSON serializer should always use UTC (as indicated by 81 | * "Z") when printing the Timestamp type and a proto3 JSON parser should be 82 | * able to accept both UTC and other timezones (as indicated by an offset). 83 | * 84 | * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 85 | * 01:30 UTC on January 15, 2017. 86 | * 87 | * In JavaScript, one can convert a Date object to this format using the 88 | * standard 89 | * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) 90 | * method. In Python, a standard `datetime.datetime` object can be converted 91 | * to this format using 92 | * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with 93 | * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use 94 | * the Joda Time's [`ISODateTimeFormat.dateTime()`]( 95 | * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D 96 | * ) to obtain a formatter capable of generating timestamps in this format. 97 | */ 98 | export interface Timestamp { 99 | /** 100 | * Represents seconds of UTC time since Unix epoch 101 | * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 102 | * 9999-12-31T23:59:59Z inclusive. 103 | */ 104 | seconds: number; 105 | /** 106 | * Non-negative fractions of a second at nanosecond resolution. Negative 107 | * second values with fractions must still have non-negative nanos values 108 | * that count forward in time. Must be from 0 to 999,999,999 109 | * inclusive. 110 | */ 111 | nanos: number; 112 | } 113 | 114 | function createBaseTimestamp(): Timestamp { 115 | return { seconds: 0, nanos: 0 }; 116 | } 117 | 118 | export const Timestamp = { 119 | encode(message: Timestamp, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 120 | if (message.seconds !== 0) { 121 | writer.uint32(8).int64(message.seconds); 122 | } 123 | if (message.nanos !== 0) { 124 | writer.uint32(16).int32(message.nanos); 125 | } 126 | return writer; 127 | }, 128 | 129 | decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp { 130 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 131 | let end = length === undefined ? reader.len : reader.pos + length; 132 | const message = createBaseTimestamp(); 133 | while (reader.pos < end) { 134 | const tag = reader.uint32(); 135 | switch (tag >>> 3) { 136 | case 1: 137 | message.seconds = longToNumber(reader.int64() as Long); 138 | break; 139 | case 2: 140 | message.nanos = reader.int32(); 141 | break; 142 | default: 143 | reader.skipType(tag & 7); 144 | break; 145 | } 146 | } 147 | return message; 148 | }, 149 | 150 | fromJSON(object: any): Timestamp { 151 | return { 152 | seconds: isSet(object.seconds) ? Number(object.seconds) : 0, 153 | nanos: isSet(object.nanos) ? Number(object.nanos) : 0, 154 | }; 155 | }, 156 | 157 | toJSON(message: Timestamp): unknown { 158 | const obj: any = {}; 159 | message.seconds !== undefined && (obj.seconds = Math.round(message.seconds)); 160 | message.nanos !== undefined && (obj.nanos = Math.round(message.nanos)); 161 | return obj; 162 | }, 163 | 164 | create, I>>(base?: I): Timestamp { 165 | return Timestamp.fromPartial(base ?? {}); 166 | }, 167 | 168 | fromPartial, I>>(object: I): Timestamp { 169 | const message = createBaseTimestamp(); 170 | message.seconds = object.seconds ?? 0; 171 | message.nanos = object.nanos ?? 0; 172 | return message; 173 | }, 174 | }; 175 | 176 | declare var self: any | undefined; 177 | declare var window: any | undefined; 178 | declare var global: any | undefined; 179 | var tsProtoGlobalThis: any = (() => { 180 | if (typeof globalThis !== "undefined") { 181 | return globalThis; 182 | } 183 | if (typeof self !== "undefined") { 184 | return self; 185 | } 186 | if (typeof window !== "undefined") { 187 | return window; 188 | } 189 | if (typeof global !== "undefined") { 190 | return global; 191 | } 192 | throw "Unable to locate global object"; 193 | })(); 194 | 195 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 196 | 197 | export type DeepPartial = T extends Builtin ? T 198 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 199 | : T extends {} ? { [K in keyof T]?: DeepPartial } 200 | : Partial; 201 | 202 | type KeysOfUnion = T extends T ? keyof T : never; 203 | export type Exact = P extends Builtin ? P 204 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 205 | 206 | function longToNumber(long: Long): number { 207 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 208 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 209 | } 210 | return long.toNumber(); 211 | } 212 | 213 | if (_m0.util.Long !== Long) { 214 | _m0.util.Long = Long as any; 215 | _m0.configure(); 216 | } 217 | 218 | function isSet(value: any): boolean { 219 | return value !== null && value !== undefined; 220 | } 221 | -------------------------------------------------------------------------------- /src/gen/block-engine/packet.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | 5 | export const protobufPackage = "packet"; 6 | 7 | export interface PacketBatch { 8 | packets: Packet[]; 9 | } 10 | 11 | export interface Packet { 12 | data: Uint8Array; 13 | meta: Meta | undefined; 14 | } 15 | 16 | export interface Meta { 17 | size: number; 18 | addr: string; 19 | port: number; 20 | flags: PacketFlags | undefined; 21 | senderStake: number; 22 | } 23 | 24 | export interface PacketFlags { 25 | discard: boolean; 26 | forwarded: boolean; 27 | repair: boolean; 28 | simpleVoteTx: boolean; 29 | tracerPacket: boolean; 30 | } 31 | 32 | function createBasePacketBatch(): PacketBatch { 33 | return { packets: [] }; 34 | } 35 | 36 | export const PacketBatch = { 37 | encode(message: PacketBatch, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 38 | for (const v of message.packets) { 39 | Packet.encode(v!, writer.uint32(10).fork()).ldelim(); 40 | } 41 | return writer; 42 | }, 43 | 44 | decode(input: _m0.Reader | Uint8Array, length?: number): PacketBatch { 45 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 46 | let end = length === undefined ? reader.len : reader.pos + length; 47 | const message = createBasePacketBatch(); 48 | while (reader.pos < end) { 49 | const tag = reader.uint32(); 50 | switch (tag >>> 3) { 51 | case 1: 52 | message.packets.push(Packet.decode(reader, reader.uint32())); 53 | break; 54 | default: 55 | reader.skipType(tag & 7); 56 | break; 57 | } 58 | } 59 | return message; 60 | }, 61 | 62 | fromJSON(object: any): PacketBatch { 63 | return { packets: Array.isArray(object?.packets) ? object.packets.map((e: any) => Packet.fromJSON(e)) : [] }; 64 | }, 65 | 66 | toJSON(message: PacketBatch): unknown { 67 | const obj: any = {}; 68 | if (message.packets) { 69 | obj.packets = message.packets.map((e) => e ? Packet.toJSON(e) : undefined); 70 | } else { 71 | obj.packets = []; 72 | } 73 | return obj; 74 | }, 75 | 76 | create, I>>(base?: I): PacketBatch { 77 | return PacketBatch.fromPartial(base ?? {}); 78 | }, 79 | 80 | fromPartial, I>>(object: I): PacketBatch { 81 | const message = createBasePacketBatch(); 82 | message.packets = object.packets?.map((e) => Packet.fromPartial(e)) || []; 83 | return message; 84 | }, 85 | }; 86 | 87 | function createBasePacket(): Packet { 88 | return { data: new Uint8Array(), meta: undefined }; 89 | } 90 | 91 | export const Packet = { 92 | encode(message: Packet, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 93 | if (message.data.length !== 0) { 94 | writer.uint32(10).bytes(message.data); 95 | } 96 | if (message.meta !== undefined) { 97 | Meta.encode(message.meta, writer.uint32(18).fork()).ldelim(); 98 | } 99 | return writer; 100 | }, 101 | 102 | decode(input: _m0.Reader | Uint8Array, length?: number): Packet { 103 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 104 | let end = length === undefined ? reader.len : reader.pos + length; 105 | const message = createBasePacket(); 106 | while (reader.pos < end) { 107 | const tag = reader.uint32(); 108 | switch (tag >>> 3) { 109 | case 1: 110 | message.data = reader.bytes(); 111 | break; 112 | case 2: 113 | message.meta = Meta.decode(reader, reader.uint32()); 114 | break; 115 | default: 116 | reader.skipType(tag & 7); 117 | break; 118 | } 119 | } 120 | return message; 121 | }, 122 | 123 | fromJSON(object: any): Packet { 124 | return { 125 | data: isSet(object.data) ? bytesFromBase64(object.data) : new Uint8Array(), 126 | meta: isSet(object.meta) ? Meta.fromJSON(object.meta) : undefined, 127 | }; 128 | }, 129 | 130 | toJSON(message: Packet): unknown { 131 | const obj: any = {}; 132 | message.data !== undefined && 133 | (obj.data = base64FromBytes(message.data !== undefined ? message.data : new Uint8Array())); 134 | message.meta !== undefined && (obj.meta = message.meta ? Meta.toJSON(message.meta) : undefined); 135 | return obj; 136 | }, 137 | 138 | create, I>>(base?: I): Packet { 139 | return Packet.fromPartial(base ?? {}); 140 | }, 141 | 142 | fromPartial, I>>(object: I): Packet { 143 | const message = createBasePacket(); 144 | message.data = object.data ?? new Uint8Array(); 145 | message.meta = (object.meta !== undefined && object.meta !== null) ? Meta.fromPartial(object.meta) : undefined; 146 | return message; 147 | }, 148 | }; 149 | 150 | function createBaseMeta(): Meta { 151 | return { size: 0, addr: "", port: 0, flags: undefined, senderStake: 0 }; 152 | } 153 | 154 | export const Meta = { 155 | encode(message: Meta, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 156 | if (message.size !== 0) { 157 | writer.uint32(8).uint64(message.size); 158 | } 159 | if (message.addr !== "") { 160 | writer.uint32(18).string(message.addr); 161 | } 162 | if (message.port !== 0) { 163 | writer.uint32(24).uint32(message.port); 164 | } 165 | if (message.flags !== undefined) { 166 | PacketFlags.encode(message.flags, writer.uint32(34).fork()).ldelim(); 167 | } 168 | if (message.senderStake !== 0) { 169 | writer.uint32(40).uint64(message.senderStake); 170 | } 171 | return writer; 172 | }, 173 | 174 | decode(input: _m0.Reader | Uint8Array, length?: number): Meta { 175 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 176 | let end = length === undefined ? reader.len : reader.pos + length; 177 | const message = createBaseMeta(); 178 | while (reader.pos < end) { 179 | const tag = reader.uint32(); 180 | switch (tag >>> 3) { 181 | case 1: 182 | message.size = longToNumber(reader.uint64() as Long); 183 | break; 184 | case 2: 185 | message.addr = reader.string(); 186 | break; 187 | case 3: 188 | message.port = reader.uint32(); 189 | break; 190 | case 4: 191 | message.flags = PacketFlags.decode(reader, reader.uint32()); 192 | break; 193 | case 5: 194 | message.senderStake = longToNumber(reader.uint64() as Long); 195 | break; 196 | default: 197 | reader.skipType(tag & 7); 198 | break; 199 | } 200 | } 201 | return message; 202 | }, 203 | 204 | fromJSON(object: any): Meta { 205 | return { 206 | size: isSet(object.size) ? Number(object.size) : 0, 207 | addr: isSet(object.addr) ? String(object.addr) : "", 208 | port: isSet(object.port) ? Number(object.port) : 0, 209 | flags: isSet(object.flags) ? PacketFlags.fromJSON(object.flags) : undefined, 210 | senderStake: isSet(object.senderStake) ? Number(object.senderStake) : 0, 211 | }; 212 | }, 213 | 214 | toJSON(message: Meta): unknown { 215 | const obj: any = {}; 216 | message.size !== undefined && (obj.size = Math.round(message.size)); 217 | message.addr !== undefined && (obj.addr = message.addr); 218 | message.port !== undefined && (obj.port = Math.round(message.port)); 219 | message.flags !== undefined && (obj.flags = message.flags ? PacketFlags.toJSON(message.flags) : undefined); 220 | message.senderStake !== undefined && (obj.senderStake = Math.round(message.senderStake)); 221 | return obj; 222 | }, 223 | 224 | create, I>>(base?: I): Meta { 225 | return Meta.fromPartial(base ?? {}); 226 | }, 227 | 228 | fromPartial, I>>(object: I): Meta { 229 | const message = createBaseMeta(); 230 | message.size = object.size ?? 0; 231 | message.addr = object.addr ?? ""; 232 | message.port = object.port ?? 0; 233 | message.flags = (object.flags !== undefined && object.flags !== null) 234 | ? PacketFlags.fromPartial(object.flags) 235 | : undefined; 236 | message.senderStake = object.senderStake ?? 0; 237 | return message; 238 | }, 239 | }; 240 | 241 | function createBasePacketFlags(): PacketFlags { 242 | return { discard: false, forwarded: false, repair: false, simpleVoteTx: false, tracerPacket: false }; 243 | } 244 | 245 | export const PacketFlags = { 246 | encode(message: PacketFlags, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 247 | if (message.discard === true) { 248 | writer.uint32(8).bool(message.discard); 249 | } 250 | if (message.forwarded === true) { 251 | writer.uint32(16).bool(message.forwarded); 252 | } 253 | if (message.repair === true) { 254 | writer.uint32(24).bool(message.repair); 255 | } 256 | if (message.simpleVoteTx === true) { 257 | writer.uint32(32).bool(message.simpleVoteTx); 258 | } 259 | if (message.tracerPacket === true) { 260 | writer.uint32(40).bool(message.tracerPacket); 261 | } 262 | return writer; 263 | }, 264 | 265 | decode(input: _m0.Reader | Uint8Array, length?: number): PacketFlags { 266 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 267 | let end = length === undefined ? reader.len : reader.pos + length; 268 | const message = createBasePacketFlags(); 269 | while (reader.pos < end) { 270 | const tag = reader.uint32(); 271 | switch (tag >>> 3) { 272 | case 1: 273 | message.discard = reader.bool(); 274 | break; 275 | case 2: 276 | message.forwarded = reader.bool(); 277 | break; 278 | case 3: 279 | message.repair = reader.bool(); 280 | break; 281 | case 4: 282 | message.simpleVoteTx = reader.bool(); 283 | break; 284 | case 5: 285 | message.tracerPacket = reader.bool(); 286 | break; 287 | default: 288 | reader.skipType(tag & 7); 289 | break; 290 | } 291 | } 292 | return message; 293 | }, 294 | 295 | fromJSON(object: any): PacketFlags { 296 | return { 297 | discard: isSet(object.discard) ? Boolean(object.discard) : false, 298 | forwarded: isSet(object.forwarded) ? Boolean(object.forwarded) : false, 299 | repair: isSet(object.repair) ? Boolean(object.repair) : false, 300 | simpleVoteTx: isSet(object.simpleVoteTx) ? Boolean(object.simpleVoteTx) : false, 301 | tracerPacket: isSet(object.tracerPacket) ? Boolean(object.tracerPacket) : false, 302 | }; 303 | }, 304 | 305 | toJSON(message: PacketFlags): unknown { 306 | const obj: any = {}; 307 | message.discard !== undefined && (obj.discard = message.discard); 308 | message.forwarded !== undefined && (obj.forwarded = message.forwarded); 309 | message.repair !== undefined && (obj.repair = message.repair); 310 | message.simpleVoteTx !== undefined && (obj.simpleVoteTx = message.simpleVoteTx); 311 | message.tracerPacket !== undefined && (obj.tracerPacket = message.tracerPacket); 312 | return obj; 313 | }, 314 | 315 | create, I>>(base?: I): PacketFlags { 316 | return PacketFlags.fromPartial(base ?? {}); 317 | }, 318 | 319 | fromPartial, I>>(object: I): PacketFlags { 320 | const message = createBasePacketFlags(); 321 | message.discard = object.discard ?? false; 322 | message.forwarded = object.forwarded ?? false; 323 | message.repair = object.repair ?? false; 324 | message.simpleVoteTx = object.simpleVoteTx ?? false; 325 | message.tracerPacket = object.tracerPacket ?? false; 326 | return message; 327 | }, 328 | }; 329 | 330 | declare var self: any | undefined; 331 | declare var window: any | undefined; 332 | declare var global: any | undefined; 333 | var tsProtoGlobalThis: any = (() => { 334 | if (typeof globalThis !== "undefined") { 335 | return globalThis; 336 | } 337 | if (typeof self !== "undefined") { 338 | return self; 339 | } 340 | if (typeof window !== "undefined") { 341 | return window; 342 | } 343 | if (typeof global !== "undefined") { 344 | return global; 345 | } 346 | throw "Unable to locate global object"; 347 | })(); 348 | 349 | function bytesFromBase64(b64: string): Uint8Array { 350 | if (tsProtoGlobalThis.Buffer) { 351 | return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, "base64")); 352 | } else { 353 | const bin = tsProtoGlobalThis.atob(b64); 354 | const arr = new Uint8Array(bin.length); 355 | for (let i = 0; i < bin.length; ++i) { 356 | arr[i] = bin.charCodeAt(i); 357 | } 358 | return arr; 359 | } 360 | } 361 | 362 | function base64FromBytes(arr: Uint8Array): string { 363 | if (tsProtoGlobalThis.Buffer) { 364 | return tsProtoGlobalThis.Buffer.from(arr).toString("base64"); 365 | } else { 366 | const bin: string[] = []; 367 | arr.forEach((byte) => { 368 | bin.push(String.fromCharCode(byte)); 369 | }); 370 | return tsProtoGlobalThis.btoa(bin.join("")); 371 | } 372 | } 373 | 374 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 375 | 376 | export type DeepPartial = T extends Builtin ? T 377 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 378 | : T extends {} ? { [K in keyof T]?: DeepPartial } 379 | : Partial; 380 | 381 | type KeysOfUnion = T extends T ? keyof T : never; 382 | export type Exact = P extends Builtin ? P 383 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 384 | 385 | function longToNumber(long: Long): number { 386 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 387 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 388 | } 389 | return long.toNumber(); 390 | } 391 | 392 | if (_m0.util.Long !== Long) { 393 | _m0.util.Long = Long as any; 394 | _m0.configure(); 395 | } 396 | 397 | function isSet(value: any): boolean { 398 | return value !== null && value !== undefined; 399 | } 400 | -------------------------------------------------------------------------------- /src/gen/block-engine/relayer.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { 3 | CallOptions, 4 | ChannelCredentials, 5 | Client, 6 | ClientOptions, 7 | ClientReadableStream, 8 | ClientUnaryCall, 9 | handleServerStreamingCall, 10 | handleUnaryCall, 11 | makeGenericClientConstructor, 12 | Metadata, 13 | ServiceError, 14 | UntypedServiceImplementation, 15 | } from "@grpc/grpc-js"; 16 | import _m0 from "protobufjs/minimal"; 17 | import { PacketBatch } from "./packet"; 18 | import { Header, Heartbeat, Socket } from "./shared"; 19 | 20 | export const protobufPackage = "relayer"; 21 | 22 | export interface GetTpuConfigsRequest { 23 | } 24 | 25 | export interface GetTpuConfigsResponse { 26 | tpu: Socket | undefined; 27 | tpuForward: Socket | undefined; 28 | } 29 | 30 | export interface SubscribePacketsRequest { 31 | } 32 | 33 | export interface SubscribePacketsResponse { 34 | header: Header | undefined; 35 | heartbeat?: Heartbeat | undefined; 36 | batch?: PacketBatch | undefined; 37 | } 38 | 39 | function createBaseGetTpuConfigsRequest(): GetTpuConfigsRequest { 40 | return {}; 41 | } 42 | 43 | export const GetTpuConfigsRequest = { 44 | encode(_: GetTpuConfigsRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 45 | return writer; 46 | }, 47 | 48 | decode(input: _m0.Reader | Uint8Array, length?: number): GetTpuConfigsRequest { 49 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 50 | let end = length === undefined ? reader.len : reader.pos + length; 51 | const message = createBaseGetTpuConfigsRequest(); 52 | while (reader.pos < end) { 53 | const tag = reader.uint32(); 54 | switch (tag >>> 3) { 55 | default: 56 | reader.skipType(tag & 7); 57 | break; 58 | } 59 | } 60 | return message; 61 | }, 62 | 63 | fromJSON(_: any): GetTpuConfigsRequest { 64 | return {}; 65 | }, 66 | 67 | toJSON(_: GetTpuConfigsRequest): unknown { 68 | const obj: any = {}; 69 | return obj; 70 | }, 71 | 72 | create, I>>(base?: I): GetTpuConfigsRequest { 73 | return GetTpuConfigsRequest.fromPartial(base ?? {}); 74 | }, 75 | 76 | fromPartial, I>>(_: I): GetTpuConfigsRequest { 77 | const message = createBaseGetTpuConfigsRequest(); 78 | return message; 79 | }, 80 | }; 81 | 82 | function createBaseGetTpuConfigsResponse(): GetTpuConfigsResponse { 83 | return { tpu: undefined, tpuForward: undefined }; 84 | } 85 | 86 | export const GetTpuConfigsResponse = { 87 | encode(message: GetTpuConfigsResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 88 | if (message.tpu !== undefined) { 89 | Socket.encode(message.tpu, writer.uint32(10).fork()).ldelim(); 90 | } 91 | if (message.tpuForward !== undefined) { 92 | Socket.encode(message.tpuForward, writer.uint32(18).fork()).ldelim(); 93 | } 94 | return writer; 95 | }, 96 | 97 | decode(input: _m0.Reader | Uint8Array, length?: number): GetTpuConfigsResponse { 98 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 99 | let end = length === undefined ? reader.len : reader.pos + length; 100 | const message = createBaseGetTpuConfigsResponse(); 101 | while (reader.pos < end) { 102 | const tag = reader.uint32(); 103 | switch (tag >>> 3) { 104 | case 1: 105 | message.tpu = Socket.decode(reader, reader.uint32()); 106 | break; 107 | case 2: 108 | message.tpuForward = Socket.decode(reader, reader.uint32()); 109 | break; 110 | default: 111 | reader.skipType(tag & 7); 112 | break; 113 | } 114 | } 115 | return message; 116 | }, 117 | 118 | fromJSON(object: any): GetTpuConfigsResponse { 119 | return { 120 | tpu: isSet(object.tpu) ? Socket.fromJSON(object.tpu) : undefined, 121 | tpuForward: isSet(object.tpuForward) ? Socket.fromJSON(object.tpuForward) : undefined, 122 | }; 123 | }, 124 | 125 | toJSON(message: GetTpuConfigsResponse): unknown { 126 | const obj: any = {}; 127 | message.tpu !== undefined && (obj.tpu = message.tpu ? Socket.toJSON(message.tpu) : undefined); 128 | message.tpuForward !== undefined && 129 | (obj.tpuForward = message.tpuForward ? Socket.toJSON(message.tpuForward) : undefined); 130 | return obj; 131 | }, 132 | 133 | create, I>>(base?: I): GetTpuConfigsResponse { 134 | return GetTpuConfigsResponse.fromPartial(base ?? {}); 135 | }, 136 | 137 | fromPartial, I>>(object: I): GetTpuConfigsResponse { 138 | const message = createBaseGetTpuConfigsResponse(); 139 | message.tpu = (object.tpu !== undefined && object.tpu !== null) ? Socket.fromPartial(object.tpu) : undefined; 140 | message.tpuForward = (object.tpuForward !== undefined && object.tpuForward !== null) 141 | ? Socket.fromPartial(object.tpuForward) 142 | : undefined; 143 | return message; 144 | }, 145 | }; 146 | 147 | function createBaseSubscribePacketsRequest(): SubscribePacketsRequest { 148 | return {}; 149 | } 150 | 151 | export const SubscribePacketsRequest = { 152 | encode(_: SubscribePacketsRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 153 | return writer; 154 | }, 155 | 156 | decode(input: _m0.Reader | Uint8Array, length?: number): SubscribePacketsRequest { 157 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 158 | let end = length === undefined ? reader.len : reader.pos + length; 159 | const message = createBaseSubscribePacketsRequest(); 160 | while (reader.pos < end) { 161 | const tag = reader.uint32(); 162 | switch (tag >>> 3) { 163 | default: 164 | reader.skipType(tag & 7); 165 | break; 166 | } 167 | } 168 | return message; 169 | }, 170 | 171 | fromJSON(_: any): SubscribePacketsRequest { 172 | return {}; 173 | }, 174 | 175 | toJSON(_: SubscribePacketsRequest): unknown { 176 | const obj: any = {}; 177 | return obj; 178 | }, 179 | 180 | create, I>>(base?: I): SubscribePacketsRequest { 181 | return SubscribePacketsRequest.fromPartial(base ?? {}); 182 | }, 183 | 184 | fromPartial, I>>(_: I): SubscribePacketsRequest { 185 | const message = createBaseSubscribePacketsRequest(); 186 | return message; 187 | }, 188 | }; 189 | 190 | function createBaseSubscribePacketsResponse(): SubscribePacketsResponse { 191 | return { header: undefined, heartbeat: undefined, batch: undefined }; 192 | } 193 | 194 | export const SubscribePacketsResponse = { 195 | encode(message: SubscribePacketsResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 196 | if (message.header !== undefined) { 197 | Header.encode(message.header, writer.uint32(10).fork()).ldelim(); 198 | } 199 | if (message.heartbeat !== undefined) { 200 | Heartbeat.encode(message.heartbeat, writer.uint32(18).fork()).ldelim(); 201 | } 202 | if (message.batch !== undefined) { 203 | PacketBatch.encode(message.batch, writer.uint32(26).fork()).ldelim(); 204 | } 205 | return writer; 206 | }, 207 | 208 | decode(input: _m0.Reader | Uint8Array, length?: number): SubscribePacketsResponse { 209 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 210 | let end = length === undefined ? reader.len : reader.pos + length; 211 | const message = createBaseSubscribePacketsResponse(); 212 | while (reader.pos < end) { 213 | const tag = reader.uint32(); 214 | switch (tag >>> 3) { 215 | case 1: 216 | message.header = Header.decode(reader, reader.uint32()); 217 | break; 218 | case 2: 219 | message.heartbeat = Heartbeat.decode(reader, reader.uint32()); 220 | break; 221 | case 3: 222 | message.batch = PacketBatch.decode(reader, reader.uint32()); 223 | break; 224 | default: 225 | reader.skipType(tag & 7); 226 | break; 227 | } 228 | } 229 | return message; 230 | }, 231 | 232 | fromJSON(object: any): SubscribePacketsResponse { 233 | return { 234 | header: isSet(object.header) ? Header.fromJSON(object.header) : undefined, 235 | heartbeat: isSet(object.heartbeat) ? Heartbeat.fromJSON(object.heartbeat) : undefined, 236 | batch: isSet(object.batch) ? PacketBatch.fromJSON(object.batch) : undefined, 237 | }; 238 | }, 239 | 240 | toJSON(message: SubscribePacketsResponse): unknown { 241 | const obj: any = {}; 242 | message.header !== undefined && (obj.header = message.header ? Header.toJSON(message.header) : undefined); 243 | message.heartbeat !== undefined && 244 | (obj.heartbeat = message.heartbeat ? Heartbeat.toJSON(message.heartbeat) : undefined); 245 | message.batch !== undefined && (obj.batch = message.batch ? PacketBatch.toJSON(message.batch) : undefined); 246 | return obj; 247 | }, 248 | 249 | create, I>>(base?: I): SubscribePacketsResponse { 250 | return SubscribePacketsResponse.fromPartial(base ?? {}); 251 | }, 252 | 253 | fromPartial, I>>(object: I): SubscribePacketsResponse { 254 | const message = createBaseSubscribePacketsResponse(); 255 | message.header = (object.header !== undefined && object.header !== null) 256 | ? Header.fromPartial(object.header) 257 | : undefined; 258 | message.heartbeat = (object.heartbeat !== undefined && object.heartbeat !== null) 259 | ? Heartbeat.fromPartial(object.heartbeat) 260 | : undefined; 261 | message.batch = (object.batch !== undefined && object.batch !== null) 262 | ? PacketBatch.fromPartial(object.batch) 263 | : undefined; 264 | return message; 265 | }, 266 | }; 267 | 268 | /** 269 | * / Relayers offer a TPU and TPU forward proxy for Solana validators. 270 | * / Validators can connect and fetch the TPU configuration for the relayer and start to advertise the 271 | * / relayer's information in gossip. 272 | * / They can also subscribe to packets which arrived on the TPU ports at the relayer 273 | */ 274 | export type RelayerService = typeof RelayerService; 275 | export const RelayerService = { 276 | /** 277 | * The relayer has TPU and TPU forward sockets that validators can leverage. 278 | * A validator can fetch this config and change its TPU and TPU forward port in gossip. 279 | */ 280 | getTpuConfigs: { 281 | path: "/relayer.Relayer/GetTpuConfigs", 282 | requestStream: false, 283 | responseStream: false, 284 | requestSerialize: (value: GetTpuConfigsRequest) => Buffer.from(GetTpuConfigsRequest.encode(value).finish()), 285 | requestDeserialize: (value: Buffer) => GetTpuConfigsRequest.decode(value), 286 | responseSerialize: (value: GetTpuConfigsResponse) => Buffer.from(GetTpuConfigsResponse.encode(value).finish()), 287 | responseDeserialize: (value: Buffer) => GetTpuConfigsResponse.decode(value), 288 | }, 289 | /** 290 | * Validators can subscribe to packets from the relayer and receive a multiplexed signal that contains a mixture 291 | * of packets and heartbeats 292 | */ 293 | subscribePackets: { 294 | path: "/relayer.Relayer/SubscribePackets", 295 | requestStream: false, 296 | responseStream: true, 297 | requestSerialize: (value: SubscribePacketsRequest) => Buffer.from(SubscribePacketsRequest.encode(value).finish()), 298 | requestDeserialize: (value: Buffer) => SubscribePacketsRequest.decode(value), 299 | responseSerialize: (value: SubscribePacketsResponse) => 300 | Buffer.from(SubscribePacketsResponse.encode(value).finish()), 301 | responseDeserialize: (value: Buffer) => SubscribePacketsResponse.decode(value), 302 | }, 303 | } as const; 304 | 305 | export interface RelayerServer extends UntypedServiceImplementation { 306 | /** 307 | * The relayer has TPU and TPU forward sockets that validators can leverage. 308 | * A validator can fetch this config and change its TPU and TPU forward port in gossip. 309 | */ 310 | getTpuConfigs: handleUnaryCall; 311 | /** 312 | * Validators can subscribe to packets from the relayer and receive a multiplexed signal that contains a mixture 313 | * of packets and heartbeats 314 | */ 315 | subscribePackets: handleServerStreamingCall; 316 | } 317 | 318 | export interface RelayerClient extends Client { 319 | /** 320 | * The relayer has TPU and TPU forward sockets that validators can leverage. 321 | * A validator can fetch this config and change its TPU and TPU forward port in gossip. 322 | */ 323 | getTpuConfigs( 324 | request: GetTpuConfigsRequest, 325 | callback: (error: ServiceError | null, response: GetTpuConfigsResponse) => void, 326 | ): ClientUnaryCall; 327 | getTpuConfigs( 328 | request: GetTpuConfigsRequest, 329 | metadata: Metadata, 330 | callback: (error: ServiceError | null, response: GetTpuConfigsResponse) => void, 331 | ): ClientUnaryCall; 332 | getTpuConfigs( 333 | request: GetTpuConfigsRequest, 334 | metadata: Metadata, 335 | options: Partial, 336 | callback: (error: ServiceError | null, response: GetTpuConfigsResponse) => void, 337 | ): ClientUnaryCall; 338 | /** 339 | * Validators can subscribe to packets from the relayer and receive a multiplexed signal that contains a mixture 340 | * of packets and heartbeats 341 | */ 342 | subscribePackets( 343 | request: SubscribePacketsRequest, 344 | options?: Partial, 345 | ): ClientReadableStream; 346 | subscribePackets( 347 | request: SubscribePacketsRequest, 348 | metadata?: Metadata, 349 | options?: Partial, 350 | ): ClientReadableStream; 351 | } 352 | 353 | export const RelayerClient = makeGenericClientConstructor(RelayerService, "relayer.Relayer") as unknown as { 354 | new (address: string, credentials: ChannelCredentials, options?: Partial): RelayerClient; 355 | service: typeof RelayerService; 356 | }; 357 | 358 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 359 | 360 | export type DeepPartial = T extends Builtin ? T 361 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 362 | : T extends {} ? { [K in keyof T]?: DeepPartial } 363 | : Partial; 364 | 365 | type KeysOfUnion = T extends T ? keyof T : never; 366 | export type Exact = P extends Builtin ? P 367 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 368 | 369 | function isSet(value: any): boolean { 370 | return value !== null && value !== undefined; 371 | } 372 | -------------------------------------------------------------------------------- /src/gen/block-engine/shared.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | import { Timestamp } from "./google/protobuf/timestamp"; 5 | 6 | export const protobufPackage = "shared"; 7 | 8 | export interface Header { 9 | ts: Date | undefined; 10 | } 11 | 12 | export interface Heartbeat { 13 | count: number; 14 | } 15 | 16 | export interface Socket { 17 | ip: string; 18 | port: number; 19 | } 20 | 21 | function createBaseHeader(): Header { 22 | return { ts: undefined }; 23 | } 24 | 25 | export const Header = { 26 | encode(message: Header, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 27 | if (message.ts !== undefined) { 28 | Timestamp.encode(toTimestamp(message.ts), writer.uint32(10).fork()).ldelim(); 29 | } 30 | return writer; 31 | }, 32 | 33 | decode(input: _m0.Reader | Uint8Array, length?: number): Header { 34 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 35 | let end = length === undefined ? reader.len : reader.pos + length; 36 | const message = createBaseHeader(); 37 | while (reader.pos < end) { 38 | const tag = reader.uint32(); 39 | switch (tag >>> 3) { 40 | case 1: 41 | message.ts = fromTimestamp(Timestamp.decode(reader, reader.uint32())); 42 | break; 43 | default: 44 | reader.skipType(tag & 7); 45 | break; 46 | } 47 | } 48 | return message; 49 | }, 50 | 51 | fromJSON(object: any): Header { 52 | return { ts: isSet(object.ts) ? fromJsonTimestamp(object.ts) : undefined }; 53 | }, 54 | 55 | toJSON(message: Header): unknown { 56 | const obj: any = {}; 57 | message.ts !== undefined && (obj.ts = message.ts.toISOString()); 58 | return obj; 59 | }, 60 | 61 | create, I>>(base?: I): Header { 62 | return Header.fromPartial(base ?? {}); 63 | }, 64 | 65 | fromPartial, I>>(object: I): Header { 66 | const message = createBaseHeader(); 67 | message.ts = object.ts ?? undefined; 68 | return message; 69 | }, 70 | }; 71 | 72 | function createBaseHeartbeat(): Heartbeat { 73 | return { count: 0 }; 74 | } 75 | 76 | export const Heartbeat = { 77 | encode(message: Heartbeat, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 78 | if (message.count !== 0) { 79 | writer.uint32(8).uint64(message.count); 80 | } 81 | return writer; 82 | }, 83 | 84 | decode(input: _m0.Reader | Uint8Array, length?: number): Heartbeat { 85 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 86 | let end = length === undefined ? reader.len : reader.pos + length; 87 | const message = createBaseHeartbeat(); 88 | while (reader.pos < end) { 89 | const tag = reader.uint32(); 90 | switch (tag >>> 3) { 91 | case 1: 92 | message.count = longToNumber(reader.uint64() as Long); 93 | break; 94 | default: 95 | reader.skipType(tag & 7); 96 | break; 97 | } 98 | } 99 | return message; 100 | }, 101 | 102 | fromJSON(object: any): Heartbeat { 103 | return { count: isSet(object.count) ? Number(object.count) : 0 }; 104 | }, 105 | 106 | toJSON(message: Heartbeat): unknown { 107 | const obj: any = {}; 108 | message.count !== undefined && (obj.count = Math.round(message.count)); 109 | return obj; 110 | }, 111 | 112 | create, I>>(base?: I): Heartbeat { 113 | return Heartbeat.fromPartial(base ?? {}); 114 | }, 115 | 116 | fromPartial, I>>(object: I): Heartbeat { 117 | const message = createBaseHeartbeat(); 118 | message.count = object.count ?? 0; 119 | return message; 120 | }, 121 | }; 122 | 123 | function createBaseSocket(): Socket { 124 | return { ip: "", port: 0 }; 125 | } 126 | 127 | export const Socket = { 128 | encode(message: Socket, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 129 | if (message.ip !== "") { 130 | writer.uint32(10).string(message.ip); 131 | } 132 | if (message.port !== 0) { 133 | writer.uint32(16).int64(message.port); 134 | } 135 | return writer; 136 | }, 137 | 138 | decode(input: _m0.Reader | Uint8Array, length?: number): Socket { 139 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 140 | let end = length === undefined ? reader.len : reader.pos + length; 141 | const message = createBaseSocket(); 142 | while (reader.pos < end) { 143 | const tag = reader.uint32(); 144 | switch (tag >>> 3) { 145 | case 1: 146 | message.ip = reader.string(); 147 | break; 148 | case 2: 149 | message.port = longToNumber(reader.int64() as Long); 150 | break; 151 | default: 152 | reader.skipType(tag & 7); 153 | break; 154 | } 155 | } 156 | return message; 157 | }, 158 | 159 | fromJSON(object: any): Socket { 160 | return { ip: isSet(object.ip) ? String(object.ip) : "", port: isSet(object.port) ? Number(object.port) : 0 }; 161 | }, 162 | 163 | toJSON(message: Socket): unknown { 164 | const obj: any = {}; 165 | message.ip !== undefined && (obj.ip = message.ip); 166 | message.port !== undefined && (obj.port = Math.round(message.port)); 167 | return obj; 168 | }, 169 | 170 | create, I>>(base?: I): Socket { 171 | return Socket.fromPartial(base ?? {}); 172 | }, 173 | 174 | fromPartial, I>>(object: I): Socket { 175 | const message = createBaseSocket(); 176 | message.ip = object.ip ?? ""; 177 | message.port = object.port ?? 0; 178 | return message; 179 | }, 180 | }; 181 | 182 | declare var self: any | undefined; 183 | declare var window: any | undefined; 184 | declare var global: any | undefined; 185 | var tsProtoGlobalThis: any = (() => { 186 | if (typeof globalThis !== "undefined") { 187 | return globalThis; 188 | } 189 | if (typeof self !== "undefined") { 190 | return self; 191 | } 192 | if (typeof window !== "undefined") { 193 | return window; 194 | } 195 | if (typeof global !== "undefined") { 196 | return global; 197 | } 198 | throw "Unable to locate global object"; 199 | })(); 200 | 201 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 202 | 203 | export type DeepPartial = T extends Builtin ? T 204 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 205 | : T extends {} ? { [K in keyof T]?: DeepPartial } 206 | : Partial; 207 | 208 | type KeysOfUnion = T extends T ? keyof T : never; 209 | export type Exact = P extends Builtin ? P 210 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 211 | 212 | function toTimestamp(date: Date): Timestamp { 213 | const seconds = date.getTime() / 1_000; 214 | const nanos = (date.getTime() % 1_000) * 1_000_000; 215 | return { seconds, nanos }; 216 | } 217 | 218 | function fromTimestamp(t: Timestamp): Date { 219 | let millis = t.seconds * 1_000; 220 | millis += t.nanos / 1_000_000; 221 | return new Date(millis); 222 | } 223 | 224 | function fromJsonTimestamp(o: any): Date { 225 | if (o instanceof Date) { 226 | return o; 227 | } else if (typeof o === "string") { 228 | return new Date(o); 229 | } else { 230 | return fromTimestamp(Timestamp.fromJSON(o)); 231 | } 232 | } 233 | 234 | function longToNumber(long: Long): number { 235 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 236 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 237 | } 238 | return long.toNumber(); 239 | } 240 | 241 | if (_m0.util.Long !== Long) { 242 | _m0.util.Long = Long as any; 243 | _m0.configure(); 244 | } 245 | 246 | function isSet(value: any): boolean { 247 | return value !== null && value !== undefined; 248 | } 249 | -------------------------------------------------------------------------------- /src/gen/block-engine/shredstream.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { 3 | CallOptions, 4 | ChannelCredentials, 5 | Client, 6 | ClientOptions, 7 | ClientUnaryCall, 8 | handleUnaryCall, 9 | makeGenericClientConstructor, 10 | Metadata, 11 | ServiceError, 12 | UntypedServiceImplementation, 13 | } from "@grpc/grpc-js"; 14 | import _m0 from "protobufjs/minimal"; 15 | import { Socket } from "./shared"; 16 | 17 | export const protobufPackage = "shredstream"; 18 | 19 | export interface Heartbeat { 20 | /** 21 | * don't trust IP:PORT from tcp header since it can be tampered over the wire 22 | * `socket.ip` must match incoming packet's ip. this prevents spamming an unwitting destination 23 | */ 24 | socket: 25 | | Socket 26 | | undefined; 27 | /** 28 | * regions for shredstream proxy to receive shreds from 29 | * list of valid regions: https://jito-labs.gitbook.io/mev/systems/connecting/mainnet 30 | */ 31 | regions: string[]; 32 | } 33 | 34 | export interface HeartbeatResponse { 35 | /** client must respond within `ttl_ms` to keep stream alive */ 36 | ttlMs: number; 37 | } 38 | 39 | function createBaseHeartbeat(): Heartbeat { 40 | return { socket: undefined, regions: [] }; 41 | } 42 | 43 | export const Heartbeat = { 44 | encode(message: Heartbeat, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 45 | if (message.socket !== undefined) { 46 | Socket.encode(message.socket, writer.uint32(10).fork()).ldelim(); 47 | } 48 | for (const v of message.regions) { 49 | writer.uint32(18).string(v!); 50 | } 51 | return writer; 52 | }, 53 | 54 | decode(input: _m0.Reader | Uint8Array, length?: number): Heartbeat { 55 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 56 | let end = length === undefined ? reader.len : reader.pos + length; 57 | const message = createBaseHeartbeat(); 58 | while (reader.pos < end) { 59 | const tag = reader.uint32(); 60 | switch (tag >>> 3) { 61 | case 1: 62 | message.socket = Socket.decode(reader, reader.uint32()); 63 | break; 64 | case 2: 65 | message.regions.push(reader.string()); 66 | break; 67 | default: 68 | reader.skipType(tag & 7); 69 | break; 70 | } 71 | } 72 | return message; 73 | }, 74 | 75 | fromJSON(object: any): Heartbeat { 76 | return { 77 | socket: isSet(object.socket) ? Socket.fromJSON(object.socket) : undefined, 78 | regions: Array.isArray(object?.regions) ? object.regions.map((e: any) => String(e)) : [], 79 | }; 80 | }, 81 | 82 | toJSON(message: Heartbeat): unknown { 83 | const obj: any = {}; 84 | message.socket !== undefined && (obj.socket = message.socket ? Socket.toJSON(message.socket) : undefined); 85 | if (message.regions) { 86 | obj.regions = message.regions.map((e) => e); 87 | } else { 88 | obj.regions = []; 89 | } 90 | return obj; 91 | }, 92 | 93 | create, I>>(base?: I): Heartbeat { 94 | return Heartbeat.fromPartial(base ?? {}); 95 | }, 96 | 97 | fromPartial, I>>(object: I): Heartbeat { 98 | const message = createBaseHeartbeat(); 99 | message.socket = (object.socket !== undefined && object.socket !== null) 100 | ? Socket.fromPartial(object.socket) 101 | : undefined; 102 | message.regions = object.regions?.map((e) => e) || []; 103 | return message; 104 | }, 105 | }; 106 | 107 | function createBaseHeartbeatResponse(): HeartbeatResponse { 108 | return { ttlMs: 0 }; 109 | } 110 | 111 | export const HeartbeatResponse = { 112 | encode(message: HeartbeatResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 113 | if (message.ttlMs !== 0) { 114 | writer.uint32(8).uint32(message.ttlMs); 115 | } 116 | return writer; 117 | }, 118 | 119 | decode(input: _m0.Reader | Uint8Array, length?: number): HeartbeatResponse { 120 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 121 | let end = length === undefined ? reader.len : reader.pos + length; 122 | const message = createBaseHeartbeatResponse(); 123 | while (reader.pos < end) { 124 | const tag = reader.uint32(); 125 | switch (tag >>> 3) { 126 | case 1: 127 | message.ttlMs = reader.uint32(); 128 | break; 129 | default: 130 | reader.skipType(tag & 7); 131 | break; 132 | } 133 | } 134 | return message; 135 | }, 136 | 137 | fromJSON(object: any): HeartbeatResponse { 138 | return { ttlMs: isSet(object.ttlMs) ? Number(object.ttlMs) : 0 }; 139 | }, 140 | 141 | toJSON(message: HeartbeatResponse): unknown { 142 | const obj: any = {}; 143 | message.ttlMs !== undefined && (obj.ttlMs = Math.round(message.ttlMs)); 144 | return obj; 145 | }, 146 | 147 | create, I>>(base?: I): HeartbeatResponse { 148 | return HeartbeatResponse.fromPartial(base ?? {}); 149 | }, 150 | 151 | fromPartial, I>>(object: I): HeartbeatResponse { 152 | const message = createBaseHeartbeatResponse(); 153 | message.ttlMs = object.ttlMs ?? 0; 154 | return message; 155 | }, 156 | }; 157 | 158 | export type ShredstreamService = typeof ShredstreamService; 159 | export const ShredstreamService = { 160 | /** RPC endpoint to send heartbeats to keep shreds flowing */ 161 | sendHeartbeat: { 162 | path: "/shredstream.Shredstream/SendHeartbeat", 163 | requestStream: false, 164 | responseStream: false, 165 | requestSerialize: (value: Heartbeat) => Buffer.from(Heartbeat.encode(value).finish()), 166 | requestDeserialize: (value: Buffer) => Heartbeat.decode(value), 167 | responseSerialize: (value: HeartbeatResponse) => Buffer.from(HeartbeatResponse.encode(value).finish()), 168 | responseDeserialize: (value: Buffer) => HeartbeatResponse.decode(value), 169 | }, 170 | } as const; 171 | 172 | export interface ShredstreamServer extends UntypedServiceImplementation { 173 | /** RPC endpoint to send heartbeats to keep shreds flowing */ 174 | sendHeartbeat: handleUnaryCall; 175 | } 176 | 177 | export interface ShredstreamClient extends Client { 178 | /** RPC endpoint to send heartbeats to keep shreds flowing */ 179 | sendHeartbeat( 180 | request: Heartbeat, 181 | callback: (error: ServiceError | null, response: HeartbeatResponse) => void, 182 | ): ClientUnaryCall; 183 | sendHeartbeat( 184 | request: Heartbeat, 185 | metadata: Metadata, 186 | callback: (error: ServiceError | null, response: HeartbeatResponse) => void, 187 | ): ClientUnaryCall; 188 | sendHeartbeat( 189 | request: Heartbeat, 190 | metadata: Metadata, 191 | options: Partial, 192 | callback: (error: ServiceError | null, response: HeartbeatResponse) => void, 193 | ): ClientUnaryCall; 194 | } 195 | 196 | export const ShredstreamClient = makeGenericClientConstructor( 197 | ShredstreamService, 198 | "shredstream.Shredstream", 199 | ) as unknown as { 200 | new (address: string, credentials: ChannelCredentials, options?: Partial): ShredstreamClient; 201 | service: typeof ShredstreamService; 202 | }; 203 | 204 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 205 | 206 | export type DeepPartial = T extends Builtin ? T 207 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 208 | : T extends {} ? { [K in keyof T]?: DeepPartial } 209 | : Partial; 210 | 211 | type KeysOfUnion = T extends T ? keyof T : never; 212 | export type Exact = P extends Builtin ? P 213 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 214 | 215 | function isSet(value: any): boolean { 216 | return value !== null && value !== undefined; 217 | } 218 | -------------------------------------------------------------------------------- /src/gen/geyser/google/protobuf/timestamp.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Long from "long"; 3 | import _m0 from "protobufjs/minimal"; 4 | 5 | export const protobufPackage = "google.protobuf"; 6 | 7 | /** 8 | * A Timestamp represents a point in time independent of any time zone or local 9 | * calendar, encoded as a count of seconds and fractions of seconds at 10 | * nanosecond resolution. The count is relative to an epoch at UTC midnight on 11 | * January 1, 1970, in the proleptic Gregorian calendar which extends the 12 | * Gregorian calendar backwards to year one. 13 | * 14 | * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap 15 | * second table is needed for interpretation, using a [24-hour linear 16 | * smear](https://developers.google.com/time/smear). 17 | * 18 | * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By 19 | * restricting to that range, we ensure that we can convert to and from [RFC 20 | * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. 21 | * 22 | * # Examples 23 | * 24 | * Example 1: Compute Timestamp from POSIX `time()`. 25 | * 26 | * Timestamp timestamp; 27 | * timestamp.set_seconds(time(NULL)); 28 | * timestamp.set_nanos(0); 29 | * 30 | * Example 2: Compute Timestamp from POSIX `gettimeofday()`. 31 | * 32 | * struct timeval tv; 33 | * gettimeofday(&tv, NULL); 34 | * 35 | * Timestamp timestamp; 36 | * timestamp.set_seconds(tv.tv_sec); 37 | * timestamp.set_nanos(tv.tv_usec * 1000); 38 | * 39 | * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 40 | * 41 | * FILETIME ft; 42 | * GetSystemTimeAsFileTime(&ft); 43 | * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 44 | * 45 | * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 46 | * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 47 | * Timestamp timestamp; 48 | * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 49 | * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 50 | * 51 | * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 52 | * 53 | * long millis = System.currentTimeMillis(); 54 | * 55 | * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 56 | * .setNanos((int) ((millis % 1000) * 1000000)).build(); 57 | * 58 | * Example 5: Compute Timestamp from Java `Instant.now()`. 59 | * 60 | * Instant now = Instant.now(); 61 | * 62 | * Timestamp timestamp = 63 | * Timestamp.newBuilder().setSeconds(now.getEpochSecond()) 64 | * .setNanos(now.getNano()).build(); 65 | * 66 | * Example 6: Compute Timestamp from current time in Python. 67 | * 68 | * timestamp = Timestamp() 69 | * timestamp.GetCurrentTime() 70 | * 71 | * # JSON Mapping 72 | * 73 | * In JSON format, the Timestamp type is encoded as a string in the 74 | * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 75 | * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 76 | * where {year} is always expressed using four digits while {month}, {day}, 77 | * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 78 | * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 79 | * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 80 | * is required. A proto3 JSON serializer should always use UTC (as indicated by 81 | * "Z") when printing the Timestamp type and a proto3 JSON parser should be 82 | * able to accept both UTC and other timezones (as indicated by an offset). 83 | * 84 | * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 85 | * 01:30 UTC on January 15, 2017. 86 | * 87 | * In JavaScript, one can convert a Date object to this format using the 88 | * standard 89 | * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) 90 | * method. In Python, a standard `datetime.datetime` object can be converted 91 | * to this format using 92 | * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with 93 | * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use 94 | * the Joda Time's [`ISODateTimeFormat.dateTime()`]( 95 | * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D 96 | * ) to obtain a formatter capable of generating timestamps in this format. 97 | */ 98 | export interface Timestamp { 99 | /** 100 | * Represents seconds of UTC time since Unix epoch 101 | * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 102 | * 9999-12-31T23:59:59Z inclusive. 103 | */ 104 | seconds: number; 105 | /** 106 | * Non-negative fractions of a second at nanosecond resolution. Negative 107 | * second values with fractions must still have non-negative nanos values 108 | * that count forward in time. Must be from 0 to 999,999,999 109 | * inclusive. 110 | */ 111 | nanos: number; 112 | } 113 | 114 | function createBaseTimestamp(): Timestamp { 115 | return { seconds: 0, nanos: 0 }; 116 | } 117 | 118 | export const Timestamp = { 119 | encode(message: Timestamp, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { 120 | if (message.seconds !== 0) { 121 | writer.uint32(8).int64(message.seconds); 122 | } 123 | if (message.nanos !== 0) { 124 | writer.uint32(16).int32(message.nanos); 125 | } 126 | return writer; 127 | }, 128 | 129 | decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp { 130 | const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); 131 | let end = length === undefined ? reader.len : reader.pos + length; 132 | const message = createBaseTimestamp(); 133 | while (reader.pos < end) { 134 | const tag = reader.uint32(); 135 | switch (tag >>> 3) { 136 | case 1: 137 | message.seconds = longToNumber(reader.int64() as Long); 138 | break; 139 | case 2: 140 | message.nanos = reader.int32(); 141 | break; 142 | default: 143 | reader.skipType(tag & 7); 144 | break; 145 | } 146 | } 147 | return message; 148 | }, 149 | 150 | fromJSON(object: any): Timestamp { 151 | return { 152 | seconds: isSet(object.seconds) ? Number(object.seconds) : 0, 153 | nanos: isSet(object.nanos) ? Number(object.nanos) : 0, 154 | }; 155 | }, 156 | 157 | toJSON(message: Timestamp): unknown { 158 | const obj: any = {}; 159 | message.seconds !== undefined && (obj.seconds = Math.round(message.seconds)); 160 | message.nanos !== undefined && (obj.nanos = Math.round(message.nanos)); 161 | return obj; 162 | }, 163 | 164 | create, I>>(base?: I): Timestamp { 165 | return Timestamp.fromPartial(base ?? {}); 166 | }, 167 | 168 | fromPartial, I>>(object: I): Timestamp { 169 | const message = createBaseTimestamp(); 170 | message.seconds = object.seconds ?? 0; 171 | message.nanos = object.nanos ?? 0; 172 | return message; 173 | }, 174 | }; 175 | 176 | declare var self: any | undefined; 177 | declare var window: any | undefined; 178 | declare var global: any | undefined; 179 | var tsProtoGlobalThis: any = (() => { 180 | if (typeof globalThis !== "undefined") { 181 | return globalThis; 182 | } 183 | if (typeof self !== "undefined") { 184 | return self; 185 | } 186 | if (typeof window !== "undefined") { 187 | return window; 188 | } 189 | if (typeof global !== "undefined") { 190 | return global; 191 | } 192 | throw "Unable to locate global object"; 193 | })(); 194 | 195 | type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; 196 | 197 | export type DeepPartial = T extends Builtin ? T 198 | : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> 199 | : T extends {} ? { [K in keyof T]?: DeepPartial } 200 | : Partial; 201 | 202 | type KeysOfUnion = T extends T ? keyof T : never; 203 | export type Exact = P extends Builtin ? P 204 | : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; 205 | 206 | function longToNumber(long: Long): number { 207 | if (long.gt(Number.MAX_SAFE_INTEGER)) { 208 | throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER"); 209 | } 210 | return long.toNumber(); 211 | } 212 | 213 | if (_m0.util.Long !== Long) { 214 | _m0.util.Long = Long as any; 215 | _m0.configure(); 216 | } 217 | 218 | function isSet(value: any): boolean { 219 | return value !== null && value !== undefined; 220 | } 221 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './sdk'; 2 | -------------------------------------------------------------------------------- /src/sdk/block-engine/auth.ts: -------------------------------------------------------------------------------- 1 | import * as ed from '@noble/ed25519'; 2 | import { 3 | InterceptingCall, 4 | Interceptor, 5 | InterceptorOptions, 6 | Listener, 7 | Metadata, 8 | ServiceError, 9 | } from '@grpc/grpc-js'; 10 | 11 | import {Keypair} from '@solana/web3.js'; 12 | import {NextCall} from '@grpc/grpc-js/build/src/client-interceptors'; 13 | 14 | import { 15 | AuthServiceClient, 16 | GenerateAuthChallengeRequest, 17 | GenerateAuthChallengeResponse, 18 | GenerateAuthTokensRequest, 19 | GenerateAuthTokensResponse, 20 | RefreshAccessTokenRequest, 21 | RefreshAccessTokenResponse, 22 | Role, 23 | Token, 24 | } from '../../gen/block-engine/auth'; 25 | import {unixTimestampFromDate} from './utils'; 26 | 27 | // Intercepts requests and sets the auth header. 28 | export const authInterceptor = (authProvider: AuthProvider): Interceptor => { 29 | return (opts: InterceptorOptions, nextCall: NextCall) => { 30 | return new InterceptingCall(nextCall(opts), { 31 | start: async function (metadata: Metadata, listener: Listener, next) { 32 | const callback = (accessToken: Jwt) => { 33 | metadata.set('authorization', `Bearer ${accessToken.token}`); 34 | next(metadata, listener); 35 | }; 36 | authProvider.injectAccessToken(callback); 37 | }, 38 | }); 39 | }; 40 | }; 41 | 42 | // Represents server issued JWT tokens. 43 | export class Jwt { 44 | readonly token: string; 45 | private readonly expiration: number; 46 | 47 | constructor(token: string, expiration: number) { 48 | this.token = token; 49 | this.expiration = expiration; 50 | } 51 | 52 | isExpired(): boolean { 53 | const now: number = unixTimestampFromDate(new Date()); 54 | return this.expiration <= now; 55 | } 56 | } 57 | 58 | // Handles requesting and refreshing tokens, providing them via callbacks. 59 | export class AuthProvider { 60 | private client: AuthServiceClient; 61 | private readonly authKeypair: Keypair; 62 | private accessToken: Jwt | undefined; 63 | private refreshToken: Jwt | undefined; 64 | private refreshing: Promise | null = null; 65 | 66 | constructor(client: AuthServiceClient, authKeypair: Keypair) { 67 | this.client = client; 68 | this.authKeypair = authKeypair; 69 | } 70 | 71 | // Injects the current access token into the provided callback. 72 | // If it's expired then refreshes, if the refresh token is expired then runs the full auth flow. 73 | public injectAccessToken(callback: (accessToken: Jwt) => void) { 74 | if ( 75 | !this.accessToken || 76 | !this.refreshToken || 77 | this.refreshToken.isExpired() 78 | ) { 79 | this.fullAuth((accessToken: Jwt, refreshToken: Jwt) => { 80 | this.accessToken = accessToken; 81 | this.refreshToken = refreshToken; 82 | callback(accessToken); 83 | }); 84 | 85 | return; 86 | } 87 | 88 | if (!this.accessToken?.isExpired()) { 89 | callback(this.accessToken); 90 | return; 91 | } 92 | 93 | if (!this.refreshing) { 94 | this.refreshing = this.refreshAccessToken().finally(() => { 95 | this.refreshing = null; 96 | }); 97 | } 98 | 99 | this.refreshing.then(() => { 100 | if (this.accessToken) { 101 | callback(this.accessToken); 102 | } 103 | }); 104 | } 105 | 106 | // Refresh access token. 107 | private async refreshAccessToken() { 108 | return new Promise((resolve, reject) => { 109 | this.client.refreshAccessToken( 110 | { 111 | refreshToken: this.refreshToken?.token, 112 | } as RefreshAccessTokenRequest, 113 | async (e: ServiceError | null, resp: RefreshAccessTokenResponse) => { 114 | if (e) { 115 | return reject(e); 116 | } 117 | 118 | if (!AuthProvider.isValidToken(resp.accessToken)) { 119 | return reject(`received invalid access token ${resp.accessToken}`); 120 | } 121 | this.accessToken = new Jwt( 122 | resp.accessToken?.value || '', 123 | unixTimestampFromDate(resp.accessToken?.expiresAtUtc || new Date()) 124 | ); 125 | resolve(); 126 | } 127 | ); 128 | }); 129 | } 130 | 131 | // Creates an AuthProvider object, and asynchronously performs full authentication flow. 132 | public static async create( 133 | client: AuthServiceClient, 134 | authKeypair: Keypair 135 | ): Promise { 136 | const provider = new AuthProvider(client, authKeypair); 137 | await provider.fullAuth((accessToken: Jwt, refreshToken: Jwt) => { 138 | provider.accessToken = accessToken; 139 | provider.refreshToken = refreshToken; 140 | }); 141 | 142 | return provider; 143 | } 144 | 145 | // Run entire auth flow: 146 | // - fetch a server generated challenge 147 | // - sign the challenge and submit in exchange for an access and refresh token 148 | // - inject the tokens into the provided callback 149 | private fullAuth( 150 | callback: (accessToken: Jwt, refreshToken: Jwt) => void 151 | ): void { 152 | this.client.generateAuthChallenge( 153 | { 154 | role: Role.SEARCHER, 155 | pubkey: this.authKeypair.publicKey.toBytes(), 156 | } as GenerateAuthChallengeRequest, 157 | async (e: ServiceError | null, resp: GenerateAuthChallengeResponse) => { 158 | if (e) { 159 | throw e; 160 | } 161 | 162 | // Append pubkey to ensure what we're signing is garbage. 163 | const challenge = `${this.authKeypair.publicKey.toString()}-${ 164 | resp.challenge 165 | }`; 166 | const signedChallenge = await ed.sign( 167 | Buffer.from(challenge), 168 | // First 32 bytes is the private key, last 32 public key. 169 | this.authKeypair.secretKey.slice(0, 32) 170 | ); 171 | 172 | this.client.generateAuthTokens( 173 | { 174 | challenge, 175 | clientPubkey: this.authKeypair.publicKey.toBytes(), 176 | signedChallenge, 177 | } as GenerateAuthTokensRequest, 178 | (e: ServiceError | null, resp: GenerateAuthTokensResponse) => { 179 | if (e) { 180 | throw e; 181 | } 182 | 183 | if (!AuthProvider.isValidToken(resp.accessToken)) { 184 | throw `received invalid access token ${resp.accessToken}`; 185 | } 186 | const accessToken = new Jwt( 187 | resp.accessToken?.value || '', 188 | unixTimestampFromDate( 189 | resp.accessToken?.expiresAtUtc || new Date() 190 | ) 191 | ); 192 | 193 | if (!AuthProvider.isValidToken(resp.refreshToken)) { 194 | throw `received invalid refresh token ${resp.refreshToken}`; 195 | } 196 | const refreshToken = new Jwt( 197 | resp.refreshToken?.value || '', 198 | unixTimestampFromDate( 199 | resp.refreshToken?.expiresAtUtc || new Date() 200 | ) 201 | ); 202 | 203 | callback(accessToken, refreshToken); 204 | } 205 | ); 206 | } 207 | ); 208 | } 209 | 210 | private static isValidToken(token: Token | undefined) { 211 | if (!token) { 212 | return false; 213 | } 214 | if (!token.expiresAtUtc) { 215 | return false; 216 | } 217 | 218 | return true; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/sdk/block-engine/index.ts: -------------------------------------------------------------------------------- 1 | export * as bundle from './types'; 2 | export * as searcher from './searcher'; 3 | -------------------------------------------------------------------------------- /src/sdk/block-engine/searcher.ts: -------------------------------------------------------------------------------- 1 | import {Keypair} from '@solana/web3.js'; 2 | import { 3 | ChannelCredentials, 4 | ChannelOptions, 5 | ClientReadableStream, 6 | ServiceError, 7 | status, 8 | } from '@grpc/grpc-js'; 9 | 10 | import {AuthServiceClient} from '../../gen/block-engine/auth'; 11 | import {BundleResult} from '../../gen/block-engine/bundle'; 12 | import { 13 | ConnectedLeadersResponse, 14 | GetTipAccountsResponse, 15 | NextScheduledLeaderResponse, 16 | SearcherServiceClient, 17 | SendBundleRequest, 18 | SendBundleResponse, 19 | SlotList, 20 | } from '../../gen/block-engine/searcher'; 21 | import {authInterceptor, AuthProvider} from './auth'; 22 | import {Bundle} from './types'; 23 | import {Result, Ok, Err} from './utils'; 24 | 25 | export class SearcherClientError extends Error { 26 | constructor(public code: status, message: string, public details: string) { 27 | super(`${message}${details ? `: ${details}` : ''}`); 28 | this.name = 'SearcherClientError'; 29 | } 30 | } 31 | 32 | export class SearcherClient { 33 | private client: SearcherServiceClient; 34 | private readonly retryOptions: Readonly<{ 35 | maxRetries: number; 36 | baseDelay: number; 37 | maxDelay: number; 38 | factor: number; 39 | }>; 40 | 41 | constructor(client: SearcherServiceClient) { 42 | this.client = client; 43 | this.retryOptions = Object.freeze({ 44 | maxRetries: 3, 45 | baseDelay: 1000, 46 | maxDelay: 10000, 47 | factor: 2, 48 | }); 49 | } 50 | 51 | private handleError(e: ServiceError): SearcherClientError { 52 | const errorDetails = e.details || 'No additional details provided'; 53 | 54 | switch (e.code) { 55 | case status.OK: 56 | return new SearcherClientError(e.code, 'Unexpected OK status in error', errorDetails); 57 | case status.CANCELLED: 58 | return new SearcherClientError(e.code, 'The operation was cancelled', errorDetails); 59 | case status.UNKNOWN: 60 | return new SearcherClientError(e.code, 'Unknown error', errorDetails); 61 | case status.INVALID_ARGUMENT: 62 | return new SearcherClientError(e.code, 'Invalid argument provided', errorDetails); 63 | case status.DEADLINE_EXCEEDED: 64 | return new SearcherClientError(e.code, 'Deadline exceeded', errorDetails); 65 | case status.NOT_FOUND: 66 | return new SearcherClientError(e.code, 'Requested entity not found', errorDetails); 67 | case status.ALREADY_EXISTS: 68 | return new SearcherClientError(e.code, 'The entity already exists', errorDetails); 69 | case status.PERMISSION_DENIED: 70 | return new SearcherClientError(e.code, 'Lacking required permission', errorDetails); 71 | case status.RESOURCE_EXHAUSTED: 72 | return new SearcherClientError(e.code, 'Resource has been exhausted', errorDetails); 73 | case status.FAILED_PRECONDITION: 74 | return new SearcherClientError(e.code, 'Operation rejected, system not in correct state', errorDetails); 75 | case status.ABORTED: 76 | return new SearcherClientError(e.code, 'The operation was aborted', errorDetails); 77 | case status.OUT_OF_RANGE: 78 | return new SearcherClientError(e.code, 'Operation attempted past the valid range', errorDetails); 79 | case status.UNIMPLEMENTED: 80 | return new SearcherClientError(e.code, 'Operation not implemented or supported', errorDetails); 81 | case status.INTERNAL: 82 | return new SearcherClientError(e.code, 'Internal error', errorDetails); 83 | case status.UNAVAILABLE: 84 | let unavailableMessage = 'The service is currently unavailable'; 85 | if (errorDetails.includes('upstream connect error or disconnect/reset before headers')) { 86 | unavailableMessage = 'Service unavailable: Envoy overloaded'; 87 | } else if (errorDetails.toLowerCase().includes('dns resolution failed')) { 88 | unavailableMessage = 'Service unavailable: DNS resolution failed'; 89 | } else if (errorDetails.toLowerCase().includes('ssl handshake failed')) { 90 | unavailableMessage = 'Service unavailable: SSL handshake failed'; 91 | } else if (errorDetails.toLowerCase().includes('connection refused')) { 92 | unavailableMessage = 'Service unavailable: Connection refused'; 93 | } else if (errorDetails.toLowerCase().includes('network unreachable')) { 94 | unavailableMessage = 'Service unavailable: Network is unreachable'; 95 | } else if (errorDetails.toLowerCase().includes('timeout')) { 96 | unavailableMessage = 'Service unavailable: Connection timed out'; 97 | } 98 | return new SearcherClientError(e.code, unavailableMessage, errorDetails); 99 | case status.DATA_LOSS: 100 | return new SearcherClientError(e.code, 'Unrecoverable data loss or corruption', errorDetails); 101 | case status.UNAUTHENTICATED: 102 | return new SearcherClientError(e.code, 'Request not authenticated', errorDetails); 103 | default: 104 | return new SearcherClientError(status.UNKNOWN, `Unexpected error: ${e.message}`, errorDetails); 105 | } 106 | } 107 | 108 | private async retryWithBackoff( 109 | operation: () => Promise>, 110 | retries = 0 111 | ): Promise> { 112 | try { 113 | return await operation(); 114 | } catch (error) { 115 | if (retries >= this.retryOptions.maxRetries || !this.isRetryableError(error)) { 116 | return Err(error as SearcherClientError); 117 | } 118 | 119 | const delay = Math.min( 120 | this.retryOptions.baseDelay * Math.pow(this.retryOptions.factor, retries), 121 | this.retryOptions.maxDelay 122 | ); 123 | console.warn(`Operation failed. Retrying in ${delay}ms... (Attempt ${retries + 1} of ${this.retryOptions.maxRetries})`); 124 | await new Promise(resolve => setTimeout(resolve, delay)); 125 | 126 | return this.retryWithBackoff(operation, retries + 1); 127 | } 128 | } 129 | 130 | private isRetryableError(error: any): boolean { 131 | if (error instanceof SearcherClientError) { 132 | if (error.code === status.UNAVAILABLE) { 133 | const nonRetryableMessages = [ 134 | 'Service unavailable: DNS resolution failed', 135 | 'Service unavailable: SSL handshake failed' 136 | ]; 137 | return !nonRetryableMessages.some(msg => error.message.includes(msg)); 138 | } 139 | const retryableCodes = [ 140 | status.UNAVAILABLE, 141 | status.RESOURCE_EXHAUSTED, 142 | status.DEADLINE_EXCEEDED, 143 | ]; 144 | return retryableCodes.includes(error.code); 145 | } 146 | return false; 147 | } 148 | 149 | /** 150 | * Submits a bundle to the block-engine. 151 | * 152 | * @param bundle - The Bundle object to be sent. 153 | * @returns A Promise that resolves to the bundle's UUID (string) on successful submission. 154 | * @throws A ServiceError if there's an issue with the server while sending the bundle. 155 | */ 156 | async sendBundle(bundle: Bundle): Promise> { 157 | return this.retryWithBackoff(() => { 158 | return new Promise>((resolve) => { 159 | this.client.sendBundle( 160 | { bundle } as SendBundleRequest, 161 | (e: ServiceError | null, resp: SendBundleResponse) => { 162 | if (e) { 163 | resolve(Err(this.handleError(e))); 164 | } else { 165 | resolve(Ok(resp.uuid)); 166 | } 167 | } 168 | ); 169 | }); 170 | }); 171 | } 172 | 173 | /** 174 | * Retrieves tip accounts from the server. 175 | * 176 | * @returns A Promise that resolves to an array of account strings (usually public keys). 177 | * @throws A ServiceError if there's an issue with the server while fetching tip accounts. 178 | */ 179 | async getTipAccounts(): Promise> { 180 | return this.retryWithBackoff(() => { 181 | return new Promise>((resolve) => { 182 | this.client.getTipAccounts( 183 | {}, 184 | (e: ServiceError | null, resp: GetTipAccountsResponse) => { 185 | if (e) { 186 | resolve(Err(this.handleError(e))); 187 | } else { 188 | resolve(Ok(resp.accounts)); 189 | } 190 | } 191 | ); 192 | }); 193 | }); 194 | } 195 | 196 | /** 197 | * Retrieves connected leaders (validators) from the server. 198 | * 199 | * @returns A Promise that resolves to a map, where keys are validator identity keys (usually public keys), and values are SlotList objects. 200 | * @throws A ServiceError if there's an issue with the server while fetching connected leaders. 201 | */ 202 | async getConnectedLeaders(): Promise> { 203 | return this.retryWithBackoff(() => { 204 | return new Promise>((resolve) => { 205 | this.client.getConnectedLeaders( 206 | {}, 207 | async (e: ServiceError | null, resp: ConnectedLeadersResponse) => { 208 | if (e) { 209 | resolve(Err(this.handleError(e))); 210 | } else { 211 | resolve(Ok(resp.connectedValidators)); 212 | } 213 | } 214 | ); 215 | }); 216 | }); 217 | } 218 | 219 | /** 220 | * Returns the next scheduled leader connected to the block-engine. 221 | * 222 | * @returns A Promise that resolves with an object containing: 223 | * - currentSlot: The current slot number the backend is on 224 | * - nextLeaderSlot: The slot number of the next scheduled leader 225 | * - nextLeaderIdentity: The identity of the next scheduled leader 226 | * @throws A ServiceError if there's an issue with the server while fetching the next scheduled leader. 227 | */ 228 | async getNextScheduledLeader(): Promise> { 233 | return this.retryWithBackoff(() => { 234 | return new Promise>((resolve) => { 239 | this.client.getNextScheduledLeader( 240 | { 241 | regions: [], 242 | }, 243 | async (e: ServiceError | null, resp: NextScheduledLeaderResponse) => { 244 | if (e) { 245 | resolve(Err(this.handleError(e))); 246 | } else { 247 | resolve(Ok(resp)); 248 | } 249 | } 250 | ); 251 | }); 252 | }); 253 | } 254 | 255 | /** 256 | * Triggers the provided callback on BundleResult updates. 257 | * 258 | * @param successCallback - A callback function that receives the BundleResult updates 259 | * @param errorCallback - A callback function that receives the stream error (Error) 260 | * @returns A function to cancel the subscription 261 | */ 262 | onBundleResult( 263 | successCallback: (bundleResult: BundleResult) => void, 264 | errorCallback: (e: Error) => void 265 | ): () => void { 266 | const stream: ClientReadableStream = 267 | this.client.subscribeBundleResults({}); 268 | 269 | stream.on('readable', () => { 270 | const msg = stream.read(1); 271 | if (msg) { 272 | successCallback(msg); 273 | } 274 | }); 275 | stream.on('error', e => { 276 | errorCallback(new Error(`Stream error: ${e.message}`)); 277 | }); 278 | 279 | return () => stream.cancel(); 280 | } 281 | 282 | /** 283 | * Yields on bundle results. 284 | * 285 | * @param onError - A callback function that receives the stream error (Error) 286 | * @returns An async generator that yields BundleResult updates 287 | */ 288 | async *bundleResults( 289 | onError: (e: Error) => void 290 | ): AsyncGenerator { 291 | const stream: ClientReadableStream = 292 | this.client.subscribeBundleResults({}); 293 | 294 | stream.on('error', e => { 295 | onError(e); 296 | }); 297 | 298 | for await (const bundleResult of stream) { 299 | yield bundleResult; 300 | } 301 | } 302 | } 303 | 304 | /** 305 | * Creates and returns a SearcherClient instance. 306 | * 307 | * @param url - The URL of the SearcherService 308 | * @param authKeypair - Optional Keypair authorized for the block engine 309 | * @param grpcOptions - Optional configuration options for the gRPC client 310 | * @returns SearcherClient - An instance of the SearcherClient 311 | */ 312 | export const searcherClient = ( 313 | url: string, 314 | authKeypair?: Keypair, 315 | grpcOptions?: Partial 316 | ): SearcherClient => { 317 | if (authKeypair) { 318 | const authProvider = new AuthProvider( 319 | new AuthServiceClient(url, ChannelCredentials.createSsl()), 320 | authKeypair 321 | ); 322 | const client = new SearcherServiceClient( 323 | url, 324 | ChannelCredentials.createSsl(), 325 | {interceptors: [authInterceptor(authProvider)], ...grpcOptions} 326 | ); 327 | return new SearcherClient(client); 328 | } else { 329 | return new SearcherClient( 330 | new SearcherServiceClient( 331 | url, 332 | ChannelCredentials.createSsl(), 333 | grpcOptions 334 | ) 335 | ); 336 | } 337 | }; -------------------------------------------------------------------------------- /src/sdk/block-engine/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Keypair, 3 | PublicKey, 4 | SystemProgram, 5 | TransactionMessage, 6 | VersionedTransaction, 7 | } from '@solana/web3.js'; 8 | 9 | import {Bundle as IBundle} from '../../gen/block-engine/bundle'; 10 | import {Header} from '../../gen/block-engine/shared'; 11 | import {Packet} from '../../gen/block-engine/packet'; 12 | import {serializeTransactions} from './utils'; 13 | 14 | // Represents a bundle of transactions expected to execute all or nothing, atomically and sequentially. 15 | export class Bundle implements IBundle { 16 | private transactions: VersionedTransaction[]; 17 | // Maximum number of transactions a bundle may have. 18 | private readonly transactionLimit: number; 19 | header: Header | undefined; 20 | packets: Packet[]; 21 | 22 | constructor(txs: VersionedTransaction[], transactionLimit: number) { 23 | this.transactions = txs; 24 | this.transactionLimit = transactionLimit; 25 | this.packets = serializeTransactions(txs); 26 | } 27 | 28 | // Adds transactions to the bundle. 29 | addTransactions(...transactions: VersionedTransaction[]): Bundle | Error { 30 | const numTransactions = this.transactions.length + transactions.length; 31 | if (numTransactions > this.transactionLimit) { 32 | return new Error( 33 | `${numTransactions} exceeds transaction limit of ${this.transactionLimit}` 34 | ); 35 | } 36 | 37 | this.transactions.push(...transactions); 38 | this.packets = this.packets.concat(serializeTransactions(transactions)); 39 | 40 | return this; 41 | } 42 | 43 | // Creates a new transaction to tip. 44 | addTipTx( 45 | keypair: Keypair, 46 | tipLamports: number, 47 | tipAccount: PublicKey, 48 | recentBlockhash: string 49 | ): Bundle | Error { 50 | const numTransactions = this.transactions.length + 1; 51 | if (numTransactions > this.transactionLimit) { 52 | return new Error( 53 | `${numTransactions} exceeds transaction limit of ${this.transactionLimit}` 54 | ); 55 | } 56 | 57 | const tipIx = SystemProgram.transfer({ 58 | fromPubkey: keypair.publicKey, 59 | toPubkey: tipAccount, 60 | lamports: tipLamports, 61 | }); 62 | 63 | const instructions = [tipIx]; 64 | 65 | const messageV0 = new TransactionMessage({ 66 | payerKey: keypair.publicKey, 67 | recentBlockhash: recentBlockhash, 68 | instructions, 69 | }).compileToV0Message(); 70 | 71 | const tipTx = new VersionedTransaction(messageV0); 72 | 73 | tipTx.sign([keypair]); 74 | 75 | this.transactions.push(tipTx); 76 | this.packets = this.packets.concat(serializeTransactions([tipTx])); 77 | 78 | return this; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/sdk/block-engine/utils.ts: -------------------------------------------------------------------------------- 1 | import {VersionedTransaction} from '@solana/web3.js'; 2 | 3 | import {Meta, Packet} from '../../gen/block-engine/packet'; 4 | 5 | export type Result = { 6 | ok: true; 7 | value: T; 8 | } | { 9 | ok: false; 10 | error: E; 11 | }; 12 | 13 | export function Ok(value: T): Result { 14 | return { ok: true, value }; 15 | } 16 | 17 | export function Err(error: E): Result { 18 | return { ok: false, error }; 19 | } 20 | 21 | export const unixTimestampFromDate = (date: Date) => { 22 | return Math.floor(date.getTime() / 1000); 23 | }; 24 | 25 | export const deserializeTransactions = ( 26 | packets: Packet[] 27 | ): VersionedTransaction[] => { 28 | return packets.map(p => { 29 | return VersionedTransaction.deserialize(p.data); 30 | }); 31 | }; 32 | 33 | export const serializeTransactions = ( 34 | txs: VersionedTransaction[] 35 | ): Packet[] => { 36 | return txs.map(tx => { 37 | const data = tx.serialize(); 38 | 39 | return { 40 | data, 41 | meta: { 42 | port: 0, 43 | addr: '0.0.0.0', 44 | senderStake: 0, 45 | size: data.length, 46 | flags: undefined, 47 | } as Meta, 48 | } as Packet; 49 | }); 50 | }; 51 | 52 | export const isError = (value: T | Error): value is Error => { 53 | return value instanceof Error; 54 | }; 55 | -------------------------------------------------------------------------------- /src/sdk/geyser/auth.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InterceptingCall, 3 | Interceptor, 4 | InterceptorOptions, 5 | Listener, 6 | Metadata, 7 | } from '@grpc/grpc-js'; 8 | import {NextCall} from '@grpc/grpc-js/build/src/client-interceptors'; 9 | 10 | // Intercepts requests and sets the auth header. 11 | export const authInterceptor = (accessToken: string): Interceptor => { 12 | return (opts: InterceptorOptions, nextCall: NextCall) => { 13 | return new InterceptingCall(nextCall(opts), { 14 | start: async function (metadata: Metadata, listener: Listener, next) { 15 | metadata.set('access-token', accessToken); 16 | next(metadata, listener); 17 | }, 18 | }); 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /src/sdk/geyser/geyser.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChannelCredentials, 3 | ChannelOptions, 4 | ClientReadableStream, 5 | ServiceError, 6 | } from '@grpc/grpc-js'; 7 | import {PublicKey} from '@solana/web3.js'; 8 | 9 | import {authInterceptor} from './auth'; 10 | import { 11 | GetHeartbeatIntervalResponse, 12 | GeyserClient as GeyserClientStub, 13 | TimestampedAccountUpdate, 14 | TimestampedBlockUpdate, 15 | } from '../../gen/geyser/geyser'; 16 | 17 | export class GeyserClient { 18 | private client: GeyserClientStub; 19 | 20 | constructor(client: GeyserClientStub) { 21 | this.client = client; 22 | } 23 | 24 | /** 25 | * Retrieves the heartbeat interval in milliseconds from the server. 26 | * 27 | * @returns A Promise that resolves to a number representing the heartbeat interval in milliseconds. 28 | * @throws A ServiceError if there's an issue with the server while fetching the heartbeat interval. 29 | 30 | */ 31 | async getHeartbeatIntervalMillis(): Promise { 32 | return new Promise((resolve, reject) => { 33 | this.client.getHeartbeatInterval( 34 | {}, 35 | async (e: ServiceError | null, resp: GetHeartbeatIntervalResponse) => { 36 | if (e) { 37 | reject(e); 38 | } else { 39 | resolve(resp.heartbeatIntervalMs); 40 | } 41 | } 42 | ); 43 | }); 44 | } 45 | 46 | /** 47 | * Triggers the supplied callback on an update of the provided accounts of interest. 48 | * 49 | * @param accountsOfInterest - An array of PublicKeys of the accounts to subscribe for updates. 50 | * @param successCallback - A callback function that receives a TimestampedAccountUpdate object whenever updates are available. 51 | * @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process. 52 | * @returns A function that can be called to cancel the subscription. 53 | */ 54 | onAccountUpdate( 55 | accountsOfInterest: PublicKey[], 56 | successCallback: (resp: TimestampedAccountUpdate) => void, 57 | errorCallback: (e: Error) => void 58 | ): () => void { 59 | const accounts = accountsOfInterest.map(a => a.toBytes()); 60 | const stream: ClientReadableStream = 61 | this.client.subscribeAccountUpdates({accounts}); 62 | 63 | stream.on('readable', () => { 64 | const msg = stream.read(1); 65 | if (msg) { 66 | successCallback(msg); 67 | } 68 | }); 69 | 70 | stream.on('error', e => 71 | errorCallback(new Error(`Stream error: ${e.message}`)) 72 | ); 73 | 74 | return () => stream.cancel(); 75 | } 76 | 77 | /** 78 | * Triggers the supplied callback on an account update owned by the provided programs of interest. 79 | * 80 | * @param programsOfInterest - An array of PublicKeys of the programs to subscribe for updates. 81 | * @param successCallback - A callback function that receives a TimestampedAccountUpdate object whenever updates are available. 82 | * @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process. 83 | * @returns A function that can be called to cancel the subscription. 84 | */ 85 | onProgramUpdate( 86 | programsOfInterest: PublicKey[], 87 | successCallback: (resp: TimestampedAccountUpdate) => void, 88 | errorCallback: (e: Error) => void 89 | ): () => void { 90 | const programs = programsOfInterest.map(a => a.toBytes()); 91 | const stream: ClientReadableStream = 92 | this.client.subscribeProgramUpdates({programs}); 93 | 94 | stream.on('readable', () => { 95 | const msg = stream.read(1); 96 | if (msg) { 97 | successCallback(msg); 98 | } 99 | }); 100 | 101 | stream.on('error', e => 102 | errorCallback(new Error(`Stream error: ${e.message}`)) 103 | ); 104 | 105 | return () => stream.cancel(); 106 | } 107 | 108 | /** 109 | * Triggers the supplied callback for every processed block. 110 | * 111 | * @param successCallback - A callback function that receives a TimestampedBlockUpdate object whenever a block update is available. 112 | * @param errorCallback - A callback function that is triggered whenever an error occurs during the subscription process. 113 | * @returns A function that can be called to cancel the subscription. 114 | */ 115 | onProcessedBlock( 116 | successCallback: (resp: TimestampedBlockUpdate) => void, 117 | errorCallback: (e: Error) => void 118 | ): () => void { 119 | const stream: ClientReadableStream = 120 | this.client.subscribeBlockUpdates({}); 121 | 122 | stream.on('readable', () => { 123 | const msg = stream.read(1); 124 | if (msg) { 125 | successCallback(msg); 126 | } 127 | }); 128 | 129 | stream.on('error', e => 130 | errorCallback(new Error(`Stream error: ${e.message}`)) 131 | ); 132 | 133 | return () => stream.cancel(); 134 | } 135 | } 136 | 137 | /** 138 | * Creates and returns a new GeyserClient instance. 139 | * 140 | * @param url - The gRPC server endpoint URL. 141 | * @param accessToken - The access token required for authentication. 142 | * @param grpcOptions - Optional configuration options for the gRPC client 143 | * @returns A GeyserClient instance with the specified configuration. 144 | */ 145 | export const geyserClient = ( 146 | url: string, 147 | accessToken: string, 148 | grpcOptions?: Partial 149 | ): GeyserClient => { 150 | const client = new GeyserClientStub(url, ChannelCredentials.createSsl(), { 151 | interceptors: [authInterceptor(accessToken)], 152 | ...grpcOptions, 153 | }); 154 | 155 | return new GeyserClient(client); 156 | }; 157 | -------------------------------------------------------------------------------- /src/sdk/geyser/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './geyser'; 3 | -------------------------------------------------------------------------------- /src/sdk/index.ts: -------------------------------------------------------------------------------- 1 | export * from './block-engine'; 2 | export * from './geyser'; 3 | export * from './rpc'; 4 | -------------------------------------------------------------------------------- /src/sdk/rpc/connection.ts: -------------------------------------------------------------------------------- 1 | // most stuff copied from @solana/web3.js 1.74.0 - see direct references in the comment of each snippet 2 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts 3 | 4 | /* eslint-disable @typescript-eslint/no-explicit-any */ 5 | import { 6 | Commitment, 7 | Connection, 8 | ConnectionConfig, 9 | FetchFn, 10 | FetchMiddleware, 11 | HttpHeaders, 12 | RpcResponseAndContext, 13 | SendTransactionError, 14 | SimulatedTransactionAccountInfo, 15 | TransactionError, 16 | TransactionReturnData, 17 | VersionedTransaction, 18 | } from '@solana/web3.js'; 19 | import { 20 | type as pick, 21 | number, 22 | string, 23 | array, 24 | boolean, 25 | literal, 26 | union, 27 | optional, 28 | nullable, 29 | coerce, 30 | create, 31 | tuple, 32 | unknown, 33 | any, 34 | Struct, 35 | } from 'superstruct'; 36 | import type {Agent as NodeHttpAgent} from 'http'; 37 | import {Agent as NodeHttpsAgent} from 'https'; 38 | import fetchImpl, {Response} from './fetch-impl'; 39 | import HttpKeepAliveAgent, { 40 | HttpsAgent as HttpsKeepAliveAgent, 41 | } from 'agentkeepalive'; 42 | 43 | import RpcClient from 'jayson/lib/client/browser'; 44 | import {sleep} from './utils'; 45 | 46 | export type Slot = number; 47 | export type Tip = 'tip'; 48 | 49 | /** 50 | * Simulate on top of bank with the provided commitment or on the provided slot's bank or on top of the RPC's highest slot's bank i.e. the working bank. 51 | */ 52 | export type SimulationSlotConfig = Commitment | Slot | Tip; 53 | 54 | export type SimulateBundleConfig = { 55 | /** list of accounts to return the pre transaction execution state for. The length of the array must be equal to the number transactions in the bundle */ 56 | preExecutionAccountsConfigs: ({ 57 | encoding: 'base64'; 58 | addresses: string[]; 59 | } | null)[]; 60 | /** list of accounts to return the post transaction execution state for. The length of the array must be equal to the number transactions in the bundle */ 61 | postExecutionAccountsConfigs: ({ 62 | encoding: 'base64'; 63 | addresses: string[]; 64 | } | null)[]; 65 | /** Optional parameter to specify the bank to run simulation against */ 66 | simulationBank?: SimulationSlotConfig; 67 | /** Optional parameter used to enable signature verification before simulation */ 68 | skipSigVerify?: boolean; 69 | /** Optional parameter used to replace the simulated transaction's recent blockhash with the latest blockhash */ 70 | replaceRecentBlockhash?: boolean; 71 | }; 72 | 73 | export type SimulatedBundleTransactionResult = { 74 | err: TransactionError | string | null; 75 | logs: Array | null; 76 | preExecutionAccounts?: SimulatedTransactionAccountInfo[] | null; 77 | postExecutionAccounts?: SimulatedTransactionAccountInfo[] | null; 78 | unitsConsumed?: number; 79 | returnData?: TransactionReturnData | null; 80 | }; 81 | 82 | export type BundleError = {} | string; 83 | 84 | export type BundleSimulationSummary = 85 | | 'succeeded' 86 | | { 87 | failed: { 88 | error: BundleError; 89 | tx_signature: string; 90 | }; 91 | }; 92 | 93 | export type SimulatedBundleResponse = { 94 | summary: BundleSimulationSummary; 95 | transactionResults: SimulatedBundleTransactionResult[]; 96 | }; 97 | 98 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L387 99 | function createRpcResult(result: Struct) { 100 | return union([ 101 | pick({ 102 | jsonrpc: literal('2.0'), 103 | id: string(), 104 | result, 105 | }), 106 | pick({ 107 | jsonrpc: literal('2.0'), 108 | id: string(), 109 | error: pick({ 110 | code: unknown(), 111 | message: string(), 112 | data: optional(any()), 113 | }), 114 | }), 115 | ]); 116 | } 117 | 118 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L406 119 | const UnknownRpcResult = createRpcResult(unknown()); 120 | 121 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L411 122 | function jsonRpcResult(schema: Struct) { 123 | return coerce(createRpcResult(schema), UnknownRpcResult, value => { 124 | if ('error' in value) { 125 | return value; 126 | } else { 127 | return { 128 | ...value, 129 | result: create(value.result, schema), 130 | }; 131 | } 132 | }); 133 | } 134 | 135 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L427 136 | function jsonRpcResultAndContext(value: Struct) { 137 | return jsonRpcResult( 138 | pick({ 139 | context: pick({ 140 | slot: number(), 141 | }), 142 | value, 143 | }) 144 | ); 145 | } 146 | 147 | const SimulatedBundleResponseStruct = jsonRpcResultAndContext( 148 | pick({ 149 | summary: union([ 150 | pick({ 151 | failed: pick({ 152 | error: union([pick({}), string()]), 153 | tx_signature: string(), 154 | }), 155 | }), 156 | literal('succeeded'), 157 | ]), 158 | transactionResults: array( 159 | pick({ 160 | err: nullable(union([pick({}), string()])), 161 | logs: nullable(array(string())), 162 | preExecutionAccounts: optional( 163 | nullable( 164 | array( 165 | pick({ 166 | executable: boolean(), 167 | owner: string(), 168 | lamports: number(), 169 | data: array(string()), 170 | rentEpoch: optional(number()), 171 | }) 172 | ) 173 | ) 174 | ), 175 | postExecutionAccounts: optional( 176 | nullable( 177 | array( 178 | pick({ 179 | executable: boolean(), 180 | owner: string(), 181 | lamports: number(), 182 | data: array(string()), 183 | rentEpoch: optional(number()), 184 | }) 185 | ) 186 | ) 187 | ), 188 | unitsConsumed: optional(number()), 189 | returnData: optional( 190 | nullable( 191 | pick({ 192 | programId: string(), 193 | data: tuple([string(), literal('base64')]), 194 | }) 195 | ) 196 | ), 197 | }) 198 | ), 199 | }) 200 | ); 201 | 202 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L1489 203 | function createRpcClient( 204 | url: string, 205 | httpHeaders?: HttpHeaders, 206 | customFetch?: FetchFn, 207 | fetchMiddleware?: FetchMiddleware, 208 | disableRetryOnRateLimit?: boolean, 209 | httpAgent?: NodeHttpAgent | NodeHttpsAgent | false 210 | ): RpcClient { 211 | const fetch = customFetch ? customFetch : fetchImpl; 212 | let agent: NodeHttpAgent | NodeHttpsAgent | undefined; 213 | if (process.env.BROWSER) { 214 | // eslint-disable-next-line eqeqeq 215 | if (httpAgent != null) { 216 | console.warn( 217 | 'You have supplied an `httpAgent` when creating a `Connection` in a browser environment.' + 218 | 'It has been ignored; `httpAgent` is only used in Node environments.' 219 | ); 220 | } 221 | } else { 222 | // eslint-disable-next-line eqeqeq 223 | if (httpAgent == null) { 224 | if (process.env.NODE_ENV !== 'test') { 225 | const agentOptions = { 226 | // One second fewer than the Solana RPC's keepalive timeout. 227 | // Read more: https://github.com/solana-labs/solana/issues/27859#issuecomment-1340097889 228 | freeSocketTimeout: 19000, 229 | keepAlive: true, 230 | maxSockets: 25, 231 | }; 232 | if (url.startsWith('https:')) { 233 | agent = new HttpsKeepAliveAgent(agentOptions); 234 | } else { 235 | agent = new HttpKeepAliveAgent(agentOptions); 236 | } 237 | } 238 | } else { 239 | if (httpAgent !== false) { 240 | const isHttps = url.startsWith('https:'); 241 | if (isHttps && !(httpAgent instanceof NodeHttpsAgent)) { 242 | throw new Error( 243 | 'The endpoint `' + 244 | url + 245 | '` can only be paired with an `https.Agent`. You have, instead, supplied an ' + 246 | '`http.Agent` through `httpAgent`.' 247 | ); 248 | } else if (!isHttps && httpAgent instanceof NodeHttpsAgent) { 249 | throw new Error( 250 | 'The endpoint `' + 251 | url + 252 | '` can only be paired with an `http.Agent`. You have, instead, supplied an ' + 253 | '`https.Agent` through `httpAgent`.' 254 | ); 255 | } 256 | agent = httpAgent; 257 | } 258 | } 259 | } 260 | 261 | let fetchWithMiddleware: FetchFn | undefined; 262 | 263 | if (fetchMiddleware) { 264 | fetchWithMiddleware = async (info, init) => { 265 | const modifiedFetchArgs = await new Promise>( 266 | (resolve, reject) => { 267 | try { 268 | fetchMiddleware(info, init, (modifiedInfo, modifiedInit) => 269 | resolve([modifiedInfo, modifiedInit]) 270 | ); 271 | } catch (error) { 272 | reject(error); 273 | } 274 | } 275 | ); 276 | return await fetch(...modifiedFetchArgs); 277 | }; 278 | } 279 | 280 | const clientBrowser = new RpcClient(async (request, callback) => { 281 | const options = { 282 | method: 'POST', 283 | body: request, 284 | agent, 285 | headers: Object.assign( 286 | { 287 | 'Content-Type': 'application/json', 288 | }, 289 | httpHeaders || {} 290 | ), 291 | }; 292 | 293 | try { 294 | let too_many_requests_retries = 5; 295 | let res: Response; 296 | let waitTime = 500; 297 | for (;;) { 298 | if (fetchWithMiddleware) { 299 | res = await fetchWithMiddleware(url, options); 300 | } else { 301 | res = await fetch(url, options); 302 | } 303 | 304 | if (res.status !== 429 /* Too many requests */) { 305 | break; 306 | } 307 | if (disableRetryOnRateLimit === true) { 308 | break; 309 | } 310 | too_many_requests_retries -= 1; 311 | if (too_many_requests_retries === 0) { 312 | break; 313 | } 314 | console.log( 315 | `Server responded with ${res.status} ${res.statusText}. Retrying after ${waitTime}ms delay...` 316 | ); 317 | await sleep(waitTime); 318 | waitTime *= 2; 319 | } 320 | 321 | const text = await res.text(); 322 | if (res.ok) { 323 | callback(null, text); 324 | } else { 325 | callback(new Error(`${res.status} ${res.statusText}: ${text}`)); 326 | } 327 | } catch (err) { 328 | if (err instanceof Error) callback(err); 329 | } 330 | }, {}); 331 | 332 | return clientBrowser; 333 | } 334 | 335 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L210 336 | type RpcRequest = (methodName: string, args: Array) => Promise; 337 | 338 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L1620 339 | function createRpcRequest(client: RpcClient): RpcRequest { 340 | return (method, args) => { 341 | return new Promise((resolve, reject) => { 342 | client.request(method, args, (err: any, response: any) => { 343 | if (err) { 344 | reject(err); 345 | return; 346 | } 347 | resolve(response); 348 | }); 349 | }); 350 | }; 351 | } 352 | 353 | /** 354 | * The JitoRpcConnection class extends the Connection class from @solana/web3.js 355 | * to provide an additional method called 'simulateBundle'. 356 | * 357 | * When constructing the JitoRpcConnection object, an httpAgent can be passed as 358 | * part of the ConnectionConfig. If it is not provided, the constructor will 359 | * internally create a separate httpAgent to be used for the 'simulateBundle' method. 360 | * This means that if a httpAgent is not passed, a separate TCP connection will 361 | * be used for 'simulateBundle'. 362 | */ 363 | export class JitoRpcConnection extends Connection { 364 | /** @internal */ _commitment?: Commitment; 365 | /** @internal */ _confirmTransactionInitialTimeout?: number; 366 | /** @internal */ _rpcClient: RpcClient; 367 | /** @internal */ _rpcRequest: RpcRequest; 368 | 369 | // copied from here but removed unused fields 370 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/connection.ts#L3060 371 | constructor( 372 | endpoint: string, 373 | commitmentOrConfig?: Commitment | ConnectionConfig 374 | ) { 375 | super(endpoint, commitmentOrConfig); 376 | 377 | let httpHeaders; 378 | let fetch; 379 | let fetchMiddleware; 380 | let disableRetryOnRateLimit; 381 | let httpAgent; 382 | if (commitmentOrConfig && typeof commitmentOrConfig === 'string') { 383 | this._commitment = commitmentOrConfig; 384 | } else if (commitmentOrConfig) { 385 | this._commitment = commitmentOrConfig.commitment; 386 | this._confirmTransactionInitialTimeout = 387 | commitmentOrConfig.confirmTransactionInitialTimeout; 388 | httpHeaders = commitmentOrConfig.httpHeaders; 389 | fetch = commitmentOrConfig.fetch; 390 | fetchMiddleware = commitmentOrConfig.fetchMiddleware; 391 | disableRetryOnRateLimit = commitmentOrConfig.disableRetryOnRateLimit; 392 | httpAgent = commitmentOrConfig.httpAgent; 393 | } 394 | 395 | this._rpcClient = createRpcClient( 396 | endpoint, 397 | httpHeaders, 398 | fetch, 399 | fetchMiddleware, 400 | disableRetryOnRateLimit, 401 | httpAgent 402 | ); 403 | this._rpcRequest = createRpcRequest(this._rpcClient); 404 | } 405 | 406 | /** 407 | * Simulate a bundle 408 | */ 409 | async simulateBundle( 410 | bundle: VersionedTransaction[], 411 | config?: SimulateBundleConfig 412 | ): Promise> { 413 | if ( 414 | config && 415 | bundle.length !== config.preExecutionAccountsConfigs.length && 416 | bundle.length !== config.postExecutionAccountsConfigs.length 417 | ) { 418 | throw new Error( 419 | 'pre/post execution account config length must match bundle length' 420 | ); 421 | } 422 | 423 | const encodedTransactions = bundle.map(versionedTx => { 424 | return Buffer.from(versionedTx.serialize()).toString('base64'); 425 | }); 426 | 427 | const simulationConfig: any = config || {}; 428 | simulationConfig.transactionEncoding = 'base64'; 429 | const args = [{encodedTransactions}, simulationConfig]; 430 | const unsafeRes = await this._rpcRequest('simulateBundle', args); 431 | const res = create(unsafeRes, SimulatedBundleResponseStruct); 432 | 433 | if ('error' in res) { 434 | let logs; 435 | if ('data' in res.error) { 436 | logs = res.error.data.logs; 437 | if (logs && Array.isArray(logs)) { 438 | const traceIndent = '\n '; 439 | const logTrace = traceIndent + logs.join(traceIndent); 440 | console.error(res.error.message, logTrace); 441 | } 442 | } 443 | throw new SendTransactionError( 444 | 'failed to simulate bundle: ' + res.error.message, 445 | logs 446 | ); 447 | } 448 | return res.result; 449 | } 450 | } 451 | -------------------------------------------------------------------------------- /src/sdk/rpc/errors.ts: -------------------------------------------------------------------------------- 1 | // copied from @solana/web3.js 1.74.0 2 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/errors.ts#L1 3 | export class SendTransactionError extends Error { 4 | logs: string[] | undefined; 5 | 6 | constructor(message: string, logs?: string[]) { 7 | super(message); 8 | 9 | this.logs = logs; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/sdk/rpc/fetch-impl.ts: -------------------------------------------------------------------------------- 1 | // copied from @solana/web3.js 1.74.0 2 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/fetch-impl.ts 3 | import * as nodeFetch from 'node-fetch'; 4 | 5 | export {Response} from 'node-fetch'; 6 | export default async function ( 7 | input: nodeFetch.RequestInfo, 8 | init?: nodeFetch.RequestInit 9 | ): Promise { 10 | const processedInput = 11 | typeof input === 'string' && input.slice(0, 2) === '//' 12 | ? 'https:' + input 13 | : input; 14 | return await nodeFetch.default(processedInput, init); 15 | } 16 | -------------------------------------------------------------------------------- /src/sdk/rpc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './connection'; 2 | -------------------------------------------------------------------------------- /src/sdk/rpc/utils.ts: -------------------------------------------------------------------------------- 1 | // copied from @solana/web3.js 1.74.0 2 | // https://github.com/solana-labs/solana-web3.js/blob/3cd0cfd91a7fe08b9c67ac6f0d0c31c0c2ae8157/packages/library-legacy/src/utils/sleep.ts 3 | export function sleep(ms: number): Promise { 4 | return new Promise(resolve => setTimeout(resolve, ms)); 5 | } 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./node_modules/gts/tsconfig-google.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "noEmit": false, 6 | "rootDir": "src", 7 | "outDir": "dist", 8 | "resolveJsonModule": false, 9 | "esModuleInterop": true, 10 | "lib": ["DOM"] 11 | }, 12 | "include": [ 13 | "src/**/*.ts", 14 | "test/**/*.ts" 15 | ], 16 | } 17 | --------------------------------------------------------------------------------