├── .editorconfig
├── .eslintrc
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── docs
├── .gitignore
└── _config.yml
├── lerna.json
├── package.json
├── packages
├── associated-token
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── borsh
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── tsconfig.json
├── common
│ ├── package.json
│ ├── src
│ │ ├── connection.ts
│ │ ├── index.ts
│ │ ├── provider.ts
│ │ ├── simulate-transaction.ts
│ │ └── token.ts
│ ├── test
│ │ └── example.spec.ts
│ └── tsconfig.json
├── pool
│ ├── .eslintignore
│ ├── README.md
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ ├── admin-controlled-pool.ts
│ │ ├── index.ts
│ │ ├── instructions.ts
│ │ ├── schema.test.ts
│ │ ├── schema.ts
│ │ ├── scripts
│ │ │ └── create-pool-and-do-stuff-with-it.ts
│ │ ├── simulate-transaction.ts
│ │ └── transactions.ts
│ └── tsconfig.json
├── serum
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── README.md
│ ├── jest.config.js
│ ├── package.json
│ ├── shell
│ ├── src
│ │ ├── error.ts
│ │ ├── fees.ts
│ │ ├── index.js
│ │ ├── instructions.js
│ │ ├── instructions.test.js
│ │ ├── layout.js
│ │ ├── market-proxy
│ │ │ ├── index.ts
│ │ │ └── middleware.ts
│ │ ├── market.test.js
│ │ ├── market.ts
│ │ ├── markets.json
│ │ ├── queue.ts
│ │ ├── slab.test.js
│ │ ├── slab.ts
│ │ ├── token-instructions.js
│ │ ├── token-mints.json
│ │ └── tokens_and_markets.ts
│ └── tsconfig.json
├── spl-token-swap
│ ├── CHANGELOG.md
│ ├── package-lock.json
│ ├── package.json
│ ├── shell
│ ├── src
│ │ ├── index.ts
│ │ ├── instructions.ts
│ │ ├── pools.ts
│ │ ├── types.ts
│ │ └── utils.ts
│ ├── test
│ │ └── example.spec.ts
│ └── tsconfig.json
├── swap
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── README.md
│ ├── examples
│ │ └── swap.js
│ ├── jest.config.js
│ ├── package.json
│ ├── src
│ │ ├── idl.ts
│ │ ├── index.ts
│ │ ├── swap-markets.ts
│ │ └── utils.ts
│ └── tsconfig.json
├── token
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── instructions.ts
│ │ ├── metadata.ts
│ │ └── state.ts
│ └── tsconfig.json
└── tokens
│ ├── package.json
│ ├── rollup
│ ├── rollup.config.browser.ts
│ └── rollup.config.ts
│ ├── src
│ ├── devnet.json
│ ├── index.ts
│ ├── mainnet-beta.json
│ └── testnet.json
│ └── tsconfig.json
├── tsconfig.json
├── types
└── buffer-layout
│ └── index.d.ts
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "plugins": ["@typescript-eslint"],
4 | "extends": [
5 | "eslint:recommended",
6 | "plugin:@typescript-eslint/recommended",
7 | "prettier",
8 | "prettier/@typescript-eslint"
9 | ],
10 | "env": {
11 | "node": true,
12 | "jest": true
13 | },
14 | "parserOptions": {
15 | "ecmaVersion": 2020,
16 | "sourceType": "module"
17 | },
18 | "rules": {
19 | "no-constant-condition": ["error", { "checkLoops": false }],
20 | "no-empty-function": "off",
21 | "@typescript-eslint/ban-ts-comment": "off",
22 | "@typescript-eslint/no-explicit-any": "off"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | dist/
4 | lib/
5 | deploy/
6 | docs/lockup-ui/
7 | .DS_Store
8 | *~
9 | .idea
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | private/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js: 12
3 | dist: bionic
4 | cache: yarn
5 | before_script:
6 | - yarn build
7 |
--------------------------------------------------------------------------------
/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 2020 Serum Foundation
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 |
2 |

3 |
4 |
serum-ts
5 |
6 |
7 | Project Serum Monorepo
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Website
18 | |
19 | Academy
20 | |
21 | Awesome
22 | |
23 | DEX
24 | |
25 | Rust
26 |
27 |
28 |
29 | ## Packages
30 |
31 | | Package | Version | Description |
32 | | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
33 | | [`@project-serum/borsh`](/packages/borsh) | [](https://www.npmjs.com/package/@project-serum/borsh) | Borsh serialization primitives |
34 | | [`@project-serum/common`](/packages/common) | [](https://www.npmjs.com/package/@project-serum/common) | Common utilities |
35 | | [`@project-serum/serum`](/packages/serum) | [](https://www.npmjs.com/package/@project-serum/serum) | Library for interacting with the Serum DEX |
36 | | [`@project-serum/pool`](/packages/pool) | [](https://www.npmjs.com/package/@project-serum/pool) | Client for interacting with Pools |
37 | | [`@project-serum/spl-token-swap`](/packages/spl-token-swap) | [](https://www.npmjs.com/package/@project-serum/spl-token-swap) | Client for interacting with the SPL Token Swap Program |
38 | | [`@project-serum/swap`](/packages/swap) | [](https://www.npmjs.com/package/@project-serum/swap) | Client for swapping on the Serum DEX |
39 | | [`@project-serum/tokens`](/packages/tokens) | [](https://www.npmjs.com/package/@project-serum/tokens) | Solana token addresses |
40 |
41 | ## Contributing
42 |
43 | ### Installing
44 |
45 | To get started first install the required build tools:
46 |
47 | ```
48 | npm install -g lerna
49 | npm install -g yarn
50 | ```
51 |
52 | Then bootstrap the workspace:
53 |
54 | ```
55 | yarn
56 | ```
57 |
58 | ### Building
59 |
60 | To build the workspace:
61 |
62 | ```
63 | yarn build
64 | ```
65 |
66 | ### Testing
67 |
68 | To run all tests:
69 |
70 | ```
71 | yarn test
72 | ```
73 |
74 | ### Linting
75 |
76 | To lint:
77 |
78 | ```
79 | yarn lint
80 | ```
81 |
82 | To apply lint fixes:
83 |
84 | ```
85 | yarn lint:fix
86 | ```
87 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | /associated-token
2 | /borsh
3 | /pool
4 | /token
5 | /stake-ui
6 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | include:
2 | - "_*_.html"
3 | - "_*_.*.html"
4 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "3.4.3",
3 | "npmClient": "yarn",
4 | "useWorkspaces": true,
5 | "packages": ["packages/*"],
6 | "version": "independent",
7 | "publishConfig": {
8 | "access": "public",
9 | "registry": "https://registry.npmjs.org"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "keywords": [],
4 | "workspaces": {
5 | "packages": [
6 | "packages/*"
7 | ]
8 | },
9 | "license": "Apache-2.0",
10 | "engines": {
11 | "node": ">=6.0.0"
12 | },
13 | "scripts": {
14 | "build": "lerna run build",
15 | "lint": "eslint 'packages/*/{src,test}/**/*.ts' && prettier -c 'packages/*/{src,test}/**/*.ts'",
16 | "lint:fix": "eslint --fix 'packages/*/{src,test}/**/*.ts' && prettier --write 'packages/*/{src,test}/**/*.ts'",
17 | "deploy": "run-s deploy:docs build deploy:apps && gh-pages -d docs",
18 | "deploy:docs": "lerna run docs",
19 | "deploy:apps": "lerna run deploy:app",
20 | "test": "lerna run test --concurrency 1 --stream"
21 | },
22 | "lint-staged": {
23 | "packages/*/{src,test}/**/*.ts": [
24 | "prettier --write"
25 | ]
26 | },
27 | "husky": {
28 | "hooks": {
29 | "pre-commit": "lint-staged"
30 | }
31 | },
32 | "prettier": {
33 | "arrowParens": "avoid",
34 | "semi": true,
35 | "singleQuote": true,
36 | "trailingComma": "all"
37 | },
38 | "commitlint": {
39 | "extends": [
40 | "@commitlint/config-conventional"
41 | ]
42 | },
43 | "devDependencies": {
44 | "@commitlint/cli": "^8.2.0",
45 | "@commitlint/config-conventional": "^8.2.0",
46 | "@types/jest": "^26.0.15",
47 | "@typescript-eslint/eslint-plugin": "^4.6.0",
48 | "@typescript-eslint/parser": "^4.6.0",
49 | "eslint": "^7.12.1",
50 | "eslint-config-prettier": "^6.15.0",
51 | "gh-pages": "^3.1.0",
52 | "husky": "^4.3.0",
53 | "jest": "26.6.0",
54 | "jest-config": "26.6.0",
55 | "lerna": "3.22.1",
56 | "lint-staged": "^10.5.0",
57 | "prettier": "^2.1.2",
58 | "rollup": "^1.23.1",
59 | "rollup-plugin-commonjs": "^10.1.0",
60 | "rollup-plugin-json": "^4.0.0",
61 | "rollup-plugin-node-resolve": "^5.2.0",
62 | "rollup-plugin-sourcemaps": "^0.4.2",
63 | "rollup-plugin-terser": "^5.1.3",
64 | "rollup-plugin-typescript2": "^0.25.2",
65 | "ts-jest": "^26.4.3",
66 | "ts-node": "^9.0.0",
67 | "typescript": "^4.0.5"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/packages/associated-token/README.md:
--------------------------------------------------------------------------------
1 | JavaScript library to interact with SPL Associated Token Accounts.
2 |
3 | [API Reference](https://project-serum.github.io/serum-ts/associated-token/modules/_index_.html)
4 |
--------------------------------------------------------------------------------
/packages/associated-token/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@project-serum/associated-token",
3 | "version": "0.1.1",
4 | "description": "Library for interacting with SPL Associated Token Accounts",
5 | "repository": "project-serum/serum-ts",
6 | "main": "dist/lib/index.js",
7 | "types": "dist/lib/index.d.ts",
8 | "exports": {
9 | ".": "./dist/lib/index.js"
10 | },
11 | "license": "Apache-2.0",
12 | "publishConfig": {
13 | "access": "public"
14 | },
15 | "engines": {
16 | "node": ">=10"
17 | },
18 | "scripts": {
19 | "build": "tsc",
20 | "docs": "typedoc --out ../../docs/associated-token --mode library --composite false --rootDir src src/index.ts src/*.d.ts",
21 | "test": "",
22 | "clean": "rm -rf dist",
23 | "prepare": "run-s clean build"
24 | },
25 | "peerDependencies": {
26 | "@solana/web3.js": "^0.90.0"
27 | },
28 | "devDependencies": {
29 | "@solana/web3.js": "^0.90.0"
30 | },
31 | "files": [
32 | "dist"
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/packages/associated-token/src/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | PublicKey,
3 | SystemProgram,
4 | SYSVAR_RENT_PUBKEY,
5 | TransactionInstruction,
6 | } from '@solana/web3.js';
7 |
8 | const TOKEN_PROGRAM_ID = new PublicKey(
9 | 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
10 | );
11 |
12 | /** Program ID for the associated token account program. */
13 | export const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey(
14 | 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL',
15 | );
16 |
17 | /**
18 | * Derives the associated token address for the given wallet address and token mint.
19 | * @param owner Wallet address
20 | * @param mint Mint address
21 | */
22 | export async function getAssociatedTokenAddress(
23 | owner: PublicKey,
24 | mint: PublicKey,
25 | ): Promise {
26 | const [address] = await PublicKey.findProgramAddress(
27 | [owner.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()],
28 | ASSOCIATED_TOKEN_PROGRAM_ID,
29 | );
30 | return address;
31 | }
32 |
33 | /**
34 | * Instruction to create the associated token address for the given wallet address and token mint.
35 | *
36 | * @param payer Account to use to pay for fees
37 | * @param owner Wallet address for the new associated token address
38 | * @param mint Mint address for the new associated token address
39 | */
40 | export async function createAssociatedTokenAccount(
41 | payer: PublicKey,
42 | owner: PublicKey,
43 | mint: PublicKey,
44 | ): Promise {
45 | const associatedTokenAddress = await getAssociatedTokenAddress(owner, mint);
46 | return new TransactionInstruction({
47 | keys: [
48 | { pubkey: payer, isSigner: true, isWritable: true },
49 | { pubkey: associatedTokenAddress, isSigner: false, isWritable: true },
50 | { pubkey: owner, isSigner: false, isWritable: false },
51 | { pubkey: mint, isSigner: false, isWritable: false },
52 | { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
53 | { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
54 | { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
55 | ],
56 | programId: ASSOCIATED_TOKEN_PROGRAM_ID,
57 | });
58 | }
59 |
--------------------------------------------------------------------------------
/packages/associated-token/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2019",
5 |
6 | "outDir": "./dist/lib",
7 | "rootDir": "./src",
8 |
9 | "composite": true,
10 | "declaration": true,
11 | "declarationMap": true,
12 | "sourceMap": true,
13 |
14 | "strict": true,
15 | "esModuleInterop": true,
16 | "skipLibCheck": true,
17 | "forceConsistentCasingInFileNames": true,
18 | "typeRoots": ["../../types/", "../../node_modules/@types"]
19 | },
20 | "include": ["src/**/*"],
21 | "exclude": ["src/**/*.test.ts", "**/node_modules"]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/borsh/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@project-serum/borsh",
3 | "version": "0.2.5",
4 | "description": "Serum Borsh",
5 | "main": "dist/lib/index.js",
6 | "types": "dist/lib/index.d.ts",
7 | "exports": {
8 | ".": "./dist/lib/index.js"
9 | },
10 | "license": "Apache-2.0",
11 | "publishConfig": {
12 | "access": "public"
13 | },
14 | "engines": {
15 | "node": ">=10"
16 | },
17 | "scripts": {
18 | "build": "tsc",
19 | "docs": "typedoc --out ../../docs/borsh --mode library --composite false --rootDir src src/index.ts src/*.d.ts",
20 | "test": "",
21 | "clean": "rm -rf dist",
22 | "prepare": "run-s clean build"
23 | },
24 | "dependencies": {
25 | "bn.js": "^5.1.2",
26 | "buffer-layout": "^1.2.0"
27 | },
28 | "peerDependencies": {
29 | "@solana/web3.js": "^1.2.0"
30 | },
31 | "files": [
32 | "dist"
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/packages/borsh/src/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | blob,
3 | Layout as LayoutCls,
4 | offset,
5 | seq,
6 | struct,
7 | u32,
8 | u8,
9 | union,
10 | } from 'buffer-layout';
11 | import { PublicKey } from '@solana/web3.js';
12 | import BN from 'bn.js';
13 | export {
14 | u8,
15 | s8 as i8,
16 | u16,
17 | s16 as i16,
18 | u32,
19 | s32 as i32,
20 | f32,
21 | f64,
22 | struct,
23 | } from 'buffer-layout';
24 |
25 | export interface Layout {
26 | span: number;
27 | property?: string;
28 |
29 | decode(b: Buffer, offset?: number): T;
30 |
31 | encode(src: T, b: Buffer, offset?: number): number;
32 |
33 | getSpan(b: Buffer, offset?: number): number;
34 |
35 | replicate(name: string): this;
36 | }
37 |
38 | class BNLayout extends LayoutCls {
39 | blob: Layout;
40 | signed: boolean;
41 |
42 | constructor(span: number, signed: boolean, property?: string) {
43 | super(span, property);
44 | this.blob = blob(span);
45 | this.signed = signed;
46 | }
47 |
48 | decode(b: Buffer, offset = 0) {
49 | const num = new BN(this.blob.decode(b, offset), 10, 'le');
50 | if (this.signed) {
51 | return num.fromTwos(this.span * 8).clone();
52 | }
53 | return num;
54 | }
55 |
56 | encode(src: BN, b: Buffer, offset = 0) {
57 | if (this.signed) {
58 | src = src.toTwos(this.span * 8);
59 | }
60 | return this.blob.encode(
61 | src.toArrayLike(Buffer, 'le', this.span),
62 | b,
63 | offset,
64 | );
65 | }
66 | }
67 |
68 | export function u64(property?: string): Layout {
69 | return new BNLayout(8, false, property);
70 | }
71 |
72 | export function i64(property?: string): Layout {
73 | return new BNLayout(8, true, property);
74 | }
75 |
76 | export function u128(property?: string): Layout {
77 | return new BNLayout(16, false, property);
78 | }
79 |
80 | export function i128(property?: string): Layout {
81 | return new BNLayout(16, true, property);
82 | }
83 |
84 | class WrappedLayout extends LayoutCls {
85 | layout: Layout;
86 | decoder: (data: T) => U;
87 | encoder: (src: U) => T;
88 |
89 | constructor(
90 | layout: Layout,
91 | decoder: (data: T) => U,
92 | encoder: (src: U) => T,
93 | property?: string,
94 | ) {
95 | super(layout.span, property);
96 | this.layout = layout;
97 | this.decoder = decoder;
98 | this.encoder = encoder;
99 | }
100 |
101 | decode(b: Buffer, offset?: number): U {
102 | return this.decoder(this.layout.decode(b, offset));
103 | }
104 |
105 | encode(src: U, b: Buffer, offset?: number): number {
106 | return this.layout.encode(this.encoder(src), b, offset);
107 | }
108 |
109 | getSpan(b: Buffer, offset?: number): number {
110 | return this.layout.getSpan(b, offset);
111 | }
112 | }
113 |
114 | export function publicKey(property?: string): Layout {
115 | return new WrappedLayout(
116 | blob(32),
117 | (b: Buffer) => new PublicKey(b),
118 | (key: PublicKey) => key.toBuffer(),
119 | property,
120 | );
121 | }
122 |
123 | class OptionLayout extends LayoutCls {
124 | layout: Layout;
125 | discriminator: Layout;
126 |
127 | constructor(layout: Layout, property?: string) {
128 | super(-1, property);
129 | this.layout = layout;
130 | this.discriminator = u8();
131 | }
132 |
133 | encode(src: T | null, b: Buffer, offset = 0): number {
134 | if (src === null || src === undefined) {
135 | return this.discriminator.encode(0, b, offset);
136 | }
137 | this.discriminator.encode(1, b, offset);
138 | return this.layout.encode(src, b, offset + 1) + 1;
139 | }
140 |
141 | decode(b: Buffer, offset = 0): T | null {
142 | const discriminator = this.discriminator.decode(b, offset);
143 | if (discriminator === 0) {
144 | return null;
145 | } else if (discriminator === 1) {
146 | return this.layout.decode(b, offset + 1);
147 | }
148 | throw new Error('Invalid option ' + this.property);
149 | }
150 |
151 | getSpan(b: Buffer, offset = 0): number {
152 | const discriminator = this.discriminator.decode(b, offset);
153 | if (discriminator === 0) {
154 | return 1;
155 | } else if (discriminator === 1) {
156 | return this.layout.getSpan(b, offset + 1) + 1;
157 | }
158 | throw new Error('Invalid option ' + this.property);
159 | }
160 | }
161 |
162 | export function option(
163 | layout: Layout,
164 | property?: string,
165 | ): Layout {
166 | return new OptionLayout(layout, property);
167 | }
168 |
169 | export function bool(property?: string): Layout {
170 | return new WrappedLayout(u8(), decodeBool, encodeBool, property);
171 | }
172 |
173 | function decodeBool(value: number): boolean {
174 | if (value === 0) {
175 | return false;
176 | } else if (value === 1) {
177 | return true;
178 | }
179 | throw new Error('Invalid bool: ' + value);
180 | }
181 |
182 | function encodeBool(value: boolean): number {
183 | return value ? 1 : 0;
184 | }
185 |
186 | export function vec(
187 | elementLayout: Layout,
188 | property?: string,
189 | ): Layout {
190 | const length = u32('length');
191 | const layout: Layout<{ values: T[] }> = struct([
192 | length,
193 | seq(elementLayout, offset(length, -length.span), 'values'),
194 | ]);
195 | return new WrappedLayout(
196 | layout,
197 | ({ values }) => values,
198 | values => ({ values }),
199 | property,
200 | );
201 | }
202 |
203 | export function tagged(
204 | tag: BN,
205 | layout: Layout,
206 | property?: string,
207 | ): Layout {
208 | const wrappedLayout: Layout<{ tag: BN; data: T }> = struct([
209 | u64('tag'),
210 | layout.replicate('data'),
211 | ]);
212 |
213 | function decodeTag({ tag: receivedTag, data }: { tag: BN; data: T }) {
214 | if (!receivedTag.eq(tag)) {
215 | throw new Error(
216 | 'Invalid tag, expected: ' +
217 | tag.toString('hex') +
218 | ', got: ' +
219 | receivedTag.toString('hex'),
220 | );
221 | }
222 | return data;
223 | }
224 |
225 | return new WrappedLayout(
226 | wrappedLayout,
227 | decodeTag,
228 | data => ({ tag, data }),
229 | property,
230 | );
231 | }
232 |
233 | export function vecU8(property?: string): Layout {
234 | const length = u32('length');
235 | const layout: Layout<{ data: Buffer }> = struct([
236 | length,
237 | blob(offset(length, -length.span), 'data'),
238 | ]);
239 | return new WrappedLayout(
240 | layout,
241 | ({ data }) => data,
242 | data => ({ data }),
243 | property,
244 | );
245 | }
246 |
247 | export function str(property?: string): Layout {
248 | return new WrappedLayout(
249 | vecU8(),
250 | data => data.toString('utf-8'),
251 | s => Buffer.from(s, 'utf-8'),
252 | property,
253 | );
254 | }
255 |
256 | export interface EnumLayout extends Layout {
257 | registry: Record>;
258 | }
259 |
260 | export function rustEnum(
261 | variants: Layout[],
262 | property?: string,
263 | discriminant?: Layout,
264 | ): EnumLayout {
265 | const unionLayout = union(discriminant ?? u8(), property);
266 | variants.forEach((variant, index) =>
267 | unionLayout.addVariant(index, variant, variant.property),
268 | );
269 | return unionLayout;
270 | }
271 |
272 | export function array(
273 | elementLayout: Layout,
274 | length: number,
275 | property?: string,
276 | ): Layout {
277 | const layout: Layout<{ values: T[] }> = struct([
278 | seq(elementLayout, length, 'values'),
279 | ]);
280 | return new WrappedLayout(
281 | layout,
282 | ({ values }) => values,
283 | values => ({ values }),
284 | property,
285 | );
286 | }
287 |
288 | class MapEntryLayout extends LayoutCls<[K, V]> {
289 | keyLayout: Layout;
290 | valueLayout: Layout;
291 |
292 | constructor(keyLayout: Layout, valueLayout: Layout, property?: string) {
293 | super(keyLayout.span + valueLayout.span, property);
294 | this.keyLayout = keyLayout;
295 | this.valueLayout = valueLayout;
296 | }
297 |
298 | decode(b: Buffer, offset?: number): [K, V] {
299 | offset = offset || 0;
300 | const key = this.keyLayout.decode(b, offset);
301 | const value = this.valueLayout.decode(
302 | b,
303 | offset + this.keyLayout.getSpan(b, offset),
304 | );
305 | return [key, value];
306 | }
307 |
308 | encode(src: [K, V], b: Buffer, offset?: number): number {
309 | offset = offset || 0;
310 | const keyBytes = this.keyLayout.encode(src[0], b, offset);
311 | const valueBytes = this.valueLayout.encode(src[1], b, offset + keyBytes);
312 | return keyBytes + valueBytes;
313 | }
314 |
315 | getSpan(b: Buffer, offset?: number): number {
316 | return (
317 | this.keyLayout.getSpan(b, offset) + this.valueLayout.getSpan(b, offset)
318 | );
319 | }
320 | }
321 |
322 | export function map(
323 | keyLayout: Layout,
324 | valueLayout: Layout,
325 | property?: string,
326 | ): Layout