├── .gitignore ├── .npmrc ├── .nvmrc ├── .prettierrc.js ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── packages ├── covalent-sdk │ ├── package.json │ ├── readme.md │ ├── scripts │ │ ├── generateSDK.ts │ │ ├── schema.json │ │ └── updateSchema.ts │ ├── src │ │ └── index.ts │ ├── test │ │ └── test.spec.ts │ └── tsconfig.json ├── lz-sdk │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── constants │ │ │ ├── addresses.ts │ │ │ ├── blockTime.ts │ │ │ ├── index.ts │ │ │ └── rpcs.ts │ │ ├── enums │ │ │ ├── ChainId.ts │ │ │ ├── ChainKey.ts │ │ │ ├── ChainListId.ts │ │ │ ├── ChainStage.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── utils │ │ │ ├── hardhatDeploy.ts │ │ │ ├── helpers.test.ts │ │ │ ├── helpers.ts │ │ │ └── index.ts │ ├── tsconfig.json │ └── tsup.config.ts └── sg-sdk │ ├── .npmrc │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ ├── constants.ts │ ├── constants │ │ ├── addresses.ts │ │ ├── gasEstimate.ts │ │ ├── pool.ts │ │ ├── testAddresses.ts │ │ ├── testToken.ts │ │ └── token.ts │ ├── entities │ │ ├── bonding.test.ts │ │ ├── bonding.ts │ │ ├── fee.test.ts │ │ ├── fee.ts │ │ ├── index.ts │ │ ├── pool.test.ts │ │ ├── pool.ts │ │ ├── votingEscrow.test.ts │ │ └── votingEscrow.ts │ ├── enums │ │ ├── PoolId.ts │ │ ├── TokenSymbol.ts │ │ └── index.ts │ ├── index.ts │ └── utils │ │ ├── constants.ts │ │ ├── data │ │ └── farming.json │ │ ├── estimateDstNativeAmt.ts │ │ ├── getFarmApy.test.ts │ │ ├── getFarmApy.ts │ │ ├── helpers.ts │ │ ├── index.ts │ │ ├── invariantHelper.ts │ │ ├── printPoolMesh.js │ │ ├── validateAndParseAddress.test.ts │ │ └── validateAndParseAddress.ts │ ├── tsconfig.json │ └── tsup.config.ts └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .idea 4 | .DS_Store 5 | .env 6 | 7 | # yarn 8 | yarn-error.log 9 | .yarn 10 | .yarnrc.yml 11 | 12 | # hardhat 13 | cache 14 | artifacts 15 | 16 | # lerna 17 | lerna-debug.log 18 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.12.0 -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | overrides: [ 3 | { 4 | files: "*.ts", 5 | options: { 6 | printWidth: 145, 7 | semi: false, 8 | tabWidth: 4, 9 | useTabs: false, 10 | trailingComma: "es5", 11 | }, 12 | }, 13 | { 14 | files: "*.js", 15 | options: { 16 | printWidth: 145, 17 | semi: false, 18 | tabWidth: 4, 19 | useTabs: false, 20 | trailingComma: "es5", 21 | }, 22 | }, 23 | ], 24 | } 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Business Source License 1.1 2 | 3 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. 4 | "Business Source License" is a trademark of MariaDB Corporation Ab. 5 | 6 | ----------------------------------------------------------------------------- 7 | 8 | Parameters 9 | 10 | Licensor: LayerZero Labs Ltd 11 | 12 | Licensed Work: LayerZero SDK 13 | The Licensed Work is (c) 2022 LayerZero Labs Ltd 14 | 15 | Change Date: 2025-02-01 16 | 17 | ----------------------------------------------------------------------------- 18 | 19 | Terms 20 | 21 | The Licensor hereby grants you the right to copy, modify, create derivative 22 | works, redistribute, and make non-production use of the Licensed Work. The 23 | Licensor may make an Additional Use Grant, above, permitting limited 24 | production use. 25 | 26 | Effective on the Change Date, or the fourth anniversary of the first publicly 27 | available distribution of a specific version of the Licensed Work under this 28 | License, whichever comes first, the Licensor hereby grants you rights under 29 | the terms of the Change License, and the rights granted in the paragraph 30 | above terminate. 31 | 32 | If your use of the Licensed Work does not comply with the requirements 33 | currently in effect as described in this License, you must purchase a 34 | commercial license from the Licensor, its affiliated entities, or authorized 35 | resellers, or you must refrain from using the Licensed Work. 36 | 37 | All copies of the original and modified Licensed Work, and derivative works 38 | of the Licensed Work, are subject to this License. This License applies 39 | separately for each version of the Licensed Work and the Change Date may vary 40 | for each version of the Licensed Work released by Licensor. 41 | 42 | You must conspicuously display this License on each original or modified copy 43 | of the Licensed Work. If you receive the Licensed Work in original or 44 | modified form from a third party, the terms and conditions set forth in this 45 | License apply to your use of that work. 46 | 47 | Any use of the Licensed Work in violation of this License will automatically 48 | terminate your rights under this License for the current and all other 49 | versions of the Licensed Work. 50 | 51 | This License does not grant you any right in any trademark or logo of 52 | Licensor or its affiliates (provided that you may use a trademark or logo of 53 | Licensor as expressly required by this License). 54 | 55 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON 56 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, 57 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF 58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND 59 | TITLE. 60 | 61 | MariaDB hereby grants you permission to use this License’s text to license 62 | your works, and to refer to it using the trademark "Business Source License", 63 | as long as you comply with the Covenants of Licensor below. 64 | 65 | ----------------------------------------------------------------------------- 66 | 67 | Covenants of Licensor 68 | 69 | In consideration of the right to use this License’s text and the "Business 70 | Source License" name and trademark, Licensor covenants to MariaDB, and to all 71 | other recipients of the licensed work to be provided by Licensor: 72 | 73 | 1. To specify as the Change License the GPL Version 2.0 or any later version, 74 | or a license that is compatible with GPL Version 2.0 or a later version, 75 | where "compatible" means that software provided under the Change License can 76 | be included in a program with software provided under GPL Version 2.0 or a 77 | later version. Licensor may specify additional Change Licenses without 78 | limitation. 79 | 80 | 2. To either: (a) specify an additional grant of rights to use that does not 81 | impose any additional restriction on the right granted in this License, as 82 | the Additional Use Grant; or (b) insert the text "None". 83 | 84 | 3. To specify a Change Date. 85 | 86 | 4. Not to modify this License in any other way. 87 | 88 | ----------------------------------------------------------------------------- 89 | 90 | Notice 91 | 92 | The Business Source License (this document, or the "License") is not an Open 93 | Source license. However, the Licensed Work will eventually be made available 94 | under an Open Source License, as stated in this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 | 5 | The packages in this repository have moved to [LayerZero-Labs/ui-monorepo](https://github.com/LayerZero-Labs/ui-monorepo) and will no longer receive updates here. 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "packages": ["packages/*"], 5 | "command": { 6 | "version": { 7 | "exact": true 8 | }, 9 | "ignoreChanges": [ 10 | "**/CHANGELOG.md", 11 | "**/node_modules/**", 12 | "**/package.json", 13 | "**/*.md" 14 | ], 15 | "publish": { 16 | "npmClient": "npm", 17 | "allowBranch": ["main", "dev", "feat/*"], 18 | "registry": "https://registry.npmjs.org/" 19 | } 20 | }, 21 | "version": "independent" 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@layerzerolabs/sdk", 3 | "private": true, 4 | "workspaces": [ 5 | "packages/*" 6 | ], 7 | "scripts": { 8 | "lerna": "lerna", 9 | "build": "lerna run build --stream", 10 | "test": "lerna run test --stream", 11 | "watch": "lerna run watch --stream", 12 | "publish:main": "lerna publish from-package", 13 | "publish:dev": "lerna publish from-package --dist-tag dev --preid dev", 14 | "lint": "prettier --write packages/**/**/*.ts && prettier --write packages/**/**/**/*.ts" 15 | }, 16 | "description": "LayerZero Labs SDKs", 17 | "main": "index.js", 18 | "dependencies": { 19 | "@types/node": "^16.9.1", 20 | "lerna": "^4.0.0" 21 | }, 22 | "devDependencies": { 23 | "@nomiclabs/hardhat-ethers": "^2.0.0", 24 | "@nomiclabs/hardhat-solhint": "^2.0.0", 25 | "@nomiclabs/hardhat-waffle": "^2.0.1", 26 | "@nomiclabs/hardhat-web3": "^2.0.0", 27 | "ethers": "^5.4.7", 28 | "hardhat": "2.8.2", 29 | "hardhat-contract-sizer": "^2.1.1", 30 | "hardhat-deploy": "^0.10.5", 31 | "hardhat-deploy-ethers": "^0.3.0-beta.13", 32 | "hardhat-gas-reporter": "^1.0.6", 33 | "prettier": "^2.6.2", 34 | "ts-node": "^10.6.0", 35 | "typescript": "^4.6.2" 36 | }, 37 | "engines": { 38 | "node": ">=12.0.0" 39 | }, 40 | "packageManager": "yarn@3.1.1" 41 | } 42 | -------------------------------------------------------------------------------- /packages/covalent-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@layerzerolabs/covalent-sdk", 3 | "version": "0.0.8", 4 | "main": "./dist/index.js", 5 | "exports": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "files": [ 8 | "dist/**" 9 | ], 10 | "scripts": { 11 | "prebuild": "ts-node ./scripts/generateSDK.ts", 12 | "build": "tsdx build", 13 | "start": "tsdx watch", 14 | "test": "vitest run" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "BUSL-1.1", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/LayerZero-Labs/sdk.git", 22 | "directory": "packages/covalent-sdk" 23 | }, 24 | "devDependencies": { 25 | "json-schema-to-typescript": "^11.0.1", 26 | "lodash": "^4.17.21", 27 | "prettier": "^2.7.1", 28 | "ts-node": "^10.9.1", 29 | "tsdx": "^0.14.1", 30 | "typescript": "^4.9.5", 31 | "vitest": "^0.31.2" 32 | }, 33 | "peerDependencies": { 34 | "axios": "*" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/covalent-sdk/readme.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | 3 | ```sh 4 | yarn add @layerzerolabs/covalent-sdk 5 | or 6 | npm i @layerzerolabs/covalent-sdk 7 | ``` 8 | 9 | ## Usage 10 | 11 | ```typescript 12 | import {Covalent} from '@layerzerolabs/covalent-sdk'; 13 | 14 | const client = new Covalent.Client(process.env.COVALENT_API_KEY); 15 | 16 | const result = await client.getTokenBalancesForAddress({ 17 | chainId: Covalent.ChainId.ETHEREUM, 18 | address: '0x6d9F1a927CBcb5e2c28D13CA735bc6d6131406da', 19 | }); 20 | ``` 21 | -------------------------------------------------------------------------------- /packages/covalent-sdk/scripts/generateSDK.ts: -------------------------------------------------------------------------------- 1 | import schema from "./schema.json" 2 | import { camelCase } from "lodash" 3 | import { compile } from "json-schema-to-typescript" 4 | import prettier from "prettier" 5 | import fs from "fs" 6 | import path from "path" 7 | 8 | // schema downloaded from 9 | // https://api.covalenthq.com/v1/openapiv2/v20220805105331/ 10 | // todo: add zod 11 | 12 | function mapType({ type, name }: { name: string; type: string }) { 13 | if (name === "chain_id") return "ChainId" 14 | return type === "integer" ? "number" : type 15 | } 16 | function mapParamName(n: string) { 17 | return camelCase(n) 18 | } 19 | 20 | function toUrlExpression(path: string, params: any[]) { 21 | params.forEach((param) => { 22 | path = path.replace(":" + param.name, "${" + mapParamName(param.name) + "}") 23 | }) 24 | return "`" + path + "`" 25 | } 26 | 27 | function fixComponents(schema: T): T { 28 | // very naive - parser fails otherwise 29 | return JSON.parse(JSON.stringify(schema).replaceAll("#/components/schemas/", "#/components/")) 30 | } 31 | 32 | Promise.all( 33 | schema.map(async (def) => { 34 | const methodName = camelCase(def.title) 35 | const response = fixComponents(def.response) 36 | 37 | const jsonSchema = { 38 | ...response.schema, 39 | description: def.description, 40 | title: response.name, 41 | components: response.components, 42 | } 43 | 44 | const responseType = def.response.name 45 | const responseDeclaration = await compile(jsonSchema as any, responseType) 46 | 47 | const jsDoc = `/** 48 | * ${def.description.split("\n").join(" ")} 49 | ${def.params.map((p) => `* @param ${mapParamName(p.name)} - ${p.description}`).join("\n")} 50 | */` 51 | 52 | const args = "{" + def.params.map((p) => mapParamName(p.name)).join(", ") + "}" 53 | const argsType = "{" + def.params.map((p) => `${mapParamName(p.name)}${p.required === false ? "?" : ""} :${mapType(p)}`).join(", ") + "}" 54 | 55 | const queryParams = def.params 56 | .filter((p) => p.pathParam === false) 57 | .map((p) => `"${p.name}": ` + mapParamName(p.name)) 58 | .join(", ") 59 | 60 | const signature = def.params.length ? `${args} : ${argsType}` : "" 61 | const functionDeclaration = ` 62 | ${jsDoc} 63 | async ${methodName}(${signature}) { 64 | const url = ${toUrlExpression(def.path, def.params)}; 65 | const {data} = await this.http.get>(url, {params:{${queryParams}}}); 66 | if(data.error){ 67 | throw new Error(data.error_message); 68 | } 69 | return data.data; 70 | }` 71 | 72 | const moduleCode = { 73 | functionDeclaration, 74 | responseDeclaration, 75 | } 76 | 77 | return moduleCode 78 | }) 79 | ) 80 | .then(async (modules) => { 81 | const responseDeclaration = `type CovalentResponse = { 82 | data: T, 83 | error: false, 84 | error_code: null, 85 | error_message: null, 86 | } | { 87 | data: null, 88 | error: true, 89 | error_code: unknown, 90 | error_message: string 91 | }` 92 | const clientDeclaration = ` 93 | export class Client { 94 | private http: Axios; 95 | constructor(private apiKey: string, private baseURL = "https://api.covalenthq.com") { 96 | this.http = axios.create({ 97 | baseURL, 98 | params: { 99 | key: apiKey, 100 | }, 101 | }); 102 | } 103 | 104 | ${modules.map((m) => m.functionDeclaration).join("\n\n")} 105 | }` 106 | 107 | const typesDeclaration = modules.map((m) => m.responseDeclaration).join("\n\n") 108 | 109 | const fileName = path.resolve(__dirname, "../src/index.ts") 110 | const prettierConfig = await prettier.resolveConfig(fileName) 111 | 112 | const sourceCode = prettier.format( 113 | ` 114 | // @ts-nocheck 115 | import axios, {Axios} from 'axios'; 116 | 117 | export namespace Covalent { 118 | 119 | export enum ChainId { 120 | ETHEREUM = 1, 121 | ETHEREUM_KOVAN = 42, 122 | POLYGON = 137, 123 | POLYGON_MUMBAI = 80001, 124 | AVALANCHE = 43114, 125 | AVALANCHE_FUJI = 43113, 126 | BSC = 56, 127 | BSC_TESTNET = 97, 128 | FANTOM = 250, 129 | FANTOM_TESTNET = 4002, 130 | RONIN = 2020, 131 | MOONBEAM_TESTNET = 1287, 132 | MOONBEAM_POLKADOT = 1284, 133 | MOONRIVER_KUSAMA = 1285, 134 | RSK_MAINNET = 30, 135 | RSK_TESTNET = 31, 136 | ARBITRUM_MAINNET = 42161, 137 | ARBITRUM_TESTNET = 421611, 138 | PALM_MAINNET = 11297108109, 139 | PALM_TESTNET = 11297108099, 140 | KLAYTN_MAINNET_CYPRESS = 8217, 141 | HECO_MAINNET = 128, 142 | HECO_TESTNET = 256, 143 | POLYJUICE_TESTNET = 71393, 144 | IOTEX_MAINNET = 4689, 145 | IOTEX_TESTNET = 4690, 146 | EVMOS_TESTNET = 9000, 147 | ASTAR_MAINNET = 592, 148 | ASTAR_TESTNET = 81, 149 | SHIDEN = 336, 150 | HARMONY_MAINNET = 1666600000, 151 | AURORA_MAINNET = 1313161554, 152 | CRONOS_MAINNET = 25, 153 | SOLANA = 1399811149, 154 | } 155 | 156 | export ${clientDeclaration}; 157 | export ${responseDeclaration} 158 | 159 | ${typesDeclaration} 160 | }`, 161 | { ...prettierConfig, parser: "typescript" } 162 | ) 163 | 164 | fs.writeFileSync(fileName, sourceCode) 165 | }) 166 | .catch(console.error) 167 | -------------------------------------------------------------------------------- /packages/covalent-sdk/scripts/updateSchema.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import fs from 'fs'; 3 | import axios from 'axios'; 4 | 5 | async function updateSchema() { 6 | const url = 'https://api.covalenthq.com/v1/openapiv2/'; 7 | const {data} = await axios.get(url); 8 | if (!Array.isArray(data)) throw new Error(`Invalid response from ${url}`); 9 | const schema = JSON.stringify(data, null, 4); 10 | fs.writeFileSync(path.resolve(__dirname, 'schema.json'), schema); 11 | } 12 | 13 | updateSchema(); 14 | -------------------------------------------------------------------------------- /packages/covalent-sdk/test/test.spec.ts: -------------------------------------------------------------------------------- 1 | import { assert, it } from "vitest" 2 | import { Covalent } from "../src" 3 | 4 | it.skip("getTokenBalancesForAddress", async () => { 5 | assert(process.env.COVALENT_API_KEY, "COVALENT_API_KEY env missing") 6 | const sdk = new Covalent.Client(process.env.COVALENT_API_KEY) 7 | 8 | const result = await sdk.getTokenBalancesForAddress({ 9 | chainId: Covalent.ChainId.ETHEREUM, 10 | address: "0x6d9F1a927CBcb5e2c28D13CA735bc6d6131406da", 11 | }) 12 | assert(result, "no result") 13 | }) 14 | 15 | it.skip("getTransactionsForAddress", async () => { 16 | assert(process.env.COVALENT_API_KEY, "COVALENT_API_KEY env missing") 17 | const sdk = new Covalent.Client(process.env.COVALENT_API_KEY) 18 | 19 | const result = await sdk.getTransactionsForAddress({ 20 | chainId: Covalent.ChainId.ETHEREUM, 21 | address: "0x6d9F1a927CBcb5e2c28D13CA735bc6d6131406da", 22 | }) 23 | assert(result.items, "items") 24 | }, 10_000) 25 | -------------------------------------------------------------------------------- /packages/covalent-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "rootDir": "src", 6 | "target": "es6", 7 | "module": "esnext", 8 | "lib": ["esnext"], 9 | "importHelpers": true, 10 | "declaration": true, 11 | "sourceMap": true, 12 | "strict": true, 13 | "noImplicitAny": true, 14 | "strictNullChecks": true, 15 | "strictFunctionTypes": true, 16 | "strictPropertyInitialization": true, 17 | "noImplicitThis": true, 18 | "alwaysStrict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "moduleResolution": "node", 24 | "esModuleInterop": true, 25 | "resolveJsonModule": true 26 | }, 27 | "ts-node": { 28 | // these options are overrides used only by ts-node 29 | // same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable 30 | "compilerOptions": { 31 | "module": "commonjs" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/lz-sdk/LICENSE: -------------------------------------------------------------------------------- 1 | Business Source License 1.1 2 | 3 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. 4 | "Business Source License" is a trademark of MariaDB Corporation Ab. 5 | 6 | ----------------------------------------------------------------------------- 7 | 8 | Parameters 9 | 10 | Licensor: LayerZero Labs Ltd 11 | 12 | Licensed Work: LayerZero SDK 13 | The Licensed Work is (c) 2022 LayerZero Labs Ltd 14 | 15 | Change Date: 2025-02-01 16 | 17 | ----------------------------------------------------------------------------- 18 | 19 | Terms 20 | 21 | The Licensor hereby grants you the right to copy, modify, create derivative 22 | works, redistribute, and make non-production use of the Licensed Work. The 23 | Licensor may make an Additional Use Grant, above, permitting limited 24 | production use. 25 | 26 | Effective on the Change Date, or the fourth anniversary of the first publicly 27 | available distribution of a specific version of the Licensed Work under this 28 | License, whichever comes first, the Licensor hereby grants you rights under 29 | the terms of the Change License, and the rights granted in the paragraph 30 | above terminate. 31 | 32 | If your use of the Licensed Work does not comply with the requirements 33 | currently in effect as described in this License, you must purchase a 34 | commercial license from the Licensor, its affiliated entities, or authorized 35 | resellers, or you must refrain from using the Licensed Work. 36 | 37 | All copies of the original and modified Licensed Work, and derivative works 38 | of the Licensed Work, are subject to this License. This License applies 39 | separately for each version of the Licensed Work and the Change Date may vary 40 | for each version of the Licensed Work released by Licensor. 41 | 42 | You must conspicuously display this License on each original or modified copy 43 | of the Licensed Work. If you receive the Licensed Work in original or 44 | modified form from a third party, the terms and conditions set forth in this 45 | License apply to your use of that work. 46 | 47 | Any use of the Licensed Work in violation of this License will automatically 48 | terminate your rights under this License for the current and all other 49 | versions of the Licensed Work. 50 | 51 | This License does not grant you any right in any trademark or logo of 52 | Licensor or its affiliates (provided that you may use a trademark or logo of 53 | Licensor as expressly required by this License). 54 | 55 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON 56 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, 57 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF 58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND 59 | TITLE. 60 | 61 | MariaDB hereby grants you permission to use this License’s text to license 62 | your works, and to refer to it using the trademark "Business Source License", 63 | as long as you comply with the Covenants of Licensor below. 64 | 65 | ----------------------------------------------------------------------------- 66 | 67 | Covenants of Licensor 68 | 69 | In consideration of the right to use this License’s text and the "Business 70 | Source License" name and trademark, Licensor covenants to MariaDB, and to all 71 | other recipients of the licensed work to be provided by Licensor: 72 | 73 | 1. To specify as the Change License the GPL Version 2.0 or any later version, 74 | or a license that is compatible with GPL Version 2.0 or a later version, 75 | where "compatible" means that software provided under the Change License can 76 | be included in a program with software provided under GPL Version 2.0 or a 77 | later version. Licensor may specify additional Change Licenses without 78 | limitation. 79 | 80 | 2. To either: (a) specify an additional grant of rights to use that does not 81 | impose any additional restriction on the right granted in this License, as 82 | the Additional Use Grant; or (b) insert the text "None". 83 | 84 | 3. To specify a Change Date. 85 | 86 | 4. Not to modify this License in any other way. 87 | 88 | ----------------------------------------------------------------------------- 89 | 90 | Notice 91 | 92 | The Business Source License (this document, or the "License") is not an Open 93 | Source license. However, the Licensed Work will eventually be made available 94 | under an Open Source License, as stated in this License. -------------------------------------------------------------------------------- /packages/lz-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 | 5 | This package has moved to [LayerZero-Labs/ui-monorepo](https://github.com/LayerZero-Labs/ui-monorepo/tree/main/packages/lz-sdk) and will no longer receive updates here. 6 | -------------------------------------------------------------------------------- /packages/lz-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@layerzerolabs/lz-sdk", 3 | "version": "0.0.38", 4 | "license": "BUSL-1.1", 5 | "description": "LayerZero SDK", 6 | "type": "module", 7 | "main": "./dist/index.cjs", 8 | "module": "./dist/index.mjs", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | "types": "./dist/index.d.ts", 12 | "require": "./dist/index.cjs", 13 | "import": "./dist/index.mjs" 14 | }, 15 | "files": [ 16 | "dist/*" 17 | ], 18 | "publishConfig": { 19 | "access": "public", 20 | "registry": "https://registry.npmjs.org/" 21 | }, 22 | "scripts": { 23 | "build": "npx tsup", 24 | "dev": "npx tsup --watch", 25 | "test": "vitest run" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "https://github.com/LayerZero-Labs/sdk.git", 30 | "directory": "packages/lz-sdk" 31 | }, 32 | "devDependencies": { 33 | "@layerzerolabs/tsup-config": "~0.0.4", 34 | "vitest": "^0.31.2" 35 | }, 36 | "engines": { 37 | "node": ">=10" 38 | }, 39 | "gitHead": "9747743d0351d9f038b3306f8ef2b9f95b08bffd" 40 | } 41 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/constants/blockTime.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "../enums" 2 | 3 | // in seconds 4 | // keep list sorted alphabetically 5 | // @deprecated 6 | export const AVERAGE_BLOCK_TIME: { [chainId in ChainId]: number } = { 7 | [ChainId.AAVEGOTCHI_TESTNET]: 5, 8 | [ChainId.APTOS_TESTNET_SANDBOX]: 1, 9 | [ChainId.APTOS_TESTNET]: 1, 10 | [ChainId.APTOS]: 1, 11 | [ChainId.ARBITRUM_GOERLI_SANDBOX]: 15.2, 12 | [ChainId.ARBITRUM_GOERLI]: 15.2, 13 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: 15.2, 14 | [ChainId.ARBITRUM_RINKEBY]: 15.2, 15 | [ChainId.ARBITRUM]: 13.5, 16 | [ChainId.ARCANA_TESTNET_SANDBOX]: 2, 17 | [ChainId.ARCANA_TESTNET]: 2, 18 | [ChainId.ARCANA]: 1, 19 | [ChainId.ASTAR_TESTNET_SANDBOX]: 1, 20 | [ChainId.ASTAR_TESTNET]: 1, 21 | [ChainId.ASTAR]: 1, 22 | [ChainId.AURORA_TESTNET_SANDBOX]: 2, 23 | [ChainId.AURORA_TESTNET]: 2, 24 | [ChainId.AURORA]: 2, 25 | [ChainId.AVALANCHE]: 2.1, 26 | [ChainId.BASE]: 1, 27 | [ChainId.BASE_TESTNET]: 1, 28 | [ChainId.BOBA_TESTNET_SANDBOX]: 2, 29 | [ChainId.BOBA_TESTNET]: 2, 30 | [ChainId.BOBA]: 2, 31 | [ChainId.BSC_TESTNET_SANDBOX]: 3.1, 32 | [ChainId.BSC_TESTNET]: 3.1, 33 | [ChainId.BSC]: 3.1, 34 | [ChainId.CANTO]: 8, 35 | [ChainId.CANTO_TESTNET]: 8, 36 | [ChainId.CASTLECRUSH_TESTNET_SANDBOX]: 5, 37 | [ChainId.CASTLECRUSH_TESTNET]: 5, 38 | [ChainId.CASTLECRUSH]: 5, 39 | [ChainId.CELO_TESTNET_SANDBOX]: 5, 40 | [ChainId.CELO_TESTNET]: 5, 41 | [ChainId.CELO]: 5, 42 | [ChainId.COREDAO_TESTNET]: 5, 43 | [ChainId.COREDAO]: 5, 44 | [ChainId.DEXALOT_TESTNET_SANDBOX]: 10, 45 | [ChainId.DEXALOT_TESTNET]: 10, 46 | [ChainId.DEXALOT]: 10, 47 | [ChainId.DFK_TESTNET_SANDBOX]: 10, 48 | [ChainId.DFK_TESTNET]: 10, 49 | [ChainId.DFK]: 2.5, 50 | [ChainId.DOS_TESTNET]: 1, 51 | [ChainId.DOS]: 1, 52 | [ChainId.ETHEREUM]: 13.5, 53 | [ChainId.FANTOM_TESTNET_SANDBOX]: 3.5, 54 | [ChainId.FANTOM_TESTNET]: 3.5, 55 | [ChainId.FANTOM]: 1, 56 | [ChainId.FUJI_SANDBOX]: 2.1, 57 | [ChainId.FUJI]: 2.1, 58 | [ChainId.FUSE_TESTNET_SANDBOX]: 5, 59 | [ChainId.FUSE_TESTNET]: 5, 60 | [ChainId.FUSE]: 5, 61 | [ChainId.GNOSIS_TESTNET_SANDBOX]: 12.5, 62 | [ChainId.GNOSIS_TESTNET]: 12.5, 63 | [ChainId.GNOSIS]: 12.5, 64 | [ChainId.GOERLI_MAINNET]: 1, 65 | [ChainId.GOERLI_SANDBOX]: 15, 66 | [ChainId.GOERLI]: 15, 67 | [ChainId.HARMONY_TESTNET_SANDBOX]: 2, 68 | [ChainId.HARMONY_TESTNET]: 2, 69 | [ChainId.HARMONY]: 2, 70 | [ChainId.INTAIN_TESTNET_SANDBOX]: 1, 71 | [ChainId.INTAIN_TESTNET]: 1, 72 | [ChainId.INTAIN]: 1, 73 | [ChainId.KAVA]: 1, 74 | [ChainId.KAVA_TESTNET]: 1, 75 | [ChainId.KLAYTN_TESTNET]: 1, 76 | [ChainId.KLAYTN]: 1, 77 | [ChainId.KOVAN_SANDBOX]: 4.2, 78 | [ChainId.KOVAN]: 4.2, 79 | [ChainId.LOOT]: 2, 80 | [ChainId.LOOT_TESTNET]: 2, 81 | [ChainId.MANTLE]: 5, 82 | [ChainId.MANTLE_TESTNET]: 7, 83 | [ChainId.METER_TESTNET]: 1, 84 | [ChainId.METER]: 1, 85 | [ChainId.METIS_TESTNET]: 1, 86 | [ChainId.METIS]: 1, 87 | [ChainId.MOONBEAM_TESTNET_SANDBOX]: 12, 88 | [ChainId.MOONBEAM_TESTNET]: 12, 89 | [ChainId.MOONBEAM]: 12, 90 | [ChainId.MOONRIVER_TESTNET]: 15, 91 | [ChainId.MOONRIVER]: 15, 92 | [ChainId.MUMBAI_SANDBOX]: 3.5, 93 | [ChainId.MUMBAI]: 3.5, 94 | [ChainId.NOVA]: 1, 95 | [ChainId.OKX_TESTNET]: 1, 96 | [ChainId.OKX]: 1, 97 | [ChainId.OPTIMISM_GOERLI_SANDBOX]: 1, 98 | [ChainId.OPTIMISM_GOERLI]: 1, 99 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: 1, 100 | [ChainId.OPTIMISM_KOVAN]: 1, 101 | [ChainId.OPTIMISM]: 2, 102 | [ChainId.POLYGON]: 2.5, 103 | [ChainId.PORTAL_TESTNET_SANDBOX]: 2, 104 | [ChainId.PORTAL_TESTNET]: 2, 105 | [ChainId.PORTAL]: 1, 106 | [ChainId.RINKEBY_SANDBOX]: 15.2, 107 | [ChainId.RINKEBY]: 15.2, 108 | [ChainId.SEPOLIA_TESTNET]: 13, 109 | [ChainId.SEPOLIA]: 13, 110 | [ChainId.SHRAPNEL_TESTNET]: 1, 111 | [ChainId.SHRAPNEL]: 1, 112 | [ChainId.SOLANA_TESTNET]: 1, 113 | [ChainId.SOLANA]: 1, 114 | [ChainId.SWIMMER_TESTNET_SANDBOX]: 5, 115 | [ChainId.SWIMMER_TESTNET]: 5, 116 | [ChainId.SWIMMER]: 5, 117 | [ChainId.TELOS_TESTNET]: 1, // They don't actually produce blocks at regular intervals 118 | [ChainId.TENET]: 3.5, 119 | [ChainId.TENET_TESTNET]: 3.7, 120 | [ChainId.TOMO_TESTNET]: 3, 121 | [ChainId.ZKCONSENSYS]: 1, 122 | [ChainId.ZKCONSENSYS_TESTNET]: 1, 123 | [ChainId.ZKPOLYGON_TESTNET]: 2, 124 | [ChainId.ZKPOLYGON]: 2, 125 | [ChainId.ZKSYNC_TESTNET]: 1.4, 126 | [ChainId.ZKSYNC]: 1.6, 127 | [ChainId.BLOCKGEN_TESTNET]: 1, 128 | [ChainId.BEAM]: 1, 129 | [ChainId.BEAM_TESTNET]: 1, 130 | [ChainId.ZORA_TESTNET]: 1.8, 131 | } 132 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./addresses" 2 | export * from "./rpcs" 3 | export * from "./blockTime" 4 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/constants/rpcs.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "../enums" 2 | 3 | export const RPCS: { [chainId in ChainId]?: string[] } = { 4 | [ChainId.ETHEREUM]: [ 5 | "https://main-rpc.linkpool.io", 6 | "https://main-light.eth.linkpool.io", 7 | "https://eth-mainnet.gateway.pokt.network/v1/5f3453978e354ab992c4da79", 8 | "https://eth-rpc.gateway.pokt.network", 9 | "https://cloudflare-eth.com", 10 | "https://mainnet-nethermind.blockscout.com", 11 | "https://rpc.flashbots.net", 12 | "https://mainnet.infura.io/v3/", 13 | ], 14 | [ChainId.RINKEBY]: ["https://rinkeby-light.eth.linkpool.io"], 15 | [ChainId.RINKEBY_SANDBOX]: ["https://rinkeby-light.eth.linkpool.io"], 16 | [ChainId.KOVAN]: ["http://kovan.poa.network:8545", "https://kovan.poa.network"], 17 | [ChainId.KOVAN_SANDBOX]: ["http://kovan.poa.network:8545", "https://kovan.poa.network"], 18 | [ChainId.GOERLI]: ["https://rpc.goerli.mudit.blog/"], 19 | [ChainId.GOERLI_SANDBOX]: ["https://rpc.goerli.mudit.blog/"], 20 | [ChainId.BSC]: [ 21 | "https://rpc-bsc.bnb48.club", 22 | "https://bsc-dataseed2.ninicoin.io", 23 | "https://bsc-dataseed1.ninicoin.io", 24 | "https://bsc-dataseed4.binance.org", 25 | "https://bsc-dataseed2.defibit.io", 26 | "https://bsc-dataseed3.ninicoin.io", 27 | "https://bsc-dataseed1.defibit.io", 28 | "https://binance.nodereal.io", 29 | "https://bsc-dataseed3.binance.org", 30 | "https://bsc-dataseed.binance.org", 31 | "https://bsc-dataseed1.binance.org", 32 | "https://bsc-dataseed3.defibit.io", 33 | "https://bsc-dataseed2.binance.org", 34 | "https://bsc-dataseed4.ninicoin.io", 35 | "https://bsc-dataseed4.defibit.io", 36 | ], 37 | [ChainId.BSC_TESTNET]: [ 38 | "https://data-seed-prebsc-2-s3.binance.org:8545", 39 | "https://data-seed-prebsc-1-s2.binance.org:8545", 40 | "https://data-seed-prebsc-2-s2.binance.org:8545", 41 | ], 42 | [ChainId.BSC_TESTNET_SANDBOX]: [ 43 | "https://data-seed-prebsc-2-s3.binance.org:8545", 44 | "https://data-seed-prebsc-1-s2.binance.org:8545", 45 | "https://data-seed-prebsc-2-s2.binance.org:8545", 46 | ], 47 | [ChainId.CANTO]: ["https://mainnode.plexnode.org:8545", "https://canto.neobase.one", "https://canto.slingshot.finance"], 48 | [ChainId.CANTO_TESTNET]: ["https://eth.plexnode.wtf"], 49 | [ChainId.AVALANCHE]: ["https://api.avax.network/ext/bc/C/rpc"], 50 | [ChainId.FUJI]: ["https://api.avax-test.network/ext/bc/C/rpc"], 51 | [ChainId.FUJI_SANDBOX]: ["https://api.avax-test.network/ext/bc/C/rpc"], 52 | [ChainId.POLYGON]: [ 53 | "https://poly-rpc.gateway.pokt.network", 54 | "https://polygon-rpc.com", 55 | "https://rpc-mainnet.matic.quiknode.pro", 56 | "https://rpc-mainnet.matic.network", 57 | "https://matic-mainnet.chainstacklabs.com", 58 | "https://matic-mainnet-full-rpc.bwarelabs.com", 59 | "https://matic-mainnet-archive-rpc.bwarelabs.com", 60 | ], 61 | [ChainId.MUMBAI]: ["https://rpc-mumbai.maticvigil.com", "https://matic-mumbai.chainstacklabs.com"], 62 | [ChainId.MUMBAI_SANDBOX]: ["https://rpc-mumbai.maticvigil.com", "https://matic-mumbai.chainstacklabs.com"], 63 | [ChainId.ARBITRUM]: ["https://arb1.arbitrum.io/rpc"], 64 | [ChainId.ARBITRUM_RINKEBY]: ["https://rinkeby.arbitrum.io/rpc"], 65 | [ChainId.ARBITRUM_GOERLI]: ["https://goerli-rollup.arbitrum.io/rpc/"], 66 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: ["https://rinkeby.arbitrum.io/rpc"], 67 | [ChainId.OPTIMISM]: ["https://mainnet.optimism.io"], 68 | [ChainId.OPTIMISM_KOVAN]: ["https://kovan.optimism.io/"], 69 | [ChainId.OPTIMISM_GOERLI]: ["https://goerli.optimism.io/"], 70 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: ["https://kovan.optimism.io/"], 71 | [ChainId.FANTOM]: [ 72 | "https://rpc.ftm.tools", 73 | "https://rpc.fantom.network", 74 | "https://rpcapi.fantom.network", 75 | "https://rpc3.fantom.network", 76 | "https://rpc2.fantom.network", 77 | ], 78 | [ChainId.FANTOM_TESTNET]: ["https://rpc.testnet.fantom.network/"], 79 | [ChainId.FANTOM_TESTNET_SANDBOX]: ["https://rpc.testnet.fantom.network/"], 80 | [ChainId.SWIMMER]: ["https://subnets.avax.network/swimmer/mainnet/rpc"], 81 | [ChainId.SWIMMER_TESTNET]: ["https://subnets.avax.network/swimmer/testnet/rpc"], 82 | [ChainId.SWIMMER_TESTNET_SANDBOX]: ["https://subnets.avax.network/swimmer/testnet/rpc"], 83 | [ChainId.DFK]: ["https://subnets.avax.network/defi-kingdoms/dfk-chain/rpc"], 84 | [ChainId.DFK_TESTNET]: ["https://subnets.avax.network/defi-kingdoms/dfk-chain-testnet/rpc"], 85 | [ChainId.DFK_TESTNET_SANDBOX]: ["https://subnets.avax.network/defi-kingdoms/dfk-chain-testnet/rpc"], 86 | [ChainId.HARMONY]: ["https://api.harmony.one", "https://api.s0.t.hmny.io/"], 87 | [ChainId.HARMONY_TESTNET]: [ 88 | "https://api.s0.b.hmny.io/", 89 | "https://api.s1.b.hmny.io", 90 | "https://api.s0.backup1.b.hmny.io/", 91 | "https://api.s0.pops.one/", 92 | ], 93 | [ChainId.HARMONY_TESTNET_SANDBOX]: [ 94 | "https://api.s0.b.hmny.io/", 95 | "https://api.s1.b.hmny.io", 96 | "https://api.s0.backup1.b.hmny.io/", 97 | "https://api.s0.pops.one/", 98 | ], 99 | [ChainId.ARCANA_TESTNET]: ["https://blockchain-dev.arcana.network/"], 100 | [ChainId.ARCANA_TESTNET_SANDBOX]: ["https://blockchain-dev.arcana.network/"], 101 | [ChainId.DEXALOT_TESTNET]: [ 102 | "https://subnets.avax.network/dexalot/testnet/rpc", 103 | "https://node.dexalot-test.com/ext/bc/XuEPnCE59rtutASDPCDeYw8geQaGWwteWjkDXYLWvssfuirde/rpc", 104 | ], 105 | [ChainId.DEXALOT_TESTNET_SANDBOX]: [ 106 | "https://subnets.avax.network/dexalot/testnet/rpc", 107 | "https://node.dexalot-test.com/ext/bc/XuEPnCE59rtutASDPCDeYw8geQaGWwteWjkDXYLWvssfuirde/rpc", 108 | ], 109 | [ChainId.CASTLECRUSH_TESTNET]: ["https://subnets.avax.network/castle-crush/testnet/rpc"], 110 | [ChainId.CASTLECRUSH_TESTNET_SANDBOX]: ["https://subnets.avax.network/castle-crush/testnet/rpc"], 111 | [ChainId.CELO]: ["https://forno.celo.org", "https://rpc.ankr.com/celo"], 112 | [ChainId.CELO_TESTNET]: ["https://alfajores-forno.celo-testnet.org"], 113 | [ChainId.CELO_TESTNET_SANDBOX]: ["https://alfajores-forno.celo-testnet.org"], 114 | [ChainId.MANTLE]: ["https://rpc.mantle.xyz", "https://mantle.publicnode.com"], 115 | [ChainId.MANTLE_TESTNET]: ["https://rpc.testnet.mantle.xyz"], 116 | [ChainId.MOONBEAM]: [ 117 | "https://moonbeam.public.blastapi.io", 118 | "https://moonbeam-rpc.dwellir.com", 119 | "https://rpc.ankr.com/moonbeam", 120 | "https://moonbeam.api.onfinality.io/public", 121 | "https://moonbeam-mainnet.gateway.pokt.network/v1/lb/629a2b5650ec8c0039bb30f0", 122 | ], 123 | [ChainId.MOONBEAM_TESTNET]: [ 124 | "https://rpc.api.moonbase.moonbeam.network", 125 | "https://moonbase-alpha.public.blastapi.io", 126 | "https://moonbeam-alpha.api.onfinality.io/public", 127 | ], 128 | [ChainId.MOONBEAM_TESTNET_SANDBOX]: [ 129 | "https://rpc.api.moonbase.moonbeam.network", 130 | "https://moonbase-alpha.public.blastapi.io", 131 | "https://moonbeam-alpha.api.onfinality.io/public", 132 | ], 133 | [ChainId.GNOSIS_TESTNET]: ["https://optimism.gnosischain.com"], 134 | [ChainId.GNOSIS_TESTNET_SANDBOX]: ["https://optimism.gnosischain.com"], 135 | [ChainId.BOBA]: [ 136 | "https://mainnet.boba.network", 137 | "https://lightning-replica.boba.network", 138 | "https://boba-mainnet.gateway.pokt.network/v1/lb/623ad21b20354900396fed7f", 139 | ], 140 | [ChainId.BOBA_TESTNET]: ["https://rinkeby.boba.network/"], 141 | [ChainId.BOBA_TESTNET_SANDBOX]: ["https://rinkeby.boba.network/"], 142 | [ChainId.PORTAL_TESTNET]: ["http://3.212.233.100:9650/ext/bc/29oXNywCkGdJCuYikXkkqG6Pe5Q8tuS5VfyLHNGfeqmDzBoTPq/rpc"], 143 | [ChainId.PORTAL_TESTNET_SANDBOX]: ["http://3.212.233.100:9650/ext/bc/29oXNywCkGdJCuYikXkkqG6Pe5Q8tuS5VfyLHNGfeqmDzBoTPq/rpc"], 144 | [ChainId.AURORA]: ["https://mainnet.aurora.dev"], 145 | [ChainId.AURORA_TESTNET]: ["https://testnet.aurora.dev/"], 146 | [ChainId.AURORA_TESTNET_SANDBOX]: ["https://testnet.aurora.dev/"], 147 | [ChainId.APTOS]: ["https://fullnode.devnet.aptoslabs.com/v1"], 148 | [ChainId.APTOS_TESTNET]: ["https://fullnode.devnet.aptoslabs.com/v1"], 149 | [ChainId.APTOS_TESTNET_SANDBOX]: ["https://fullnode.devnet.aptoslabs.com/v1"], 150 | [ChainId.METIS]: ["https://andromeda.metis.io/?owner=1088"], 151 | [ChainId.METIS_TESTNET]: ["https://goerli.gateway.metisdevops.link"], 152 | [ChainId.NOVA]: [ 153 | "https://nova.arbitrum.io/rpc", 154 | "https://arbitrum-nova.blockpi.network/v1/rpc/public", 155 | "https://arbitrum-nova.publicnode.com", 156 | "https://arbitrum-nova.public.blastapi.io", 157 | ], 158 | [ChainId.COREDAO_TESTNET]: ["https://rpc.test.btcs.network"], 159 | [ChainId.COREDAO]: ["https://rpc.coredao.org"], 160 | [ChainId.AAVEGOTCHI_TESTNET]: ["https://edge.testnet-rc.gotchichain.com/"], 161 | [ChainId.TENET]: ["https://rpc.tenet.org"], 162 | [ChainId.TENET_TESTNET]: ["https://rpc.testnet.tenet.org"], 163 | [ChainId.ZKPOLYGON]: [ 164 | "https://zkevm-rpc.com", 165 | "https://rpc.ankr.com/polygon_zkevm", 166 | "https://1rpc.io/zkevm", 167 | "https://rpc.polygon-zkevm.gateway.fm", 168 | ], 169 | [ChainId.KLAYTN]: [ 170 | "https://1rpc.io/klay", 171 | "https://klaytn.blockpi.network/v1/rpc/public", 172 | "https://public-node-api.klaytnapi.com/v1/cypress", 173 | "https://klaytn.api.onfinality.io/public", 174 | ], 175 | [ChainId.OKX]: ["https://exchainrpc.okex.org"], 176 | [ChainId.METER]: ["https://meter.blockpi.network/v1/rpc/public", "https://rpc.meter.io"], 177 | [ChainId.MOONRIVER]: [ 178 | "https://rpc.api.moonriver.moonbeam.network", 179 | "https://moonriver.public.blastapi.io", 180 | "https://moonriver.api.onfinality.io/public", 181 | ], 182 | [ChainId.GNOSIS]: [ 183 | "https://rpc.gnosischain.com", 184 | "https://xdai-rpc.gateway.pokt.network", 185 | "https://xdai-archive.blockscout.com", 186 | "https://rpc.gnosis.gateway.fm", 187 | "https://gnosis-mainnet.public.blastapi.io", 188 | "https://rpc.ankr.com/gnosis", 189 | "https://rpc.ap-southeast-1.gateway.fm/v4/gnosis/non-archival/mainnet", 190 | "https://gnosis.blockpi.network/v1/rpc/public", 191 | "https://gnosis.api.onfinality.io/public", 192 | "https://gnosischain-rpc.gateway.pokt.network", 193 | "https://web3endpoints.com/gnosischain-mainnet", 194 | ], 195 | [ChainId.BEAM]: ["https://subnets.avax.network/beam/mainnet/rpc"], 196 | [ChainId.TELOS_TESTNET]: ["https://testnet15a.telos.net/evm"], 197 | [ChainId.TOMO_TESTNET]: ["https://rpc.testnet.tomochain.com"], 198 | [ChainId.LOOT]: ["https://rpc.lootchain.com/http", "https://rpc.lootchain.com/replica-http"], 199 | [ChainId.LOOT_TESTNET]: ["https://testnet.rpc.lootchain.com/http"], 200 | [ChainId.ZORA_TESTNET]: ["https://testnet.rpc.zora.energy"], 201 | } 202 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/enums/ChainId.ts: -------------------------------------------------------------------------------- 1 | // keep list sorted alphabetically 2 | export enum ChainId { 3 | AAVEGOTCHI_TESTNET = 10191, 4 | APTOS = 108, 5 | APTOS_TESTNET = 10108, 6 | APTOS_TESTNET_SANDBOX = 20308, 7 | ARBITRUM = 110, 8 | ARBITRUM_GOERLI = 10143, 9 | ARBITRUM_GOERLI_SANDBOX = 20143, 10 | ARBITRUM_RINKEBY = 10110, 11 | ARBITRUM_RINKEBY_SANDBOX = 20110, 12 | ARCANA = 117, 13 | ARCANA_TESTNET = 10117, 14 | ARCANA_TESTNET_SANDBOX = 20117, 15 | ASTAR = 146, 16 | ASTAR_TESTNET = 10146, 17 | ASTAR_TESTNET_SANDBOX = 20146, 18 | AURORA = 129, 19 | AURORA_TESTNET = 10129, 20 | AURORA_TESTNET_SANDBOX = 20129, 21 | AVALANCHE = 106, 22 | BASE = 184, 23 | BASE_TESTNET = 10160, 24 | BEAM = 198, 25 | BEAM_TESTNET = 10178, 26 | BLOCKGEN_TESTNET = 10177, 27 | BOBA = 127, 28 | BOBA_TESTNET = 10144, 29 | BOBA_TESTNET_SANDBOX = 20144, 30 | BSC = 102, 31 | BSC_TESTNET = 10102, 32 | BSC_TESTNET_SANDBOX = 20102, 33 | CANTO = 159, 34 | CANTO_TESTNET = 10159, 35 | CASTLECRUSH = 119, 36 | CASTLECRUSH_TESTNET = 10119, 37 | CASTLECRUSH_TESTNET_SANDBOX = 20119, 38 | CELO = 125, 39 | CELO_TESTNET = 10125, 40 | CELO_TESTNET_SANDBOX = 20125, 41 | COREDAO = 153, 42 | COREDAO_TESTNET = 10153, 43 | DEXALOT = 118, 44 | DEXALOT_TESTNET = 10118, 45 | DEXALOT_TESTNET_SANDBOX = 20118, 46 | DFK = 115, 47 | DFK_TESTNET = 10115, 48 | DFK_TESTNET_SANDBOX = 20115, 49 | DOS = 149, 50 | DOS_TESTNET = 10162, 51 | ETHEREUM = 101, 52 | FANTOM = 112, 53 | FANTOM_TESTNET = 10112, 54 | FANTOM_TESTNET_SANDBOX = 20112, 55 | FUJI = 10106, 56 | FUJI_SANDBOX = 20106, 57 | FUSE = 138, 58 | FUSE_TESTNET = 10138, 59 | FUSE_TESTNET_SANDBOX = 20138, 60 | GNOSIS = 145, 61 | GNOSIS_TESTNET = 10145, 62 | GNOSIS_TESTNET_SANDBOX = 20145, 63 | GOERLI = 10121, 64 | GOERLI_MAINNET = 154, 65 | GOERLI_SANDBOX = 20121, 66 | HARMONY = 116, 67 | HARMONY_TESTNET = 10133, 68 | HARMONY_TESTNET_SANDBOX = 20133, 69 | INTAIN = 152, 70 | INTAIN_TESTNET = 10152, 71 | INTAIN_TESTNET_SANDBOX = 20152, 72 | KAVA = 177, 73 | KAVA_TESTNET = 10172, 74 | KLAYTN = 150, 75 | KLAYTN_TESTNET = 10150, 76 | LOOT = 197, 77 | LOOT_TESTNET = 10197, 78 | KOVAN = 10120, 79 | KOVAN_SANDBOX = 20120, 80 | MANTLE = 181, 81 | MANTLE_TESTNET = 10181, 82 | METER = 156, 83 | METER_TESTNET = 10156, 84 | METIS = 151, 85 | METIS_TESTNET = 10151, 86 | MOONBEAM = 126, 87 | MOONBEAM_TESTNET = 10126, 88 | MOONBEAM_TESTNET_SANDBOX = 20126, 89 | MOONRIVER = 167, 90 | MOONRIVER_TESTNET = 10166, 91 | MUMBAI = 10109, 92 | MUMBAI_SANDBOX = 20109, 93 | NOVA = 175, 94 | OKX = 155, 95 | OKX_TESTNET = 10155, 96 | OPTIMISM = 111, 97 | OPTIMISM_GOERLI = 10132, 98 | OPTIMISM_GOERLI_SANDBOX = 20132, 99 | OPTIMISM_KOVAN = 10111, 100 | OPTIMISM_KOVAN_SANDBOX = 20111, 101 | POLYGON = 109, 102 | PORTAL = 128, 103 | PORTAL_TESTNET = 10128, 104 | PORTAL_TESTNET_SANDBOX = 20128, 105 | RINKEBY = 10101, 106 | RINKEBY_SANDBOX = 20101, 107 | SEPOLIA = 161, 108 | SEPOLIA_TESTNET = 10161, 109 | SHRAPNEL = 148, 110 | SHRAPNEL_TESTNET = 10164, 111 | SOLANA = 168, 112 | SOLANA_TESTNET = 10168, 113 | SWIMMER = 114, 114 | SWIMMER_TESTNET = 10130, 115 | SWIMMER_TESTNET_SANDBOX = 20130, 116 | TELOS_TESTNET = 10199, 117 | TENET = 173, 118 | TENET_TESTNET = 10173, 119 | TOMO_TESTNET = 10196, 120 | ZKCONSENSYS = 183, 121 | ZKCONSENSYS_TESTNET = 10157, 122 | ZKPOLYGON = 158, 123 | ZKPOLYGON_TESTNET = 10158, 124 | ZKSYNC = 165, 125 | ZKSYNC_TESTNET = 10165, 126 | ZORA_TESTNET = 10195, 127 | } 128 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/enums/ChainKey.ts: -------------------------------------------------------------------------------- 1 | // keep list sorted alphabetically 2 | export enum ChainKey { 3 | AAVEGOTCHI_TESTNET = "aavegotchi-testnet", 4 | APTOS = "aptos", 5 | APTOS_TESTNET = "aptos-testnet", 6 | APTOS_TESTNET_SANDBOX = "aptos-testnet-sandbox", 7 | ARBITRUM = "arbitrum", 8 | ARBITRUM_GOERLI = "arbitrum-goerli", 9 | ARBITRUM_GOERLI_SANDBOX = "arbitrum-goerli-sandbox", 10 | ARBITRUM_RINKEBY = "arbitrum-rinkeby", 11 | ARBITRUM_RINKEBY_SANDBOX = "arbitrum-rinkeby-sandbox", 12 | ARCANA = "arcana", 13 | ARCANA_TESTNET = "arcana-testnet", 14 | ARCANA_TESTNET_SANDBOX = "arcana-testnet-sandbox", 15 | ASTAR = "astar", 16 | ASTAR_TESTNET = "astar-testnet", 17 | ASTAR_TESTNET_SANDBOX = "astar-testnet-sandbox", 18 | AURORA = "aurora", 19 | AURORA_TESTNET = "aurora-testnet", 20 | AURORA_TESTNET_SANDBOX = "aurora-testnet-sandbox", 21 | AVALANCHE = "avalanche", 22 | BASE = "base", 23 | BASE_TESTNET = "base-testnet", 24 | BEAM = "beam", 25 | BEAM_TESTNET = "beam-testnet", 26 | BLOCKGEN_TESTNET = "blockgen-testnet", 27 | BOBA = "boba", 28 | BOBA_TESTNET = "boba-testnet", 29 | BOBA_TESTNET_SANDBOX = "boba-testnet-sandbox", 30 | BSC = "bsc", 31 | BSC_TESTNET = "bsc-testnet", 32 | BSC_TESTNET_SANDBOX = "bsc-testnet-sandbox", 33 | CANTO = "canto", 34 | CANTO_TESTNET = "canto-testnet", 35 | CASTLECRUSH = "castlecrush", 36 | CASTLECRUSH_TESTNET = "castlecrush-testnet", 37 | CASTLECRUSH_TESTNET_SANDBOX = "castlecrush-testnet-sandbox", 38 | CELO = "celo", 39 | CELO_TESTNET = "celo-testnet", 40 | CELO_TESTNET_SANDBOX = "celo-testnet-sandbox", 41 | COREDAO = "coredao", 42 | COREDAO_TESTNET = "coredao-testnet", 43 | DEXALOT = "dexalot", 44 | DEXALOT_TESTNET = "dexalot-testnet", 45 | DEXALOT_TESTNET_SANDBOX = "dexalot-testnet-sandbox", 46 | DFK = "dfk", 47 | DFK_TESTNET = "dfk-testnet", 48 | DFK_TESTNET_SANDBOX = "dfk-testnet-sandbox", 49 | DOS = "dos", 50 | DOS_TESTNET = "dos-testnet", 51 | ETHEREUM = "ethereum", 52 | FANTOM = "fantom", 53 | FANTOM_TESTNET = "fantom-testnet", 54 | FANTOM_TESTNET_SANDBOX = "fantom-testnet-sandbox", 55 | FUJI = "fuji", 56 | FUJI_SANDBOX = "fuji-sandbox", 57 | FUSE = "fuse", 58 | FUSE_TESTNET = "fuse-testnet", 59 | FUSE_TESTNET_SANDBOX = "fuse-testnet-sandbox", 60 | GNOSIS = "gnosis", 61 | GNOSIS_TESTNET = "gnosis-testnet", 62 | GNOSIS_TESTNET_SANDBOX = "gnosis-testnet-sandbox", 63 | GOERLI = "goerli", 64 | GOERLI_MAINNET = "goerli-mainnet", 65 | GOERLI_SANDBOX = "goerli-sandbox", 66 | HARMONY = "harmony", 67 | HARMONY_TESTNET = "harmony-testnet", 68 | HARMONY_TESTNET_SANDBOX = "harmony-testnet-sandbox", 69 | INTAIN = "intain", 70 | INTAIN_TESTNET = "intain-testnet", 71 | INTAIN_TESTNET_SANDBOX = "intain-testnet-sandbox", 72 | KAVA = "kava", 73 | KAVA_TESTNET = "kava-testnet", 74 | KLAYTN = "klaytn", 75 | KLAYTN_TESTNET = "klaytn-testnet", 76 | KOVAN = "kovan", 77 | KOVAN_SANDBOX = "kovan-sandbox", 78 | LOOT = "loot", 79 | LOOT_TESTNET = "loot-testnet", 80 | MANTLE = "mantle", 81 | MANTLE_TESTNET = "mantle-testnet", 82 | METER = "meter", 83 | METER_TESTNET = "meter-testnet", 84 | METIS = "metis", 85 | METIS_TESTNET = "metis-testnet", 86 | MOONBEAM = "moonbeam", 87 | MOONBEAM_TESTNET = "moonbeam-testnet", 88 | MOONBEAM_TESTNET_SANDBOX = "moonbeam-testnet-sandbox", 89 | MOONRIVER = "moonriver", 90 | MOONRIVER_TESTNET = "moonriver-testnet", 91 | MUMBAI = "mumbai", 92 | MUMBAI_SANDBOX = "mumbai-sandbox", 93 | NOVA = "nova", 94 | OKX = "okx", 95 | OKX_TESTNET = "okx-testnet", 96 | OPTIMISM = "optimism", 97 | OPTIMISM_GOERLI = "optimism-goerli", 98 | OPTIMISM_GOERLI_SANDBOX = "optimism-goerli-sandbox", 99 | OPTIMISM_KOVAN = "optimism-kovan", 100 | OPTIMISM_KOVAN_SANDBOX = "optimism-kovan-sandbox", 101 | POLYGON = "polygon", 102 | PORTAL = "portal", 103 | PORTAL_TESTNET = "portal-testnet", 104 | PORTAL_TESTNET_SANDBOX = "portal-testnet-sandbox", 105 | RINKEBY = "rinkeby", 106 | RINKEBY_SANDBOX = "rinkeby-sandbox", 107 | SEPOLIA = "sepolia", 108 | SEPOLIA_TESTNET = "sepolia-testnet", 109 | SHRAPNEL = "shrapnel", 110 | SHRAPNEL_TESTNET = "shrapnel-testnet", 111 | SOLANA = "solana", 112 | SOLANA_TESTNET = "solana-testnet", 113 | SWIMMER = "swimmer", 114 | SWIMMER_TESTNET = "swimmer-testnet", 115 | SWIMMER_TESTNET_SANDBOX = "swimmer-testnet-sandbox", 116 | TELOS_TESTNET = "telos-testnet", 117 | TENET = "tenet", 118 | TENET_TESTNET = "tenet-testnet", 119 | TOMO_TESTNET = "tomo-testnet", 120 | ZKCONSENSYS = "zkconsensys", 121 | ZKCONSENSYS_TESTNET = "zkconsensys-testnet", 122 | ZKPOLYGON = "zkpolygon", 123 | ZKPOLYGON_TESTNET = "zkpolygon-testnet", 124 | ZKSYNC = "zksync", 125 | ZKSYNC_TESTNET = "zksync-testnet", 126 | ZORA_TESTNET = "zora-testnet", 127 | } 128 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/enums/ChainListId.ts: -------------------------------------------------------------------------------- 1 | // keep list sorted alphabetically 2 | export enum ChainListId { 3 | AAVEGOTCHI_TESTNET = 202103, 4 | APTOS = 1, 5 | APTOS_TESTNET = 2, 6 | APTOS_TESTNET_SANDBOX = 3, 7 | ARBITRUM = 42161, 8 | ARBITRUM_GOERLI = 421613, 9 | ARBITRUM_GOERLI_SANDBOX = 421613, 10 | ARBITRUM_RINKEBY = 421611, 11 | ARBITRUM_RINKEBY_SANDBOX = 421611, 12 | ARCANA_TESTNET = 40404, 13 | ARCANA_TESTNET_SANDBOX = 40404, 14 | ASTAR = 592, 15 | AURORA = 1313161554, 16 | AURORA_TESTNET = 1313161555, 17 | AURORA_TESTNET_SANDBOX = 1313161555, 18 | AVALANCHE = 43114, 19 | BASE = 8453, 20 | BASE_TESTNET = 84531, 21 | BEAM = 4337, 22 | BEAM_TESTNET = 13337, 23 | BOBA = 288, 24 | BOBA_TESTNET = 28, 25 | BOBA_TESTNET_SANDBOX = 28, 26 | BSC = 56, 27 | BSC_TESTNET = 97, 28 | BSC_TESTNET_SANDBOX = 97, 29 | CANTO = 7700, 30 | CANTO_TESTNET = 740, 31 | CASTLECRUSH_TESTNET = 31416, 32 | CASTLECRUSH_TESTNET_SANDBOX = 31416, 33 | CELO = 42220, 34 | CELO_TESTNET = 44787, 35 | CELO_TESTNET_SANDBOX = 44787, 36 | COREDAO = 1116, 37 | COREDAO_TESTNET = 1115, 38 | DEXALOT = 432204, 39 | DEXALOT_TESTNET = 432201, 40 | DEXALOT_TESTNET_SANDBOX = 432201, 41 | DFK = 53935, 42 | DFK_TESTNET = 335, 43 | DFK_TESTNET_SANDBOX = 335, 44 | DOS = 7979, 45 | DOS_TESTNET = 3939, 46 | ETHEREUM = 1, 47 | FANTOM = 250, 48 | FANTOM_TESTNET = 4002, 49 | FANTOM_TESTNET_SANDBOX = 4002, 50 | FUJI = 43113, 51 | FUJI_SANDBOX = 43113, 52 | FUSE = 122, 53 | GNOSIS = 100, 54 | GNOSIS_TESTNET = 300, 55 | GNOSIS_TESTNET_SANDBOX = 300, 56 | GOERLI = 5, 57 | GOERLI_MAINNET = 5, 58 | GOERLI_SANDBOX = 5, 59 | HARMONY = 1666600000, 60 | HARMONY_TESTNET = 1666700000, 61 | HARMONY_TESTNET_SANDBOX = 1666700000, 62 | KAVA = 2222, 63 | KAVA_TESTNET = 2221, 64 | KLAYTN = 8217, 65 | KLAYTN_TESTNET = 1001, 66 | KOVAN = 42, 67 | KOVAN_SANDBOX = 42, 68 | LOOT = 5151706, 69 | LOOT_TESTNET = 9088912, 70 | MANTLE = 5000, 71 | MANTLE_TESTNET = 5001, 72 | METER = 82, 73 | METER_TESTNET = 83, 74 | METIS = 1088, 75 | METIS_TESTNET = 599, 76 | MOONBEAM = 1284, 77 | MOONBEAM_TESTNET = 1287, 78 | MOONBEAM_TESTNET_SANDBOX = 1287, 79 | MOONRIVER = 1285, 80 | MUMBAI = 80001, 81 | MUMBAI_SANDBOX = 80001, 82 | NOVA = 42170, 83 | OKX = 66, 84 | OPTIMISM = 10, 85 | OPTIMISM_GOERLI = 420, 86 | OPTIMISM_GOERLI_SANDBOX = 420, 87 | OPTIMISM_KOVAN = 69, 88 | OPTIMISM_KOVAN_SANDBOX = 69, 89 | POLYGON = 137, 90 | PORTAL_TESTNET = 808, 91 | PORTAL_TESTNET_SANDBOX = 808, 92 | RINKEBY = 4, 93 | RINKEBY_SANDBOX = 4, 94 | SEPOLIA = 11155111, 95 | SHRAPNEL = 2044, 96 | SWIMMER = 73772, 97 | SWIMMER_TESTNET = 73771, 98 | SWIMMER_TESTNET_SANDBOX = 73771, 99 | TELOS = 40, 100 | TELOS_TESTNET = 41, 101 | TENET = 1559, 102 | TENET_TESTNET = 155, 103 | TOMO = 88, 104 | TOMO_TESTNET = 89, 105 | ZKCONSENSYS = 59144, 106 | ZKCONSENSYS_TESTNET = 59140, 107 | ZKPOLYGON = 1101, 108 | ZKPOLYGON_TESTNET = 1442, 109 | ZKSYNC = 324, 110 | ZKSYNC_TESTNET = 280, 111 | ZORA = 7777777, 112 | ZORA_TESTNET = 999, 113 | } 114 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/enums/ChainStage.ts: -------------------------------------------------------------------------------- 1 | export enum ChainStage { 2 | MAINNET, 3 | TESTNET, 4 | TESTNET_SANDBOX, 5 | } 6 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/enums/index.ts: -------------------------------------------------------------------------------- 1 | export { ChainId } from './ChainId' 2 | export { ChainKey } from './ChainKey' 3 | export { ChainListId } from './ChainListId' 4 | export { ChainStage } from './ChainStage' 5 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constants' 2 | export * from './enums' 3 | export * from './utils' 4 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/utils/hardhatDeploy.ts: -------------------------------------------------------------------------------- 1 | import { ChainId, ChainKey } from "../enums" 2 | import { RPCS } from "../constants" 3 | import { getChainKey, getChainListId } from "./helpers" 4 | 5 | export function getMnemonic(networkName?: string) { 6 | if (networkName) { 7 | const mnemonic = process.env["MNEMONIC_" + networkName.toUpperCase()] 8 | if (mnemonic && mnemonic !== "") { 9 | return mnemonic 10 | } 11 | } 12 | 13 | const mnemonic = process.env.MNEMONIC 14 | if (!mnemonic || mnemonic === "") { 15 | return "test test test test test test test test test test test junk" 16 | } 17 | return mnemonic 18 | } 19 | 20 | export function accounts(chainKey?: string) { 21 | return { mnemonic: getMnemonic(chainKey) } 22 | } 23 | 24 | //https://hardhat.org/hardhat-network/reference/#config 25 | //accounts and chainId set by setupNetwork 26 | export type HardhatNetwork = { [network: string]: any } 27 | export type HardhatNetworks = { [chainKey in ChainKey]?: any } 28 | 29 | export function setupNetwork(networkConfig: any, chainIds: ChainId[]): HardhatNetworks { 30 | const networks: HardhatNetworks = {} 31 | 32 | for (let chainId of chainIds) { 33 | const chainKey = getChainKey(chainId) 34 | if (chainKey === undefined) { 35 | throw new Error("ChainId not setup in core-sdk") 36 | } 37 | 38 | const chainListId = getChainListId(chainId) 39 | networks[chainKey] = { 40 | ...networkConfig, 41 | chainId: chainListId, 42 | accounts: accounts(chainKey), 43 | } 44 | } 45 | return networks 46 | } 47 | 48 | export function setupNetworks(chainIds: [ChainId, { rpcIndex?: number }][]): HardhatNetworks { 49 | const networks: HardhatNetworks = {} 50 | 51 | for (let [chainId, config] of chainIds) { 52 | const rpcIndex = config.rpcIndex ? config.rpcIndex : 0 53 | 54 | const chainKey = getChainKey(chainId) 55 | if (chainKey === undefined) { 56 | throw new Error("ChainId not setup in core-sdk") 57 | } 58 | 59 | const chainListId = getChainListId(chainId) 60 | const url = RPCS[chainId]?.[rpcIndex] 61 | if (!url) { 62 | throw new Error("ChainId not setup in core-sdk") 63 | } 64 | 65 | networks[chainKey] = { 66 | chainId: chainListId, 67 | accounts: accounts(chainKey), 68 | url, 69 | } 70 | } 71 | return networks 72 | } 73 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/utils/helpers.test.ts: -------------------------------------------------------------------------------- 1 | import { getChainIdByChainKey, getChainKey, getChainListId } from "./helpers" 2 | import { ChainId } from "../enums/ChainId" 3 | import { ChainKey } from "../enums/ChainKey" 4 | import { describe, it, expect } from "vitest" 5 | 6 | const chainIds: ChainId[] = Object.values(ChainId) 7 | .map((string) => Number(string)) 8 | .filter((number) => Number.isFinite(number)) 9 | 10 | describe("getChainListId", () => { 11 | const exceptions = [ 12 | // 13 | ChainId.ARCANA, 14 | ChainId.ASTAR_TESTNET_SANDBOX, 15 | ChainId.ASTAR_TESTNET, 16 | ChainId.BASE_TESTNET, 17 | ChainId.BLOCKGEN_TESTNET, 18 | ChainId.CASTLECRUSH_TESTNET_SANDBOX, 19 | ChainId.CASTLECRUSH_TESTNET, 20 | ChainId.CASTLECRUSH, 21 | ChainId.FUSE_TESTNET_SANDBOX, 22 | ChainId.FUSE_TESTNET, 23 | ChainId.INTAIN_TESTNET_SANDBOX, 24 | ChainId.INTAIN_TESTNET, 25 | ChainId.INTAIN, 26 | ChainId.MERITCIRCLE_TESTNET, 27 | ChainId.MOONRIVER_TESTNET, 28 | ChainId.OKX_TESTNET, 29 | ChainId.PORTAL_TESTNET_SANDBOX, 30 | ChainId.PORTAL_TESTNET, 31 | ChainId.PORTAL, 32 | ChainId.SEPOLIA_TESTNET, 33 | ChainId.SHRAPNEL_TESTNET, 34 | ChainId.SHRAPNEL, 35 | ChainId.SOLANA_TESTNET, 36 | ChainId.SOLANA, 37 | ChainId.ZKCONSENSYS, 38 | ChainId.ZKPOLYGON_TESTNET, 39 | ChainId.ZKPOLYGON, 40 | ] 41 | it("Should return values for all chains", () => { 42 | for (const chainId of chainIds) { 43 | if (exceptions.includes(chainId)) continue 44 | 45 | const chainListId = getChainListId(chainId) 46 | expect(chainListId).toBeDefined() 47 | } 48 | }) 49 | }) 50 | 51 | describe("getChainKey", () => { 52 | it("Should return values for all chains", () => { 53 | for (const chainId of chainIds) { 54 | const chainKey = getChainKey(chainId) 55 | expect(chainKey).toBeDefined() 56 | } 57 | }) 58 | }) 59 | 60 | describe("getChainIdByChainKey", () => { 61 | it("Should return values for all chains", () => { 62 | for (const chainKeyOrString in ChainKey) { 63 | const isUppercase = chainKeyOrString.toUpperCase() === chainKeyOrString 64 | if (isUppercase) continue 65 | const chainKey = chainKeyOrString as ChainKey 66 | const chainId = getChainIdByChainKey(chainKey) 67 | expect(chainId).toBeDefined() 68 | } 69 | }) 70 | }) 71 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/utils/helpers.ts: -------------------------------------------------------------------------------- 1 | import { ChainId, ChainKey, ChainListId, ChainStage } from "../enums" 2 | 3 | // @deprecated - use getChainKey 4 | export function getNetworkNameByEndpointId(endpointId: ChainId | number): ChainKey { 5 | return getChainKey(endpointId) 6 | } 7 | 8 | // @deprecated - use getChainIdByChainKey 9 | export function getEndpointIdByName(networkName: ChainKey | string): ChainId { 10 | return getChainIdByChainKey(networkName as ChainKey) 11 | } 12 | 13 | const CHAIN_STAGE: Record = { 14 | mainnet: ChainStage.MAINNET, 15 | testnet: ChainStage.TESTNET, 16 | sandbox: ChainStage.TESTNET_SANDBOX, 17 | } 18 | 19 | export function getNetworksForEnv(chainStageAsString: string) { 20 | const chainStage = CHAIN_STAGE[chainStageAsString] 21 | if (!chainStage) throw new Error(`No ChainStage for ${chainStageAsString}`) 22 | const networks: ChainKey[] = [] 23 | for (const chainIdAsString in ChainId) { 24 | const chainId = Number(chainIdAsString) 25 | if (!Number.isFinite(chainId)) continue 26 | if (getChainStage(chainId) === (chainStage as any)) { 27 | networks.push(getChainKey(chainId)) 28 | } 29 | } 30 | return networks 31 | } 32 | 33 | export function getChainStage(chainId: number): ChainStage { 34 | if (chainId < 10000) return ChainStage.MAINNET 35 | if (chainId < 20000) return ChainStage.TESTNET 36 | return ChainStage.TESTNET_SANDBOX 37 | } 38 | 39 | export function getChainKey(chainId: ChainId): ChainKey { 40 | // @ts-ignore 41 | const key = ChainId[chainId] 42 | // @ts-ignore 43 | const chainKey: ChainKey = ChainKey[key] 44 | if (chainKey) return chainKey 45 | throw new Error(`No ChainKey for ${chainId}`) 46 | } 47 | 48 | export function getChainListId(chainId: ChainId): ChainListId { 49 | // @ts-ignore 50 | const key = ChainId[chainId] 51 | // @ts-ignore 52 | const chainListId: ChainListId = ChainListId[key] 53 | if (chainListId) return chainListId 54 | throw new Error(`No ChainListId for ${chainId}`) 55 | } 56 | 57 | export function getChainIdByChainKey(chainKey: ChainKey): ChainId { 58 | // @ts-ignore 59 | const key = ChainKey[chainKey] 60 | // @ts-ignore 61 | const chainId: ChainId = ChainId[key] 62 | if (chainId) return chainId 63 | throw new Error(`No chainId for ${chainKey}`) 64 | } 65 | -------------------------------------------------------------------------------- /packages/lz-sdk/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hardhatDeploy' 2 | export * from './helpers' 3 | -------------------------------------------------------------------------------- /packages/lz-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "rootDir": "src", 6 | "target": "es2018", 7 | "module": "esnext", 8 | "importHelpers": true, 9 | "declaration": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "esModuleInterop": true, 24 | "resolveJsonModule": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/lz-sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, getDefaultConfig } from "@layerzerolabs/tsup-config" 2 | 3 | export default defineConfig({ 4 | ...getDefaultConfig(), 5 | entry: ["src/index.ts"], 6 | }) 7 | -------------------------------------------------------------------------------- /packages/sg-sdk/.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 2 | -------------------------------------------------------------------------------- /packages/sg-sdk/LICENSE: -------------------------------------------------------------------------------- 1 | Business Source License 1.1 2 | 3 | License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. 4 | "Business Source License" is a trademark of MariaDB Corporation Ab. 5 | 6 | ----------------------------------------------------------------------------- 7 | 8 | Parameters 9 | 10 | Licensor: LayerZero Labs Ltd 11 | 12 | Licensed Work: LayerZero SDK 13 | The Licensed Work is (c) 2022 LayerZero Labs Ltd 14 | 15 | Change Date: 2025-02-01 16 | 17 | ----------------------------------------------------------------------------- 18 | 19 | Terms 20 | 21 | The Licensor hereby grants you the right to copy, modify, create derivative 22 | works, redistribute, and make non-production use of the Licensed Work. The 23 | Licensor may make an Additional Use Grant, above, permitting limited 24 | production use. 25 | 26 | Effective on the Change Date, or the fourth anniversary of the first publicly 27 | available distribution of a specific version of the Licensed Work under this 28 | License, whichever comes first, the Licensor hereby grants you rights under 29 | the terms of the Change License, and the rights granted in the paragraph 30 | above terminate. 31 | 32 | If your use of the Licensed Work does not comply with the requirements 33 | currently in effect as described in this License, you must purchase a 34 | commercial license from the Licensor, its affiliated entities, or authorized 35 | resellers, or you must refrain from using the Licensed Work. 36 | 37 | All copies of the original and modified Licensed Work, and derivative works 38 | of the Licensed Work, are subject to this License. This License applies 39 | separately for each version of the Licensed Work and the Change Date may vary 40 | for each version of the Licensed Work released by Licensor. 41 | 42 | You must conspicuously display this License on each original or modified copy 43 | of the Licensed Work. If you receive the Licensed Work in original or 44 | modified form from a third party, the terms and conditions set forth in this 45 | License apply to your use of that work. 46 | 47 | Any use of the Licensed Work in violation of this License will automatically 48 | terminate your rights under this License for the current and all other 49 | versions of the Licensed Work. 50 | 51 | This License does not grant you any right in any trademark or logo of 52 | Licensor or its affiliates (provided that you may use a trademark or logo of 53 | Licensor as expressly required by this License). 54 | 55 | TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON 56 | AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, 57 | EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF 58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND 59 | TITLE. 60 | 61 | MariaDB hereby grants you permission to use this License’s text to license 62 | your works, and to refer to it using the trademark "Business Source License", 63 | as long as you comply with the Covenants of Licensor below. 64 | 65 | ----------------------------------------------------------------------------- 66 | 67 | Covenants of Licensor 68 | 69 | In consideration of the right to use this License’s text and the "Business 70 | Source License" name and trademark, Licensor covenants to MariaDB, and to all 71 | other recipients of the licensed work to be provided by Licensor: 72 | 73 | 1. To specify as the Change License the GPL Version 2.0 or any later version, 74 | or a license that is compatible with GPL Version 2.0 or a later version, 75 | where "compatible" means that software provided under the Change License can 76 | be included in a program with software provided under GPL Version 2.0 or a 77 | later version. Licensor may specify additional Change Licenses without 78 | limitation. 79 | 80 | 2. To either: (a) specify an additional grant of rights to use that does not 81 | impose any additional restriction on the right granted in this License, as 82 | the Additional Use Grant; or (b) insert the text "None". 83 | 84 | 3. To specify a Change Date. 85 | 86 | 4. Not to modify this License in any other way. 87 | 88 | ----------------------------------------------------------------------------- 89 | 90 | Notice 91 | 92 | The Business Source License (this document, or the "License") is not an Open 93 | Source license. However, the Licensed Work will eventually be made available 94 | under an Open Source License, as stated in this License. -------------------------------------------------------------------------------- /packages/sg-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Stargate SDK 2 | 3 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 | 5 | This package has moved to [LayerZero-Labs/ui-monorepo](https://github.com/LayerZero-Labs/ui-monorepo/tree/main/packages/sg-sdk) and will no longer receive updates here. 6 | -------------------------------------------------------------------------------- /packages/sg-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@layerzerolabs/sg-sdk", 3 | "version": "0.5.4", 4 | "license": "BUSL-1.1", 5 | "description": "Stargate SDK", 6 | "type": "module", 7 | "main": "./dist/index.cjs", 8 | "module": "./dist/index.mjs", 9 | "types": "./dist/index.d.ts", 10 | "exports": { 11 | "types": "./dist/index.d.ts", 12 | "require": "./dist/index.cjs", 13 | "import": "./dist/index.mjs" 14 | }, 15 | "files": [ 16 | "dist/*" 17 | ], 18 | "scripts": { 19 | "build": "npx tsup", 20 | "dev": "npx tsup --watch", 21 | "test": "vitest run" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/LayerZero-Labs/sdk.git", 26 | "directory": "packages/sg-sdk" 27 | }, 28 | "publishConfig": { 29 | "access": "public", 30 | "registry": "https://registry.npmjs.org/" 31 | }, 32 | "devDependencies": { 33 | "@ethersproject/address": "^5.0.2", 34 | "@layerzerolabs/lz-sdk": "~0.0.33", 35 | "@layerzerolabs/tsup-config": "~0.0.4", 36 | "@layerzerolabs/ui-core": "~0.2.12", 37 | "vitest": "^0.31.2" 38 | }, 39 | "peerDependencies": { 40 | "@ethersproject/address": "^5.0.2", 41 | "@layerzerolabs/lz-sdk": "~0.0.33", 42 | "@layerzerolabs/ui-core": "~0.2.12" 43 | }, 44 | "engines": { 45 | "node": ">=10" 46 | }, 47 | "gitHead": "9747743d0351d9f038b3306f8ef2b9f95b08bffd" 48 | } 49 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/constants.ts: -------------------------------------------------------------------------------- 1 | // exports for external consumption 2 | export type BigintIsh = bigint | string | number 3 | 4 | export enum Rounding { 5 | ROUND_DOWN, 6 | ROUND_HALF_UP, 7 | ROUND_UP, 8 | } 9 | 10 | export const MaxUint256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 11 | export * from "./constants/addresses" 12 | export * from "./constants/token" 13 | export * from "./constants/pool" 14 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/constants/gasEstimate.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | 3 | export const REVERT_REDEEM_LOCAL: { [chainId in ChainId]?: number } = { 4 | [ChainId.ETHEREUM]: 120000, 5 | [ChainId.RINKEBY]: 120000, 6 | [ChainId.BSC]: 120000, 7 | [ChainId.BSC_TESTNET]: 120000, 8 | [ChainId.AVALANCHE]: 120000, 9 | [ChainId.FUJI]: 120000, 10 | [ChainId.POLYGON]: 120000, 11 | [ChainId.MUMBAI]: 120000, 12 | [ChainId.ARBITRUM]: 705000, 13 | [ChainId.ARBITRUM_RINKEBY]: 705000, 14 | [ChainId.ARBITRUM_GOERLI]: 705000, 15 | [ChainId.OPTIMISM]: 120000, 16 | [ChainId.OPTIMISM_KOVAN]: 120000, 17 | [ChainId.OPTIMISM_GOERLI]: 120000, 18 | [ChainId.FANTOM]: 120000, 19 | [ChainId.FANTOM_TESTNET]: 120000, 20 | [ChainId.METIS]: 120000, 21 | [ChainId.METIS_TESTNET]: 120000, 22 | [ChainId.GOERLI]: 120000, 23 | [ChainId.BASE]: 120000, 24 | } 25 | 26 | export const ERC20_TRANSFER: { [chainId in ChainId]?: number } = { 27 | [ChainId.ETHEREUM]: 65000, 28 | [ChainId.RINKEBY]: 65000, 29 | [ChainId.BSC]: 65000, 30 | [ChainId.BSC_TESTNET]: 65000, 31 | [ChainId.AVALANCHE]: 65000, 32 | [ChainId.FUJI]: 65000, 33 | [ChainId.POLYGON]: 65000, 34 | [ChainId.MUMBAI]: 65000, 35 | [ChainId.ARBITRUM]: 390000, 36 | [ChainId.ARBITRUM_RINKEBY]: 390000, 37 | [ChainId.ARBITRUM_GOERLI]: 390000, 38 | [ChainId.OPTIMISM]: 65000, 39 | [ChainId.OPTIMISM_KOVAN]: 65000, 40 | [ChainId.OPTIMISM_GOERLI]: 65000, 41 | [ChainId.FANTOM]: 65000, 42 | [ChainId.FANTOM_TESTNET]: 65000, 43 | [ChainId.METIS]: 65000, 44 | [ChainId.METIS_TESTNET]: 65000, 45 | [ChainId.BASE]: 65000, 46 | } 47 | 48 | export const ERC20_APPROVE: { [chainId in ChainId]?: number } = { 49 | [ChainId.ETHEREUM]: 47000, 50 | [ChainId.RINKEBY]: 47000, 51 | [ChainId.BSC]: 47000, 52 | [ChainId.BSC_TESTNET]: 47000, 53 | [ChainId.AVALANCHE]: 47000, 54 | [ChainId.FUJI]: 47000, 55 | [ChainId.POLYGON]: 47000, 56 | [ChainId.MUMBAI]: 47000, 57 | [ChainId.ARBITRUM]: 282000, 58 | [ChainId.ARBITRUM_RINKEBY]: 282000, 59 | [ChainId.ARBITRUM_GOERLI]: 282000, 60 | [ChainId.OPTIMISM]: 47000, 61 | [ChainId.OPTIMISM_KOVAN]: 47000, 62 | [ChainId.OPTIMISM_GOERLI]: 47000, 63 | [ChainId.FANTOM]: 47000, 64 | [ChainId.FANTOM_TESTNET]: 47000, 65 | [ChainId.METIS]: 47000, 66 | [ChainId.METIS_TESTNET]: 47000, 67 | [ChainId.BASE]: 47000, 68 | } 69 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/constants/testAddresses.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | import { TokenSymbol } from "../enums" 3 | 4 | export const ROUTER_ADDRESS: { [chainId: number]: string } = { 5 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 6 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 7 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 8 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 9 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 10 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 11 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 12 | } 13 | 14 | export const BRIDGE_ADDRESS: { [chainId: number]: string } = { 15 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 16 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 17 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 18 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 19 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 20 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 21 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 22 | } 23 | 24 | export const BONDING_ADDRESS: { [chainId in ChainId]?: string } = { 25 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 26 | [ChainId.BSC_TESTNET_SANDBOX]: "0xC6599c0e7CA3E9Cd82dCf1B9FECecE17D4cffe51", 27 | [ChainId.FUJI_SANDBOX]: "0xd9a81ca33Ea3ddb7Ccc2F9c8326A54125a8B1059", 28 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 29 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x41bF482d39b331AFD1d3857036d51eeE3A0aeF49", 30 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 31 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 32 | } 33 | 34 | export const VESTG_ADDRESS: { [chainId: number]: string } = { 35 | [ChainId.RINKEBY_SANDBOX]: "0x3f86ACfB36D30CbbFcd97cE5d4E6CFB559952216", 36 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 37 | [ChainId.FUJI_SANDBOX]: "0x2119BC620375D045505A106230ac76834C11479c", 38 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 39 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 40 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 41 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 42 | } 43 | 44 | export const FARM_ADDRESS: { [chainId: number]: string } = { 45 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 46 | [ChainId.BSC_TESTNET_SANDBOX]: "0xf157c02C52F914046E11a245100D792D20333966", 47 | [ChainId.FUJI_SANDBOX]: "0xA4e3E68a347F4E96F76b77555F9afb8Ed0539A6e", 48 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 49 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0xbC4901B6A00792924b41FEF9cDc32bD74C0488ca", 50 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 51 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 52 | } 53 | 54 | export const POOL_ADDRESS: { [tokenSymbol in TokenSymbol]?: { [chainId: number]: string } } = { 55 | [TokenSymbol.BUSD]: { 56 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 57 | [ChainId.BSC_TESTNET_SANDBOX]: "0xa1F8160c523fb36b034B3Cd110d3B8127eaf9E13", 58 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 59 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 60 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 61 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 62 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 63 | }, 64 | [TokenSymbol.DAI]: { 65 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 66 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 67 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 68 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 69 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 70 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 71 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 72 | }, 73 | [TokenSymbol.MIM]: { 74 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 75 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 76 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 77 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 78 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 79 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 80 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 81 | }, 82 | [TokenSymbol.SLP]: { 83 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 84 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 85 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 86 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 87 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 88 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 89 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 90 | }, 91 | [TokenSymbol.STG]: { 92 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 93 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 94 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 95 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 96 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 97 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 98 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 99 | }, 100 | [TokenSymbol.USDC]: { 101 | [ChainId.RINKEBY_SANDBOX]: "0x5307BA24C42Adf808AB26B77aE1841f05023266B", 102 | [ChainId.BSC_TESTNET_SANDBOX]: "0xa8701888048874E41A39a554877c8e32810BF1CD", 103 | [ChainId.FUJI_SANDBOX]: "0xE278977Fa8A7138DDb2951Ae76233C6bdF27347A", 104 | [ChainId.MUMBAI_SANDBOX]: "0xCb1eF474A8E1b223F09aD45Fd2E911df7A3186CC", 105 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0xF958d8E40b405e2d8200ba88f9752A17C9657785", 106 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0xC3821A059E9bCC511f980286bDcBB4f8Cece9A01", 107 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0xa5e79BA3147c93B05d03eed9cD8bbBAeca016EeC", 108 | }, 109 | [TokenSymbol.USDT]: { 110 | [ChainId.RINKEBY_SANDBOX]: "0x8B58AEED2A4a42f819609F698c689372246a2960", 111 | [ChainId.BSC_TESTNET_SANDBOX]: "0x45Af6439BfE5E37888F3131673d580b1D318891b", 112 | [ChainId.FUJI_SANDBOX]: "0xEd26Ff7bbE1b7d410c7cFe65A314a77D29083B29", 113 | [ChainId.MUMBAI_SANDBOX]: "0xBB67BeEe338d8eE6aFc88d86a88219D88736e45c", 114 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0xBB67BeEe338d8eE6aFc88d86a88219D88736e45c", 115 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 116 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 117 | }, 118 | [TokenSymbol.aSTG]: { 119 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 120 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 121 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 122 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 123 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 124 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 125 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 126 | }, 127 | [TokenSymbol.pSTG]: { 128 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 129 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 130 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 131 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 132 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 133 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 134 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 135 | }, 136 | [TokenSymbol.veSTG]: { 137 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 138 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 139 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 140 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 141 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 142 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 143 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 144 | }, 145 | [TokenSymbol.WETH]: { 146 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 147 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 148 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 149 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 150 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 151 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 152 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 153 | }, 154 | [TokenSymbol.USDD]: { 155 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 156 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 157 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 158 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 159 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 160 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 161 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 162 | }, 163 | [TokenSymbol.SGETH]: { 164 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 165 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 166 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 167 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 168 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 169 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 170 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 171 | }, 172 | } 173 | export const BUSD_ADDRESS: { [chainId: number]: string } = { 174 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 175 | [ChainId.BSC_TESTNET_SANDBOX]: "0x1010Bb1b9Dff29e6233E7947e045e0ba58f6E92e", 176 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 177 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 178 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 179 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 180 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 181 | } 182 | 183 | export const DAI_ADDRESS: { [chainId: number]: string } = { 184 | [ChainId.RINKEBY_SANDBOX]: "0x7fd6c1670afa595a7500bcff72db11a4745c5425", 185 | [ChainId.BSC_TESTNET_SANDBOX]: "0xed7d3B6fb460304fABCf137069eb0410A256cdcD", 186 | [ChainId.FUJI_SANDBOX]: "0xd57608EEe5e9A7e618d7fF87Cc70ecAa97C4f06F", 187 | [ChainId.MUMBAI_SANDBOX]: "0x309f8A65A5d61C88724AD3b800026855F6137D7e", 188 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x54A8E9B21A694bA8420330157f7A0c175FfF4F3B", 189 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x7a4D2C8884bc3113F84b3a7Dc0Dc247b229626dF", 190 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x9130D98D47984BF9dc796829618C36CBdA43EBb9", 191 | } 192 | 193 | export const MIM_ADDRESS: { [chainId: number]: string } = { 194 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 195 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 196 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 197 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 198 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 199 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 200 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 201 | } 202 | 203 | export const SLP_ADDRESS: { [chainId: number]: string } = { 204 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 205 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 206 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 207 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 208 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 209 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 210 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 211 | } 212 | 213 | export const STG_ADDRESS: { [chainId: number]: string } = { 214 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 215 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 216 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 217 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 218 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 219 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 220 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 221 | } 222 | 223 | export const USDC_ADDRESS: { [chainId: number]: string } = { 224 | [ChainId.RINKEBY_SANDBOX]: "0xDaEeC3a8EC82d313C3Ab4348DBc525FF8D5091Ea", 225 | [ChainId.BSC_TESTNET_SANDBOX]: "0xc1b2fdF83108882462eEd380D9E793d7eeD41C71", 226 | [ChainId.FUJI_SANDBOX]: "0xB2A2148bc3fb261347E84c96B9b25DCdd9d582a1", 227 | [ChainId.MUMBAI_SANDBOX]: "0x89F70048a0DaE7FbE1F12E75B10179ecEBc28217", 228 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x4916B4aeE6850330F639902150bf0050cb3a2eC8", 229 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x44F29Fa5237e6BA7bC6DD2FBE758E11dDc5e67A6", 230 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0xeE4C1648ad2662b85401f9f5F5dd7d4A3a949Ad9", 231 | } 232 | 233 | export const USDT_ADDRESS: { [chainId: number]: string } = { 234 | [ChainId.RINKEBY_SANDBOX]: "0x13873c138c5efa3ca971ffcb99cd02efa4ded850", 235 | [ChainId.BSC_TESTNET_SANDBOX]: "0xcf894ae205a552298d485d0f0d7ec84d31293ed6", 236 | [ChainId.FUJI_SANDBOX]: "0x366f40FD7327FEa8FcE96978A78076e2A087f2c9", 237 | [ChainId.MUMBAI_SANDBOX]: "0xAB58dBFEAd051081370c93f225d960799cEd6A94", 238 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x168830092E7f691aE34e5f3267F2E89AeE45B5DF", 239 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0xdCa5cF4084A3b1aCBAa0e3C6789E730fd74Bb44c", 240 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x68D92080C987FfFfDC7c3e937AB4f70fd9d34EA9", 241 | } 242 | 243 | export const aSTG_ADDRESS: { [chainId: number]: string } = { 244 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 245 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 246 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 247 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 248 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 249 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 250 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 251 | } 252 | 253 | export const pSTG_ADDRESS: { [chainId: number]: string } = { 254 | [ChainId.RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 255 | [ChainId.BSC_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 256 | [ChainId.FUJI_SANDBOX]: "0x0000000000000000000000000000000000000000", 257 | [ChainId.MUMBAI_SANDBOX]: "0x0000000000000000000000000000000000000000", 258 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0x0000000000000000000000000000000000000000", 259 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x0000000000000000000000000000000000000000", 260 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0x0000000000000000000000000000000000000000", 261 | } 262 | 263 | export const veSTG_ADDRESS: { [chainId: number]: string } = { 264 | [ChainId.RINKEBY_SANDBOX]: "0x970D7F99f96b8FDC8847988F9c6700C4Ed66bEB3", 265 | [ChainId.BSC_TESTNET_SANDBOX]: "0xB651fA2792B57BB361F85cE9aB51a54ce5ab374c", 266 | [ChainId.FUJI_SANDBOX]: "0x2970385168D4a070E2E2E09A1CC22d176dfa24f8", 267 | [ChainId.MUMBAI_SANDBOX]: "0x1251E2aE5fa45f31d88146d308C348397d080138", 268 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0xc0DdBAbd09A56ee7956fe950605FBe07215B12F3", 269 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0x044beEdBefDd5CCC267Ad65cF339b42FDD243436", 270 | [ChainId.FANTOM_TESTNET_SANDBOX]: "0xB77d9902fF285490cBD5465fDfb0db5eDfDC1274", 271 | } 272 | 273 | export const WETH_ADDRESS: { [chainId: number]: string } = { 274 | [ChainId.RINKEBY_SANDBOX]: "0xc778417E063141139Fce010982780140Aa0cD5Ab", 275 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: "0xbC2b378C03f86BBC4523B05e1343751d635b0FBA", 276 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: "0xF8Ac33Bf8Ebf07722253514afAE0a0db73b9F033", 277 | } 278 | 279 | export const SGETH_ADDRESS: { [chainId: number]: string } = { 280 | [ChainId.RINKEBY_SANDBOX]: '0x195EFf74d864307407c68A978a3036B1Dc4A0be4', 281 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: '0x1450e45e7345c4f6967b2A7DD91d9b0D3f65ff83', 282 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: '0x8b299936aa5e0eEA763f55267ACcE7394F0d83C0', 283 | } 284 | 285 | export const USDD_ADDRESS: { [chainId: number]: string } = { 286 | [ChainId.RINKEBY_SANDBOX]: '0x0000000000000000000000000000000000000000', 287 | [ChainId.BSC_TESTNET_SANDBOX]: '0x0000000000000000000000000000000000000000', 288 | } -------------------------------------------------------------------------------- /packages/sg-sdk/src/constants/testToken.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | import { PoolId, TokenSymbol } from "../enums" 3 | import { DAI_ADDRESS, POOL_ADDRESS, STG_ADDRESS, USDC_ADDRESS, USDT_ADDRESS, WETH_ADDRESS } from "./addresses" 4 | import { Token } from "@layerzerolabs/ui-core" 5 | 6 | export const DAI: { [chainId: number]: Token } = { 7 | [ChainId.RINKEBY_SANDBOX]: new Token(ChainId.RINKEBY_SANDBOX, DAI_ADDRESS[ChainId.RINKEBY_SANDBOX], 6, "DAI", "DAT"), 8 | [ChainId.BSC_TESTNET_SANDBOX]: new Token(ChainId.BSC_TESTNET_SANDBOX, DAI_ADDRESS[ChainId.BSC_TESTNET_SANDBOX], 6, "DAI", "DAI"), 9 | [ChainId.FUJI_SANDBOX]: new Token(ChainId.FUJI_SANDBOX, DAI_ADDRESS[ChainId.FUJI_SANDBOX], 6, "DAI", "DAI"), 10 | } 11 | 12 | export const STG: { [chainId: number]: Token } = { 13 | [ChainId.RINKEBY_SANDBOX]: new Token(ChainId.RINKEBY_SANDBOX, STG_ADDRESS[ChainId.RINKEBY_SANDBOX], 18, "STG", "StargateToken"), 14 | [ChainId.BSC_TESTNET_SANDBOX]: new Token(ChainId.BSC_TESTNET_SANDBOX, STG_ADDRESS[ChainId.BSC_TESTNET_SANDBOX], 18, "STG", "StargateToken"), 15 | [ChainId.FUJI_SANDBOX]: new Token(ChainId.FUJI_SANDBOX, STG_ADDRESS[ChainId.FUJI_SANDBOX], 18, "STG", "StargateToken"), 16 | } 17 | 18 | export const USDC: { [chainId: number]: Token } = { 19 | [ChainId.RINKEBY_SANDBOX]: new Token(ChainId.RINKEBY_SANDBOX, USDC_ADDRESS[ChainId.RINKEBY_SANDBOX], 6, "USDC", "USD Coin"), 20 | [ChainId.BSC_TESTNET_SANDBOX]: new Token(ChainId.BSC_TESTNET_SANDBOX, USDC_ADDRESS[ChainId.BSC_TESTNET_SANDBOX], 6, "USDC", "USD Coin"), 21 | [ChainId.FUJI_SANDBOX]: new Token(ChainId.FUJI_SANDBOX, USDC_ADDRESS[ChainId.FUJI_SANDBOX], 6, "USDC", "USD Coin"), 22 | } 23 | 24 | export const USDT: { [chainId: number]: Token } = { 25 | [ChainId.RINKEBY_SANDBOX]: new Token(ChainId.RINKEBY_SANDBOX, USDT_ADDRESS[ChainId.RINKEBY_SANDBOX], 6, "USDT", "USD Tether"), 26 | [ChainId.BSC_TESTNET_SANDBOX]: new Token(ChainId.BSC_TESTNET_SANDBOX, USDT_ADDRESS[ChainId.BSC_TESTNET_SANDBOX], 6, "USDT", "USD Tether"), 27 | [ChainId.FUJI_SANDBOX]: new Token(ChainId.FUJI_SANDBOX, USDT_ADDRESS[ChainId.FUJI_SANDBOX], 6, "USDT", "USD Tether"), 28 | } 29 | 30 | export const LPTOKEN: { [chainId: number]: { [poolId: number]: Token } } = { 31 | [ChainId.RINKEBY_SANDBOX]: { 32 | [PoolId.USDC]: new Token(ChainId.RINKEBY_SANDBOX, POOL_ADDRESS[TokenSymbol.USDC][ChainId.RINKEBY_SANDBOX], 6, "S*USDC", "STG-USDC LP"), 33 | [PoolId.USDT]: new Token(ChainId.RINKEBY_SANDBOX, POOL_ADDRESS[TokenSymbol.USDT][ChainId.RINKEBY_SANDBOX], 6, "S*USDT", "STG-USDT LP"), 34 | }, 35 | [ChainId.BSC_TESTNET_SANDBOX]: { 36 | [PoolId.BUSD]: new Token( 37 | ChainId.BSC_TESTNET_SANDBOX, 38 | POOL_ADDRESS[TokenSymbol.USDC][ChainId.BSC_TESTNET_SANDBOX], 39 | 6, 40 | "S*BUSD", 41 | "STG-BUSD LP" 42 | ), 43 | [PoolId.USDT]: new Token( 44 | ChainId.BSC_TESTNET_SANDBOX, 45 | POOL_ADDRESS[TokenSymbol.USDT][ChainId.BSC_TESTNET_SANDBOX], 46 | 6, 47 | "S*USDT", 48 | "STG-USDT LP" 49 | ), 50 | }, 51 | [ChainId.FUJI_SANDBOX]: { 52 | [PoolId.USDC]: new Token(ChainId.FUJI_SANDBOX, POOL_ADDRESS[TokenSymbol.USDC][ChainId.FUJI_SANDBOX], 6, "S*USDC", "STG-USDC LP"), 53 | [PoolId.USDT]: new Token(ChainId.FUJI_SANDBOX, POOL_ADDRESS[TokenSymbol.USDT][ChainId.FUJI_SANDBOX], 6, "S*USDT", "STG-USDT LP"), 54 | }, 55 | [ChainId.MUMBAI_SANDBOX]: { 56 | [PoolId.USDC]: new Token(ChainId.MUMBAI_SANDBOX, POOL_ADDRESS[TokenSymbol.USDC][ChainId.MUMBAI_SANDBOX], 6, "S*USDC", "STG-USDC LP"), 57 | [PoolId.USDT]: new Token(ChainId.MUMBAI_SANDBOX, POOL_ADDRESS[TokenSymbol.USDT][ChainId.MUMBAI_SANDBOX], 6, "S*USDT", "STG-USDT LP"), 58 | }, 59 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: { 60 | [PoolId.USDC]: new Token( 61 | ChainId.ARBITRUM_RINKEBY_SANDBOX, 62 | POOL_ADDRESS[TokenSymbol.USDC][ChainId.ARBITRUM_RINKEBY_SANDBOX], 63 | 6, 64 | "S*USDC", 65 | "STG-USDC LP" 66 | ), 67 | [PoolId.USDT]: new Token( 68 | ChainId.ARBITRUM_RINKEBY_SANDBOX, 69 | POOL_ADDRESS[TokenSymbol.USDT][ChainId.ARBITRUM_RINKEBY_SANDBOX], 70 | 6, 71 | "S*USDT", 72 | "STG-USDT LP" 73 | ), 74 | }, 75 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: { 76 | [PoolId.USDC]: new Token( 77 | ChainId.OPTIMISM_KOVAN_SANDBOX, 78 | POOL_ADDRESS[TokenSymbol.USDC][ChainId.OPTIMISM_KOVAN_SANDBOX], 79 | 6, 80 | "S*USDC", 81 | "STG-USDC LP" 82 | ), 83 | }, 84 | [ChainId.FANTOM_TESTNET_SANDBOX]: { 85 | [PoolId.USDC]: new Token( 86 | ChainId.FANTOM_TESTNET_SANDBOX, 87 | POOL_ADDRESS[TokenSymbol.USDC][ChainId.FANTOM_TESTNET_SANDBOX], 88 | 6, 89 | "S*USDC", 90 | "STG-USDC LP" 91 | ), 92 | }, 93 | } 94 | 95 | export const WETH: { [chainId: number]: Token } = { 96 | [ChainId.RINKEBY_SANDBOX]: new Token(ChainId.RINKEBY_SANDBOX, WETH_ADDRESS[ChainId.RINKEBY_SANDBOX], 18, "WETH", "WETH"), 97 | [ChainId.ARBITRUM_RINKEBY_SANDBOX]: new Token( 98 | ChainId.ARBITRUM_RINKEBY_SANDBOX, 99 | WETH_ADDRESS[ChainId.ARBITRUM_RINKEBY_SANDBOX], 100 | 18, 101 | "WETH", 102 | "WETH" 103 | ), 104 | [ChainId.OPTIMISM_KOVAN_SANDBOX]: new Token( 105 | ChainId.OPTIMISM_KOVAN_SANDBOX, 106 | WETH_ADDRESS[ChainId.OPTIMISM_KOVAN_SANDBOX], 107 | 18, 108 | "WETH", 109 | "WETH" 110 | ), 111 | } 112 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/constants/token.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | import { TokenSymbol } from "../enums/TokenSymbol" 3 | import { 4 | DAI_ADDRESS, 5 | STG_ADDRESS, 6 | USDC_ADDRESS, 7 | USDT_ADDRESS, 8 | VESTG_ADDRESS, 9 | SVESTG_ADDRESS, 10 | POOL_ADDRESS, 11 | BUSD_ADDRESS, 12 | WHITELIST_AUCTION_ADDRESS, 13 | USDD_ADDRESS, 14 | SGETH_ADDRESS, 15 | FRAX_ADDRESS, 16 | SUSD_ADDRESS, 17 | LUSD_ADDRESS, 18 | MAI_ADDRESS, 19 | } from "./addresses" 20 | import * as TEST from "./testToken" 21 | import { PoolId } from "../enums" 22 | import { 23 | SGETH_SHARE_DECIMALS, 24 | USDD_SHARE_DECIMALS, 25 | FRAX_SHARE_DECIMALS, 26 | SUSD_SHARE_DECIMALS, 27 | LUSD_SHARE_DECIMALS, 28 | DAI_SHARE_DECIMALS, 29 | MAI_SHARE_DECIMALS, 30 | } from "./pool" 31 | import { Token } from "@layerzerolabs/ui-core" 32 | 33 | export const BUSD: { [chainId: number]: Token } = { 34 | [ChainId.BSC]: new Token(ChainId.BSC, BUSD_ADDRESS[ChainId.BSC], 18, "BUSD", "BUSD Coin"), 35 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, BUSD_ADDRESS[ChainId.BSC_TESTNET], 18, "BUSD", "BUSD Coin"), 36 | } 37 | 38 | const DAI_DECIMALS = 18 39 | // prettier-ignore 40 | export const DAI: { [chainId: number]: Token } = { 41 | ...TEST.DAI, 42 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, DAI_ADDRESS[ChainId.ETHEREUM], DAI_DECIMALS, 'DAI', 'DAI'), 43 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, DAI_ADDRESS[ChainId.RINKEBY], DAI_DECIMALS, 'DAI', 'DAI'), 44 | [ChainId.BSC]: new Token(ChainId.BSC, DAI_ADDRESS[ChainId.BSC], DAI_DECIMALS, 'DAI', 'DAI'), 45 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, DAI_ADDRESS[ChainId.BSC_TESTNET], DAI_DECIMALS, 'DAI', 'DAI'), 46 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, DAI_ADDRESS[ChainId.AVALANCHE], DAI_DECIMALS, 'DAI', 'DAI'), 47 | [ChainId.FUJI]: new Token(ChainId.FUJI, DAI_ADDRESS[ChainId.FUJI], DAI_DECIMALS, 'DAI', 'DAI'), 48 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, DAI_ADDRESS[ChainId.POLYGON], DAI_DECIMALS, 'DAI', 'DAI'), 49 | [ChainId.MUMBAI]: new Token(ChainId.MUMBAI, DAI_ADDRESS[ChainId.MUMBAI], DAI_DECIMALS, 'DAI', 'DAI'), 50 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, DAI_ADDRESS[ChainId.ARBITRUM], DAI_DECIMALS, 'DAI', 'DAI'), 51 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, DAI_ADDRESS[ChainId.ARBITRUM_RINKEBY], DAI_DECIMALS, 'DAI', 'DAI'), 52 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, DAI_ADDRESS[ChainId.OPTIMISM], DAI_DECIMALS, 'DAI', 'DAI'), 53 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, DAI_ADDRESS[ChainId.OPTIMISM_KOVAN], DAI_DECIMALS, 'DAI', 'DAI'), 54 | [ChainId.FANTOM]: new Token(ChainId.FANTOM, DAI_ADDRESS[ChainId.FANTOM], DAI_DECIMALS, 'DAI', 'DAI'), 55 | [ChainId.FANTOM_TESTNET]: new Token(ChainId.FANTOM_TESTNET, DAI_ADDRESS[ChainId.FANTOM_TESTNET], DAI_DECIMALS, 'DAI', 'DAI'), 56 | } 57 | 58 | export const SLP: { [chainId: number]: Token } = {} 59 | 60 | // prettier-ignore 61 | export const STG: { [chainId: number]: Token } = { 62 | ...TEST.STG, 63 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, STG_ADDRESS[ChainId.ETHEREUM], 18, 'STG', 'StargateToken'), 64 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, STG_ADDRESS[ChainId.RINKEBY], 18, 'STG', 'StargateToken'), 65 | [ChainId.BSC]: new Token(ChainId.BSC, STG_ADDRESS[ChainId.BSC], 18, 'STG', 'StargateToken'), 66 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, STG_ADDRESS[ChainId.BSC_TESTNET], 18, 'STG', 'StargateToken'), 67 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, STG_ADDRESS[ChainId.AVALANCHE], 18, 'STG', 'StargateToken'), 68 | [ChainId.FUJI]: new Token(ChainId.FUJI, STG_ADDRESS[ChainId.FUJI], 18, 'STG', 'StargateToken'), 69 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, STG_ADDRESS[ChainId.POLYGON], 18, 'STG', 'StargateToken'), 70 | [ChainId.MUMBAI]: new Token(ChainId.MUMBAI, STG_ADDRESS[ChainId.MUMBAI], 18, 'STG', 'StargateToken'), 71 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, STG_ADDRESS[ChainId.ARBITRUM], 18, 'STG', 'StargateToken'), 72 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, STG_ADDRESS[ChainId.ARBITRUM_RINKEBY], 18, 'STG', 'StargateToken'), 73 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, STG_ADDRESS[ChainId.OPTIMISM], 18, 'STG', 'StargateToken'), 74 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, STG_ADDRESS[ChainId.OPTIMISM_KOVAN], 18, 'STG', 'StargateToken'), 75 | [ChainId.FANTOM]: new Token(ChainId.FANTOM, STG_ADDRESS[ChainId.FANTOM], 18, 'STG', 'StargateToken'), 76 | [ChainId.FANTOM_TESTNET]: new Token(ChainId.FANTOM_TESTNET, STG_ADDRESS[ChainId.FANTOM_TESTNET], 18, 'STG', 'StargateToken'), 77 | } 78 | 79 | // prettier-ignore 80 | export const VESTG: { [chainId: number]: Token } = { 81 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, VESTG_ADDRESS[ChainId.ETHEREUM], 18, TokenSymbol.veSTG, 'veStargateToken'), 82 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, VESTG_ADDRESS[ChainId.RINKEBY], 18, TokenSymbol.veSTG, 'veStargateToken'), 83 | [ChainId.BSC]: new Token(ChainId.BSC, VESTG_ADDRESS[ChainId.BSC], 18, TokenSymbol.veSTG, 'veStargateToken'), 84 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, VESTG_ADDRESS[ChainId.BSC_TESTNET], 18, TokenSymbol.veSTG, 'veStargateToken'), 85 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, VESTG_ADDRESS[ChainId.AVALANCHE], 18, TokenSymbol.veSTG, 'veStargateToken'), 86 | [ChainId.FUJI]: new Token(ChainId.FUJI, VESTG_ADDRESS[ChainId.FUJI], 18, TokenSymbol.veSTG, 'veStargateToken'), 87 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, VESTG_ADDRESS[ChainId.POLYGON], 18, TokenSymbol.veSTG, 'veStargateToken'), 88 | [ChainId.MUMBAI]: new Token(ChainId.MUMBAI, VESTG_ADDRESS[ChainId.MUMBAI], 18, TokenSymbol.veSTG, 'veStargateToken'), 89 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, VESTG_ADDRESS[ChainId.ARBITRUM], 18, TokenSymbol.veSTG, 'veStargateToken'), 90 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, VESTG_ADDRESS[ChainId.ARBITRUM_RINKEBY], 18, TokenSymbol.veSTG, 'veStargateToken'), 91 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, VESTG_ADDRESS[ChainId.OPTIMISM], 18, TokenSymbol.veSTG, 'veStargateToken'), 92 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, VESTG_ADDRESS[ChainId.OPTIMISM_KOVAN], 18, TokenSymbol.veSTG, 'veStargateToken'), 93 | [ChainId.FANTOM]: new Token(ChainId.FANTOM, VESTG_ADDRESS[ChainId.FANTOM], 18, TokenSymbol.veSTG, 'veStargateToken'), 94 | [ChainId.FANTOM_TESTNET]: new Token(ChainId.FANTOM_TESTNET, VESTG_ADDRESS[ChainId.FANTOM_TESTNET], 18, TokenSymbol.veSTG, 'veStargateToken'), 95 | } 96 | 97 | // prettier-ignore 98 | export const SVESTG: { [chainId: number]: Token } = { 99 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, SVESTG_ADDRESS[ChainId.ETHEREUM], 18, 'sveSTG', 'sveStargateToken'), 100 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, SVESTG_ADDRESS[ChainId.RINKEBY], 18, 'sveSTG', 'sveStargateToken'), 101 | } 102 | 103 | export const AASTG: { [chainId: number]: Token } = { 104 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, WHITELIST_AUCTION_ADDRESS[ChainId.ETHEREUM] as string, 6, "aaSTG", "aaStargateToken"), 105 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, WHITELIST_AUCTION_ADDRESS[ChainId.RINKEBY] as string, 6, "aaSTG", "aaStargateToken"), 106 | } 107 | 108 | // prettier-ignore 109 | export const USDC: { [chainId: number]: Token } = { 110 | ...TEST.USDC, 111 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, USDC_ADDRESS[ChainId.ETHEREUM], 6, 'USDC', 'USD Coin'), 112 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, USDC_ADDRESS[ChainId.RINKEBY], 6, 'USDC', 'USD Coin'), 113 | [ChainId.BSC]: new Token(ChainId.BSC, USDC_ADDRESS[ChainId.BSC], 18, 'USDC', 'USD Coin'), 114 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, USDC_ADDRESS[ChainId.BSC_TESTNET], 18, 'USDC', 'USD Coin'), 115 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, USDC_ADDRESS[ChainId.AVALANCHE], 6, 'USDC', 'USD Coin'), 116 | [ChainId.FUJI]: new Token(ChainId.FUJI, USDC_ADDRESS[ChainId.FUJI], 6, 'USDC', 'USD Coin'), 117 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, USDC_ADDRESS[ChainId.POLYGON], 6, 'USDC', 'USD Coin'), 118 | [ChainId.MUMBAI]: new Token(ChainId.MUMBAI, USDC_ADDRESS[ChainId.MUMBAI], 6, 'USDC', 'USD Coin'), 119 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, USDC_ADDRESS[ChainId.ARBITRUM], 6, 'USDC', 'USD Coin'), 120 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, USDC_ADDRESS[ChainId.ARBITRUM_RINKEBY], 6, 'USDC', 'USD Coin'), 121 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, USDC_ADDRESS[ChainId.OPTIMISM], 6, 'USDC', 'USD Coin'), 122 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, USDC_ADDRESS[ChainId.OPTIMISM_KOVAN], 6, 'USDC', 'USD Coin'), 123 | [ChainId.FANTOM]: new Token(ChainId.FANTOM, USDC_ADDRESS[ChainId.FANTOM], 6, 'USDC', 'USD Coin'), 124 | [ChainId.FANTOM_TESTNET]: new Token(ChainId.FANTOM_TESTNET, USDC_ADDRESS[ChainId.FANTOM_TESTNET], 6, 'USDC', 'USD Coin'), 125 | } 126 | 127 | export const USDT: { [chainId: number]: Token } = { 128 | ...TEST.USDT, 129 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, USDT_ADDRESS[ChainId.ETHEREUM], 6, "USDT", "USD Tether"), 130 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, USDT_ADDRESS[ChainId.RINKEBY], 6, "USDT", "USD Tether"), 131 | [ChainId.BSC]: new Token(ChainId.BSC, USDT_ADDRESS[ChainId.BSC], 18, "USDT", "USD Tether"), 132 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, USDT_ADDRESS[ChainId.BSC_TESTNET], 18, "USDT", "USD Tether"), 133 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, USDT_ADDRESS[ChainId.AVALANCHE], 6, "USDT", "USD Tether"), 134 | [ChainId.FUJI]: new Token(ChainId.FUJI, USDT_ADDRESS[ChainId.FUJI], 6, "USDT", "USD Tether"), 135 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, USDT_ADDRESS[ChainId.POLYGON], 6, "USDT", "USD Tether"), 136 | [ChainId.MUMBAI]: new Token(ChainId.MUMBAI, USDT_ADDRESS[ChainId.MUMBAI], 6, "USDT", "USD Tether"), 137 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, USDT_ADDRESS[ChainId.ARBITRUM], 6, "USDT", "USD Tether"), 138 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, USDT_ADDRESS[ChainId.ARBITRUM_RINKEBY], 6, "USDT", "USD Tether"), 139 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, USDT_ADDRESS[ChainId.OPTIMISM], 6, "USDT", "USD Tether"), 140 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, USDT_ADDRESS[ChainId.OPTIMISM_KOVAN], 6, "USDT", "USD Tether"), 141 | [ChainId.FANTOM]: new Token(ChainId.FANTOM, USDT_ADDRESS[ChainId.FANTOM], 6, "USDT", "USD Tether"), 142 | [ChainId.FANTOM_TESTNET]: new Token(ChainId.FANTOM_TESTNET, USDT_ADDRESS[ChainId.FANTOM_TESTNET], 6, "USDT", "USD Tether"), 143 | } 144 | 145 | // prettier-ignore 146 | export const LPTOKEN: { [chainId: number]: { [poolId: number]: Token } } = { 147 | ...TEST.LPTOKEN, 148 | [ChainId.ETHEREUM]: { 149 | [PoolId.USDC]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.USDC][ChainId.ETHEREUM], 6, "S*USDC", "STG-USDC LP"), 150 | [PoolId.USDT]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.USDT][ChainId.ETHEREUM], 6, "S*USDT", "STG-USDT LP"), 151 | [PoolId.SGETH]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.ETHEREUM], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 152 | [PoolId.USDD]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.USDD][ChainId.ETHEREUM], USDD_SHARE_DECIMALS, "S*USDD", "STG-USDD LP"), 153 | [PoolId.FRAX]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.FRAX][ChainId.ETHEREUM], FRAX_SHARE_DECIMALS, "S*FRAX", "STG-FRAX LP"), 154 | [PoolId.SUSD]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.SUSD][ChainId.ETHEREUM], SUSD_SHARE_DECIMALS, "S*SUSD", "STG-SUSD LP"), 155 | [PoolId.LUSD]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.LUSD][ChainId.ETHEREUM], LUSD_SHARE_DECIMALS, "S*LUSD", "STG-LUSD LP"), 156 | [PoolId.DAI]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.DAI][ChainId.ETHEREUM], DAI_SHARE_DECIMALS, "S*DAI", "STG-DAI LP"), 157 | [PoolId.MAI]: new Token(ChainId.ETHEREUM, POOL_ADDRESS[TokenSymbol.MAI][ChainId.ETHEREUM], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 158 | }, 159 | [ChainId.RINKEBY]: { 160 | [PoolId.USDC]: new Token(ChainId.RINKEBY, POOL_ADDRESS[TokenSymbol.USDC][ChainId.RINKEBY], 6, "S*USDC", "STG-USDC LP"), 161 | [PoolId.USDT]: new Token(ChainId.RINKEBY, POOL_ADDRESS[TokenSymbol.USDT][ChainId.RINKEBY], 6, "S*USDT", "STG-USDT LP"), 162 | [PoolId.USDD]: new Token(ChainId.RINKEBY, POOL_ADDRESS[TokenSymbol.USDD][ChainId.RINKEBY], USDD_SHARE_DECIMALS, "S*USDD", "STG-USDD LP"), 163 | [PoolId.SGETH]: new Token(ChainId.RINKEBY, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.RINKEBY], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 164 | }, 165 | [ChainId.BSC]: { 166 | [PoolId.BUSD]: new Token(ChainId.BSC, POOL_ADDRESS[TokenSymbol.BUSD][ChainId.BSC], 6, "S*BUSD", "STG-BUSD LP"), 167 | [PoolId.USDT]: new Token(ChainId.BSC, POOL_ADDRESS[TokenSymbol.USDT][ChainId.BSC], 6, "S*USDT", "STG-USDT LP"), 168 | [PoolId.USDD]: new Token(ChainId.BSC, POOL_ADDRESS[TokenSymbol.USDD][ChainId.BSC], USDD_SHARE_DECIMALS, "S*USDD", "STG-USDD LP"), 169 | [PoolId.MAI]: new Token(ChainId.BSC, POOL_ADDRESS[TokenSymbol.MAI][ChainId.BSC], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 170 | }, 171 | [ChainId.BSC_TESTNET]: { 172 | [PoolId.BUSD]: new Token(ChainId.BSC_TESTNET, POOL_ADDRESS[TokenSymbol.BUSD][ChainId.BSC_TESTNET], 6, "S*BUSD", "STG-BUSD LP"), 173 | [PoolId.USDT]: new Token(ChainId.BSC_TESTNET, POOL_ADDRESS[TokenSymbol.USDT][ChainId.BSC_TESTNET], 6, "S*USDT", "STG-USDT LP"), 174 | [PoolId.USDD]: new Token(ChainId.BSC_TESTNET, POOL_ADDRESS[TokenSymbol.USDD][ChainId.BSC_TESTNET], USDD_SHARE_DECIMALS, "S*USDD", "STG-USDD LP"), 175 | }, 176 | [ChainId.AVALANCHE]: { 177 | [PoolId.USDC]: new Token(ChainId.AVALANCHE, POOL_ADDRESS[TokenSymbol.USDC][ChainId.AVALANCHE], 6, "S*USDC", "STG-USDCe LP"), 178 | [PoolId.USDT]: new Token(ChainId.AVALANCHE, POOL_ADDRESS[TokenSymbol.USDT][ChainId.AVALANCHE], 6, "S*USDT", "STG-USDTe LP"), 179 | [PoolId.FRAX]: new Token(ChainId.AVALANCHE, POOL_ADDRESS[TokenSymbol.FRAX][ChainId.AVALANCHE], 6, "S*FRAX", "STG-FRAX LP"), 180 | [PoolId.MAI]: new Token(ChainId.AVALANCHE, POOL_ADDRESS[TokenSymbol.MAI][ChainId.AVALANCHE], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 181 | }, 182 | [ChainId.FUJI]: { 183 | [PoolId.USDC]: new Token(ChainId.FUJI, POOL_ADDRESS[TokenSymbol.USDC][ChainId.FUJI], 6, "S*USDC", "STG-USDC LP"), 184 | [PoolId.USDT]: new Token(ChainId.FUJI, POOL_ADDRESS[TokenSymbol.USDT][ChainId.FUJI], 6, "S*USDT", "STG-USDT LP"), 185 | }, 186 | [ChainId.POLYGON]: { 187 | [PoolId.USDC]: new Token(ChainId.POLYGON, POOL_ADDRESS[TokenSymbol.USDC][ChainId.POLYGON], 6, "S*USDC", "STG-USDC LP"), 188 | [PoolId.USDT]: new Token(ChainId.POLYGON, POOL_ADDRESS[TokenSymbol.USDT][ChainId.POLYGON], 6, "S*USDT", "STG-USDT LP"), 189 | [PoolId.DAI]: new Token(ChainId.POLYGON, POOL_ADDRESS[TokenSymbol.DAI][ChainId.POLYGON], DAI_SHARE_DECIMALS, "S*DAI", "STG-DAI LP"), 190 | [PoolId.MAI]: new Token(ChainId.POLYGON, POOL_ADDRESS[TokenSymbol.MAI][ChainId.POLYGON], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 191 | }, 192 | [ChainId.MUMBAI]: { 193 | [PoolId.USDC]: new Token(ChainId.MUMBAI, POOL_ADDRESS[TokenSymbol.USDC][ChainId.MUMBAI], 6, "S*USDC", "STG-USDC LP"), 194 | [PoolId.USDT]: new Token(ChainId.MUMBAI, POOL_ADDRESS[TokenSymbol.USDT][ChainId.MUMBAI], 6, "S*USDT", "STG-USDT LP"), 195 | }, 196 | [ChainId.ARBITRUM]: { 197 | [PoolId.USDC]: new Token(ChainId.ARBITRUM, POOL_ADDRESS[TokenSymbol.USDC][ChainId.ARBITRUM], 6, "S*USDC", "STG-USDC LP"), 198 | [PoolId.USDT]: new Token(ChainId.ARBITRUM, POOL_ADDRESS[TokenSymbol.USDT][ChainId.ARBITRUM], 6, "S*USDT", "STG-USDT LP"), 199 | [PoolId.SGETH]: new Token(ChainId.ARBITRUM, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.ARBITRUM], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 200 | [PoolId.FRAX]: new Token(ChainId.ARBITRUM, POOL_ADDRESS[TokenSymbol.FRAX][ChainId.ARBITRUM], FRAX_SHARE_DECIMALS, "S*FRAX", "STG-FRAX LP"), 201 | [PoolId.MAI]: new Token(ChainId.ARBITRUM, POOL_ADDRESS[TokenSymbol.MAI][ChainId.ARBITRUM], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 202 | }, 203 | [ChainId.ARBITRUM_RINKEBY]: { 204 | [PoolId.USDC]: new Token(ChainId.ARBITRUM_RINKEBY, POOL_ADDRESS[TokenSymbol.USDC][ChainId.ARBITRUM_RINKEBY], 6, "S*USDC", "STG-USDC LP"), 205 | [PoolId.USDT]: new Token(ChainId.ARBITRUM_RINKEBY, POOL_ADDRESS[TokenSymbol.USDT][ChainId.ARBITRUM_RINKEBY], 6, "S*USDT", "STG-USDT LP"), 206 | [PoolId.SGETH]: new Token(ChainId.ARBITRUM_RINKEBY, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.ARBITRUM_RINKEBY], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 207 | }, 208 | [ChainId.OPTIMISM]: { 209 | [PoolId.USDC]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.USDC][ChainId.OPTIMISM], 6, "S*USDC", "STG-USDC LP"), 210 | [PoolId.SGETH]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.OPTIMISM], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 211 | [PoolId.FRAX]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.FRAX][ChainId.OPTIMISM], FRAX_SHARE_DECIMALS, "S*FRAX", "STG-FRAX LP"), 212 | [PoolId.SUSD]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.SUSD][ChainId.OPTIMISM], SUSD_SHARE_DECIMALS, "S*SUSD", "STG-SUSD LP"), 213 | [PoolId.LUSD]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.LUSD][ChainId.OPTIMISM], LUSD_SHARE_DECIMALS, "S*LUSD", "STG-LUSD LP"), 214 | [PoolId.DAI]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.DAI][ChainId.OPTIMISM], DAI_SHARE_DECIMALS, "S*DAI", "STG-DAI LP"), 215 | [PoolId.MAI]: new Token(ChainId.OPTIMISM, POOL_ADDRESS[TokenSymbol.MAI][ChainId.OPTIMISM], MAI_SHARE_DECIMALS, "S*MAI", "STG-MAI LP"), 216 | }, 217 | [ChainId.OPTIMISM_KOVAN]: { 218 | [PoolId.USDC]: new Token(ChainId.OPTIMISM_KOVAN, POOL_ADDRESS[TokenSymbol.USDC][ChainId.OPTIMISM_KOVAN], 6, "S*USDC", "STG-USDC LP"), 219 | [PoolId.SGETH]: new Token(ChainId.OPTIMISM_KOVAN, POOL_ADDRESS[TokenSymbol.SGETH][ChainId.OPTIMISM_KOVAN], SGETH_SHARE_DECIMALS, "S*SGETH", "STG-SGETH LP"), 220 | }, 221 | [ChainId.FANTOM]: { 222 | [PoolId.USDC]: new Token(ChainId.FANTOM, POOL_ADDRESS[TokenSymbol.USDC][ChainId.FANTOM], 6, "S*USDC", "STG-USDC LP"), 223 | }, 224 | [ChainId.FANTOM_TESTNET]: { 225 | [PoolId.USDC]: new Token(ChainId.FANTOM_TESTNET, POOL_ADDRESS[TokenSymbol.USDC][ChainId.FANTOM_TESTNET], 6, "S*USDC", "STG-USDC LP"), 226 | }, 227 | } 228 | 229 | export const SGETH: { [chainId: number]: Token } = { 230 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, SGETH_ADDRESS[ChainId.ETHEREUM], 18, "SGETH", "SGETH"), 231 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, SGETH_ADDRESS[ChainId.RINKEBY], 18, "SGETH", "SGETH"), 232 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, SGETH_ADDRESS[ChainId.ARBITRUM], 18, "SGETH", "SGETH"), 233 | [ChainId.ARBITRUM_RINKEBY]: new Token(ChainId.ARBITRUM_RINKEBY, SGETH_ADDRESS[ChainId.ARBITRUM_RINKEBY], 18, "SGETH", "SGETH"), 234 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, SGETH_ADDRESS[ChainId.OPTIMISM], 18, "SGETH", "SGETH"), 235 | [ChainId.OPTIMISM_KOVAN]: new Token(ChainId.OPTIMISM_KOVAN, SGETH_ADDRESS[ChainId.OPTIMISM_KOVAN], 18, "SGETH", "SGETH"), 236 | } 237 | 238 | export const USDD: { [chainId: number]: Token } = { 239 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, USDD_ADDRESS[ChainId.ETHEREUM], 18, "USDD", "USDD"), 240 | [ChainId.RINKEBY]: new Token(ChainId.RINKEBY, USDD_ADDRESS[ChainId.RINKEBY], 18, "USDD", "USDD"), 241 | [ChainId.BSC]: new Token(ChainId.BSC, USDD_ADDRESS[ChainId.BSC], 18, "USDD", "USDD"), 242 | [ChainId.BSC_TESTNET]: new Token(ChainId.BSC_TESTNET, USDD_ADDRESS[ChainId.BSC_TESTNET], 18, "USDD", "USDD"), 243 | } 244 | 245 | const FRAX_DECIMALS = 18 246 | export const FRAX: { [chainId: number]: Token } = { 247 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, FRAX_ADDRESS[ChainId.ETHEREUM], FRAX_DECIMALS, "FRAX", "FRAX"), 248 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, FRAX_ADDRESS[ChainId.AVALANCHE], FRAX_DECIMALS, "FRAX", "FRAX"), 249 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, FRAX_ADDRESS[ChainId.ARBITRUM], FRAX_DECIMALS, "FRAX", "FRAX"), 250 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, FRAX_ADDRESS[ChainId.OPTIMISM], FRAX_DECIMALS, "FRAX", "FRAX"), 251 | } 252 | const SUSD_DECIMALS = 18 253 | export const SUSD: { [chainId: number]: Token } = { 254 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, SUSD_ADDRESS[ChainId.ETHEREUM], SUSD_DECIMALS, "SUSD", "SUSD"), 255 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, SUSD_ADDRESS[ChainId.OPTIMISM], SUSD_DECIMALS, "SUSD", "SUSD"), 256 | } 257 | 258 | const LUSD_DECIMALS = 18 259 | export const LUSD: { [chainId: number]: Token } = { 260 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, LUSD_ADDRESS[ChainId.ETHEREUM], LUSD_DECIMALS, "LUSD", "LUSD"), 261 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, LUSD_ADDRESS[ChainId.OPTIMISM], LUSD_DECIMALS, "LUSD", "LUSD"), 262 | } 263 | 264 | const MAI_DECIMALS = 18 265 | export const MAI: { [chainId: number]: Token } = { 266 | [ChainId.ETHEREUM]: new Token(ChainId.ETHEREUM, MAI_ADDRESS[ChainId.ETHEREUM], MAI_DECIMALS, "MAI", "MAI"), 267 | [ChainId.BSC]: new Token(ChainId.BSC, MAI_ADDRESS[ChainId.BSC], MAI_DECIMALS, "MAI", "MAI"), 268 | [ChainId.AVALANCHE]: new Token(ChainId.AVALANCHE, MAI_ADDRESS[ChainId.AVALANCHE], MAI_DECIMALS, "MAI", "MAI"), 269 | [ChainId.POLYGON]: new Token(ChainId.POLYGON, MAI_ADDRESS[ChainId.POLYGON], MAI_DECIMALS, "MAI", "MAI"), 270 | [ChainId.ARBITRUM]: new Token(ChainId.ARBITRUM, MAI_ADDRESS[ChainId.ARBITRUM], MAI_DECIMALS, "MAI", "MAI"), 271 | [ChainId.OPTIMISM]: new Token(ChainId.OPTIMISM, MAI_ADDRESS[ChainId.OPTIMISM], MAI_DECIMALS, "MAI", "MAI"), 272 | } 273 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/bonding.test.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | import { USDC, STG } from "../constants/token" 3 | import { Bonding } from "./bonding" 4 | import { TokenSymbol } from "../enums" 5 | import { describe, it, expect } from "vitest" 6 | import { CurrencyAmount, Fraction, Token } from "@layerzerolabs/ui-core" 7 | 8 | describe("Bonding", () => { 9 | const chainId = ChainId.FUJI_SANDBOX 10 | const stargateToken = STG[chainId] 11 | const stableCoin = USDC[chainId] 12 | const initialPrice = BigInt(5) * BigInt(10) ** BigInt(17) // 0.5 13 | const oneMilllionSTG = BigInt(1000000) * BigInt(10) ** BigInt(18) 14 | const totalstargateTokenForBonding = BigInt(50000000) * BigInt(10) ** BigInt(18) //50m 15 | const bonding = new Bonding( 16 | stargateToken, 17 | stableCoin, 18 | new Fraction(5, 100000000), 19 | CurrencyAmount.fromRawAmount(stargateToken, initialPrice), 20 | CurrencyAmount.fromRawAmount(stargateToken, totalstargateTokenForBonding), 21 | CurrencyAmount.fromRawAmount(stargateToken, oneMilllionSTG) //1mil already sold 22 | ) 23 | 24 | describe("#computeCostFromQuantity", function () { 25 | it("quantity = 0", function () { 26 | const quantity = BigInt(0) 27 | expect(() => bonding.computeCostFromQuantity(CurrencyAmount.fromRawAmount(stargateToken, quantity))).toThrow("QUANTITY_ZERO") 28 | }) 29 | 30 | it("quantity < quota", function () { 31 | const cost = bonding.computeCostFromQuantity(CurrencyAmount.fromRawAmount(stargateToken, oneMilllionSTG)) 32 | expect(cost.currency).toEqual(stableCoin) 33 | expect(cost.toExact()).toEqual("575000") 34 | }) 35 | 36 | it("quantity = quota", function () { 37 | const quantity = BigInt(49000000) * BigInt(10) ** BigInt(18) //25m 38 | const cost = bonding.computeCostFromQuantity(CurrencyAmount.fromRawAmount(stargateToken, quantity)) 39 | expect(cost.currency).toEqual(stableCoin) 40 | 41 | expect(cost.toExact()).toEqual("86975000") 42 | }) 43 | 44 | it("quantity > quota", function () { 45 | const quantity = BigInt(50000000) * BigInt(10) ** BigInt(18) //51m 46 | const cost = bonding.computeCostFromQuantity(CurrencyAmount.fromRawAmount(stargateToken, quantity)) 47 | expect(cost.currency).toEqual(stableCoin) 48 | expect(cost.toExact()).toEqual("86975000") 49 | }) 50 | }) 51 | 52 | describe("#computeQuantityFromCost", function () { 53 | it("cost = 0", function () { 54 | const cost = BigInt(0) 55 | expect(() => bonding.computeQuantityFromCost(CurrencyAmount.fromRawAmount(stableCoin, cost))).toThrow("COST_ZERO") 56 | }) 57 | 58 | it("cost < quota", function () { 59 | const cost = BigInt(575000) * BigInt(10) ** BigInt(6) 60 | const quantity = bonding.computeQuantityFromCost(CurrencyAmount.fromRawAmount(stableCoin, cost)) 61 | expect(quantity.currency).toEqual(stargateToken) 62 | expect(quantity.toExact()).toEqual("1000000") //1m 63 | }) 64 | 65 | it("cost = quota", function () { 66 | const cost = BigInt(86975000) * BigInt(10) ** BigInt(6) 67 | const quantity = bonding.computeQuantityFromCost(CurrencyAmount.fromRawAmount(stableCoin, cost)) 68 | expect(quantity.currency).toEqual(stargateToken) 69 | expect(quantity.toExact()).toEqual("49000000") //1m 70 | }) 71 | 72 | it("cost > quota", function () { 73 | const cost = BigInt(87500000) * BigInt(10) ** BigInt(6) 74 | const quantity = bonding.computeQuantityFromCost(CurrencyAmount.fromRawAmount(stableCoin, cost)) 75 | expect(quantity.currency).toEqual(stargateToken) 76 | expect(quantity.toExact()).toEqual("49000000") //1m 77 | }) 78 | }) 79 | 80 | describe("getCurrentPrice", () => { 81 | const chainId = ChainId.FUJI_SANDBOX 82 | const stableCoin = new Token(chainId, "0x0000000000000000000000000000000000000000", 18, TokenSymbol.USDC) 83 | const token = new Token(chainId, "0x0000000000000000000000000000000000000000", 18, TokenSymbol.STG) 84 | 85 | const slope = new Fraction(5, 100000000) 86 | const initialPrice = CurrencyAmount.fromRawAmount(stableCoin, 0.5e18) 87 | let totalBonded = CurrencyAmount.fromRawAmount(token, 1000000e18) 88 | let curPrice = Bonding.getCurrentPrice(initialPrice, totalBonded, slope) 89 | 90 | it("returns expected price", () => { 91 | expect(parseFloat(curPrice.toSignificant(4)).toFixed(2)).toEqual("0.55") 92 | 93 | totalBonded = CurrencyAmount.fromRawAmount(stableCoin, 2000000e18) 94 | curPrice = Bonding.getCurrentPrice(initialPrice, totalBonded, slope) 95 | expect(parseFloat(curPrice.toSignificant(4)).toFixed(2)).toEqual("0.60") 96 | }) 97 | 98 | it("returns the stablecoin token", () => { 99 | expect(curPrice.currency.symbol).toEqual("USDC") 100 | }) 101 | }) 102 | }) 103 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/bonding.ts: -------------------------------------------------------------------------------- 1 | import { invariant as assert } from "../utils/invariantHelper" 2 | import { Currency, Fraction, CurrencyAmount } from "@layerzerolabs/ui-core" 3 | 4 | const ZERO: bigint = BigInt(0) 5 | const TWO: bigint = BigInt(2) 6 | 7 | export class Bonding { 8 | public readonly stargateToken: Currency 9 | public readonly stableCoinToken: Currency 10 | public readonly slope: Fraction 11 | public readonly initialPrice: CurrencyAmount 12 | public readonly totalStargateForBonding: CurrencyAmount 13 | public readonly totalStargateBonded: CurrencyAmount 14 | public readonly quota: CurrencyAmount 15 | public readonly convertRate: bigint 16 | 17 | public constructor( 18 | _stargateToken: Currency, 19 | _stableCoinToken: Currency, 20 | _slope: Fraction, 21 | _initialPrice: CurrencyAmount, //stargate token 22 | _totalStargateForBonding: CurrencyAmount, //stargate token 23 | _totalStargateBonded: CurrencyAmount //stargate token 24 | ) { 25 | assert(_stargateToken.decimals >= _stableCoinToken.decimals, "DECIMALS") 26 | this.stargateToken = _stargateToken 27 | this.stableCoinToken = _stableCoinToken 28 | 29 | this.slope = _slope 30 | 31 | assert(_initialPrice.currency.equals(this.stargateToken), "TOKEN") 32 | assert(_initialPrice.greaterThan(ZERO), "PRICE_ZERO") 33 | this.initialPrice = _initialPrice 34 | 35 | assert(_totalStargateForBonding.currency.equals(this.stargateToken), "TOKEN") 36 | this.totalStargateForBonding = _totalStargateForBonding 37 | 38 | assert(_totalStargateBonded.currency.equals(this.stargateToken), "TOKEN") 39 | this.totalStargateBonded = _totalStargateBonded 40 | 41 | this.quota = this.totalStargateForBonding.subtract(this.totalStargateBonded) 42 | this.convertRate = BigInt(10) ** BigInt(this.stargateToken.decimals - this.stableCoinToken.decimals) 43 | } 44 | 45 | public computeCostFromQuantity(_quantity: CurrencyAmount): CurrencyAmount { 46 | assert(_quantity.currency.equals(this.stargateToken), "TOKEN") 47 | let quantity = _quantity 48 | if (_quantity.greaterThan(this.quota)) { 49 | quantity = this.quota 50 | } 51 | assert(quantity.greaterThan(ZERO), "QUANTITY_ZERO") 52 | 53 | const startPrice = this.totalStargateBonded.multiply(this.slope.numerator).divide(this.slope.denominator).add(this.initialPrice) 54 | const endPrice = startPrice.add(quantity.multiply(this.slope.numerator).divide(this.slope.denominator)) 55 | const avgPrice = startPrice.add(endPrice).divide(TWO) 56 | 57 | return CurrencyAmount.fromFractionalAmount( 58 | this.stableCoinToken, 59 | this.toStableCoinDecimals(avgPrice.multiply(quantity)).quotient, 60 | BigInt(10) ** BigInt(this.stargateToken.decimals) 61 | ) 62 | } 63 | 64 | public computeQuantityFromCost(_cost: CurrencyAmount): CurrencyAmount { 65 | assert(_cost.currency.equals(this.stableCoinToken), "TOKEN") 66 | assert(_cost.greaterThan(ZERO), "COST_ZERO") 67 | const _startPrice = this.totalStargateBonded.multiply(this.slope.numerator).divide(this.slope.denominator).add(this.initialPrice) 68 | 69 | const startPrice = parseFloat(_startPrice.toSignificant(this.stargateToken.decimals)) 70 | const cost = parseFloat(_cost.toSignificant(this.stableCoinToken.decimals)) 71 | const slope = parseFloat(this.slope.toSignificant(this.stargateToken.decimals)) 72 | 73 | const quantity = CurrencyAmount.fromRawAmount( 74 | this.stargateToken, 75 | BigInt(parseInt(((Math.sqrt(startPrice ** 2 + 2 * slope * cost) - startPrice) / slope).toFixed(this.stableCoinToken.decimals))) * 76 | BigInt(10) ** BigInt(this.stargateToken.decimals) 77 | ) 78 | 79 | if (quantity.greaterThan(this.quota)) { 80 | return this.quota 81 | } 82 | return quantity 83 | } 84 | 85 | toStableCoinDecimals(amount: CurrencyAmount): CurrencyAmount { 86 | assert(amount.currency.equals(this.stargateToken), "TOKEN") 87 | return CurrencyAmount.fromFractionalAmount(this.stableCoinToken, amount.quotient, this.convertRate) 88 | } 89 | 90 | /** 91 | * Get the current price of the token in the bonding curve 92 | * @param initialPrice Initial price of the bonding curve 93 | * @param totalBonded Total tokens bonded 94 | * @param slope slope of the bonding curve 95 | * @returns current price of the stablecoin passed in the initialPrice Token 96 | */ 97 | public static getCurrentPrice(initialPrice: CurrencyAmount, totalBonded: CurrencyAmount, slope: Fraction) { 98 | const token = initialPrice.currency 99 | const price = slope.multiply(totalBonded).add(initialPrice) 100 | return CurrencyAmount.fromFractionalAmount(token, price.numerator, price.denominator) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/fee.test.ts: -------------------------------------------------------------------------------- 1 | import { FeeLibraryV02Defaults, FeeV01, FeeV02 } from "./fee" 2 | import { TokenSymbol } from "../enums" 3 | import { describe, it, expect } from "vitest" 4 | import { Fraction, Token, CurrencyAmount } from "@layerzerolabs/ui-core" 5 | 6 | const fraction = new Fraction(100, 10000) // 1% 7 | const token = new Token(0, "0x0000000000000000000000000000000000000000", 18, TokenSymbol.USDC) 8 | const lpToken = new Token(0, "0x0000000000000000000000000000000000000000", 6, TokenSymbol.SLP) 9 | 10 | const expectedEqFee = [ 11 | "0.000000000000000", 12 | "0.000030000000000", 13 | "0.000060000000000", 14 | "0.000090000000000", 15 | "0.000120000000000", 16 | "0.000150000000000", 17 | "0.000180000000000", 18 | "0.000210000000000", 19 | "0.000240000000000", 20 | "0.000270000000000", 21 | "0.000300000000000", 22 | "0.000330000000000", 23 | "0.000360000000000", 24 | "0.000390000000000", 25 | "0.000420000000000", 26 | "0.000450000000000", 27 | "0.000480000000000", 28 | "0.000510000000000", 29 | "0.000540000000000", 30 | "0.000570000000000", 31 | "0.000600000000000", 32 | "0.000630000000000", 33 | "0.000660000000000", 34 | "0.000690000000000", 35 | "0.000720000000000", 36 | "0.000750000000000", 37 | "0.000780000000000", 38 | "0.000810000000000", 39 | "0.000840000000000", 40 | "0.000870000000000", 41 | "0.000900000000000", 42 | "0.000930000000000", 43 | "0.000960000000000", 44 | "0.000990000000000", 45 | "0.001020000000000", 46 | "0.001050000000000", 47 | "0.001080000000000", 48 | "0.001110000000000", 49 | "0.001140000000000", 50 | "0.001170000000000", 51 | "0.001200000000000", 52 | "0.000036363636364", 53 | "0.000145454545455", 54 | "0.000327272727273", 55 | "0.000581818181818", 56 | "0.000909090909091", 57 | "0.001309090909091", 58 | "0.001781818181818", 59 | "0.002327272727273", 60 | "0.002945454545455", 61 | "0.003636363636364", 62 | "0.004400000000000", 63 | "0.005236363636364", 64 | "0.006145454545455", 65 | "0.007127272727273", 66 | "0.008181818181818", 67 | "0.009309090909091", 68 | "0.010509090909091", 69 | "0.011781818181818", 70 | "0.013127272727273", 71 | "0.014545454545455", 72 | "0.016036363636364", 73 | "0.017600000000000", 74 | "0.019236363636364", 75 | "0.020945454545455", 76 | "0.022727272727273", 77 | "0.024581818181818", 78 | "0.026509090909091", 79 | "0.028509090909091", 80 | "0.030581818181818", 81 | "0.032727272727273", 82 | "0.034945454545455", 83 | "0.037236363636364", 84 | "0.039600000000000", 85 | "0.042036363636364", 86 | "0.044545454545455", 87 | "0.047127272727273", 88 | "0.049781818181818", 89 | "0.052509090909091", 90 | "0.055309090909091", 91 | "0.058181818181818", 92 | "0.061127272727273", 93 | "0.064145454545455", 94 | "0.067236363636364", 95 | "0.070400000000000", 96 | "0.073636363636364", 97 | "0.076945454545455", 98 | "0.080327272727273", 99 | "0.083781818181818", 100 | "0.087309090909091", 101 | "0.090909090909091", 102 | "0.094581818181818", 103 | "0.098327272727273", 104 | "0.102145454545455", 105 | "0.106036363636364", 106 | "0.110000000000000", 107 | "0.213600000000000", 108 | "0.516400000000000", 109 | "1.018400000000000", 110 | "1.719600000000000", 111 | "2.620000000000000", 112 | ] 113 | 114 | function approx(a: number, b: number, precision: number = 1e-10) { 115 | if (a == b && a == 0) { 116 | return true 117 | } 118 | return (2 * Math.abs(a - b)) / (a + b) <= precision 119 | } 120 | 121 | describe("Fee", () => { 122 | it("FeeLibraryV01", () => { 123 | const fee = new FeeV01( 124 | { 125 | version: "1.0.0", 126 | eqFeeRate: fraction, 127 | eqRewardRate: fraction, 128 | lpFeeRate: fraction, 129 | protocolFeeRate: fraction, 130 | }, 131 | token, 132 | lpToken 133 | ) 134 | 135 | const amount = CurrencyAmount.fromRawAmount(token, BigInt(100)) 136 | const amount_1perc = amount.multiply(fraction) 137 | expect(fee.getFees(amount)).toEqual({ 138 | protocolFee: amount_1perc, 139 | lpFee: amount_1perc, 140 | eqFee: amount_1perc, 141 | eqReward: amount_1perc, 142 | }) 143 | }) 144 | 145 | describe("FeeLibraryV02", () => { 146 | const fee = new FeeV02( 147 | { 148 | ...FeeLibraryV02Defaults, 149 | }, 150 | token, 151 | lpToken 152 | ) 153 | 154 | it("equilibrium fee should be correct", function () { 155 | const idealBalance = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 156 | const beforeBalance = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 157 | const poolTokenBalance = CurrencyAmount.fromRawAmount(token, BigInt(0)) 158 | const poolTotalLiquidity = CurrencyAmount.fromRawAmount(lpToken, BigInt(0)) 159 | const eqFeePool = CurrencyAmount.fromRawAmount(lpToken, BigInt(0)) 160 | for (let i = 1; i < 100; i++) { 161 | let swapAmount = CurrencyAmount.fromRawAmount(token, BigInt(i) * BigInt(1e18)) 162 | let { eqFee } = fee.getFees(idealBalance, beforeBalance, poolTokenBalance, poolTotalLiquidity, eqFeePool, swapAmount) 163 | expect(approx(parseFloat(eqFee.toExact()), parseFloat(expectedEqFee[i]))).toBeTruthy() 164 | } 165 | }) 166 | 167 | describe("equilibrium reward", function () { 168 | const idealBalance = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 169 | const beforeBalance = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 170 | 171 | it("no reward if pool has no deficit", function () { 172 | // token balance > total liquidity, no deficit 173 | const poolTokenBalance = CurrencyAmount.fromRawAmount(token, BigInt(100e18)) 174 | const poolTotalLiquidity = CurrencyAmount.fromRawAmount(lpToken, BigInt(0)) 175 | const eqFeePool = CurrencyAmount.fromRawAmount(lpToken, BigInt(0)) 176 | const swapAmount = CurrencyAmount.fromRawAmount(token, BigInt(10e18)) 177 | 178 | let { eqReward } = fee.getFees(idealBalance, beforeBalance, poolTokenBalance, poolTotalLiquidity, eqFeePool, swapAmount) 179 | expect(eqReward.currency).toEqual(token) 180 | expect(eqReward.toExact()).toEqual("0") 181 | }) 182 | 183 | it("reward capped at eqFeePool", function () { 184 | // in a deficit of 90 185 | // swap amount of 100, 10 greater than deficit 186 | const poolTokenBalance = CurrencyAmount.fromRawAmount(token, BigInt(10e18)) 187 | const poolTotalLiquidity = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 188 | const eqFeePool = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 189 | const swapAmount = CurrencyAmount.fromRawAmount(token, BigInt(100e18)) 190 | 191 | let { eqReward } = fee.getFees(idealBalance, beforeBalance, poolTokenBalance, poolTotalLiquidity, eqFeePool, swapAmount) 192 | expect(eqReward.currency).toEqual(token) 193 | expect(eqReward.toExact()).toEqual(eqFeePool.toExact()) 194 | }) 195 | 196 | it("should work as % of eqFeePool", function () { 197 | // in a deficit of 90 198 | // swap amount of 9, 10% of deficit 199 | const poolTokenBalance = CurrencyAmount.fromRawAmount(token, BigInt(10e18)) 200 | const poolTotalLiquidity = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 201 | const eqFeePool = CurrencyAmount.fromRawAmount(lpToken, BigInt(100e6)) 202 | const swapAmount = CurrencyAmount.fromRawAmount(token, BigInt(9e18)) 203 | 204 | let { eqReward } = fee.getFees(idealBalance, beforeBalance, poolTokenBalance, poolTotalLiquidity, eqFeePool, swapAmount) 205 | expect(eqReward.currency).toEqual(token) 206 | expect(eqReward.toExact()).toEqual("10") 207 | }) 208 | }) 209 | }) 210 | }) 211 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/fee.ts: -------------------------------------------------------------------------------- 1 | import { Currency, CurrencyAmount, Fraction } from "@layerzerolabs/ui-core" 2 | import { invariant as assert } from "../utils/invariantHelper" 3 | 4 | export interface FeeObj { 5 | eqFee: CurrencyAmount 6 | eqReward: CurrencyAmount 7 | lpFee: CurrencyAmount 8 | protocolFee: CurrencyAmount 9 | } 10 | 11 | interface FeeLibrary { 12 | version: string // `${number}.${number}.${number}` 13 | } 14 | //StargateFeeLibraryV01 15 | export interface FeeLibraryV01 extends FeeLibrary { 16 | version: "1.0.0" // `1.${number}.${number}` 17 | lpFeeRate: Fraction 18 | protocolFeeRate: Fraction 19 | eqFeeRate: Fraction 20 | eqRewardRate: Fraction 21 | } 22 | 23 | //StargateFeeLibraryV02 24 | export interface FeeLibraryV02 extends FeeLibrary { 25 | version: "2.0.0" // `2.${number}.${number}` 26 | delta1Rate: Fraction 27 | delta2Rate: Fraction 28 | lambda1Rate: Fraction 29 | lambda2Rate: Fraction 30 | lpFeeRate: Fraction 31 | protocolFeeRate: Fraction 32 | protocolSubsidyRate: Fraction 33 | } 34 | 35 | //StargateFeeLibraryV03 36 | export interface FeeLibraryV03 extends FeeLibrary { 37 | version: "3.0.0" // `3.${number}.${number}` 38 | delta1Rate: Fraction 39 | delta2Rate: Fraction 40 | lambda1Rate: Fraction 41 | lambda2Rate: Fraction 42 | lpFeeRate: Fraction 43 | protocolFeeRate: Fraction 44 | protocolSubsidyRate: Fraction 45 | } 46 | 47 | export const FeeLibraryV02Defaults: FeeLibraryV02 = { 48 | version: "2.0.0", 49 | delta1Rate: new Fraction(60, 100), 50 | delta2Rate: new Fraction(5, 100), 51 | lambda1Rate: new Fraction(40, 10000), 52 | lambda2Rate: new Fraction(9960, 10000), 53 | lpFeeRate: new Fraction(45, 100000), 54 | protocolFeeRate: new Fraction(15, 100000), 55 | protocolSubsidyRate: new Fraction(3, 100000), 56 | } 57 | 58 | export const FeeLibraryV03Defaults: FeeLibraryV03 = { 59 | version: "3.0.0", 60 | delta1Rate: new Fraction(60, 100), 61 | delta2Rate: new Fraction(5, 100), 62 | lambda1Rate: new Fraction(40, 10000), 63 | lambda2Rate: new Fraction(9960, 10000), 64 | lpFeeRate: new Fraction(10, 100000), 65 | protocolFeeRate: new Fraction(50, 100000), 66 | protocolSubsidyRate: new Fraction(3, 100000), 67 | } 68 | 69 | abstract class Fee { 70 | version: string 71 | fee: FeeLibraryV01 | FeeLibraryV02 | FeeLibraryV03 72 | liquidityToken: Currency 73 | token: Currency 74 | 75 | public constructor(_fee: FeeLibraryV01 | FeeLibraryV02 | FeeLibraryV03, _token: Currency, _lpToken: Currency) { 76 | this.version = _fee.version 77 | this.fee = _fee 78 | this.token = _token 79 | this.liquidityToken = _lpToken 80 | } 81 | 82 | amountSDtoLD(amountSD: CurrencyAmount): CurrencyAmount { 83 | return CurrencyAmount.fromRawAmount( 84 | this.token, 85 | amountSD.multiply(BigInt(10) ** BigInt(this.token.decimals)).divide(amountSD.decimalScale).quotient 86 | ) 87 | } 88 | } 89 | 90 | export class FeeV01 extends Fee { 91 | public getFees(_amount: CurrencyAmount): FeeObj { 92 | const fee = this.fee 93 | return { 94 | eqFee: _amount.multiply(fee.eqFeeRate), 95 | eqReward: _amount.multiply(fee.eqRewardRate), 96 | lpFee: _amount.multiply(fee.lpFeeRate), 97 | protocolFee: _amount.multiply(fee.protocolFeeRate), 98 | } 99 | } 100 | } 101 | 102 | const ZERO = new Fraction(0) 103 | export class FeeV02 extends Fee { 104 | public getFees( 105 | _idealBalance: CurrencyAmount, // lpToken 106 | _beforeBalance: CurrencyAmount, // lpToken 107 | _poolTokenBalance: CurrencyAmount, //token (token.balanceOf(address(pool)) 108 | _poolTotalLiquidity: CurrencyAmount, //lpToken 109 | _eqFeePool: CurrencyAmount, //lpToken 110 | _amount: CurrencyAmount //token 111 | ): FeeObj { 112 | if (!_idealBalance.currency.equals(this.liquidityToken)) console.log(_idealBalance.currency, this.liquidityToken) 113 | 114 | assert(_idealBalance.currency.equals(this.liquidityToken), "LIQUIDITY") 115 | assert(_beforeBalance.currency.equals(this.liquidityToken), "LIQUIDITY") 116 | assert(_poolTokenBalance.currency.equals(this.token), "TOKEN") 117 | assert(_poolTotalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 118 | assert(_eqFeePool.currency.equals(this.liquidityToken), "LIQUIDITY") 119 | assert(_amount.currency.equals(this.token), "TOKEN") 120 | 121 | const idealBalance = this.amountSDtoLD(_idealBalance) 122 | const beforeBalance = this.amountSDtoLD(_beforeBalance) 123 | const poolTotalLiquidity = this.amountSDtoLD(_poolTotalLiquidity) 124 | const eqFeePool = this.amountSDtoLD(_eqFeePool) 125 | // console.log('beforeBalance', beforeBalance, _amount) 126 | assert(beforeBalance.greaterThan(_amount) || beforeBalance.equalTo(_amount), "not enough balance") 127 | 128 | const fee = this.fee 129 | let protocolFee = _amount.multiply(fee.protocolFeeRate) 130 | 131 | // calculate the equilibrium fee 132 | let { eqFee, protocolSubsidy } = getEquilibriumFee(idealBalance, beforeBalance, _amount, fee) 133 | protocolFee = protocolFee.subtract(protocolSubsidy) 134 | 135 | // calculate the equilibrium reward 136 | let eqReward = getEquilibriumReward(_poolTokenBalance, poolTotalLiquidity, eqFeePool, _amount) 137 | 138 | return { 139 | eqFee, 140 | eqReward, 141 | lpFee: _amount.multiply(fee.lpFeeRate), 142 | protocolFee, 143 | } 144 | } 145 | } 146 | 147 | export class FeeV03 extends Fee { 148 | public getFees( 149 | _idealBalance: CurrencyAmount, // lpToken 150 | _beforeBalance: CurrencyAmount, // lpToken 151 | _poolTokenBalance: CurrencyAmount, //token (token.balanceOf(address(pool)) 152 | _poolTotalLiquidity: CurrencyAmount, //lpToken 153 | _eqFeePool: CurrencyAmount, //lpToken 154 | _amount: CurrencyAmount //token 155 | ): FeeObj { 156 | if (!_idealBalance.currency.equals(this.liquidityToken)) console.log(_idealBalance.currency, this.liquidityToken) 157 | 158 | assert(_idealBalance.currency.equals(this.liquidityToken), "LIQUIDITY") 159 | assert(_beforeBalance.currency.equals(this.liquidityToken), "LIQUIDITY") 160 | assert(_poolTokenBalance.currency.equals(this.token), "TOKEN") 161 | assert(_poolTotalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 162 | assert(_eqFeePool.currency.equals(this.liquidityToken), "LIQUIDITY") 163 | assert(_amount.currency.equals(this.token), "TOKEN") 164 | 165 | const idealBalance = this.amountSDtoLD(_idealBalance) 166 | const beforeBalance = this.amountSDtoLD(_beforeBalance) 167 | const poolTotalLiquidity = this.amountSDtoLD(_poolTotalLiquidity) 168 | const eqFeePool = this.amountSDtoLD(_eqFeePool) 169 | // console.log('beforeBalance', beforeBalance, _amount) 170 | assert(beforeBalance.greaterThan(_amount) || beforeBalance.equalTo(_amount), "not enough balance") 171 | 172 | const fee = this.fee 173 | let protocolFee = _amount.multiply(fee.protocolFeeRate) 174 | 175 | // calculate the equilibrium fee 176 | let { eqFee, protocolSubsidy } = getEquilibriumFee(idealBalance, beforeBalance, _amount, fee) 177 | protocolFee = protocolFee.subtract(protocolSubsidy) 178 | 179 | // calculate the equilibrium reward 180 | let eqReward = getEquilibriumReward(_poolTokenBalance, poolTotalLiquidity, eqFeePool, _amount) 181 | 182 | return { 183 | eqFee, 184 | eqReward, 185 | lpFee: _amount.multiply(fee.lpFeeRate), 186 | protocolFee, 187 | } 188 | } 189 | } 190 | 191 | function getEquilibriumReward( 192 | _poolTokenBalance: CurrencyAmount, 193 | _poolTotalLiquidity: CurrencyAmount, 194 | _eqFeePool: CurrencyAmount, 195 | _amount: CurrencyAmount 196 | ): CurrencyAmount { 197 | if (_poolTotalLiquidity.greaterThan(_poolTokenBalance)) { 198 | // in deficit 199 | const poolDeficit = _poolTotalLiquidity.subtract(_poolTokenBalance) 200 | // reward capped at rewardPoolSize 201 | let eqRewards = _eqFeePool.multiply(_amount).divide(poolDeficit) 202 | if (eqRewards.greaterThan(_eqFeePool)) { 203 | eqRewards = _eqFeePool 204 | } 205 | return eqRewards 206 | } 207 | return CurrencyAmount.fromRawAmount(_amount.currency, BigInt(0)) 208 | } 209 | 210 | function getEquilibriumFee( 211 | _idealBalance: CurrencyAmount, 212 | _beforeBalance: CurrencyAmount, 213 | _amount: CurrencyAmount, 214 | _fee: FeeLibraryV02 | FeeLibraryV03 215 | ): { eqFee: CurrencyAmount; protocolSubsidy: CurrencyAmount } { 216 | const afterBalance = _beforeBalance.subtract(_amount) 217 | 218 | let safeZoneMaxCurrency = _idealBalance.multiply(_fee.delta1Rate) 219 | const safeZoneMax = new Fraction(safeZoneMaxCurrency.numerator, safeZoneMaxCurrency.denominator) 220 | const safeZoneMinCurrency = _idealBalance.multiply(_fee.delta2Rate) 221 | const safeZoneMin = new Fraction(safeZoneMinCurrency.numerator, safeZoneMinCurrency.denominator) 222 | const proxyBeforeBalanceCurrency = _beforeBalance.lessThan(safeZoneMax) ? _beforeBalance : safeZoneMax 223 | const proxyBeforeBalance = new Fraction(proxyBeforeBalanceCurrency.numerator, proxyBeforeBalanceCurrency.denominator) 224 | 225 | let eqFee = CurrencyAmount.fromRawAmount(_amount.currency, BigInt(0)) 226 | let protocolSubsidy = CurrencyAmount.fromRawAmount(_amount.currency, BigInt(0)) 227 | 228 | if (afterBalance.greaterThan(safeZoneMax) || afterBalance.equalTo(safeZoneMax)) { 229 | // no fee zone, protocol subsidezes it 230 | eqFee = _amount.multiply(_fee.protocolSubsidyRate) 231 | protocolSubsidy = eqFee 232 | } else if (afterBalance.greaterThan(safeZoneMin) || afterBalance.equalTo(safeZoneMin)) { 233 | // safe zone 234 | eqFee = getTrapezoidArea(_amount.currency, _fee.lambda1Rate, ZERO, safeZoneMax, safeZoneMin, proxyBeforeBalance, afterBalance) 235 | } else { 236 | // danger zone 237 | if (_beforeBalance.greaterThan(safeZoneMin) || _beforeBalance.equalTo(safeZoneMin)) { 238 | // across 2 or 3 zones 239 | // part 1 240 | eqFee = eqFee.add( 241 | getTrapezoidArea(_amount.currency, _fee.lambda1Rate, ZERO, safeZoneMax, safeZoneMin, proxyBeforeBalance, safeZoneMin) 242 | ) 243 | // part 2 244 | eqFee = eqFee.add( 245 | getTrapezoidArea(_amount.currency, _fee.lambda2Rate, _fee.lambda1Rate, safeZoneMin, ZERO, safeZoneMin, afterBalance) 246 | ) 247 | } else { 248 | // only in danger zone 249 | // part2 only 250 | eqFee = eqFee.add( 251 | getTrapezoidArea(_amount.currency, _fee.lambda2Rate, _fee.lambda1Rate, safeZoneMin, ZERO, _beforeBalance, afterBalance) 252 | ) 253 | } 254 | } 255 | 256 | return { 257 | eqFee, 258 | protocolSubsidy, 259 | } 260 | } 261 | 262 | function getTrapezoidArea( 263 | _token: Currency, 264 | _lambda: Fraction, 265 | _yOffset: Fraction, 266 | _xUpperBound: Fraction, 267 | _xLowerBound: Fraction, 268 | _xStart: Fraction, 269 | _xEnd: Fraction 270 | ): CurrencyAmount { 271 | assert(_xEnd.greaterThan(_xLowerBound) || _xEnd.equalTo(_xLowerBound), "out of bounds") 272 | assert(_xStart.lessThan(_xUpperBound) || _xStart.equalTo(_xUpperBound), "out of bounds") 273 | 274 | const xBoundWidth = _xUpperBound.subtract(_xLowerBound) 275 | const yStart = _xUpperBound.subtract(_xStart).multiply(_lambda).divide(xBoundWidth).add(_yOffset) 276 | const yEnd = _xUpperBound.subtract(_xEnd).multiply(_lambda).divide(xBoundWidth).add(_yOffset) 277 | const deltaX = _xStart.subtract(_xEnd) 278 | const area = yStart.add(yEnd).multiply(deltaX).divide(2) 279 | 280 | return CurrencyAmount.fromFractionalAmount(_token, area.numerator, area.denominator) 281 | } 282 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./bonding" 2 | export * from "./pool" 3 | export * from "./votingEscrow" 4 | export * from "./fee" 5 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/pool.test.ts: -------------------------------------------------------------------------------- 1 | import { ChainPaths, Pool, PoolFee } from "./pool" 2 | import { TokenSymbol } from "../enums" 3 | import { ChainId } from "@layerzerolabs/lz-sdk" 4 | import { FeeV01 } from "./fee" 5 | import { describe, it, expect } from "vitest" 6 | import { Token, Fraction, CurrencyAmount } from "@layerzerolabs/ui-core" 7 | 8 | describe("Pool", () => { 9 | const chainId = ChainId.FUJI_SANDBOX 10 | const dstChainId = ChainId.ETHEREUM 11 | const dstPoolId = 1 12 | const token = new Token(chainId, "0x0000000000000000000000000000000000000000", 18, TokenSymbol.USDC) 13 | const liquidityToken = new Token(chainId, "0x0000000000000000000000000000000000000000", 6, TokenSymbol.SLP) 14 | const fraction = new Fraction(100, 10000) // 1% 15 | 16 | const poolFee: PoolFee = { 17 | mintFeeRate: fraction, 18 | } 19 | 20 | const chainPaths: ChainPaths = { 21 | [ChainId.ETHEREUM]: { 22 | 1: { 23 | chainId: dstChainId, 24 | poolId: dstPoolId, 25 | ready: true, 26 | balance: CurrencyAmount.fromRawAmount(liquidityToken, 100e6), 27 | idealBalance: CurrencyAmount.fromRawAmount(liquidityToken, 100e6), 28 | lkb: CurrencyAmount.fromRawAmount(liquidityToken, 100e6), 29 | credit: CurrencyAmount.fromRawAmount(liquidityToken, 0), 30 | weight: 1, 31 | }, 32 | }, 33 | } 34 | 35 | describe("#tokens", () => { 36 | it("#token", () => { 37 | expect(new Pool(liquidityToken, token, poolFee, chainPaths).token).toEqual(token) 38 | }) 39 | }) 40 | 41 | describe("#chainId", () => { 42 | it("returns correct chainId", () => { 43 | expect(new Pool(liquidityToken, token, poolFee, chainPaths).getChainId()).toEqual(chainId) 44 | }) 45 | }) 46 | 47 | describe("#getSwapOutputAmount", () => { 48 | it("slippage too high", () => { 49 | // all fees are 1% 50 | // user swaps 100 and gets max 98 (2% fee) 51 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 52 | pool.setFee( 53 | new FeeV01( 54 | { 55 | version: "1.0.0", 56 | eqFeeRate: fraction, 57 | eqRewardRate: fraction, 58 | lpFeeRate: fraction, 59 | protocolFeeRate: fraction, 60 | }, 61 | pool.token, 62 | pool.liquidityToken 63 | ) 64 | ) 65 | const inputAmount = CurrencyAmount.fromRawAmount(token, 100e18) 66 | const minAmount = CurrencyAmount.fromRawAmount(token, 100e18) 67 | 68 | expect(() => 69 | pool.getSwapOutputAmount( 70 | inputAmount, 71 | minAmount, 72 | ChainId.ETHEREUM, 73 | 1, 74 | CurrencyAmount.fromRawAmount(pool.token, BigInt(0)), 75 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)), 76 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)) 77 | ) 78 | ).toThrow("SLIPPAGE_TOO_HIGH") 79 | }) 80 | 81 | it("returns correct amount", () => { 82 | // all fees are 1% 83 | // user swaps 100 and gets 98 (2% fee) 84 | // sub lpFee and protocolFee and eqFee (-3%) 85 | // add eqReward (+1%) 86 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 87 | pool.setFee( 88 | new FeeV01( 89 | { 90 | version: "1.0.0", 91 | eqFeeRate: fraction, 92 | eqRewardRate: fraction, 93 | lpFeeRate: fraction, 94 | protocolFeeRate: fraction, 95 | }, 96 | pool.token, 97 | pool.liquidityToken 98 | ) 99 | ) 100 | 101 | const inputAmount = CurrencyAmount.fromRawAmount(token, 100e18) 102 | const minAmount = CurrencyAmount.fromRawAmount(token, 100e17) 103 | 104 | expect( 105 | pool 106 | .getSwapOutputAmount( 107 | inputAmount, 108 | minAmount, 109 | ChainId.ETHEREUM, 110 | 1, 111 | CurrencyAmount.fromRawAmount(pool.token, BigInt(0)), 112 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)), 113 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)) 114 | ) 115 | .outputAmount.toExact() 116 | ).toEqual(CurrencyAmount.fromRawAmount(token, 98e18).toExact()) 117 | }) 118 | }) 119 | 120 | describe("#getLiquidityMinted", () => { 121 | it("no fees - returns correct values", () => { 122 | //100:100 supply and liquidity 123 | //user adds 200 token and gets 200 liquidity 124 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 125 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 126 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 127 | const tokenAmount = CurrencyAmount.fromRawAmount(token, 200e18) 128 | 129 | expect(pool.getLiquidityMinted(totalSupply, totalLiquidity, tokenAmount, false)).toEqual( 130 | CurrencyAmount.fromRawAmount(pool.liquidityToken, 200e6) 131 | ) 132 | }) 133 | 134 | it("with fees - returns correct values", () => { 135 | // all fees are 1% 136 | // 100:100 supply and liquidity 137 | // user adds 200 token and gets 198 liquidity, 1% mint fee 138 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 139 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 140 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 1e6) 141 | const tokenAmount = CurrencyAmount.fromRawAmount(token, 2e18) 142 | 143 | expect(pool.getLiquidityMinted(totalSupply, totalLiquidity, tokenAmount, true)).toEqual( 144 | CurrencyAmount.fromRawAmount(pool.liquidityToken, 198e6) 145 | ) 146 | }) 147 | }) 148 | 149 | describe("#getRedeemLocalInstant", () => { 150 | it("amount > deltaCredit, capped at deltaCredit", () => { 151 | //available = deltaCredit = 20 token 152 | //user has 40 tokens (in shares) and 100 lp 153 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 154 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 155 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 40e6) 156 | const deltaCredit = CurrencyAmount.fromRawAmount(pool.liquidityToken, 20e6) 157 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 158 | 159 | //trys to instant redeem 100 lp for 40 tokens 160 | //but redeemed 50lp for 20 tokens 161 | expect(pool.getRedeemLocalInstant(totalSupply, totalLiquidity, deltaCredit, lpTokenAmount)[0]).toEqual( 162 | CurrencyAmount.fromRawAmount(pool.token, 20e18) 163 | ) 164 | expect(pool.getRedeemLocalInstant(totalSupply, totalLiquidity, deltaCredit, lpTokenAmount)[1].toExact()).toEqual( 165 | CurrencyAmount.fromRawAmount(pool.liquidityToken, 50e6).toExact() 166 | ) 167 | }) 168 | 169 | it("amount <= deltaCredit", () => { 170 | //available = deltaCredit = 20 token 171 | //user has 10 tokens (in shares) and 100 lp 172 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 173 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 174 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 10e6) 175 | const deltaCredit = CurrencyAmount.fromRawAmount(pool.liquidityToken, 20e6) 176 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 177 | 178 | //trys to instant redeem 100lp for 10 tokens 179 | expect(pool.getRedeemLocalInstant(totalSupply, totalLiquidity, deltaCredit, lpTokenAmount)[0]).toEqual( 180 | CurrencyAmount.fromRawAmount(pool.token, 10e18) 181 | ) 182 | expect(pool.getRedeemLocalInstant(totalSupply, totalLiquidity, deltaCredit, lpTokenAmount)[1].toExact()).toEqual( 183 | CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6).toExact() 184 | ) 185 | }) 186 | }) 187 | 188 | describe("#getRedeemRemote", () => { 189 | //todo: how much lp one should redeem 190 | //currently capped by swappable, need to trial and error to get a more precise amount 191 | it("amount <= available", () => { 192 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 193 | pool.setFee( 194 | new FeeV01( 195 | { 196 | version: "1.0.0", 197 | eqFeeRate: fraction, 198 | eqRewardRate: fraction, 199 | lpFeeRate: fraction, 200 | protocolFeeRate: fraction, 201 | }, 202 | pool.token, 203 | pool.liquidityToken 204 | ) 205 | ) 206 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 207 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 208 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 209 | const minAmount = CurrencyAmount.fromRawAmount(pool.token, 10e6) 210 | 211 | expect( 212 | pool 213 | .getRedeemRemote( 214 | dstChainId, 215 | dstPoolId, 216 | totalSupply, 217 | totalLiquidity, 218 | lpTokenAmount, 219 | minAmount, 220 | CurrencyAmount.fromRawAmount(pool.token, BigInt(0)), 221 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)) 222 | )[0] 223 | .toExact() 224 | ).toEqual(CurrencyAmount.fromRawAmount(token, 98e18).toExact()) 225 | }) 226 | 227 | it("amount > available", () => { 228 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 229 | pool.setFee( 230 | new FeeV01( 231 | { 232 | version: "1.0.0", 233 | eqFeeRate: fraction, 234 | eqRewardRate: fraction, 235 | lpFeeRate: fraction, 236 | protocolFeeRate: fraction, 237 | }, 238 | pool.token, 239 | pool.liquidityToken 240 | ) 241 | ) 242 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 243 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 244 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 245 | const minAmount = CurrencyAmount.fromRawAmount(pool.token, 10e6) 246 | 247 | expect( 248 | pool 249 | .getRedeemRemote( 250 | dstChainId, 251 | dstPoolId, 252 | totalSupply, 253 | totalLiquidity, 254 | lpTokenAmount, 255 | minAmount, 256 | CurrencyAmount.fromRawAmount(pool.token, BigInt(0)), 257 | CurrencyAmount.fromRawAmount(pool.liquidityToken, BigInt(0)) 258 | )[0] 259 | .toExact() 260 | ).toEqual(CurrencyAmount.fromRawAmount(token, 98e18).toExact()) 261 | }) 262 | }) 263 | 264 | describe("#getRedeemLocal", function () { 265 | describe("Fee Library V01", () => { 266 | it("amount <= available", () => { 267 | //available = lkb+credit = 100 token 268 | //user has 100 tokens (in shares) and 100 lp 269 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 270 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 271 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 272 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 273 | 274 | //trys to redeem 100lp for 100 tokens and succeeds 275 | expect(pool.getRedeemLocal(dstChainId, dstPoolId, totalSupply, totalLiquidity, lpTokenAmount)[0]).toEqual( 276 | CurrencyAmount.fromRawAmount(token, 100e18) 277 | ) 278 | expect(pool.getRedeemLocal(dstChainId, dstPoolId, totalSupply, totalLiquidity, lpTokenAmount)[1].toExact()).toEqual( 279 | CurrencyAmount.fromRawAmount(liquidityToken, 100e6).toExact() 280 | ) 281 | }) 282 | 283 | it("amount > available", () => { 284 | //available = lkb+credit = 100 token 285 | //user has 200 tokens (in shares) and 100lp 286 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 287 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 288 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 200e6) 289 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 290 | 291 | //trys to redeem 100lp for 200 tokens 292 | //can only redeem 50lp for 100 tokens 293 | expect(pool.getRedeemLocal(dstChainId, dstPoolId, totalSupply, totalLiquidity, lpTokenAmount)[0]).toEqual( 294 | CurrencyAmount.fromRawAmount(token, 100e18) 295 | ) 296 | expect(pool.getRedeemLocal(dstChainId, dstPoolId, totalSupply, totalLiquidity, lpTokenAmount)[1].toExact()).toEqual( 297 | CurrencyAmount.fromRawAmount(liquidityToken, 50e6).toExact() 298 | ) 299 | }) 300 | }) 301 | }) 302 | 303 | describe("getPrice", function () { 304 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 305 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 306 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 1000e6) 307 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 10e6) 308 | const fiatValue = pool.getPrice(totalSupply, totalLiquidity, lpTokenAmount) 309 | const result = BigInt(fiatValue.toFixed(0)) 310 | it("Should be > 0", () => { 311 | expect(result > BigInt(0)).toBeTruthy() 312 | }) 313 | 314 | it("Should should return expected value", () => { 315 | // 10 % of pool sharing $1000 should equal $100 316 | expect(result === BigInt(100)).toBeTruthy() 317 | }) 318 | 319 | it("Should return the original token", () => { 320 | const originalDecimals = token.decimals 321 | expect(originalDecimals === fiatValue.currency.decimals).toBeTruthy() 322 | expect(token.symbol === fiatValue.currency.symbol).toBeTruthy() 323 | }) 324 | }) 325 | 326 | describe("getPriceStatic", function () { 327 | const pool = new Pool(liquidityToken, token, poolFee, chainPaths) 328 | const totalSupply = CurrencyAmount.fromRawAmount(pool.liquidityToken, 100e6) 329 | const totalLiquidity = CurrencyAmount.fromRawAmount(pool.liquidityToken, 1000e6) 330 | const lpTokenAmount = CurrencyAmount.fromRawAmount(pool.liquidityToken, 10e6) 331 | const fiatValue = Pool.getPriceStatic(totalSupply, totalLiquidity, lpTokenAmount, token) 332 | const result = BigInt(fiatValue.toFixed(0)) 333 | it("Should be > 0", () => { 334 | expect(result > BigInt(0)).toBeTruthy() 335 | }) 336 | 337 | it("Should should return expected value", () => { 338 | // 10 % of pool sharing $1000 should equal $100 339 | expect(result === BigInt(100)).toBeTruthy() 340 | }) 341 | 342 | it("Should return the original token", () => { 343 | const originalDecimals = token.decimals 344 | expect(originalDecimals === fiatValue.currency.decimals).toBeTruthy() 345 | expect(token.symbol === fiatValue.currency.symbol).toBeTruthy() 346 | }) 347 | }) 348 | }) 349 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/pool.ts: -------------------------------------------------------------------------------- 1 | import { ChainId } from "@layerzerolabs/lz-sdk" 2 | import { PoolId } from "../enums" 3 | import { SHARE_DECIMALS } from "../constants/pool" 4 | import { invariant as assert } from "../utils/invariantHelper" 5 | import { FeeObj, FeeV01, FeeV02 } from "./fee" 6 | import { Currency, CurrencyAmount, Fraction, Token } from "@layerzerolabs/ui-core" 7 | 8 | //Pool Fee 9 | export interface PoolFee { 10 | mintFeeRate: Fraction 11 | } 12 | 13 | export interface ChainPath { 14 | chainId: ChainId // immutable 15 | poolId: PoolId // immutable 16 | ready: boolean 17 | balance: CurrencyAmount 18 | idealBalance: CurrencyAmount 19 | lkb: CurrencyAmount 20 | credit: CurrencyAmount 21 | weight: number 22 | } 23 | 24 | export type ChainPaths = { [chainId: number]: { [poolId: number]: ChainPath } } 25 | 26 | export class Pool { 27 | public readonly liquidityToken: Token 28 | public readonly token: Currency 29 | public fee: FeeV01 | FeeV02 | undefined 30 | public readonly poolFee: PoolFee 31 | public readonly chainPaths: ChainPaths 32 | 33 | public constructor(lpToken: Token, token: Currency, poolFee: PoolFee, chainPaths: ChainPaths) { 34 | this.liquidityToken = lpToken 35 | this.token = token 36 | this.poolFee = poolFee 37 | this.chainPaths = chainPaths 38 | } 39 | 40 | public setFee(_fee: FeeV01 | FeeV02) { 41 | this.fee = _fee 42 | } 43 | 44 | public getChainId(): number { 45 | return this.token.chainId 46 | } 47 | 48 | getChainPath(chainId: ChainId, poolId: PoolId): ChainPath | undefined { 49 | return this.chainPaths[chainId]?.[poolId] 50 | } 51 | 52 | amountLDtoSD(amountLD: CurrencyAmount): CurrencyAmount { 53 | return CurrencyAmount.fromRawAmount( 54 | this.liquidityToken, 55 | amountLD.multiply(BigInt(10) ** BigInt(SHARE_DECIMALS)).divide(amountLD.decimalScale).quotient 56 | ) 57 | } 58 | 59 | amountSDtoLD(amountSD: CurrencyAmount): CurrencyAmount { 60 | return CurrencyAmount.fromRawAmount( 61 | this.token, 62 | amountSD.multiply(BigInt(10) ** BigInt(this.token.decimals)).divide(amountSD.decimalScale).quotient 63 | ) 64 | } 65 | 66 | // swap 67 | public getSwapOutputAmount( 68 | inputAmount: CurrencyAmount, 69 | minAmount: CurrencyAmount, 70 | dstChainId: ChainId, 71 | dstPoolId: PoolId, 72 | tokenBalance: CurrencyAmount, 73 | totalLiquidity: CurrencyAmount, 74 | eqFeePool: CurrencyAmount 75 | ): { outputAmount: CurrencyAmount; fee: FeeObj } { 76 | assert(inputAmount.currency.equals(this.token), "TOKEN") 77 | assert(minAmount.currency.equals(this.token), "TOKEN") 78 | assert(tokenBalance.currency.equals(this.token), "TOKEN") 79 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 80 | assert(eqFeePool.currency.equals(this.liquidityToken), "LIQUIDITY") 81 | assert(this.fee != undefined, "FEE") 82 | 83 | const cp = this.getChainPath(dstChainId, dstPoolId) 84 | assert(cp, "NO_CHAIN_PATH") 85 | 86 | // fee library 87 | let fee: FeeObj 88 | if (this.fee?.version.split(".")[0] == "1") { 89 | fee = (this.fee).getFees(inputAmount) 90 | } else { 91 | fee = (this.fee).getFees(cp.idealBalance, cp.balance, tokenBalance, totalLiquidity, eqFeePool, inputAmount) 92 | } 93 | 94 | const amount = inputAmount.subtract(fee.eqFee).subtract(fee.protocolFee).subtract(fee.lpFee) 95 | assert(amount.add(fee.eqReward).quotient >= minAmount.quotient, "SLIPPAGE_TOO_HIGH") 96 | 97 | const lkbRemove = this.amountLDtoSD(inputAmount.subtract(fee.lpFee)) 98 | assert(cp.balance.quotient >= lkbRemove.quotient, "DST_BALANCE_TOO_LOW") 99 | 100 | return { 101 | outputAmount: amount.add(fee.eqReward), 102 | fee, 103 | } 104 | } 105 | 106 | //add liquidity 107 | public getLiquidityMinted( 108 | totalSupply: CurrencyAmount, //token LP 109 | totalLiquidity: CurrencyAmount, //token LP 110 | tokenAmount: CurrencyAmount, //token 111 | feeOn: boolean = false 112 | ): CurrencyAmount { 113 | assert(tokenAmount.currency.equals(this.token), "TOKEN") 114 | assert(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY") 115 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 116 | 117 | let amountSD = this.amountLDtoSD(tokenAmount).quotient 118 | if (feeOn) { 119 | const mintFee = (amountSD * this.poolFee.mintFeeRate.numerator) / this.poolFee.mintFeeRate.denominator 120 | amountSD = amountSD - mintFee 121 | } 122 | 123 | let amountLPTokens = amountSD 124 | if (totalSupply.quotient !== BigInt(0)) { 125 | amountLPTokens = (amountSD * totalSupply.quotient) / totalLiquidity.quotient 126 | } 127 | return CurrencyAmount.fromRawAmount(this.liquidityToken, amountLPTokens) 128 | } 129 | 130 | //remove liquidity A 131 | //redeem local instant 132 | public getRedeemLocalInstant( 133 | totalSupply: CurrencyAmount, //token LP 134 | totalLiquidity: CurrencyAmount, //token Pool 135 | deltaCredit: CurrencyAmount, //token Pool 136 | lpTokenAmount: CurrencyAmount //token LP / Pool, both are in SHARED_DECIMAL 137 | ): [CurrencyAmount, CurrencyAmount] { 138 | assert(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY") 139 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 140 | assert(deltaCredit.currency.equals(this.liquidityToken), "LIQUIDITY") 141 | assert(lpTokenAmount.currency.equals(this.liquidityToken), "LIQUIDITY") 142 | 143 | let amountLP = lpTokenAmount 144 | let amountSD = lpTokenAmount.multiply(totalLiquidity).divide(totalSupply) 145 | if (deltaCredit.quotient <= amountSD.quotient) { 146 | amountSD = deltaCredit 147 | amountLP = amountSD.multiply(totalSupply).divide(totalLiquidity) 148 | } 149 | amountSD = amountLP.multiply(totalLiquidity).divide(totalSupply) 150 | const amountLD = this.amountSDtoLD(amountSD) 151 | return [CurrencyAmount.fromRawAmount(this.token, amountLD.quotient), amountLP] 152 | } 153 | 154 | //remove liquidity A->B 155 | //redeem remote 156 | //todo: how much lp one should redeem 157 | public getRedeemRemote( 158 | dstChainId: ChainId, 159 | dstPoolId: PoolId, 160 | totalSupply: CurrencyAmount, 161 | totalLiquidity: CurrencyAmount, 162 | lpTokenAmount: CurrencyAmount, 163 | minAmount: CurrencyAmount, 164 | tokenBalance: CurrencyAmount, 165 | eqFeePool: CurrencyAmount 166 | ): [CurrencyAmount, CurrencyAmount] { 167 | assert(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY") 168 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 169 | assert(lpTokenAmount.currency.equals(this.liquidityToken), "LIQUIDITY") 170 | assert(eqFeePool.currency.equals(this.liquidityToken), "LIQUIDITY") 171 | assert(minAmount.currency.equals(this.token), "TOKEN") 172 | assert(tokenBalance.currency.equals(this.token), "TOKEN") 173 | 174 | //check that pool has enough liquidity 175 | assert( 176 | totalLiquidity.quotient >= lpTokenAmount.multiply(totalLiquidity).divide(totalSupply).quotient, 177 | "POOL DOES NOT HAVE ENOUGH LIQUIDITY" 178 | ) 179 | 180 | const amountSD = lpTokenAmount.multiply(totalLiquidity).divide(totalSupply) 181 | const amountLD = this.amountSDtoLD(amountSD) 182 | return [ 183 | this.getSwapOutputAmount( 184 | CurrencyAmount.fromRawAmount(this.token, amountLD.quotient), 185 | minAmount, 186 | dstChainId, 187 | dstPoolId, 188 | tokenBalance, 189 | totalLiquidity, 190 | eqFeePool 191 | ).outputAmount, 192 | CurrencyAmount.fromRawAmount(this.token, 0), 193 | ] 194 | } 195 | 196 | //remove liquidity A->B->A 197 | //redeem local 198 | public getRedeemLocal( 199 | dstChainId: ChainId, 200 | dstPoolId: PoolId, 201 | totalSupply: CurrencyAmount, 202 | totalLiquidity: CurrencyAmount, 203 | lpTokenAmount: CurrencyAmount 204 | ): [CurrencyAmount, CurrencyAmount] { 205 | assert(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY") 206 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 207 | assert(lpTokenAmount.currency.equals(this.liquidityToken), "LIQUIDITY") 208 | 209 | const cp = this.getChainPath(dstChainId, dstPoolId) 210 | assert(cp, "NO_CHAIN_PATH") 211 | let amountSD = lpTokenAmount.multiply(totalLiquidity).divide(totalSupply) 212 | const available = cp.lkb.add(cp.credit) 213 | if (amountSD.quotient >= available.quotient) { 214 | amountSD = available 215 | } 216 | const lpAmount = amountSD.multiply(totalSupply).divide(totalLiquidity) 217 | const amountLD = this.amountSDtoLD(amountSD) 218 | return [amountLD, lpAmount] 219 | } 220 | 221 | /** 222 | * Get the price of lpTokenAmount 223 | * @param totalSupply Total LP Tokens 224 | * @param totalLiquidity Total Tokens shared in the pool 225 | * @param lpTokenAmount LP Amount 226 | * @returns price 227 | */ 228 | public getPrice(totalSupply: CurrencyAmount, totalLiquidity: CurrencyAmount, lpTokenAmount: CurrencyAmount) { 229 | assert(totalSupply.currency.equals(this.liquidityToken), "LIQUIDITY") 230 | assert(totalLiquidity.currency.equals(this.liquidityToken), "LIQUIDITY") 231 | assert(lpTokenAmount.currency.equals(this.liquidityToken), "LIQUIDITY") 232 | 233 | return this.amountSDtoLD(totalLiquidity.multiply(lpTokenAmount).divide(totalSupply)) 234 | } 235 | 236 | /** 237 | * Static method version of getPrice. 238 | * @param totalSupply Total LP Tokens 239 | * @param totalLiquidity Total Tokens shared in the pool 240 | * @param lpTokenAmount LP Amount 241 | * @param token Token 242 | * @returns price 243 | */ 244 | public static getPriceStatic(totalSupply: CurrencyAmount, totalLiquidity: CurrencyAmount, lpTokenAmount: CurrencyAmount, token: Currency) { 245 | const lpPrice = totalLiquidity.multiply(lpTokenAmount).divide(totalSupply) 246 | return CurrencyAmount.fromRawAmount(token, lpPrice.multiply(BigInt(10) ** BigInt(token.decimals)).divide(lpPrice.decimalScale).quotient) 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/votingEscrow.test.ts: -------------------------------------------------------------------------------- 1 | import { VotingEscrow } from "./votingEscrow" 2 | import { STG, VESTG } from "../constants/token" 3 | import { ChainId } from "@layerzerolabs/lz-sdk" 4 | import { describe, it, expect } from "vitest" 5 | import { CurrencyAmount } from "@layerzerolabs/ui-core" 6 | 7 | describe("VotingEscrow", () => { 8 | const WEEK = 604800 9 | const MAXTIME = 94608000 10 | const chainId = ChainId.ETHEREUM 11 | const stargateToken = STG[chainId] 12 | const veToken = VESTG[chainId] 13 | const votingEscrow = new VotingEscrow(stargateToken, veToken) 14 | 15 | const unlockInSec = WEEK * 2 16 | const stgAmount = CurrencyAmount.fromRawAmount(stargateToken, 10000e18) 17 | const result = votingEscrow.estimateVe(stgAmount, unlockInSec) 18 | 19 | describe("estimateVe", () => { 20 | it("Should return VESTG given STG for currency", () => { 21 | expect(result.currency.symbol === "VESTG") 22 | expect(result.currency.name === "veStargateToken") 23 | }) 24 | 25 | it("Should not return negative if unlock time is negative", () => { 26 | const amount = BigInt(stgAmount.toFixed().split(".")[0]) 27 | const amountPerSec = amount / BigInt(MAXTIME) 28 | const expectedAmount = amountPerSec * BigInt(0) 29 | expect(votingEscrow.estimateVe(stgAmount, -100000).equalTo(expectedAmount)) 30 | }) 31 | 32 | it("Should return around the expected value", () => { 33 | const amount = BigInt(stgAmount.toFixed().split(".")[0]) 34 | const amountPerSec = amount / BigInt(MAXTIME) 35 | const expectedAmount = amountPerSec * BigInt(unlockInSec) 36 | expect(votingEscrow.estimateVe(stgAmount, unlockInSec).equalTo(expectedAmount)) 37 | }) 38 | 39 | it("Should should properly estimate", () => { 40 | const rawAmount = CurrencyAmount.fromRawAmount(stargateToken, 160000e18) 41 | const d = 86400 42 | const m = d * 30 43 | const veAmount = votingEscrow.estimateVe(rawAmount, m * 36) 44 | console.log(veAmount.toExact()) 45 | }) 46 | }) 47 | 48 | describe("estimateVeWithTs", () => { 49 | it("Should return same values as estimateVe given a timestamp", () => { 50 | const current = +new Date() 51 | const unlocked = current + WEEK 52 | const resultWithTs = votingEscrow.estimateVeWithTs(stgAmount, current, unlocked) 53 | const resultWithSec = votingEscrow.estimateVe(stgAmount, unlockInSec) 54 | expect(resultWithSec.currency.symbol === resultWithTs.currency.symbol) 55 | expect(resultWithSec.currency.name === resultWithTs.currency.name) 56 | expect(resultWithSec.toExact() === resultWithTs.toExact()) 57 | }) 58 | }) 59 | 60 | describe("getUnlockTime", () => { 61 | it("Should return a rounded unlock time", () => { 62 | // beginning of a UTC week 63 | expect(votingEscrow.getUnlockTime(1645660800)).toEqual(1645660800) 64 | expect(votingEscrow.getUnlockTime(1645660800 + 1)).toEqual(1645660800) 65 | expect(votingEscrow.getUnlockTime(1645660800 + WEEK - 1)).toEqual(1645660800) 66 | expect(votingEscrow.getUnlockTime(1645660800 + WEEK)).toEqual(1646265600) 67 | }) 68 | }) 69 | }) 70 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/entities/votingEscrow.ts: -------------------------------------------------------------------------------- 1 | import { Currency, CurrencyAmount } from "@layerzerolabs/ui-core" 2 | import { invariant as assert } from "../utils/invariantHelper" 3 | 4 | const WEEK = 604800 5 | const MAXTIME = BigInt(94608000) 6 | 7 | export class VotingEscrow { 8 | public readonly token: Currency 9 | public readonly veToken: Currency 10 | 11 | public constructor(token: Currency, veToken: Currency) { 12 | this.token = token 13 | this.veToken = veToken 14 | } 15 | 16 | /** 17 | * Estimates the amount of veToken the user would get for staking token 18 | * @param _amount Amount of token to be staked 19 | * @param _unlock_time Seconds until unlocked 20 | * @returns CurrencyAmount of veToken 21 | */ 22 | public estimateVe(_amount: CurrencyAmount, _unlock_time: number): CurrencyAmount { 23 | assert(_amount.currency.equals(this.token), "TOKEN") 24 | let unlock_time = _unlock_time 25 | if (_unlock_time < 0) { 26 | unlock_time = 0 27 | } 28 | const ve_amount = _amount.divide(BigInt(MAXTIME)).multiply(BigInt(unlock_time)) 29 | return CurrencyAmount.fromFractionalAmount(this.veToken, ve_amount.numerator, ve_amount.denominator) 30 | } 31 | 32 | /** 33 | * Convenience method to calculate veToken given current blocktime 34 | * @param _amount Amount of token to be staked 35 | * @param _current_ts Timestamp of current block time 36 | * @param _unlock_ts Timestamp of when token will be unlocked 37 | * @returns CurrencyAmount of veToken 38 | */ 39 | public estimateVeWithTs(_amount: CurrencyAmount, _current_ts: number, _unlock_ts: number): CurrencyAmount { 40 | const diff = _unlock_ts - _current_ts 41 | return this.estimateVe(_amount, diff) 42 | } 43 | 44 | /** 45 | * The VotingEscrow contract's create_lock rounds the unlock time down to weeks. 46 | * This method does the same given an expected unlock time. 47 | * @param _unlock_ts timestamp of expected unlock time 48 | * @returns timestamp of rounded unlock time 49 | */ 50 | public getUnlockTime(_unlock_ts: number): number { 51 | return Math.floor(_unlock_ts / WEEK) * WEEK 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/enums/PoolId.ts: -------------------------------------------------------------------------------- 1 | // *Warning* you can never modify these, only add! 2 | export enum PoolId { 3 | USDC = 1, 4 | USDT = 2, 5 | DAI = 3, 6 | MIM = 4, 7 | BUSD = 5, 8 | FEI = 6, 9 | FRAX = 7, 10 | USDCe = 8, 11 | USDTe = 9, 12 | WETH = 10, // stargate uses use SGETH instead 13 | USDD = 11, 14 | STARGATE_ETH_VAULT, // deprecated 15 | SGETH, 16 | // 17 | SUSD = 14, 18 | LUSD = 15, 19 | MAI = 16, 20 | } 21 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/enums/TokenSymbol.ts: -------------------------------------------------------------------------------- 1 | export enum TokenSymbol { 2 | USDC = "USDC", 3 | USDT = "USDT", 4 | MIM = "MIM", 5 | DAI = "DAI", 6 | BUSD = "BUSD", 7 | STG = "STG", 8 | SLP = "SLP", 9 | aSTG = "aSTG", 10 | veSTG = "veSTG", 11 | sveSTG = "sveSTG", 12 | pSTG = "pSTG", 13 | aaSTG = "aaSTG", 14 | WETH = "WETH", 15 | USDD = "USDD", 16 | SGETH = "SGETH", 17 | SUSD = "SUSD", 18 | FRAX = "FRAX", 19 | LUSD = "LUSD", 20 | MAI = "MAI", 21 | } 22 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/enums/index.ts: -------------------------------------------------------------------------------- 1 | export { PoolId } from "./PoolId" 2 | export { TokenSymbol } from "./TokenSymbol" 3 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./constants" 2 | export * from "./entities" 3 | export * from "./utils" 4 | export * from "./enums" 5 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/constants.ts: -------------------------------------------------------------------------------- 1 | export const H = 3600 2 | export const DAY = 86400 3 | export const WEEK = 7 * DAY 4 | export const YEAR = DAY * 365 5 | export const TOL = 120 / WEEK 6 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/data/farming.json: -------------------------------------------------------------------------------- 1 | { 2 | "farming": [ 3 | { 4 | "alloc": 0.625, 5 | "stgPrice": 1.0, 6 | "stgPerBlock": 17.69347839, 7 | "avgBlockTime": 13.21448276, 8 | "totalLiquidity": 153317174.44, 9 | "totalLp": 153317174.44, 10 | "totalFarmLp": 139887311.23, 11 | "expectedApr": 0.188656317476879, 12 | "expectedApy": 0.207625841257641 13 | }, 14 | { 15 | "alloc": 0.375, 16 | "stgPrice": 1.0, 17 | "stgPerBlock": 17.69347839, 18 | "avgBlockTime": 13.21448276, 19 | "totalLiquidity": 101315982.2, 20 | "totalLp": 101315982.2, 21 | "totalFarmLp": 93258064.26, 22 | "expectedApr": 0.169790946495422, 23 | "expectedApy": 0.185057085086306 24 | }, 25 | { 26 | "alloc": 0.50, 27 | "stgPrice": 1.0, 28 | "stgPerBlock": 3.226398074, 29 | "avgBlockTime": 3.012068966, 30 | "totalLiquidity": 97607619.86, 31 | "totalLp": 97607619.86, 32 | "totalFarmLp": 93257471.11, 33 | "expectedApr": 0.181111494846866, 34 | "expectedApy": 0.198548803859184 35 | }, 36 | { 37 | "alloc": 0.50, 38 | "stgPrice": 1.0, 39 | "stgPerBlock": 3.226398074, 40 | "avgBlockTime": 3.012068966, 41 | "totalLiquidity": 98629579.9, 42 | "totalLp": 98629579.9, 43 | "totalFarmLp": 93257634.57, 44 | "expectedApr": 0.181111177398487, 45 | "expectedApy": 0.198548423381869 46 | }, 47 | { 48 | "alloc": 0.60, 49 | "stgPrice": 1.0, 50 | "stgPerBlock": 2.715751784, 51 | "avgBlockTime": 2.028275862, 52 | "totalLiquidity": 146922409.81, 53 | "totalLp": 146922409.81, 54 | "totalFarmLp": 139886288.39, 55 | "expectedApr": 0.181111389027651, 56 | "expectedApy": 0.198548677029696 57 | }, 58 | { 59 | "alloc": 0.4, 60 | "stgPrice": 1.0, 61 | "stgPerBlock": 2.715751784, 62 | "avgBlockTime": 2.028275862, 63 | "totalLiquidity": 98629579.9, 64 | "totalLp": 98629579.9, 65 | "totalFarmLp": 93257634.57, 66 | "expectedApr": 0.181111177389048, 67 | "expectedApy": 0.198548423370556 68 | }, 69 | { 70 | "alloc": 0.65, 71 | "stgPrice": 1.0, 72 | "stgPerBlock": 1.966311408, 73 | "avgBlockTime": 2.447586207, 74 | "totalLiquidity": 100294022.17, 75 | "totalLp": 100294022.17, 76 | "totalFarmLp": 93257900.8, 77 | "expectedApr": 0.176582893899062, 78 | "expectedApy": 0.193133326133968 79 | }, 80 | { 81 | "alloc": 0.35, 82 | "stgPrice": 1.0, 83 | "stgPerBlock": 1.966311408, 84 | "avgBlockTime": 2.447586207, 85 | "totalLiquidity": 52001192.23, 86 | "totalLp": 52001192.23, 87 | "totalFarmLp": 46629246.97, 88 | "expectedApr": 0.190164983940186, 89 | "expectedApy": 0.209449120879153 90 | }, 91 | { 92 | "alloc": 0.55, 93 | "stgPrice": 1.0, 94 | "stgPerBlock": 6.046250777, 95 | "avgBlockTime": 12.54355401, 96 | "totalLiquidity": 49579046.78, 97 | "totalLp": 49579046.78, 98 | "totalFarmLp": 46628859.55, 99 | "expectedApr": 0.17929990311952, 100 | "expectedApy": 0.196379488311625 101 | }, 102 | { 103 | "alloc": 0.45, 104 | "stgPrice": 1.0, 105 | "stgPerBlock": 6.046250777, 106 | "avgBlockTime": 12.54355401, 107 | "totalLiquidity": 39989112.42, 108 | "totalLp": 39989112.42, 109 | "totalFarmLp": 37303139.77, 110 | "expectedApr": 0.18337464465686, 111 | "expectedApy": 0.20126437106555 112 | }, 113 | { 114 | "alloc": 1, 115 | "stgPrice": 1.0, 116 | "stgPerBlock": 0.185570952, 117 | "avgBlockTime": 3.464870067, 118 | "totalLiquidity": 12276336.55, 119 | "totalLp": 12276336.55, 120 | "totalFarmLp": 9326149.47, 121 | "expectedApr": 0.181103681125416, 122 | "expectedApy": 0.198539438769274 123 | }, 124 | { 125 | "alloc": 1, 126 | "stgPrice": 1.0, 127 | "stgPerBlock": 0.2612329751, 128 | "avgBlockTime": 0.9755172414, 129 | "totalLiquidity": 56995145.03, 130 | "totalLp": 56995145.03, 131 | "totalFarmLp": 46630045.75, 132 | "expectedApr": 0.181106406036687, 133 | "expectedApy": 0.198542704687349 134 | } 135 | ] 136 | } -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/estimateDstNativeAmt.ts: -------------------------------------------------------------------------------- 1 | import { ERC20_APPROVE, ERC20_TRANSFER, REVERT_REDEEM_LOCAL } from "../constants/gasEstimate" 2 | import { ChainId } from "@layerzerolabs/lz-sdk" 3 | import { CurrencyAmount, Fraction, Percent } from "@layerzerolabs/ui-core" 4 | 5 | export interface DstPrice { 6 | dstGasPriceInWei: CurrencyAmount 7 | dstPriceRatio: Fraction 8 | } 9 | 10 | export function estimateDstNativeAmtForRedeemLocal( 11 | _dstChainId: ChainId, 12 | _dstQuotedLayerZeroFee: CurrencyAmount, //in dst currency, from: dst Router.sol 13 | _srcRelayerDstConfig: DstPrice // from: src Relayer.sol 14 | ): CurrencyAmount { 15 | const dstCost = _srcRelayerDstConfig.dstGasPriceInWei.multiply(BigInt(REVERT_REDEEM_LOCAL[_dstChainId]!)) 16 | const totalCost = _dstQuotedLayerZeroFee.add(dstCost).divide(10e10) 17 | const bufferPerc = new Percent(120) 18 | return totalCost.multiply(bufferPerc) 19 | } 20 | 21 | export function estimateDstNativeAmtForERC20Transfer( 22 | _dstChainId: ChainId, 23 | _srcRelayerDstPrice: DstPrice //from: src Relayer.sol 24 | ): CurrencyAmount { 25 | return _srcRelayerDstPrice.dstGasPriceInWei.multiply(ERC20_TRANSFER[_dstChainId]!) 26 | } 27 | 28 | export function estimateDstNativeAmtForApprove( 29 | _dstChainId: ChainId, 30 | _srcRelayerDstPrice: DstPrice //from: src Relayer.sol 31 | ): CurrencyAmount { 32 | return _srcRelayerDstPrice.dstGasPriceInWei.multiply(ERC20_APPROVE[_dstChainId]!) 33 | } 34 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/getFarmApy.test.ts: -------------------------------------------------------------------------------- 1 | import { getFarmApr, getFarmApy, getTokenFarmApr, getTokenFarmApy } from "./getFarmApy" 2 | import farmingData from "./data/farming.json" 3 | import { ChainId } from "@layerzerolabs/lz-sdk" 4 | import { USDC, LPTOKEN, STG } from "../constants/token" 5 | import { PoolId } from "../enums" 6 | import { describe, it, expect } from "vitest" 7 | import { CurrencyAmount } from "@layerzerolabs/ui-core" 8 | 9 | function approx(a: number, b: number, precision: number = 1e-10) { 10 | if (a == b && a == 0) { 11 | return true 12 | } 13 | return (2 * Math.abs(a - b)) / (a + b) <= precision 14 | } 15 | 16 | describe("getApy", () => { 17 | const data = farmingData.farming 18 | 19 | const chainId = ChainId.RINKEBY 20 | const poolId = PoolId.USDC 21 | 22 | it("Expected Apr should match", () => { 23 | data.forEach((testCase) => { 24 | // total allocation is 1 per pool contract per chain 25 | const { stgPrice, stgPerBlock, avgBlockTime, alloc, expectedApr, totalLiquidity, totalFarmLp, totalLp } = testCase 26 | 27 | const rewardPrice = CurrencyAmount.fromRawAmount(USDC[chainId], BigInt(stgPrice * 10 ** 6)) 28 | 29 | const rewardPerBlock = CurrencyAmount.fromRawAmount(STG[chainId], BigInt(stgPerBlock * 10 ** 18)) 30 | 31 | const totalLiq = CurrencyAmount.fromRawAmount(USDC[chainId], BigInt(Math.round(totalLiquidity * 10 ** 6))) 32 | const totalFLp = CurrencyAmount.fromRawAmount(LPTOKEN[chainId][poolId], BigInt(Math.round(totalFarmLp * 10 ** 6))) 33 | const totalPLp = CurrencyAmount.fromRawAmount(LPTOKEN[chainId][poolId], BigInt(Math.round(totalLp * 10 ** 6))) 34 | const apr = getFarmApr(rewardPrice, rewardPerBlock, alloc, 1, avgBlockTime, totalLiq, totalFLp, totalPLp) 35 | expect(approx(apr, expectedApr, 2)).toBeTruthy() 36 | }) 37 | }) 38 | 39 | it("Expected Apr should match NEW", () => { 40 | // total allocation is 1 per pool contract per chain 41 | // const {stgPrice, stgPerBlock, avgBlockTime, alloc, expectedApr, totalLiquidity, totalFarmLp, totalLp} = testCase 42 | const ethPoolTestCases = [ 43 | { 44 | // ethereum 45 | allocPoint: 325, 46 | avgBlockTime: 13.21448276, 47 | chainId: ChainId.ETHEREUM, 48 | rewardPrice: 0.384747, 49 | stgPerBlock: 4.906029642, 50 | totalAllocPoint: 1326, 51 | totalLiquidity: 1602.760003024600000001, 52 | totalSupply: 1602.756057244699177932, 53 | lpBalance: 1537.246218374302799112, 54 | tokenPrice: 1100, 55 | expectedApr: 0.6529266610153618, 56 | expectedApy: 0.9211551793241914, 57 | }, 58 | // optimism 59 | { 60 | allocPoint: 84, 61 | avgBlockTime: 1.458, 62 | chainId: ChainId.OPTIMISM, 63 | lpBalance: 146.447991419022073661, 64 | rewardPrice: 0.386418, 65 | stgPerBlock: 0.03372, 66 | totalAllocPoint: 1000, 67 | totalLiquidity: 156.870178410000000001, 68 | totalSupply: 156.867969526539025598, 69 | tokenPrice: 1100, 70 | expectedApr: 0.14695726281950983, 71 | expectedApy: 0.15830445930529802, 72 | }, 73 | // arbitrum 74 | { 75 | allocPoint: 32, 76 | avgBlockTime: 13.21448276, 77 | chainId: ChainId.ARBITRUM, 78 | lpBalance: 207.069515769678625158, 79 | rewardPrice: 0.386418, 80 | stgPerBlock: 2.662852115, 81 | totalAllocPoint: 1033, 82 | totalLiquidity: 217.5901843223, 83 | totalSupply: 217.589492269291255445, 84 | tokenPrice: 1100, 85 | expectedApr: 0.33396439031848696, 86 | expectedApy: 0.3964934140033758, 87 | }, 88 | ] 89 | 90 | for (let testCase of ethPoolTestCases) { 91 | const totalFarmLp = testCase.lpBalance 92 | const totalLp = testCase.totalSupply 93 | 94 | const tokenPriceSD = CurrencyAmount.fromRawAmount(USDC[testCase.chainId], BigInt(testCase.tokenPrice)) 95 | 96 | const rewardPrice = CurrencyAmount.fromRawAmount(USDC[testCase.chainId], BigInt(testCase.rewardPrice * 10 ** 6)) 97 | 98 | const rewardPerBlock = CurrencyAmount.fromRawAmount(STG[testCase.chainId], BigInt(Math.round(testCase.stgPerBlock * 10 ** 18))) 99 | 100 | const totalLiq = CurrencyAmount.fromRawAmount(USDC[testCase.chainId], BigInt(Math.round(testCase.totalLiquidity * 10 ** 6))) 101 | const totalFLp = CurrencyAmount.fromRawAmount(LPTOKEN[testCase.chainId][poolId], BigInt(Math.round(totalFarmLp * 10 ** 6))) 102 | const totalPLp = CurrencyAmount.fromRawAmount(LPTOKEN[testCase.chainId][poolId], BigInt(Math.round(totalLp * 10 ** 6))) 103 | const apr = getTokenFarmApr( 104 | rewardPrice, 105 | rewardPerBlock, 106 | testCase.allocPoint, 107 | testCase.totalAllocPoint, 108 | testCase.avgBlockTime, 109 | totalLiq, 110 | totalFLp, 111 | totalPLp, 112 | tokenPriceSD 113 | ) 114 | expect(approx(apr, testCase.expectedApr, 2)).toBeTruthy() 115 | const apy = getTokenFarmApy( 116 | rewardPrice, 117 | rewardPerBlock, 118 | testCase.allocPoint, 119 | testCase.totalAllocPoint, 120 | testCase.avgBlockTime, 121 | totalLiq, 122 | totalFLp, 123 | totalPLp, 124 | tokenPriceSD 125 | ) 126 | console.log(`chainId: ${testCase.chainId}, total apr: ${apr}, total apy: ${apy}`) 127 | } 128 | }) 129 | 130 | it("Expected Apy should match", () => { 131 | data.forEach((testCase) => { 132 | // total allocation is 1 per pool contract per chain 133 | const { stgPrice, stgPerBlock, avgBlockTime, alloc, expectedApy, totalLiquidity, totalFarmLp, totalLp } = testCase 134 | 135 | const rewardPrice = CurrencyAmount.fromRawAmount(USDC[chainId], BigInt(stgPrice * 10 ** 6)) 136 | const rewardPerBlock = CurrencyAmount.fromRawAmount(STG[chainId], BigInt(stgPerBlock * 10 ** 18)) 137 | 138 | const totalLiq = CurrencyAmount.fromRawAmount(USDC[chainId], BigInt(totalLiquidity * 10 ** 6)) 139 | const totalFLp = CurrencyAmount.fromRawAmount(LPTOKEN[chainId][poolId], BigInt(Math.round(totalFarmLp * 10 ** 6))) 140 | const totalPLp = CurrencyAmount.fromRawAmount(LPTOKEN[chainId][poolId], BigInt(Math.round(totalLp * 10 ** 6))) 141 | 142 | const apy = getFarmApy(rewardPrice, rewardPerBlock, alloc, 1, avgBlockTime, totalLiq, totalFLp, totalPLp) 143 | expect(approx(apy, expectedApy, 2)).toBeTruthy() 144 | }) 145 | }) 146 | }) 147 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/getFarmApy.ts: -------------------------------------------------------------------------------- 1 | import { CurrencyAmount, Percent, Token } from "@layerzerolabs/ui-core" 2 | import { YEAR } from "./constants" 3 | 4 | /** 5 | * Get APR for a Farm 6 | * @param rewardPrice Price of STG 7 | * @param stgPerBlock STG Reward per block 8 | * @param allocPoint Weight of the pool 9 | * @param totalAllocPoint Total weights of all pools in the contract 10 | * @param avgBlockTime Average block time 11 | * @param totalLiquidity Total liquidity deposited in Pool 12 | * @param totalFarmLp Total LP in the Farm 13 | * @param totalPoolLp Total LP in the Pool 14 | * @returns APR 15 | */ 16 | export function getFarmApr( 17 | rewardPrice: CurrencyAmount, 18 | stgPerBlock: CurrencyAmount, 19 | allocPoint: number, 20 | totalAllocPoint: number, 21 | avgBlockTime: number, 22 | totalLiquidity: CurrencyAmount, 23 | totalFarmLp: CurrencyAmount, 24 | totalPoolLp: CurrencyAmount 25 | ) { 26 | const rewardPerBlock = stgPerBlock.multiply(new Percent(allocPoint * 10000, totalAllocPoint * 10000)) 27 | const tvl = totalLiquidity.multiply(totalFarmLp).divide(totalPoolLp) 28 | const roiPerBlock = rewardPerBlock.multiply(rewardPrice).divide(tvl) 29 | const blocksPerYear = BigInt(Math.floor(YEAR / avgBlockTime)) 30 | const roiPerYear = roiPerBlock.multiply(blocksPerYear) 31 | return parseFloat(roiPerYear.toExact()) 32 | } 33 | 34 | /** 35 | * Get APY for a Farm 36 | * @param rewardPrice Price of STG 37 | * @param stgPerBlock STG Reward per block 38 | * @param allocPoint Weight of the pool 39 | * @param totalAllocPoint Total weights of all pools in the contract 40 | * @param avgBlockTime Average block time 41 | * @param totalLiquidity Total liquidity deposited in Pool 42 | * @param totalFarmLp Total LP in the Farm 43 | * @param totalPoolLp Total LP in the Pool 44 | * @returns APY 45 | */ 46 | export function getFarmApy( 47 | rewardPrice: CurrencyAmount, 48 | stgPerBlock: CurrencyAmount, 49 | allocPoint: number, 50 | totalAllocPoint: number, 51 | avgBlockTime: number, 52 | totalLiquidity: CurrencyAmount, 53 | totalFarmLp: CurrencyAmount, 54 | totalPoolLp: CurrencyAmount 55 | ) { 56 | const apr = getFarmApr(rewardPrice, stgPerBlock, allocPoint, totalAllocPoint, avgBlockTime, totalLiquidity, totalFarmLp, totalPoolLp) 57 | const apy = Math.E ** apr - 1 58 | return apy 59 | } 60 | 61 | /** 62 | * Get APR for a Farm 63 | * @param rewardPrice Price of STG 64 | * @param stgPerBlock STG Reward per block 65 | * @param allocPoint Weight of the pool 66 | * @param totalAllocPoint Total weights of all pools in the contract 67 | * @param avgBlockTime Average block time 68 | * @param totalLiquidity Total liquidity deposited in Pool 69 | * @param totalFarmLp Total LP in the Farm 70 | * @param totalPoolLp Total LP in the Pool 71 | * @param tokenPrice Token Price in USD 72 | * @returns APR 73 | */ 74 | export function getTokenFarmApr( 75 | rewardPrice: CurrencyAmount, 76 | stgPerBlock: CurrencyAmount, 77 | allocPoint: number, 78 | totalAllocPoint: number, 79 | avgBlockTime: number, 80 | totalLiquidity: CurrencyAmount, 81 | totalFarmLp: CurrencyAmount, 82 | totalPoolLp: CurrencyAmount, 83 | tokenPrice: CurrencyAmount 84 | ) { 85 | const rewardPerBlock = stgPerBlock.multiply(new Percent(allocPoint * 10000, totalAllocPoint * 10000)) 86 | const tvl = totalLiquidity.multiply(totalFarmLp).divide(totalPoolLp) 87 | const blocksPerYear = BigInt(Math.floor(YEAR / avgBlockTime)) 88 | const tvlUsd = tvl.multiply(tokenPrice) 89 | const roiPerBlockUsd = rewardPerBlock.multiply(rewardPrice).divide(tvlUsd) 90 | const roiPerYear = roiPerBlockUsd.multiply(blocksPerYear) 91 | return parseFloat(roiPerYear.toExact()) 92 | } 93 | 94 | /** 95 | * Get APY for a Farm 96 | * @param rewardPrice Price of STG 97 | * @param stgPerBlock STG Reward per block 98 | * @param allocPoint Weight of the pool 99 | * @param totalAllocPoint Total weights of all pools in the contract 100 | * @param avgBlockTime Average block time 101 | * @param totalLiquidity Total liquidity deposited in Pool 102 | * @param totalFarmLp Total LP in the Farm 103 | * @param totalPoolLp Total LP in the Pool 104 | * @returns APY 105 | */ 106 | export function getTokenFarmApy( 107 | rewardPrice: CurrencyAmount, 108 | stgPerBlock: CurrencyAmount, 109 | allocPoint: number, 110 | totalAllocPoint: number, 111 | avgBlockTime: number, 112 | totalLiquidity: CurrencyAmount, 113 | totalFarmLp: CurrencyAmount, 114 | totalPoolLp: CurrencyAmount, 115 | tokenPrice: CurrencyAmount 116 | ) { 117 | const apr = getTokenFarmApr( 118 | rewardPrice, 119 | stgPerBlock, 120 | allocPoint, 121 | totalAllocPoint, 122 | avgBlockTime, 123 | totalLiquidity, 124 | totalFarmLp, 125 | totalPoolLp, 126 | tokenPrice 127 | ) 128 | const apy = Math.E ** apr - 1 129 | return apy 130 | } 131 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/helpers.ts: -------------------------------------------------------------------------------- 1 | import {ChainKey} from "@layerzerolabs/lz-sdk"; 2 | 3 | export function getStargateNetworksForEnv(chainStage: string) { 4 | if(chainStage == 'sandbox'){ 5 | return [ 6 | ChainKey.RINKEBY_SANDBOX, 7 | ChainKey.BSC_TESTNET_SANDBOX, 8 | ChainKey.FUJI_SANDBOX, 9 | ChainKey.MUMBAI_SANDBOX, 10 | ChainKey.ARBITRUM_RINKEBY_SANDBOX, 11 | ChainKey.OPTIMISM_KOVAN_SANDBOX, 12 | ChainKey.FANTOM_TESTNET_SANDBOX 13 | ] 14 | } else if(chainStage == 'testnet'){ 15 | return [ 16 | ChainKey.RINKEBY, 17 | ChainKey.BSC_TESTNET, 18 | ChainKey.FUJI, 19 | ChainKey.MUMBAI, 20 | ChainKey.ARBITRUM_RINKEBY, 21 | ChainKey.OPTIMISM_KOVAN, 22 | ChainKey.FANTOM_TESTNET 23 | ] 24 | } else if(chainStage == 'mainnet'){ 25 | return [ 26 | ChainKey.ETHEREUM, 27 | ChainKey.BSC, 28 | ChainKey.AVALANCHE, 29 | ChainKey.POLYGON, 30 | ChainKey.ARBITRUM, 31 | ChainKey.OPTIMISM, 32 | ChainKey.FANTOM 33 | ] 34 | } else { 35 | throw new Error(`getStargateNetworksForEnv() - invalid environment: ${chainStage}`) 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { validateAndParseAddress } from "./validateAndParseAddress" 2 | export * from "./estimateDstNativeAmt" 3 | export * from "./getFarmApy" 4 | export * from "./helpers" 5 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/invariantHelper.ts: -------------------------------------------------------------------------------- 1 | export function invariant(condition: T | false | undefined | null | "" | 0, message: string): asserts condition is T { 2 | if (!condition) throw new Error(message) 3 | } 4 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/printPoolMesh.js: -------------------------------------------------------------------------------- 1 | const { USDC_ADDRESS, USDT_ADDRESS, BUSD_ADDRESS } = require("../../dist") 2 | const { POOLS, PoolId } = require("../../dist") 3 | const { CHAIN_ID, ChainId, getNetworksForEnv } = require("@layerzerolabs/lz-sdk") 4 | const { getStargateNetworksForEnv } = require("@layerzerolabs/sg-sdk") 5 | const poolIdKeys = Object.keys(PoolId) 6 | 7 | const tokenLinks = { 8 | ethereum: "https://etherscan.io/token/", 9 | bsc: "https://bscscan.com/token/", 10 | avalanche: "https://snowtrace.io/token/", 11 | polygon: "https://polygonscan.com/token/", 12 | arbitrum: "https://arbiscan.io/token/", 13 | optimism: "https://optimistic.etherscan.io/token/", 14 | fantom: "https://ftmscan.com/token/", 15 | } 16 | 17 | function returnNSpaces(n) { 18 | let counter = 0 19 | let returnString = "" 20 | while (counter !== n) { 21 | returnString = returnString + "\xa0" 22 | counter++ 23 | } 24 | return returnString 25 | } 26 | 27 | function getKeyByValue(object, value) { 28 | return Object.keys(object).find((key) => object[key] === value) 29 | } 30 | 31 | function printPoolMesh() { 32 | const networks = getStargateNetworksForEnv('mainnet') 33 | let meshArray = [] 34 | networks.map((network) => { 35 | let counter = 0 36 | poolIdKeys.map((poolId) => { 37 | let mesh = [] 38 | const mapping = POOLS[network][poolId]?.chainPaths 39 | if (mapping === undefined) { 40 | return 41 | } 42 | let tokenUrlString = "" 43 | mapping.map((row) => { 44 | if (tokenUrlString === "") { 45 | if (PoolId[poolId] === "USDC") { 46 | tokenUrlString = USDC_ADDRESS[CHAIN_ID[network]] 47 | } else if (PoolId[poolId] === "USDT") { 48 | tokenUrlString = USDT_ADDRESS[CHAIN_ID[network]] 49 | } else if (PoolId[poolId] === "BUSD") { 50 | tokenUrlString = BUSD_ADDRESS[CHAIN_ID[network]] 51 | } 52 | } 53 | 54 | if (tokenUrlString !== "0x0000000000000000000000000000000000000000") { 55 | if (mesh[`${network.toUpperCase()}-${PoolId[poolId]} -- ${tokenLinks[network]}` + `${tokenUrlString}`] === undefined) { 56 | mesh[`${network.toUpperCase()}-${PoolId[poolId]} -- ${tokenLinks[network]}` + `${tokenUrlString}`] = {} 57 | } 58 | mesh[returnNSpaces(counter)] = { 59 | "Chain-Token": `${getKeyByValue(ChainId, row.dstChainId)}-${getKeyByValue(PoolId, row.dstPoolId)}`, 60 | Weight: row.weight, 61 | } 62 | counter++ 63 | } 64 | }) 65 | if (Object.keys(mesh).length > 0) { 66 | meshArray.push(mesh) 67 | } 68 | }) 69 | }) 70 | meshArray.map((mesh) => { 71 | console.table(mesh) 72 | }) 73 | } 74 | 75 | printPoolMesh() 76 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/validateAndParseAddress.test.ts: -------------------------------------------------------------------------------- 1 | import { validateAndParseAddress } from "./validateAndParseAddress" 2 | import { describe, it, expect } from "vitest" 3 | 4 | describe("#validateAndParseAddress", () => { 5 | it("returns same address if already checksummed", () => { 6 | expect(validateAndParseAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")).toEqual("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f") 7 | }) 8 | 9 | it("returns checksummed address if not checksummed", () => { 10 | expect(validateAndParseAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f".toLowerCase())).toEqual( 11 | "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" 12 | ) 13 | }) 14 | 15 | it("throws if not valid", () => { 16 | expect(() => validateAndParseAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6")).toThrow( 17 | "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6 is not a valid address." 18 | ) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /packages/sg-sdk/src/utils/validateAndParseAddress.ts: -------------------------------------------------------------------------------- 1 | import { getAddress } from "@ethersproject/address" 2 | 3 | /** 4 | * Validates an address and returns the parsed (checksummed) version of that address 5 | * @param address the unchecksummed hex address 6 | */ 7 | export function validateAndParseAddress(address: string): string { 8 | try { 9 | return getAddress(address) 10 | } catch (error) { 11 | throw new Error(`${address} is not a valid address.`) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/sg-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "rootDir": "src", 6 | "target": "es2018", 7 | "module": "esnext", 8 | "importHelpers": true, 9 | "declaration": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictPropertyInitialization": true, 16 | "noImplicitThis": true, 17 | "alwaysStrict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "moduleResolution": "node", 23 | "esModuleInterop": true, 24 | "resolveJsonModule": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/sg-sdk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, getDefaultConfig } from "@layerzerolabs/tsup-config" 2 | 3 | export default defineConfig({ 4 | ...getDefaultConfig(), 5 | entry: ["src/index.ts"], 6 | }) 7 | --------------------------------------------------------------------------------