├── .eslintignore ├── .husky ├── .gitignore └── pre-commit ├── dist ├── validator.test.d.ts ├── util │ ├── asset │ │ ├── assetUtils.test.d.ts │ │ ├── assetConstants.d.ts │ │ ├── assetModels.d.ts │ │ └── assetUtils.d.ts │ ├── typeUtils.d.ts │ ├── error │ │ ├── NonExistentPoolError.d.ts │ │ ├── NoAvailablePoolOrRouteError.d.ts │ │ ├── OutputAmountExceedsAvailableLiquidityError.d.ts │ │ ├── TinymanError.d.ts │ │ ├── SwapError.d.ts │ │ └── SwapQuoteError.d.ts │ ├── account │ │ ├── accountConstants.d.ts │ │ ├── accountTypes.d.ts │ │ └── accountUtils.d.ts │ ├── client │ │ └── base │ │ │ ├── types.d.ts │ │ │ ├── constants.d.ts │ │ │ ├── utils.d.ts │ │ │ ├── appClient.d.ts │ │ │ ├── nullableBaseClient.d.ts │ │ │ └── baseClient.d.ts │ ├── pool │ │ ├── poolConstants.d.ts │ │ ├── v2 │ │ │ └── index.d.ts │ │ ├── v1_1 │ │ │ └── index.d.ts │ │ ├── poolTypes.d.ts │ │ └── common │ │ │ └── index.d.ts │ ├── commonTypes.d.ts │ ├── constant.d.ts │ └── transaction │ │ └── transactionUtils.d.ts ├── liquid-stake │ ├── tAlgoClient.test.d.ts │ ├── constants.d.ts │ ├── stAlgoClient.d.ts │ └── tAlgoClient.d.ts ├── swap │ ├── v1_1 │ │ ├── constants.d.ts │ │ └── utils.d.ts │ ├── v2 │ │ ├── router │ │ │ ├── index.d.ts │ │ │ ├── types.d.ts │ │ │ ├── client.d.ts │ │ │ ├── constants.d.ts │ │ │ ├── swap-router.d.ts │ │ │ └── util.d.ts │ │ ├── util.d.ts │ │ └── constants.d.ts │ ├── constants.d.ts │ ├── utils.d.ts │ └── common │ │ └── utils.d.ts ├── governance │ ├── types.d.ts │ ├── util │ │ └── utils.d.ts │ ├── proposal-voting │ │ ├── types.d.ts │ │ ├── constants.d.ts │ │ ├── transactions.d.ts │ │ └── storage.d.ts │ ├── vault │ │ ├── utils.d.ts │ │ ├── constants.d.ts │ │ └── transactions.d.ts │ ├── transactions.d.ts │ ├── staking-voting │ │ ├── constants.d.ts │ │ ├── transactions.d.ts │ │ └── storage.d.ts │ ├── rewards │ │ ├── constants.d.ts │ │ ├── transactions.d.ts │ │ └── storage.d.ts │ ├── constants.d.ts │ └── utils.d.ts ├── contract │ ├── constants.d.ts │ ├── types.d.ts │ ├── index.d.ts │ ├── v2 │ │ ├── types.d.ts │ │ └── contract.d.ts │ ├── v1_1 │ │ ├── types.d.ts │ │ └── contract.d.ts │ └── base │ │ └── contract.d.ts ├── add-liquidity │ ├── v2 │ │ ├── index.d.ts │ │ ├── constants.d.ts │ │ ├── common.d.ts │ │ ├── initial.d.ts │ │ ├── with-single-asset.d.ts │ │ ├── flexible.d.ts │ │ ├── util.d.ts │ │ └── types.d.ts │ ├── v1_1 │ │ ├── util.d.ts │ │ ├── constants.d.ts │ │ ├── types.d.ts │ │ └── index.d.ts │ ├── index.d.ts │ ├── constants.d.ts │ └── util.d.ts ├── bootstrap │ ├── common │ │ └── utils.d.ts │ ├── v2 │ │ ├── constants.d.ts │ │ └── index.d.ts │ ├── v1_1 │ │ ├── constants.d.ts │ │ └── index.d.ts │ └── utils.d.ts ├── remove-liquidity │ ├── v2 │ │ ├── constants.d.ts │ │ ├── types.d.ts │ │ └── index.d.ts │ └── v1_1 │ │ ├── constants.d.ts │ │ ├── index.d.ts │ │ └── types.d.ts ├── order │ ├── utils.d.ts │ ├── types.d.ts │ └── constants.d.ts ├── folks-lending-pools │ ├── add-liquidity │ │ ├── utils.d.ts │ │ └── index.d.ts │ ├── types.d.ts │ ├── constants.d.ts │ ├── utils.d.ts │ ├── remove-liquidity │ │ └── index.d.ts │ └── index.d.ts ├── config.d.ts ├── stake.d.ts ├── validator.d.ts └── redeem.d.ts ├── src ├── util │ ├── typeUtils.ts │ ├── account │ │ ├── accountConstants.ts │ │ └── accountTypes.ts │ ├── client │ │ └── base │ │ │ ├── types.ts │ │ │ └── constants.ts │ ├── pool │ │ ├── index.ts │ │ ├── poolConstants.ts │ │ ├── poolTypes.ts │ │ └── common │ │ │ └── index.ts │ ├── commonTypes.ts │ ├── asset │ │ ├── assetModels.ts │ │ ├── assetConstants.ts │ │ ├── assetUtils.test.ts │ │ └── assetUtils.ts │ ├── error │ │ └── SwapQuoteError.ts │ └── constant.ts ├── swap │ ├── v1_1 │ │ ├── constants.ts │ │ └── utils.ts │ ├── v2 │ │ ├── router │ │ │ ├── index.ts │ │ │ ├── constants.ts │ │ │ └── util.ts │ │ ├── constants.ts │ │ └── util.ts │ ├── constants.ts │ └── index.ts ├── governance │ ├── types.ts │ ├── proposal-voting │ │ ├── types.ts │ │ └── constants.ts │ ├── util │ │ └── utils.ts │ ├── rewards │ │ └── constants.ts │ ├── staking-voting │ │ └── constants.ts │ ├── vault │ │ ├── utils.ts │ │ └── constants.ts │ ├── transactions.ts │ └── constants.ts ├── contract │ ├── constants.ts │ ├── types.ts │ ├── v2 │ │ ├── types.ts │ │ ├── asc.json │ │ └── contract.ts │ ├── index.ts │ ├── v1_1 │ │ ├── types.ts │ │ └── asc.json │ └── base │ │ └── contract.ts ├── add-liquidity │ ├── v2 │ │ ├── index.ts │ │ ├── constants.ts │ │ ├── types.ts │ │ └── common.ts │ ├── v1_1 │ │ ├── constants.ts │ │ ├── util.ts │ │ └── types.ts │ ├── index.ts │ ├── constants.ts │ └── util.ts ├── remove-liquidity │ ├── index.ts │ ├── v1_1 │ │ ├── constants.ts │ │ └── types.ts │ └── v2 │ │ ├── constants.ts │ │ └── types.ts ├── bootstrap │ ├── v2 │ │ └── constants.ts │ ├── index.ts │ ├── v1_1 │ │ └── constants.ts │ ├── common │ │ └── utils.ts │ └── utils.ts ├── folks-lending-pools │ ├── types.ts │ ├── constants.ts │ ├── add-liquidity │ │ └── utils.ts │ └── utils.ts ├── order │ ├── types.ts │ └── utils.ts ├── validator.test.ts ├── config.ts └── liquid-stake │ └── constants.ts ├── examples ├── .gitignore ├── src │ ├── util │ │ ├── client.ts │ │ ├── other.ts │ │ ├── initiatorSigner.ts │ │ └── account.ts │ ├── operation │ │ ├── bootstrap │ │ │ └── bootstrapPool.ts │ │ ├── add-liquidity │ │ │ ├── addInitialLiquidity.ts │ │ │ ├── addFlexibleLiquidity.ts │ │ │ └── addSingleAssetLiquidity.ts │ │ └── remove-liquidity │ │ │ └── removeLiquidity.ts │ └── index.ts ├── tsconfig.json ├── package.json └── README.md ├── babel.config.js ├── .prettierrc.js ├── CONTRIBUTING.md ├── rollup.config.mjs ├── .github └── workflows │ └── new-release.yml ├── LICENSE ├── .eslintrc.js ├── .gitignore └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/**/* -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /dist/validator.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/util/asset/assetUtils.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/liquid-stake/tAlgoClient.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/util/typeUtils.ts: -------------------------------------------------------------------------------- 1 | export type ValueOf = T[keyof T]; 2 | -------------------------------------------------------------------------------- /dist/util/typeUtils.d.ts: -------------------------------------------------------------------------------- 1 | export type ValueOf = T[keyof T]; 2 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | account.json 3 | assets.json -------------------------------------------------------------------------------- /src/swap/v1_1/constants.ts: -------------------------------------------------------------------------------- 1 | export const V1_1_SWAP_TXN_COUNT = 4; 2 | -------------------------------------------------------------------------------- /dist/swap/v1_1/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const V1_1_SWAP_TXN_COUNT = 4; 2 | -------------------------------------------------------------------------------- /dist/swap/v2/router/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./swap-router"; 2 | export * from "./util"; 3 | -------------------------------------------------------------------------------- /src/swap/v2/router/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./swap-router"; 2 | export * from "./util"; 3 | -------------------------------------------------------------------------------- /dist/swap/v1_1/utils.d.ts: -------------------------------------------------------------------------------- 1 | export declare function getV1SwapTotalFee(minTxnFee: bigint): bigint; 2 | -------------------------------------------------------------------------------- /src/governance/types.ts: -------------------------------------------------------------------------------- 1 | export interface RawBoxCacheValue { 2 | [key: string]: Uint8Array; 3 | } 4 | -------------------------------------------------------------------------------- /dist/governance/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface RawBoxCacheValue { 2 | [key: string]: Uint8Array; 3 | } 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | npm run test 4 | npx lint-staged --allow-empty 5 | -------------------------------------------------------------------------------- /src/contract/constants.ts: -------------------------------------------------------------------------------- 1 | export const CONTRACT_VERSION = { 2 | V1_1: "v1_1", 3 | V2: "v2" 4 | } as const; 5 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@babel/preset-env", "@babel/preset-typescript"], 3 | plugins: [] 4 | }; 5 | -------------------------------------------------------------------------------- /dist/contract/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const CONTRACT_VERSION: { 2 | readonly V1_1: "v1_1"; 3 | readonly V2: "v2"; 4 | }; 5 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/index.d.ts: -------------------------------------------------------------------------------- 1 | export * as flexible from "./flexible"; 2 | export * as withSingleAsset from "./with-single-asset"; 3 | export * as initial from "./initial"; 4 | -------------------------------------------------------------------------------- /src/add-liquidity/v2/index.ts: -------------------------------------------------------------------------------- 1 | export * as flexible from "./flexible"; 2 | export * as withSingleAsset from "./with-single-asset"; 3 | export * as initial from "./initial"; 4 | -------------------------------------------------------------------------------- /src/swap/constants.ts: -------------------------------------------------------------------------------- 1 | export enum SwapType { 2 | FixedInput = "fixed-input", 3 | FixedOutput = "fixed-output" 4 | } 5 | 6 | export const DEFAULT_SWAP_FEE_RATE = 0.003; 7 | -------------------------------------------------------------------------------- /dist/util/error/NonExistentPoolError.d.ts: -------------------------------------------------------------------------------- 1 | declare class NonExistentPoolError extends Error { 2 | constructor(message?: string); 3 | } 4 | export default NonExistentPoolError; 5 | -------------------------------------------------------------------------------- /src/util/account/accountConstants.ts: -------------------------------------------------------------------------------- 1 | const EXECUTOR_FALLBACK_ADDRESS = 2 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"; 3 | 4 | export {EXECUTOR_FALLBACK_ADDRESS}; 5 | -------------------------------------------------------------------------------- /dist/add-liquidity/v1_1/util.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @returns the total fee for the add liquidity operation. 3 | */ 4 | export declare function getV1_1AddLiquidityTotalFee(minFee: bigint): bigint; 5 | -------------------------------------------------------------------------------- /dist/util/account/accountConstants.d.ts: -------------------------------------------------------------------------------- 1 | declare const EXECUTOR_FALLBACK_ADDRESS = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"; 2 | export { EXECUTOR_FALLBACK_ADDRESS }; 3 | -------------------------------------------------------------------------------- /dist/contract/types.d.ts: -------------------------------------------------------------------------------- 1 | import { CONTRACT_VERSION } from "./constants"; 2 | import { ValueOf } from "../util/typeUtils"; 3 | export type ContractVersionValue = ValueOf; 4 | -------------------------------------------------------------------------------- /dist/swap/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum SwapType { 2 | FixedInput = "fixed-input", 3 | FixedOutput = "fixed-output" 4 | } 5 | export declare const DEFAULT_SWAP_FEE_RATE = 0.003; 6 | -------------------------------------------------------------------------------- /src/contract/types.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "./constants"; 2 | import {ValueOf} from "../util/typeUtils"; 3 | 4 | export type ContractVersionValue = ValueOf; 5 | -------------------------------------------------------------------------------- /dist/util/error/NoAvailablePoolOrRouteError.d.ts: -------------------------------------------------------------------------------- 1 | declare class NoAvailablePoolOrRouteError extends Error { 2 | constructor(message?: string); 3 | } 4 | export default NoAvailablePoolOrRouteError; 5 | -------------------------------------------------------------------------------- /src/swap/v1_1/utils.ts: -------------------------------------------------------------------------------- 1 | import {V1_1_SWAP_TXN_COUNT} from "./constants"; 2 | 3 | export function getV1SwapTotalFee(minTxnFee: bigint) { 4 | return BigInt(V1_1_SWAP_TXN_COUNT) * minTxnFee; 5 | } 6 | -------------------------------------------------------------------------------- /dist/add-liquidity/index.d.ts: -------------------------------------------------------------------------------- 1 | import * as AddLiquidityV1_1 from "./v1_1"; 2 | import * as AddLiquidityV2 from "./v2"; 3 | export declare const AddLiquidity: { 4 | v1_1: typeof AddLiquidityV1_1; 5 | v2: typeof AddLiquidityV2; 6 | }; 7 | -------------------------------------------------------------------------------- /dist/governance/util/utils.d.ts: -------------------------------------------------------------------------------- 1 | export declare function areBuffersEqual(buf1: Uint8Array, buf2: Uint8Array): boolean; 2 | export declare function bytesToInt(buffer: Uint8Array): number; 3 | export declare function sum(values: number[]): number; 4 | -------------------------------------------------------------------------------- /dist/util/error/OutputAmountExceedsAvailableLiquidityError.d.ts: -------------------------------------------------------------------------------- 1 | declare class OutputAmountExceedsAvailableLiquidityError extends Error { 2 | constructor(message?: string); 3 | } 4 | export default OutputAmountExceedsAvailableLiquidityError; 5 | -------------------------------------------------------------------------------- /src/add-liquidity/v1_1/constants.ts: -------------------------------------------------------------------------------- 1 | export enum V1_1AddLiquidityTxnIndices { 2 | FEE_TXN = 0, 3 | VALIDATOR_APP_CALL_TXN, 4 | ASSET1_IN_TXN, 5 | ASSET2_IN_TXN, 6 | LIQUDITY_OUT_TXN 7 | } 8 | 9 | export const V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT = 5; 10 | -------------------------------------------------------------------------------- /dist/governance/proposal-voting/types.d.ts: -------------------------------------------------------------------------------- 1 | interface GenerateProposalMetadataPayload { 2 | title: string; 3 | description: string; 4 | category: string; 5 | discussionUrl: string; 6 | pollUrl: string; 7 | } 8 | export type { GenerateProposalMetadataPayload }; 9 | -------------------------------------------------------------------------------- /src/governance/proposal-voting/types.ts: -------------------------------------------------------------------------------- 1 | interface GenerateProposalMetadataPayload { 2 | title: string; 3 | description: string; 4 | category: string; 5 | discussionUrl: string; 6 | pollUrl: string; 7 | } 8 | 9 | export type {GenerateProposalMetadataPayload}; 10 | -------------------------------------------------------------------------------- /dist/add-liquidity/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const ADD_LIQUIDITY_APP_CALL_ARGUMENTS: { 2 | v1_1: Uint8Array[]; 3 | v2: { 4 | INITIAL_LIQUIDITY: Uint8Array[]; 5 | SINGLE_ASSET_MODE: Uint8Array[]; 6 | FLEXIBLE_MODE: Uint8Array[]; 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /dist/bootstrap/common/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { ContractVersionValue } from "../../contract/types"; 2 | /** 3 | * @returns Minimum balance for a pool account 4 | */ 5 | export declare function getPoolAccountMinBalance(contractVersion: ContractVersionValue, isAlgoPool: boolean): bigint; 6 | -------------------------------------------------------------------------------- /dist/util/client/base/types.d.ts: -------------------------------------------------------------------------------- 1 | type StructField = { 2 | type: string; 3 | size: number; 4 | offset: number; 5 | }; 6 | type StructDefinition = { 7 | size: number; 8 | fields: Record; 9 | }; 10 | export type { StructField, StructDefinition }; 11 | -------------------------------------------------------------------------------- /src/util/client/base/types.ts: -------------------------------------------------------------------------------- 1 | type StructField = { 2 | type: string; 3 | size: number; 4 | offset: number; 5 | }; 6 | 7 | type StructDefinition = { 8 | size: number; 9 | fields: Record; 10 | }; 11 | 12 | export type {StructField, StructDefinition}; 13 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v2/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const V2_REMOVE_LIQUIDITY_APP_CALL_INNER_TXN_COUNT = 2; 2 | export declare const V2_REMOVE_LIQUIDITY_APP_ARGUMENT: Uint8Array; 3 | export declare enum V2RemoveLiquidityTxnIndices { 4 | ASSET_TRANSFER_TXN = 0, 5 | APP_CALL_TXN = 1 6 | } 7 | -------------------------------------------------------------------------------- /dist/add-liquidity/v1_1/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V1_1AddLiquidityTxnIndices { 2 | FEE_TXN = 0, 3 | VALIDATOR_APP_CALL_TXN = 1, 4 | ASSET1_IN_TXN = 2, 5 | ASSET2_IN_TXN = 3, 6 | LIQUDITY_OUT_TXN = 4 7 | } 8 | export declare const V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT = 5; 9 | -------------------------------------------------------------------------------- /src/util/account/accountTypes.ts: -------------------------------------------------------------------------------- 1 | export interface AccountExcessWithinPool { 2 | excessAsset1: bigint; 3 | excessAsset2: bigint; 4 | excessPoolTokens: bigint; 5 | } 6 | 7 | export interface AccountExcess { 8 | poolAddress: string; 9 | assetID: number; 10 | amount: bigint; 11 | } 12 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 90, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | singleQuote: false, 7 | jsxSingleQuote: false, 8 | trailingComma: "none", 9 | bracketSpacing: false, 10 | jsxBracketSameLine: true, 11 | arrowParens: "always" 12 | }; 13 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v1_1/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V1_1RemoveLiquidityTxnIndices { 2 | FEE_TXN = 0, 3 | VALIDATOR_APP_CALL_TXN = 1, 4 | ASSET1_OUT_TXN = 2, 5 | ASSET2_OUT_TXN = 3, 6 | POOL_TOKEN_IN_TXN = 4 7 | } 8 | export declare const V1_1_REMOVE_LIQUIDITY_TXN_COUNT: number; 9 | -------------------------------------------------------------------------------- /dist/util/account/accountTypes.d.ts: -------------------------------------------------------------------------------- 1 | export interface AccountExcessWithinPool { 2 | excessAsset1: bigint; 3 | excessAsset2: bigint; 4 | excessPoolTokens: bigint; 5 | } 6 | export interface AccountExcess { 7 | poolAddress: string; 8 | assetID: number; 9 | amount: bigint; 10 | } 11 | -------------------------------------------------------------------------------- /src/add-liquidity/index.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "../contract/constants"; 2 | import * as AddLiquidityV1_1 from "./v1_1"; 3 | import * as AddLiquidityV2 from "./v2"; 4 | 5 | export const AddLiquidity = { 6 | [CONTRACT_VERSION.V1_1]: AddLiquidityV1_1, 7 | [CONTRACT_VERSION.V2]: AddLiquidityV2 8 | }; 9 | -------------------------------------------------------------------------------- /src/add-liquidity/v1_1/util.ts: -------------------------------------------------------------------------------- 1 | import {V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT} from "./constants"; 2 | 3 | /** 4 | * @returns the total fee for the add liquidity operation. 5 | */ 6 | export function getV1_1AddLiquidityTotalFee(minFee: bigint) { 7 | return BigInt(V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT) * minFee; 8 | } 9 | -------------------------------------------------------------------------------- /src/remove-liquidity/index.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "../contract/constants"; 2 | import {RemoveLiquidityV1_1} from "./v1_1"; 3 | import {RemoveLiquidityV2} from "./v2"; 4 | 5 | export const RemoveLiquidity = { 6 | [CONTRACT_VERSION.V1_1]: RemoveLiquidityV1_1, 7 | [CONTRACT_VERSION.V2]: RemoveLiquidityV2 8 | }; 9 | -------------------------------------------------------------------------------- /src/bootstrap/v2/constants.ts: -------------------------------------------------------------------------------- 1 | export enum V2BootstrapTxnGroupIndices { 2 | FUNDING_TXN = 0, 3 | VALIDATOR_APP_CALL 4 | } 5 | 6 | /** 7 | * Inner txn counts according to the pool type (ASA-ALGO or ASA-ASA) 8 | */ 9 | export const V2_BOOTSTRAP_INNER_TXN_COUNT = { 10 | ASA_ALGO: 5, 11 | ASA_ASA: 6 12 | } as const; 13 | -------------------------------------------------------------------------------- /src/remove-liquidity/v1_1/constants.ts: -------------------------------------------------------------------------------- 1 | export enum V1_1RemoveLiquidityTxnIndices { 2 | FEE_TXN = 0, 3 | VALIDATOR_APP_CALL_TXN, 4 | ASSET1_OUT_TXN, 5 | ASSET2_OUT_TXN, 6 | POOL_TOKEN_IN_TXN 7 | } 8 | 9 | export const V1_1_REMOVE_LIQUIDITY_TXN_COUNT = Object.values( 10 | V1_1RemoveLiquidityTxnIndices 11 | ).length; 12 | -------------------------------------------------------------------------------- /dist/contract/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ContractVersionValue } from "./types"; 2 | export declare function getIsV2ContractVersion(contractVersion: ContractVersionValue): boolean; 3 | export declare function getContract(contractVersion: ContractVersionValue): import("./v1_1/contract").TinymanContractV1_1 | import("./v2/contract").TinymanContractV2; 4 | -------------------------------------------------------------------------------- /dist/order/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare function createPaddedByteArray(elements: number[], length?: number, paddingValue?: number, byteSize?: number): Uint8Array; 2 | declare function getCompiledPrograms(): Promise<{ 3 | approvalProgram: Uint8Array; 4 | clearProgram: Uint8Array; 5 | }>; 6 | export { createPaddedByteArray, getCompiledPrograms }; 7 | -------------------------------------------------------------------------------- /src/remove-liquidity/v2/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | 3 | export const V2_REMOVE_LIQUIDITY_APP_CALL_INNER_TXN_COUNT = 2; 4 | export const V2_REMOVE_LIQUIDITY_APP_ARGUMENT = encodeString("remove_liquidity"); 5 | export enum V2RemoveLiquidityTxnIndices { 6 | ASSET_TRANSFER_TXN = 0, 7 | APP_CALL_TXN 8 | } 9 | -------------------------------------------------------------------------------- /examples/src/util/client.ts: -------------------------------------------------------------------------------- 1 | import algosdk from "algosdk"; 2 | 3 | console.log( 4 | "ℹ️ The examples uses the testnet AlgoExplorer API for testing purposes. You can change it in `client.ts` file.\n" 5 | ); 6 | export const algodClient = new algosdk.Algodv2( 7 | "", 8 | "https://node.testnet.algoexplorerapi.io/", 9 | "" 10 | ); 11 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/add-liquidity/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SupportedNetwork } from "../../util/commonTypes"; 3 | export declare function getFolksWrapperAppOptInRequiredAssetIDs({ client, network, assetIDs }: { 4 | client: Algodv2; 5 | network: SupportedNetwork; 6 | assetIDs: number[]; 7 | }): Promise; 8 | -------------------------------------------------------------------------------- /dist/governance/vault/utils.d.ts: -------------------------------------------------------------------------------- 1 | declare function getStartTimestampOfWeek(timestamp: number, isFloor?: boolean): number; 2 | declare function getNewTotalPowerTimestamps(oldTimeStamp: number, newTimeStamp: number): number[]; 3 | declare function getSlope(lockedAmount: number): number; 4 | export { getNewTotalPowerTimestamps, getStartTimestampOfWeek, getSlope }; 5 | -------------------------------------------------------------------------------- /examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "commonjs", 5 | "lib": ["es6"], 6 | "allowJs": true, 7 | "outDir": "build", 8 | "rootDir": "src", 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dist/bootstrap/v2/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V2BootstrapTxnGroupIndices { 2 | FUNDING_TXN = 0, 3 | VALIDATOR_APP_CALL = 1 4 | } 5 | /** 6 | * Inner txn counts according to the pool type (ASA-ALGO or ASA-ASA) 7 | */ 8 | export declare const V2_BOOTSTRAP_INNER_TXN_COUNT: { 9 | readonly ASA_ALGO: 5; 10 | readonly ASA_ASA: 6; 11 | }; 12 | -------------------------------------------------------------------------------- /src/swap/index.ts: -------------------------------------------------------------------------------- 1 | import {SwapV1_1} from "./v1_1"; 2 | import {SwapV2} from "./v2"; 3 | import {execute, generateTxns, getQuote, signTxns} from "./utils"; 4 | import {CONTRACT_VERSION} from "../contract/constants"; 5 | 6 | export const Swap = { 7 | [CONTRACT_VERSION.V1_1]: SwapV1_1, 8 | [CONTRACT_VERSION.V2]: SwapV2, 9 | getQuote, 10 | generateTxns, 11 | signTxns, 12 | execute 13 | }; 14 | -------------------------------------------------------------------------------- /src/folks-lending-pools/types.ts: -------------------------------------------------------------------------------- 1 | import {AssetWithIdAndAmount} from "../util/asset/assetModels"; 2 | 3 | export type FolksLendingAssetInfo = AssetWithIdAndAmount & { 4 | fAssetId: number; 5 | lendingAppId: number; 6 | }; 7 | 8 | export interface FolksLendingPool { 9 | appId: number; 10 | managerAppId: number; 11 | depositInterestRate: bigint; 12 | depositInterestIndex: bigint; 13 | lastUpdate: number; 14 | } 15 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/types.d.ts: -------------------------------------------------------------------------------- 1 | import { AssetWithIdAndAmount } from "../util/asset/assetModels"; 2 | export type FolksLendingAssetInfo = AssetWithIdAndAmount & { 3 | fAssetId: number; 4 | lendingAppId: number; 5 | }; 6 | export interface FolksLendingPool { 7 | appId: number; 8 | managerAppId: number; 9 | depositInterestRate: bigint; 10 | depositInterestIndex: bigint; 11 | lastUpdate: number; 12 | } 13 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/constants.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "../util/commonTypes"; 2 | declare const SECONDS_IN_YEAR: bigint; 3 | declare const ONE_14_DP: bigint; 4 | declare const ONE_16_DP: bigint; 5 | declare const FOLKS_WRAPPER_APP_ID: Record; 6 | declare const FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT = 14; 7 | export { SECONDS_IN_YEAR, ONE_14_DP, ONE_16_DP, FOLKS_WRAPPER_APP_ID, FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT }; 8 | -------------------------------------------------------------------------------- /src/contract/v2/types.ts: -------------------------------------------------------------------------------- 1 | export interface V2ValidatorApp { 2 | type: string; 3 | global_state_schema: V2ValidatorAppStateSchema; 4 | local_state_schema: V2ValidatorAppStateSchema; 5 | name: string; 6 | } 7 | 8 | interface V2ValidatorAppStateSchema { 9 | num_uints: number; 10 | num_byte_slices: number; 11 | } 12 | 13 | export interface V2PoolLogicSig { 14 | type: string; 15 | logic: { 16 | bytecode: string; 17 | }; 18 | name: string; 19 | } 20 | -------------------------------------------------------------------------------- /dist/governance/transactions.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { SuggestedParams } from "algosdk"; 2 | declare function prepareBudgetIncreaseTxn({ sender, index, suggestedParams, boxes, extraAppArgs, foreignApps }: { 3 | sender: string; 4 | index: number; 5 | suggestedParams: SuggestedParams; 6 | extraAppArgs?: Uint8Array[]; 7 | foreignApps?: number[]; 8 | boxes?: algosdk.BoxReference[]; 9 | }): algosdk.Transaction; 10 | export { prepareBudgetIncreaseTxn }; 11 | -------------------------------------------------------------------------------- /examples/src/util/other.ts: -------------------------------------------------------------------------------- 1 | import { algodClient } from "./client"; 2 | 3 | /** 4 | * Throws and error if account has no balance 5 | */ 6 | export async function assertAccountHasBalance(address: string) { 7 | const accountInfo = await algodClient.accountInformation(address).do(); 8 | if (!accountInfo["amount"]) { 9 | throw new Error( 10 | `Go to https://bank.testnet.algorand.network/?account=${address} and fund your account.` 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/util/pool/index.ts: -------------------------------------------------------------------------------- 1 | import * as V1_1PoolUtils from "./v1_1"; 2 | import * as V2PoolUtils from "./v2"; 3 | import * as commonPoolUtils from "./common"; 4 | import {CONTRACT_VERSION} from "../../contract/constants"; 5 | 6 | export const poolUtils = { 7 | [CONTRACT_VERSION.V1_1]: { 8 | ...V1_1PoolUtils, 9 | ...commonPoolUtils 10 | }, 11 | [CONTRACT_VERSION.V2]: { 12 | ...V2PoolUtils, 13 | ...commonPoolUtils 14 | }, 15 | ...commonPoolUtils 16 | }; 17 | -------------------------------------------------------------------------------- /dist/contract/v2/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface V2ValidatorApp { 2 | type: string; 3 | global_state_schema: V2ValidatorAppStateSchema; 4 | local_state_schema: V2ValidatorAppStateSchema; 5 | name: string; 6 | } 7 | interface V2ValidatorAppStateSchema { 8 | num_uints: number; 9 | num_byte_slices: number; 10 | } 11 | export interface V2PoolLogicSig { 12 | type: string; 13 | logic: { 14 | bytecode: string; 15 | }; 16 | name: string; 17 | } 18 | export {}; 19 | -------------------------------------------------------------------------------- /src/bootstrap/index.ts: -------------------------------------------------------------------------------- 1 | import {BootstrapV1_1} from "./v1_1"; 2 | import {BootstrapV2} from "./v2"; 3 | import {CONTRACT_VERSION} from "../contract/constants"; 4 | import { 5 | calculateBootstrapFundingTxnAmount, 6 | execute, 7 | generateTxns, 8 | signTxns 9 | } from "./utils"; 10 | 11 | export const Bootstrap = { 12 | [CONTRACT_VERSION.V1_1]: BootstrapV1_1, 13 | [CONTRACT_VERSION.V2]: BootstrapV2, 14 | generateTxns, 15 | signTxns, 16 | execute, 17 | calculateBootstrapFundingTxnAmount 18 | }; 19 | -------------------------------------------------------------------------------- /dist/util/client/base/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const MINIMUM_BALANCE_REQUIREMENT_PER_BOX = 2500; 2 | declare const MINIMUM_BALANCE_REQUIREMENT_PER_BOX_BYTE = 400; 3 | declare const MINIMUM_BALANCE_REQUIREMENT_PER_ACCOUNT = 100000; 4 | declare const MINIMUM_BALANCE_REQUIREMENT_PER_ASSET = 100000; 5 | declare const HTTP_NOT_FOUND_STATUS = 404; 6 | export { MINIMUM_BALANCE_REQUIREMENT_PER_ACCOUNT, MINIMUM_BALANCE_REQUIREMENT_PER_ASSET, MINIMUM_BALANCE_REQUIREMENT_PER_BOX, MINIMUM_BALANCE_REQUIREMENT_PER_BOX_BYTE, HTTP_NOT_FOUND_STATUS }; 7 | -------------------------------------------------------------------------------- /dist/governance/staking-voting/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const STAKING_VOTE_MAX_OPTION_COUNT = 8; 2 | declare const PROPOSAL_BOX_PREFIX: Uint8Array; 3 | declare const STAKING_ATTENDANCE_BOX_PREFIX: Uint8Array; 4 | declare const STAKING_VOTE_BOX_PREFIX: Uint8Array; 5 | declare const STAKING_ATTENDANCE_BOX_COST: number; 6 | declare const STAKING_VOTE_BOX_COST: number; 7 | export { STAKING_VOTE_MAX_OPTION_COUNT, PROPOSAL_BOX_PREFIX, STAKING_ATTENDANCE_BOX_PREFIX, STAKING_VOTE_BOX_PREFIX, STAKING_ATTENDANCE_BOX_COST, STAKING_VOTE_BOX_COST }; 8 | -------------------------------------------------------------------------------- /src/util/client/base/constants.ts: -------------------------------------------------------------------------------- 1 | const MINIMUM_BALANCE_REQUIREMENT_PER_BOX = 2_500; 2 | const MINIMUM_BALANCE_REQUIREMENT_PER_BOX_BYTE = 400; 3 | 4 | const MINIMUM_BALANCE_REQUIREMENT_PER_ACCOUNT = 100_000; 5 | const MINIMUM_BALANCE_REQUIREMENT_PER_ASSET = 100_000; 6 | 7 | const HTTP_NOT_FOUND_STATUS = 404; 8 | 9 | export { 10 | MINIMUM_BALANCE_REQUIREMENT_PER_ACCOUNT, 11 | MINIMUM_BALANCE_REQUIREMENT_PER_ASSET, 12 | MINIMUM_BALANCE_REQUIREMENT_PER_BOX, 13 | MINIMUM_BALANCE_REQUIREMENT_PER_BOX_BYTE, 14 | HTTP_NOT_FOUND_STATUS 15 | }; 16 | -------------------------------------------------------------------------------- /dist/add-liquidity/util.d.ts: -------------------------------------------------------------------------------- 1 | import { CONTRACT_VERSION } from "../contract/constants"; 2 | import { V2AddLiquidityType } from "./v2/constants"; 3 | /** 4 | * @returns the total fee that will be paid by the user 5 | * for the add liquidity transaction with given parameters 6 | */ 7 | declare function getAddLiquidityTotalFee(params: { 8 | minFee: bigint; 9 | } & ({ 10 | version: typeof CONTRACT_VERSION.V1_1; 11 | } | { 12 | version: typeof CONTRACT_VERSION.V2; 13 | type: V2AddLiquidityType; 14 | })): bigint; 15 | export { getAddLiquidityTotalFee }; 16 | -------------------------------------------------------------------------------- /src/contract/index.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "./constants"; 2 | import {ContractVersionValue} from "./types"; 3 | import {tinymanContract_v1_1} from "./v1_1/contract"; 4 | import {tinymanContract_v2} from "./v2/contract"; 5 | 6 | export function getIsV2ContractVersion(contractVersion: ContractVersionValue) { 7 | return contractVersion === CONTRACT_VERSION.V2; 8 | } 9 | 10 | export function getContract(contractVersion: ContractVersionValue) { 11 | return getIsV2ContractVersion(contractVersion) 12 | ? tinymanContract_v2 13 | : tinymanContract_v1_1; 14 | } 15 | -------------------------------------------------------------------------------- /src/folks-lending-pools/constants.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "../util/commonTypes"; 2 | 3 | const SECONDS_IN_YEAR = BigInt(365 * 24 * 60 * 60); 4 | const ONE_14_DP = BigInt(1e14); 5 | const ONE_16_DP = BigInt(1e16); 6 | 7 | const FOLKS_WRAPPER_APP_ID: Record = { 8 | testnet: 548587153, 9 | mainnet: 1385499515 10 | }; 11 | 12 | const FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT = 14; 13 | 14 | export { 15 | SECONDS_IN_YEAR, 16 | ONE_14_DP, 17 | ONE_16_DP, 18 | FOLKS_WRAPPER_APP_ID, 19 | FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT 20 | }; 21 | -------------------------------------------------------------------------------- /dist/governance/rewards/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const REWARD_PERIOD_BOX_PREFIX: Uint8Array; 2 | declare const REWARD_CLAIM_SHEET_BOX_SIZE = 1012; 3 | declare const REWARD_CLAIM_SHEET_BOX_PREFIX: Uint8Array; 4 | declare const REWARD_PERIOD_SIZE = 24; 5 | declare const REWARD_PERIOD_BOX_SIZE = 1008; 6 | declare const REWARD_PERIOD_BOX_ARRAY_LEN = 42; 7 | declare const REWARD_CLAIM_SHEET_BOX_COST: number; 8 | export { REWARD_CLAIM_SHEET_BOX_PREFIX, REWARD_PERIOD_BOX_PREFIX, REWARD_CLAIM_SHEET_BOX_SIZE, REWARD_PERIOD_SIZE, REWARD_PERIOD_BOX_ARRAY_LEN, REWARD_PERIOD_BOX_SIZE, REWARD_CLAIM_SHEET_BOX_COST }; 9 | -------------------------------------------------------------------------------- /dist/util/asset/assetConstants.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "../commonTypes"; 2 | import { TinymanAnalyticsApiAsset } from "./assetModels"; 3 | export declare const ALGO_ASSET_ID = 0; 4 | export declare const ALGO_ASSET: TinymanAnalyticsApiAsset; 5 | export declare const POOL_TOKEN_UNIT_NAME: { 6 | V1: string; 7 | V1_1: string; 8 | V2: string; 9 | }; 10 | export declare const TINY_ASSET_ID: Record; 11 | export declare const TALGO_ASSET_ID: Record; 12 | export declare const STALGO_ASSET_ID: Record; 13 | -------------------------------------------------------------------------------- /src/add-liquidity/constants.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "../contract/constants"; 2 | import {encodeString} from "../util/util"; 3 | 4 | const ADD_LIQUIDITY_APP_ARG_ENCODED = encodeString("add_liquidity"); 5 | 6 | export const ADD_LIQUIDITY_APP_CALL_ARGUMENTS = { 7 | [CONTRACT_VERSION.V1_1]: [encodeString("mint")], 8 | [CONTRACT_VERSION.V2]: { 9 | INITIAL_LIQUIDITY: [encodeString("add_initial_liquidity")], 10 | SINGLE_ASSET_MODE: [ADD_LIQUIDITY_APP_ARG_ENCODED, encodeString("single")], 11 | FLEXIBLE_MODE: [ADD_LIQUIDITY_APP_ARG_ENCODED, encodeString("flexible")] 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /dist/config.d.ts: -------------------------------------------------------------------------------- 1 | import { ContractVersionValue } from "./contract/types"; 2 | declare class TinymanJSSDKConfig { 3 | /** Identifier name of the SDK user */ 4 | clientName: string; 5 | constructor(); 6 | getClientName(): string; 7 | setClientName(name: string): void; 8 | /** 9 | * @returns {Uint8Array} - encoded note includings version with client name 10 | */ 11 | getAppCallTxnNoteWithClientName(contractVersion: ContractVersionValue, extraData?: Record): Uint8Array; 12 | } 13 | export declare const tinymanJSSDKConfig: TinymanJSSDKConfig; 14 | export {}; 15 | -------------------------------------------------------------------------------- /src/governance/util/utils.ts: -------------------------------------------------------------------------------- 1 | export function areBuffersEqual(buf1: Uint8Array, buf2: Uint8Array) { 2 | return Buffer.compare(buf1, buf2) === 0; 3 | } 4 | 5 | export function bytesToInt(buffer: Uint8Array): number { 6 | let num = 0n; 7 | 8 | for (let i = 0; i < buffer.byteLength; i++) { 9 | const byte = buffer[i]; 10 | 11 | num *= BigInt(0x100); 12 | num += BigInt(byte); 13 | } 14 | 15 | return Number(num); 16 | } 17 | 18 | export function sum(values: number[]): number { 19 | return values.reduce((total, value) => total + value, 0); 20 | } 21 | 22 | /* eslint-enable no-bitwise */ 23 | -------------------------------------------------------------------------------- /dist/swap/v2/router/types.d.ts: -------------------------------------------------------------------------------- 1 | import AlgodClient from "algosdk/dist/types/src/client/v2/algod/algod"; 2 | import { AssetWithIdAndAmount } from "../../../util/asset/assetModels"; 3 | import { SupportedNetwork } from "../../../util/commonTypes"; 4 | import { SwapType } from "../../constants"; 5 | export interface GenerateSwapRouterTxnsParams { 6 | client: AlgodClient; 7 | routerAppID: number; 8 | initiatorAddr: string; 9 | assetIn: AssetWithIdAndAmount; 10 | assetOut: AssetWithIdAndAmount; 11 | intermediaryAssetID: number; 12 | swapType: SwapType; 13 | network: SupportedNetwork; 14 | } 15 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tinyman-js-sdk-examples", 3 | "version": "1.0.0", 4 | "description": "Examples for Tinyman JS SDK", 5 | "main": "./src/index.ts", 6 | "scripts": { 7 | "start": "ts-node ./src/index.ts" 8 | }, 9 | "author": "Tinyman Core Team", 10 | "license": "ISC", 11 | "dependencies": { 12 | "algosdk": "^3.3.0", 13 | "@tinymanorg/tinyman-js-sdk": "github:tinymanorg/tinyman-js-sdk#63cc668726f515564a6d237f113cad617c63870e" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^18.8.5", 17 | "ts-node": "^10.9.1", 18 | "typescript": "^4.8.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /dist/swap/v2/router/client.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { Algodv2 } from "algosdk"; 2 | import TinymanBaseClient from "../../../util/client/base/baseClient"; 3 | import { SupportedNetwork } from "../../../util/commonTypes"; 4 | declare class SwapRouterClient extends TinymanBaseClient { 5 | ammAppId: number; 6 | talgoAppId: number; 7 | tAlgoAssetId: number; 8 | constructor(algod: Algodv2, network: SupportedNetwork); 9 | swap(userAddress: string, inputAmount: number, outputAmount: number, route: number[], pools: string[]): Promise; 10 | private generateGroupedReferences; 11 | } 12 | export default SwapRouterClient; 13 | -------------------------------------------------------------------------------- /dist/util/error/TinymanError.d.ts: -------------------------------------------------------------------------------- 1 | type TinymanErrorType = "LogicError" | "SlippageTolerance" | "TransactionError" | "ExceedingExcessAmountCount" | "Unknown"; 2 | declare class TinymanError extends Error { 3 | data: any; 4 | type: TinymanErrorType; 5 | constructor(data: any, defaultMessage: string, ...args: any[]); 6 | setMessage(message: string): void; 7 | getErrorType(algoSDKMessage: string): TinymanErrorType; 8 | getErrorMessage(algoSDKMessage: string, type: TinymanErrorType, defaultMessage: string): any; 9 | extractMessageFromAlgoSDKError(data: any): string; 10 | private isMessageObjectString; 11 | } 12 | export default TinymanError; 13 | -------------------------------------------------------------------------------- /src/contract/v2/asc.json: -------------------------------------------------------------------------------- 1 | { 2 | "repo": "https://github.com/tinymanorg/tinyman-contracts-v2", 3 | "contracts": { 4 | "pool_logicsig": { 5 | "type": "logicsig", 6 | "logic": { 7 | "bytecode": "BoAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQBbNQA0ADEYEkQxGYEBEkSBAUM=" 8 | }, 9 | "name": "pool_logicsig" 10 | }, 11 | "validator_app": { 12 | "type": "app", 13 | "global_state_schema": { 14 | "num_uints": 0, 15 | "num_byte_slices": 3 16 | }, 17 | "local_state_schema": { 18 | "num_uints": 12, 19 | "num_byte_slices": 2 20 | }, 21 | "name": "validator_app" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/contract/v1_1/types.ts: -------------------------------------------------------------------------------- 1 | export interface V1_1ValidatorApp { 2 | type: string; 3 | global_state_schema: V1_1ValidatorAppStateSchema; 4 | local_state_schema: V1_1ValidatorAppStateSchema; 5 | name: string; 6 | } 7 | 8 | interface V1_1ValidatorAppStateSchema { 9 | num_uints: number; 10 | num_byte_slices: number; 11 | } 12 | 13 | export interface V1_1PoolLogicSig { 14 | type: string; 15 | logic: { 16 | bytecode: string; 17 | address: string; 18 | size: number; 19 | variables: { 20 | name: string; 21 | type: string; 22 | index: number; 23 | length: number; 24 | }[]; 25 | source: string; 26 | }; 27 | name: string; 28 | } 29 | -------------------------------------------------------------------------------- /dist/governance/rewards/transactions.d.ts: -------------------------------------------------------------------------------- 1 | import { SuggestedParams, Transaction } from "algosdk"; 2 | declare function prepareClaimRewardsTransactions({ rewardsAppId, vaultAppId, tinyAssetId, sender, periodIndexStart, periodCount, accountPowerIndexes, suggestedParams, createRewardClaimSheet, appCallNote }: { 3 | rewardsAppId: number; 4 | vaultAppId: number; 5 | tinyAssetId: number; 6 | sender: string; 7 | periodIndexStart: number; 8 | periodCount: number; 9 | accountPowerIndexes: number[]; 10 | suggestedParams: SuggestedParams; 11 | createRewardClaimSheet: boolean; 12 | appCallNote?: string; 13 | }): Transaction[]; 14 | export { prepareClaimRewardsTransactions }; 15 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/utils.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility function for converting the Algorand key-value schema into a plain object. 3 | * 4 | * Algorand store keys in base64 encoding and store values as either bytes or unsigned integers depending 5 | * on the type. This function decodes this information into a more human friendly structure. 6 | * 7 | * @param kv Algorand key-value data structure to parse. 8 | * 9 | * @returns Key value dictionary parsed from the argument. 10 | */ 11 | export declare function parseState(kv: any): any; 12 | export declare function mulScale(n1: bigint, n2: bigint, scale: bigint): bigint; 13 | export declare function divScale(n1: bigint, n2: bigint, scale: bigint): bigint; 14 | -------------------------------------------------------------------------------- /dist/contract/v2/contract.d.ts: -------------------------------------------------------------------------------- 1 | import { LogicSigAccount } from "algosdk"; 2 | import { SupportedNetwork } from "../../util/commonTypes"; 3 | import { BaseTinymanContract } from "../base/contract"; 4 | import { V2PoolLogicSig, V2ValidatorApp } from "./types"; 5 | export declare class TinymanContractV2 extends BaseTinymanContract { 6 | private poolLogicSigContractTemplate; 7 | constructor(validatorApp: V2ValidatorApp, poolLogicSig: V2PoolLogicSig); 8 | generateLogicSigAccountForPool(params: { 9 | network: SupportedNetwork; 10 | asset1ID: number; 11 | asset2ID: number; 12 | }): LogicSigAccount; 13 | } 14 | export declare const tinymanContract_v2: TinymanContractV2; 15 | -------------------------------------------------------------------------------- /dist/liquid-stake/constants.d.ts: -------------------------------------------------------------------------------- 1 | import { StructDefinition } from "../util/client/base/types"; 2 | import { SupportedNetwork } from "../util/commonTypes"; 3 | declare const CURRENT_REWARD_RATE_PER_TIME_END_TIMESTAMP_KEY = "current_reward_rate_per_time_end_timestamp"; 4 | declare const STAKE_APP_ID: Record; 5 | declare const RESTAKE_APP_ID: Record; 6 | declare const VAULT_APP_ID: Record; 7 | declare const STRUCTS: Record; 8 | declare const STAKE_RATIO_COEFFICIENT = 1000000000000; 9 | export { CURRENT_REWARD_RATE_PER_TIME_END_TIMESTAMP_KEY, RESTAKE_APP_ID, STAKE_APP_ID, STRUCTS, VAULT_APP_ID, STAKE_RATIO_COEFFICIENT }; 10 | -------------------------------------------------------------------------------- /src/bootstrap/v1_1/constants.ts: -------------------------------------------------------------------------------- 1 | export enum V1_1BootstrapTxnGroupIndices { 2 | FUNDING_TXN = 0, 3 | VALIDATOR_APP_CALL, 4 | POOL_TOKEN_CREATE, 5 | ASSET1_OPT_IN, 6 | ASSET2_OPT_IN 7 | } 8 | 9 | /** 10 | * Txn counts according to the pool type (ASA-ASA or ASA-Algo) 11 | * If it's ASA-Algo, there won't be `asset2Optin` txn within the bootstrap txn group 12 | */ 13 | export const V1_1_BOOTSTRAP_TXN_COUNT = { 14 | ASA_ALGO: 4, 15 | ASA_ASA: 5 16 | } as const; 17 | 18 | /** 19 | * Bootstrap operation funding txn amounts according to 20 | * the pool type (ASA-ASA or ASA-Algo) in microalgos. 21 | */ 22 | export const V1_1_BOOTSTRAP_FUNDING_TXN_AMOUNT = { 23 | ASA_ALGO: 960_000n, 24 | ASA_ASA: 859_000n 25 | } as const; 26 | -------------------------------------------------------------------------------- /dist/contract/v1_1/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface V1_1ValidatorApp { 2 | type: string; 3 | global_state_schema: V1_1ValidatorAppStateSchema; 4 | local_state_schema: V1_1ValidatorAppStateSchema; 5 | name: string; 6 | } 7 | interface V1_1ValidatorAppStateSchema { 8 | num_uints: number; 9 | num_byte_slices: number; 10 | } 11 | export interface V1_1PoolLogicSig { 12 | type: string; 13 | logic: { 14 | bytecode: string; 15 | address: string; 16 | size: number; 17 | variables: { 18 | name: string; 19 | type: string; 20 | index: number; 21 | length: number; 22 | }[]; 23 | source: string; 24 | }; 25 | name: string; 26 | } 27 | export {}; 28 | -------------------------------------------------------------------------------- /dist/util/pool/poolConstants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const DECODED_APP_STATE_KEYS: { 2 | v1_1: { 3 | asset1: string; 4 | asset2: string; 5 | }; 6 | v2: { 7 | asset1: string; 8 | asset2: string; 9 | poolTokenID: string; 10 | issuedPoolTokens: string; 11 | asset1Reserves: string; 12 | asset2Reserves: string; 13 | asset1ProtocolFees: string; 14 | asset2ProtocolFees: string; 15 | totalFeeShare: string; 16 | protocolFeeRatio: string; 17 | cumulativePriceUpdateTimeStamp: string; 18 | }; 19 | }; 20 | /** 21 | * A small portion of the pool is reserved (locked) for possible rounding errors. 22 | */ 23 | export declare const V2_LOCKED_POOL_TOKENS = 1000; 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | ## Working with the local copy of the sdk 3 | 4 | 1. After making changes on the local clone of the repo, get a build: 5 | 6 | ```sh 7 | npm run build 8 | ``` 9 | 10 | 2. Add the new build as a dependency to your project, in `package.json`: 11 | 12 | ```json 13 | "dependencies": { 14 | "@tinymanorg/tinyman-js-sdk": "../tinyman-js-sdk", 15 | } 16 | ``` 17 | 18 | You should replace `"../tinyman-js-sdk"` part with the relative path to the local clone of the repo. 19 | 20 | 3. Install the dependencies: 21 | 22 | ```sh 23 | npm install 24 | ``` 25 | 26 | 4. Then start your project, and test it. 27 | 5. Remember to repeat step 1 to get a new build after you make any changes on the sdk code. 28 | 29 |
30 | 31 | -------------------------------------------------------------------------------- /dist/contract/v1_1/contract.d.ts: -------------------------------------------------------------------------------- 1 | import { LogicSigAccount } from "algosdk"; 2 | import { SupportedNetwork } from "../../util/commonTypes"; 3 | import { BaseTinymanContract } from "../base/contract"; 4 | import { V1_1PoolLogicSig, V1_1ValidatorApp } from "./types"; 5 | export declare class TinymanContractV1_1 extends BaseTinymanContract { 6 | private poolLogicSigContractTemplate; 7 | private templateVariables; 8 | constructor(validatorApp: V1_1ValidatorApp, poolLogicSig: V1_1PoolLogicSig); 9 | generateLogicSigAccountForPool(params: { 10 | network: SupportedNetwork; 11 | asset1ID: number; 12 | asset2ID: number; 13 | }): LogicSigAccount; 14 | } 15 | export declare const tinymanContract_v1_1: TinymanContractV1_1; 16 | -------------------------------------------------------------------------------- /dist/util/error/SwapError.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum SwapErrorType { 2 | SwapRouterStaleDataError = "SwapRouterStaleDataError", 3 | SwapRouterNoRouteError = "SwapRouterNoRouteError", 4 | SwapRouterLowSwapAmountError = "SwapRouterLowSwapAmountError", 5 | SwapRouterInsufficientReservesError = "SwapRouterInsufficientReservesError", 6 | SwapRouterPoolHasNoLiquidityError = "SwapRouterPoolHasNoLiquidityError", 7 | NoAvailablePoolError = "NoAvailablePoolError", 8 | OutputAmountExceedsAvailableLiquidityError = "OutputAmountExceedsAvailableLiquidityError" 9 | } 10 | declare class SwapError extends Error { 11 | type: SwapErrorType; 12 | message: string; 13 | constructor(type: SwapErrorType, message: string); 14 | } 15 | export default SwapError; 16 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/add-liquidity/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 3 | import { FolksLendingAssetInfo } from "../types"; 4 | export declare function generateTxns({ client, network, poolAddress, poolTokenId, lendingManagerId, asset1In, asset2In, initiatorAddr }: { 5 | client: Algodv2; 6 | network: SupportedNetwork; 7 | poolAddress: string; 8 | poolTokenId: number; 9 | lendingManagerId: number; 10 | asset1In: FolksLendingAssetInfo; 11 | asset2In: FolksLendingAssetInfo; 12 | initiatorAddr: string; 13 | }): Promise; 14 | export declare function getAddLiquidityTotalFee(minFee: bigint, wrapperAppOptInRequiredAssetIdCount?: number): bigint; 15 | -------------------------------------------------------------------------------- /dist/swap/v2/router/constants.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "../../../util/commonTypes"; 2 | import { SwapType } from "../../constants"; 3 | export declare const SWAP_ROUTER_APP_ID: Record; 4 | /** 5 | * Inner txn counts according to the swap type 6 | */ 7 | export declare const SWAP_ROUTER_INNER_TXN_COUNT: Record; 8 | export declare enum V2SwapRouterSwapAppCallArgsIndices { 9 | TxnType = 0, 10 | InputAmount = 1, 11 | OutputAmount = 2, 12 | Routes = 3, 13 | Pools = 4, 14 | Swaps = 5 15 | } 16 | export declare enum V2SwapRouterAppCallArgsTxnType { 17 | Swap = "swap", 18 | AssetOptIn = "asset_opt_in", 19 | Noop = "noop" 20 | } 21 | export declare const SWAP_ROUTER_SWAP_APP_CALL_ARGS_LENGTH = 6; 22 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import terser from "@rollup/plugin-terser"; 2 | import json from "@rollup/plugin-json"; 3 | import {babel} from "@rollup/plugin-babel"; 4 | import commonjs from "@rollup/plugin-commonjs"; 5 | import resolve from "@rollup/plugin-node-resolve"; 6 | 7 | export default [ 8 | { 9 | input: "src/index.ts", 10 | output: { 11 | dir: "dist", 12 | format: "cjs" 13 | }, 14 | plugins: [ 15 | resolve({extensions: [".js", ".jsx", ".ts", ".tsx"]}), 16 | commonjs(), 17 | babel({ 18 | extensions: [".js", ".jsx", ".ts", ".tsx"], 19 | babelHelpers: "bundled", 20 | include: ["src/**/*"] 21 | }), 22 | terser(), 23 | json() 24 | ], 25 | external: ["algosdk", "base64-js"] 26 | } 27 | ]; 28 | -------------------------------------------------------------------------------- /dist/util/pool/v2/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Address, Algodv2 } from "algosdk"; 2 | import { SupportedNetwork } from "../../commonTypes"; 3 | import { V2PoolInfo, PoolReserves, PoolAssets } from "../poolTypes"; 4 | /** 5 | * @returns Information object for the pool with given arguments 6 | */ 7 | export declare function getPoolInfo(params: { 8 | client: Algodv2; 9 | network: SupportedNetwork; 10 | asset1ID: number; 11 | asset2ID: number; 12 | }): Promise; 13 | export declare function getPoolReserves(client: Algodv2, pool: V2PoolInfo): Promise; 14 | export declare function getPoolAssets({ client, address, network }: { 15 | client: Algodv2; 16 | address: string | Address; 17 | network: SupportedNetwork; 18 | }): Promise; 19 | -------------------------------------------------------------------------------- /dist/order/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface PutTriggerOrderParams { 2 | assetInId: number; 3 | assetOutId: number; 4 | assetInAmount: bigint; 5 | assetOutAmount: bigint; 6 | isPartialAllowed: boolean; 7 | duration: number; 8 | orderAppId?: number; 9 | } 10 | export interface PutRecurringOrderParams { 11 | assetId: number; 12 | amount: bigint; 13 | targetAssetId: number; 14 | targetRecurrence: number; 15 | interval: number; 16 | minTargetPrice: number; 17 | maxTargetPrice: number; 18 | } 19 | export declare enum OrderType { 20 | Trigger = "trigger_order", 21 | Recurring = "recurring_order" 22 | } 23 | export declare enum OrderStruct { 24 | Trigger = "TriggerOrder", 25 | Recurring = "RecurringOrder", 26 | Entry = "Entry" 27 | } 28 | -------------------------------------------------------------------------------- /dist/util/pool/v1_1/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SupportedNetwork } from "../../commonTypes"; 3 | import { PoolAssets, PoolReserves, V1PoolInfo } from "../poolTypes"; 4 | export declare function getPoolInfo(params: { 5 | client: Algodv2; 6 | network: SupportedNetwork; 7 | asset1ID: number; 8 | asset2ID: number; 9 | }): Promise; 10 | export declare function getPoolReserves(client: Algodv2, pool: V1PoolInfo): Promise; 11 | /** 12 | * Find out the ids of a pool's liquidity token and assets 13 | */ 14 | export declare function getPoolAssets({ client, address, network }: { 15 | client: Algodv2; 16 | address: string; 17 | network: SupportedNetwork; 18 | }, cache?: Record): Promise; 19 | -------------------------------------------------------------------------------- /dist/bootstrap/v1_1/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V1_1BootstrapTxnGroupIndices { 2 | FUNDING_TXN = 0, 3 | VALIDATOR_APP_CALL = 1, 4 | POOL_TOKEN_CREATE = 2, 5 | ASSET1_OPT_IN = 3, 6 | ASSET2_OPT_IN = 4 7 | } 8 | /** 9 | * Txn counts according to the pool type (ASA-ASA or ASA-Algo) 10 | * If it's ASA-Algo, there won't be `asset2Optin` txn within the bootstrap txn group 11 | */ 12 | export declare const V1_1_BOOTSTRAP_TXN_COUNT: { 13 | readonly ASA_ALGO: 4; 14 | readonly ASA_ASA: 5; 15 | }; 16 | /** 17 | * Bootstrap operation funding txn amounts according to 18 | * the pool type (ASA-ASA or ASA-Algo) in microalgos. 19 | */ 20 | export declare const V1_1_BOOTSTRAP_FUNDING_TXN_AMOUNT: { 21 | readonly ASA_ALGO: 960000n; 22 | readonly ASA_ASA: 859000n; 23 | }; 24 | -------------------------------------------------------------------------------- /dist/util/commonTypes.d.ts: -------------------------------------------------------------------------------- 1 | import { Transaction } from "algosdk"; 2 | export interface SignerTransaction { 3 | txn: Transaction; 4 | /** 5 | * Optional list of addresses that must sign the transactions. 6 | * Wallet skips to sign this txn if signers is empty array. 7 | * If undefined, wallet tries to sign it. 8 | */ 9 | signers?: string[]; 10 | } 11 | export type InitiatorSigner = (txGroupList: SignerTransaction[][]) => Promise; 12 | export type SupportedNetwork = "testnet" | "mainnet"; 13 | export interface TinymanApiErrorDetailShape { 14 | [x: string]: undefined | any; 15 | } 16 | export interface TinymanApiErrorShape { 17 | type: Type; 18 | detail: TinymanApiErrorDetailShape; 19 | fallback_message: string; 20 | } 21 | -------------------------------------------------------------------------------- /dist/contract/base/contract.d.ts: -------------------------------------------------------------------------------- 1 | import { LogicSigAccount } from "algosdk"; 2 | import { SupportedNetwork } from "../../util/commonTypes"; 3 | import { V1_1ValidatorApp } from "../v1_1/types"; 4 | import { V2ValidatorApp } from "../v2/types"; 5 | export interface ValidatorAppSchema { 6 | numLocalInts: number; 7 | numLocalByteSlices: number; 8 | numGlobalInts: number; 9 | numGlobalByteSlices: number; 10 | } 11 | export declare abstract class BaseTinymanContract { 12 | schema: ValidatorAppSchema; 13 | constructor(validatorApp: ValidatorApp); 14 | abstract generateLogicSigAccountForPool(params: { 15 | network: SupportedNetwork; 16 | asset1ID: number; 17 | asset2ID: number; 18 | }): LogicSigAccount; 19 | } 20 | -------------------------------------------------------------------------------- /dist/swap/v2/util.d.ts: -------------------------------------------------------------------------------- 1 | import { SwapType } from "../constants"; 2 | /** 3 | * @returns the total fee for the swap operation including all transactions (including inner transactions) fees 4 | */ 5 | export declare function getV2SwapTotalFee(mode: SwapType, minFee: bigint): bigint; 6 | /** 7 | * @returns the minimum possible amount of assetIn that can be used for swap in V2 pools 8 | */ 9 | export declare function getV2MinSwapAssetInAmount(feeRate?: number): number; 10 | /** 11 | * @returns true if the amount of assetIn is less than the minimum possible amount of assetIn that can be used for swap in V2 pools 12 | */ 13 | export declare function isSwapAssetInAmountLow(amount: number, feeRate?: number): boolean; 14 | export declare function getSwapAppCallFeeAmount(swapType: SwapType, minFee: bigint): bigint; 15 | -------------------------------------------------------------------------------- /dist/governance/proposal-voting/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const PROPOSAL_BOX_PREFIX: Uint8Array; 2 | declare const ATTENDANCE_SHEET_BOX_PREFIX: Uint8Array; 3 | declare const ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; 4 | declare const PROPOSAL_BOX_SIZE: number; 5 | declare const PROPOSAL_BOX_COST: number; 6 | declare const ATTENDANCE_SHEET_BOX_COST: number; 7 | declare enum ProposalVote { 8 | Against = 0, 9 | For = 1, 10 | Abstain = 2 11 | } 12 | declare const EXECUTION_HASH_SIZE = 34; 13 | declare const CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT: Uint8Array; 14 | export { PROPOSAL_BOX_PREFIX, PROPOSAL_BOX_SIZE, PROPOSAL_BOX_COST, ProposalVote, ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE, ATTENDANCE_SHEET_BOX_PREFIX, ATTENDANCE_SHEET_BOX_COST, EXECUTION_HASH_SIZE, CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT }; 15 | -------------------------------------------------------------------------------- /src/util/commonTypes.ts: -------------------------------------------------------------------------------- 1 | import {Transaction} from "algosdk"; 2 | 3 | export interface SignerTransaction { 4 | txn: Transaction; 5 | /** 6 | * Optional list of addresses that must sign the transactions. 7 | * Wallet skips to sign this txn if signers is empty array. 8 | * If undefined, wallet tries to sign it. 9 | */ 10 | signers?: string[]; 11 | } 12 | 13 | export type InitiatorSigner = ( 14 | txGroupList: SignerTransaction[][] 15 | ) => Promise; 16 | 17 | export type SupportedNetwork = "testnet" | "mainnet"; 18 | 19 | export interface TinymanApiErrorDetailShape { 20 | [x: string]: undefined | any; 21 | } 22 | 23 | export interface TinymanApiErrorShape { 24 | type: Type; 25 | detail: TinymanApiErrorDetailShape; 26 | fallback_message: string; 27 | } 28 | -------------------------------------------------------------------------------- /src/governance/rewards/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | import {BOX_BYTE_MIN_BALANCE, BOX_FLAT_MIN_BALANCE} from "../constants"; 3 | 4 | const REWARD_PERIOD_BOX_PREFIX = encodeString("rp"); 5 | const REWARD_CLAIM_SHEET_BOX_SIZE = 1012; 6 | const REWARD_CLAIM_SHEET_BOX_PREFIX = encodeString("c"); 7 | 8 | const REWARD_PERIOD_SIZE = 24; 9 | const REWARD_PERIOD_BOX_SIZE = 1008; 10 | const REWARD_PERIOD_BOX_ARRAY_LEN = 42; 11 | 12 | const REWARD_CLAIM_SHEET_BOX_COST = 13 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (41 + REWARD_CLAIM_SHEET_BOX_SIZE); 14 | 15 | export { 16 | REWARD_CLAIM_SHEET_BOX_PREFIX, 17 | REWARD_PERIOD_BOX_PREFIX, 18 | REWARD_CLAIM_SHEET_BOX_SIZE, 19 | REWARD_PERIOD_SIZE, 20 | REWARD_PERIOD_BOX_ARRAY_LEN, 21 | REWARD_PERIOD_BOX_SIZE, 22 | REWARD_CLAIM_SHEET_BOX_COST 23 | }; 24 | -------------------------------------------------------------------------------- /src/order/types.ts: -------------------------------------------------------------------------------- 1 | export interface PutTriggerOrderParams { 2 | assetInId: number; 3 | assetOutId: number; 4 | assetInAmount: bigint; 5 | assetOutAmount: bigint; 6 | isPartialAllowed: boolean; 7 | duration: number; 8 | // This field is needed the first time the order app is created by the user 9 | orderAppId?: number; 10 | } 11 | 12 | export interface PutRecurringOrderParams { 13 | assetId: number; 14 | amount: bigint; 15 | targetAssetId: number; 16 | targetRecurrence: number; 17 | interval: number; 18 | minTargetPrice: number; 19 | maxTargetPrice: number; 20 | } 21 | 22 | export enum OrderType { 23 | Trigger = "trigger_order", 24 | Recurring = "recurring_order" 25 | } 26 | 27 | export enum OrderStruct { 28 | Trigger = "TriggerOrder", 29 | Recurring = "RecurringOrder", 30 | Entry = "Entry" 31 | } 32 | -------------------------------------------------------------------------------- /dist/governance/staking-voting/transactions.d.ts: -------------------------------------------------------------------------------- 1 | import { SuggestedParams } from "algosdk"; 2 | import { StakingDistributionProposal } from "./storage"; 3 | declare function prepareCastVoteForStakingDistributionProposalTransactions({ stakingVotingAppId, vaultAppId, sender, proposalId, proposal, votes, assetIds, accountPowerIndex, appBoxNames, suggestedParams, appCallNote }: { 4 | stakingVotingAppId: number; 5 | vaultAppId: number; 6 | sender: string; 7 | proposalId: string; 8 | proposal: StakingDistributionProposal; 9 | votes: number[]; 10 | assetIds: number[]; 11 | accountPowerIndex: number; 12 | appBoxNames: Uint8Array[]; 13 | suggestedParams: SuggestedParams; 14 | appCallNote: string | null; 15 | }): import("algosdk").Transaction[]; 16 | export { prepareCastVoteForStakingDistributionProposalTransactions }; 17 | -------------------------------------------------------------------------------- /dist/util/client/base/utils.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { StructDefinition } from "./types"; 3 | declare class Struct { 4 | private data; 5 | protected name: string; 6 | protected fields: Record; 7 | private structReference; 8 | size: number; 9 | constructor(name: string, structReference: Record); 10 | apply(data?: Buffer): this; 11 | getField(prop: string): bigint | Buffer | Struct | ArrayData; 12 | } 13 | declare class ArrayData { 14 | private struct; 15 | private data; 16 | private length; 17 | constructor(struct: Struct, length: number); 18 | apply(data?: Buffer): this; 19 | getField(index: number): Struct; 20 | } 21 | declare function getBoxCosts(boxes: Record): number; 22 | export { ArrayData, getBoxCosts, Struct }; 23 | -------------------------------------------------------------------------------- /src/util/asset/assetModels.ts: -------------------------------------------------------------------------------- 1 | export interface TinymanAnalyticsApiAsset { 2 | id: string; 3 | is_liquidity_token: boolean; 4 | name: string; 5 | unit_name: string; 6 | decimals: number; 7 | url: string; 8 | total_amount: string; 9 | clawback_address: string; 10 | liquidity_in_usd?: null | string; 11 | last_day_volume_in_usd?: null | string; 12 | last_day_price_change?: null | string; 13 | } 14 | 15 | export interface AssetWithIdAndAmount { 16 | id: number; 17 | amount: bigint; 18 | } 19 | 20 | export interface AssetWithIdAndDecimals { 21 | id: number; 22 | decimals: number; 23 | } 24 | 25 | export interface AssetWithAmountAndDecimals { 26 | amount: bigint; 27 | decimals: number; 28 | } 29 | 30 | export interface AssetWithIdAndAmountAndDecimals { 31 | id: number; 32 | amount: bigint; 33 | decimals: number; 34 | } 35 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/remove-liquidity/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 3 | import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 4 | import { FolksLendingAssetInfo } from "../types"; 5 | export declare function generateTxns({ client, pool, poolTokenIn, initiatorAddr, asset1Out, asset2Out, lendingManagerId, network }: { 6 | client: Algodv2; 7 | pool: Pick; 8 | poolTokenIn: number | bigint; 9 | initiatorAddr: string; 10 | asset1Out: Omit; 11 | asset2Out: Omit; 12 | lendingManagerId: number; 13 | network: SupportedNetwork; 14 | }): Promise; 15 | export declare function getRemoveLiquidityTotalFee(minFee: bigint): bigint; 16 | -------------------------------------------------------------------------------- /dist/util/asset/assetModels.d.ts: -------------------------------------------------------------------------------- 1 | export interface TinymanAnalyticsApiAsset { 2 | id: string; 3 | is_liquidity_token: boolean; 4 | name: string; 5 | unit_name: string; 6 | decimals: number; 7 | url: string; 8 | total_amount: string; 9 | clawback_address: string; 10 | liquidity_in_usd?: null | string; 11 | last_day_volume_in_usd?: null | string; 12 | last_day_price_change?: null | string; 13 | } 14 | export interface AssetWithIdAndAmount { 15 | id: number; 16 | amount: bigint; 17 | } 18 | export interface AssetWithIdAndDecimals { 19 | id: number; 20 | decimals: number; 21 | } 22 | export interface AssetWithAmountAndDecimals { 23 | amount: bigint; 24 | decimals: number; 25 | } 26 | export interface AssetWithIdAndAmountAndDecimals { 27 | id: number; 28 | amount: bigint; 29 | decimals: number; 30 | } 31 | -------------------------------------------------------------------------------- /dist/stake.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2, SuggestedParams } from "algosdk"; 2 | import { SignerTransaction, SupportedNetwork } from "./util/commonTypes"; 3 | interface CreateCommitTxnOptions { 4 | suggestedParams: SuggestedParams; 5 | stakingAppID: number; 6 | initiatorAddr: string; 7 | liquidityAssetID: number; 8 | program: { 9 | accountAddress: string; 10 | id: number; 11 | }; 12 | amount: number | bigint; 13 | } 14 | declare function prepareCommitTransactions({ client, stakingAppID, program, requiredAssetID, liquidityAssetID, amount, initiatorAddr }: Omit & { 15 | client: Algodv2; 16 | requiredAssetID?: number; 17 | }): Promise; 18 | declare function getStakingAppID(network: SupportedNetwork): 51948952 | 649588853; 19 | export { getStakingAppID, prepareCommitTransactions }; 20 | -------------------------------------------------------------------------------- /dist/swap/v2/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V2SwapTxnGroupIndices { 2 | /** 3 | * If the input asset is Algo, it'll be a payment txn, otherwise it'll be an asset transfer txn. 4 | */ 5 | INPUT_TXN = 0, 6 | APP_CALL_TXN = 1 7 | } 8 | export declare const V2_SWAP_APP_CALL_INNER_TXN_COUNT: { 9 | readonly "fixed-input": 1; 10 | readonly "fixed-output": 2; 11 | }; 12 | /** 13 | * Number of transactions in the swap transaction group (excluding inner transactions) 14 | */ 15 | export declare const V2_SWAP_TXN_COUNT = 2; 16 | export declare const V2_SWAP_APP_CALL_ARG_ENCODED: Uint8Array; 17 | export declare const V2_SWAP_APP_CALL_SWAP_TYPE_ARGS_ENCODED: { 18 | readonly "fixed-input": Uint8Array; 19 | readonly "fixed-output": Uint8Array; 20 | }; 21 | export declare const V2_SWAP_ROUTER_APP_ARGS_ENCODED: { 22 | readonly ASSET_OPT_IN: Uint8Array; 23 | }; 24 | -------------------------------------------------------------------------------- /src/swap/v2/router/constants.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "../../../util/commonTypes"; 2 | import {SwapType} from "../../constants"; 3 | 4 | export const SWAP_ROUTER_APP_ID: Record = { 5 | testnet: 184778019, 6 | mainnet: 1083651166 7 | }; 8 | 9 | /** 10 | * Inner txn counts according to the swap type 11 | */ 12 | export const SWAP_ROUTER_INNER_TXN_COUNT: Record = { 13 | [SwapType.FixedInput]: 7, 14 | [SwapType.FixedOutput]: 8 15 | } as const; 16 | 17 | export enum V2SwapRouterSwapAppCallArgsIndices { 18 | TxnType = 0, 19 | InputAmount = 1, 20 | OutputAmount = 2, 21 | Routes = 3, 22 | Pools = 4, 23 | Swaps = 5 24 | } 25 | 26 | export enum V2SwapRouterAppCallArgsTxnType { 27 | Swap = "swap", 28 | AssetOptIn = "asset_opt_in", 29 | Noop = "noop" 30 | } 31 | 32 | export const SWAP_ROUTER_SWAP_APP_CALL_ARGS_LENGTH = 6; 33 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum V2AddLiquidityType { 2 | SINGLE = "single", 3 | FLEXIBLE = "flexible", 4 | INITIAL = "initial" 5 | } 6 | export declare const V2AddLiquidityTxnIndices: { 7 | flexible: { 8 | ASSET1_IN_TXN: number; 9 | ASSET2_IN_TXN: number; 10 | VALIDATOR_APP_CALL_TXN: number; 11 | }; 12 | single: { 13 | ASSET_IN_TXN: number; 14 | VALIDATOR_APP_CALL_TXN: number; 15 | }; 16 | initial: { 17 | ASSET1_IN_TXN: number; 18 | ASSET2_IN_TXN: number; 19 | VALIDATOR_APP_CALL_TXN: number; 20 | }; 21 | }; 22 | export declare const V2_ADD_LIQUIDITY_INNER_TXN_COUNT: Record; 23 | /** 24 | * Number of transactions in the add liquidity transaction group (excluding inner transactions) 25 | */ 26 | export declare const V2_ADD_LIQUIDITY_TXN_COUNT: Record; 27 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/common.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { InitiatorSigner, SignerTransaction } from "../../util/commonTypes"; 3 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V2AddLiquidityExecution } from "./types"; 5 | export declare function signTxns({ txGroup, initiatorSigner }: { 6 | txGroup: SignerTransaction[]; 7 | initiatorSigner: InitiatorSigner; 8 | }): Promise; 9 | /** 10 | * Execute an add liquidity operation with the desired quantities. 11 | * 12 | * @param params.client An Algodv2 client. 13 | * @param params.pool Information for the pool. 14 | * @param params.txGroup The transaction group to execute. 15 | */ 16 | export declare function execute({ client, pool, txGroup, signedTxns }: { 17 | client: Algodv2; 18 | pool: V2PoolInfo; 19 | txGroup: SignerTransaction[]; 20 | signedTxns: Uint8Array[]; 21 | }): Promise; 22 | -------------------------------------------------------------------------------- /src/util/pool/poolConstants.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "../../contract/constants"; 2 | 3 | export const DECODED_APP_STATE_KEYS = { 4 | [CONTRACT_VERSION.V1_1]: { 5 | asset1: "a1", 6 | asset2: "a2" 7 | }, 8 | [CONTRACT_VERSION.V2]: { 9 | asset1: "asset_1_id", 10 | asset2: "asset_2_id", 11 | poolTokenID: "pool_token_asset_id", 12 | issuedPoolTokens: "issued_pool_tokens", 13 | asset1Reserves: "asset_1_reserves", 14 | asset2Reserves: "asset_2_reserves", 15 | asset1ProtocolFees: "asset_1_protocol_fees", 16 | asset2ProtocolFees: "asset_2_protocol_fees", 17 | totalFeeShare: "total_fee_share", 18 | protocolFeeRatio: "protocol_fee_ratio", 19 | cumulativePriceUpdateTimeStamp: "cumulative_price_update_timestamp" 20 | } 21 | }; 22 | 23 | /** 24 | * A small portion of the pool is reserved (locked) for possible rounding errors. 25 | */ 26 | export const V2_LOCKED_POOL_TOKENS = 1000; 27 | -------------------------------------------------------------------------------- /src/folks-lending-pools/add-liquidity/utils.ts: -------------------------------------------------------------------------------- 1 | import {Algodv2, getApplicationAddress} from "algosdk"; 2 | 3 | import {SupportedNetwork} from "../../util/commonTypes"; 4 | import {FOLKS_WRAPPER_APP_ID} from "../constants"; 5 | import {ALGO_ASSET_ID} from "../../util/asset/assetConstants"; 6 | 7 | export async function getFolksWrapperAppOptInRequiredAssetIDs({ 8 | client, 9 | network, 10 | assetIDs 11 | }: { 12 | client: Algodv2; 13 | network: SupportedNetwork; 14 | assetIDs: number[]; 15 | }) { 16 | const wrapperAppAddress = getApplicationAddress(FOLKS_WRAPPER_APP_ID[network]); 17 | const appInfo = await client.accountInformation(wrapperAppAddress).do(); 18 | const appOptedInAssetIDs = appInfo.assets 19 | ? appInfo.assets.map((asset) => asset.assetId) 20 | : []; 21 | 22 | return assetIDs.filter( 23 | (assetID: number) => 24 | assetID !== ALGO_ASSET_ID && !appOptedInAssetIDs.includes(BigInt(assetID)) 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /dist/util/constant.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "./commonTypes"; 2 | export declare const MAX_SLIPPAGE_FRACTION_DIGITS = 6; 3 | export declare const DEFAULT_FEE_TXN_NOTE: Uint8Array; 4 | export declare const BASE_MINIMUM_BALANCE = 100000n; 5 | export declare const MINIMUM_BALANCE_REQUIRED_PER_ASSET = 100000n; 6 | export declare const MINIMUM_BALANCE_REQUIRED_PER_APP = 100000n; 7 | export declare const MINIMUM_BALANCE_REQUIRED_PER_CREATED_APP = 100000n; 8 | export declare const MINIMUM_BALANCE_REQUIRED_PER_EXTRA_APP_PAGE = 100000n; 9 | export declare const MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA = 50000n; 10 | export declare const MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE = 28500n; 11 | export declare const MINIMUM_ADD_LIQUIDITY_AMOUNT = 1000n; 12 | export declare const DEFAULT_WAIT_FOR_CONFIRMATION_ROUNDS = 1000; 13 | export declare const TINYMAN_ANALYTICS_API_BASE_URLS: Record; 17 | -------------------------------------------------------------------------------- /dist/governance/constants.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "../util/commonTypes"; 2 | declare const HOUR_IN_S: number; 3 | declare const DAY_IN_S: number; 4 | declare const WEEK_IN_S: number; 5 | declare const SECOND_IN_MS = 1000; 6 | declare const VAULT_APP_ID: Record; 7 | declare const STAKING_VOTING_APP_ID: Record; 8 | declare const REWARDS_APP_ID: Record; 9 | declare const PROPOSAL_VOTING_APP_ID: Record; 10 | declare const BOX_FLAT_MIN_BALANCE = 2500; 11 | declare const BOX_BYTE_MIN_BALANCE = 400; 12 | declare const HOUR: number; 13 | declare const DAY: number; 14 | declare const WEEK: number; 15 | export { HOUR, DAY, WEEK }; 16 | declare const TWO_TO_THE_64: number; 17 | export { VAULT_APP_ID, STAKING_VOTING_APP_ID, REWARDS_APP_ID, BOX_BYTE_MIN_BALANCE, BOX_FLAT_MIN_BALANCE, TWO_TO_THE_64, WEEK_IN_S, DAY_IN_S, HOUR_IN_S, SECOND_IN_MS, PROPOSAL_VOTING_APP_ID }; 18 | -------------------------------------------------------------------------------- /src/governance/staking-voting/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | import {BOX_BYTE_MIN_BALANCE, BOX_FLAT_MIN_BALANCE} from "../constants"; 3 | 4 | const STAKING_VOTE_MAX_OPTION_COUNT = 8; 5 | 6 | // Box 7 | const PROPOSAL_BOX_PREFIX = encodeString("p"); 8 | const STAKING_ATTENDANCE_BOX_PREFIX = encodeString("a"); 9 | const STAKING_VOTE_BOX_PREFIX = encodeString("v"); 10 | 11 | const STAKING_ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; 12 | const STAKING_VOTE_BOX_SIZE = 8; 13 | 14 | const STAKING_ATTENDANCE_BOX_COST = 15 | BOX_FLAT_MIN_BALANCE + 16 | BOX_BYTE_MIN_BALANCE * (41 + STAKING_ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE); 17 | const STAKING_VOTE_BOX_COST = 18 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (17 + STAKING_VOTE_BOX_SIZE); 19 | 20 | export { 21 | STAKING_VOTE_MAX_OPTION_COUNT, 22 | PROPOSAL_BOX_PREFIX, 23 | STAKING_ATTENDANCE_BOX_PREFIX, 24 | STAKING_VOTE_BOX_PREFIX, 25 | STAKING_ATTENDANCE_BOX_COST, 26 | STAKING_VOTE_BOX_COST 27 | }; 28 | -------------------------------------------------------------------------------- /src/util/asset/assetConstants.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "../commonTypes"; 2 | import {TinymanAnalyticsApiAsset} from "./assetModels"; 3 | 4 | export const ALGO_ASSET_ID = 0; 5 | 6 | export const ALGO_ASSET: TinymanAnalyticsApiAsset = { 7 | id: `${ALGO_ASSET_ID}`, 8 | name: "Algorand", 9 | unit_name: "ALGO", 10 | decimals: 6, 11 | url: "https://algorand.org", 12 | is_liquidity_token: false, 13 | total_amount: "6615503326932151", 14 | clawback_address: "" 15 | }; 16 | 17 | export const POOL_TOKEN_UNIT_NAME = { 18 | V1: "TM1POOL", 19 | V1_1: "TMPOOL11", 20 | V2: "TMPOOL2" 21 | }; 22 | 23 | export const TINY_ASSET_ID: Record = { 24 | testnet: 258703304, 25 | mainnet: 2200000000 26 | }; 27 | 28 | export const TALGO_ASSET_ID: Record = { 29 | testnet: 724519992, 30 | mainnet: 2537013734 31 | }; 32 | 33 | export const STALGO_ASSET_ID: Record = { 34 | testnet: 724676936, 35 | mainnet: 2537023208 36 | }; 37 | -------------------------------------------------------------------------------- /dist/util/error/SwapQuoteError.d.ts: -------------------------------------------------------------------------------- 1 | export declare enum SwapQuoteErrorType { 2 | SwapRouterStaleDataError = "SwapRouterStaleDataError", 3 | SwapRouterNoRouteError = "SwapRouterNoRouteError", 4 | SwapRouterLowSwapAmountError = "SwapRouterLowSwapAmountError", 5 | SwapRouterInsufficientReservesError = "SwapRouterInsufficientReservesError", 6 | SwapRouterPoolHasNoLiquidityError = "SwapRouterPoolHasNoLiquidityError", 7 | NoAvailablePoolError = "NoAvailablePoolError", 8 | OutputAmountExceedsAvailableLiquidityError = "OutputAmountExceedsAvailableLiquidityError", 9 | UnknownError = "UnknownError", 10 | LowSwapAmountError = "LowSwapAmountError", 11 | AssetDoesNotBelongToPoolError = "AssetDoesNotBelongToPoolError", 12 | InvalidSwapTypeError = "InvalidSwapTypeError" 13 | } 14 | declare class SwapQuoteError extends Error { 15 | type: SwapQuoteErrorType; 16 | message: string; 17 | constructor(type: SwapQuoteErrorType, message: string); 18 | } 19 | export default SwapQuoteError; 20 | -------------------------------------------------------------------------------- /src/swap/v2/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | import {SwapType} from "../constants"; 3 | 4 | export enum V2SwapTxnGroupIndices { 5 | /** 6 | * If the input asset is Algo, it'll be a payment txn, otherwise it'll be an asset transfer txn. 7 | */ 8 | INPUT_TXN = 0, 9 | APP_CALL_TXN 10 | } 11 | 12 | export const V2_SWAP_APP_CALL_INNER_TXN_COUNT = { 13 | [SwapType.FixedInput]: 1, 14 | [SwapType.FixedOutput]: 2 15 | } as const; 16 | 17 | /** 18 | * Number of transactions in the swap transaction group (excluding inner transactions) 19 | */ 20 | export const V2_SWAP_TXN_COUNT = 2; 21 | 22 | export const V2_SWAP_APP_CALL_ARG_ENCODED = encodeString("swap"); 23 | 24 | export const V2_SWAP_APP_CALL_SWAP_TYPE_ARGS_ENCODED = { 25 | [SwapType.FixedInput]: encodeString("fixed-input"), 26 | [SwapType.FixedOutput]: encodeString("fixed-output") 27 | } as const; 28 | 29 | export const V2_SWAP_ROUTER_APP_ARGS_ENCODED = { 30 | ASSET_OPT_IN: encodeString("asset_opt_in") 31 | } as const; 32 | -------------------------------------------------------------------------------- /dist/swap/v2/router/swap-router.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { Algodv2, SuggestedParams } from "algosdk"; 2 | import { SupportedNetwork } from "../../../util/commonTypes"; 3 | import { SwapType } from "../../constants"; 4 | import { SwapRouterResponse, SwapRouterTransactionRecipe } from "../../types"; 5 | export declare function generateSwapRouterTxns({ initiatorAddr, client, route }: { 6 | client: Algodv2; 7 | initiatorAddr: string; 8 | route: SwapRouterResponse; 9 | }): Promise<{ 10 | txn: algosdk.Transaction; 11 | signers: string[]; 12 | }[]>; 13 | export declare function generateSwapRouterTxnFromRecipe(recipe: SwapRouterTransactionRecipe, suggestedParams: SuggestedParams, userAddress: string): algosdk.Transaction; 14 | export declare function getSwapRoute({ amount, assetInID, assetOutID, swapType, network, slippage }: { 15 | assetInID: number; 16 | assetOutID: number; 17 | swapType: SwapType; 18 | amount: number | bigint; 19 | network: SupportedNetwork; 20 | slippage: number; 21 | }): Promise; 22 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/initial.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { AssetWithAmountAndDecimals, AssetWithIdAndAmount } from "../../util/asset/assetModels"; 3 | import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 4 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 5 | import { V2InitialAddLiquidityQuote } from "./types"; 6 | export * from "./common"; 7 | export declare function getQuote({ pool, asset1, asset2, slippage }: { 8 | pool: V2PoolInfo; 9 | asset1: AssetWithAmountAndDecimals; 10 | asset2: AssetWithAmountAndDecimals; 11 | slippage?: number; 12 | }): V2InitialAddLiquidityQuote; 13 | export declare function generateTxns({ client, pool, network, poolAddress, asset1In, asset2In, poolTokenId, initiatorAddr }: { 14 | client: Algodv2; 15 | pool: V2PoolInfo; 16 | network: SupportedNetwork; 17 | poolAddress: string; 18 | asset1In: AssetWithIdAndAmount; 19 | asset2In: AssetWithIdAndAmount; 20 | poolTokenId: number; 21 | initiatorAddr: string; 22 | }): Promise; 23 | -------------------------------------------------------------------------------- /examples/src/util/initiatorSigner.ts: -------------------------------------------------------------------------------- 1 | import { SignerTransaction } from "@tinymanorg/tinyman-js-sdk"; 2 | import { Account } from "algosdk"; 3 | 4 | /** 5 | * @param account account data that will sign the transactions 6 | * @returns a function that will sign the transactions, can be used as `initiatorSigner` 7 | */ 8 | export default function signerWithSecretKey(account: Account) { 9 | return function (txGroups: SignerTransaction[][]): Promise { 10 | // Filter out transactions that don't need to be signed by the account 11 | const txnsToBeSigned = txGroups.flatMap((txGroup) => 12 | txGroup.filter((item) => item.signers?.includes(account.addr)) 13 | ); 14 | // Sign all transactions that need to be signed by the account 15 | const signedTxns: Uint8Array[] = txnsToBeSigned.map(({ txn }) => 16 | txn.signTxn(account.sk) 17 | ); 18 | 19 | // We wrap this with a Promise since SDK's initiatorSigner expects a Promise 20 | return new Promise((resolve) => { 21 | resolve(signedTxns); 22 | }); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/add-liquidity/util.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "../contract/constants"; 2 | import {getV1_1AddLiquidityTotalFee} from "./v1_1/util"; 3 | import {V2AddLiquidityType} from "./v2/constants"; 4 | import {getV2AddLiquidityTotalFee} from "./v2/util"; 5 | 6 | /** 7 | * @returns the total fee that will be paid by the user 8 | * for the add liquidity transaction with given parameters 9 | */ 10 | function getAddLiquidityTotalFee( 11 | params: {minFee: bigint} & ( 12 | | { 13 | version: typeof CONTRACT_VERSION.V1_1; 14 | } 15 | | { 16 | version: typeof CONTRACT_VERSION.V2; 17 | type: V2AddLiquidityType; 18 | } 19 | ) 20 | ) { 21 | switch (params.version) { 22 | case CONTRACT_VERSION.V1_1: 23 | return getV1_1AddLiquidityTotalFee(params.minFee); 24 | 25 | case CONTRACT_VERSION.V2: 26 | return getV2AddLiquidityTotalFee(params.type, params.minFee); 27 | 28 | default: 29 | throw new Error("Provided contract version was not valid."); 30 | } 31 | } 32 | 33 | export {getAddLiquidityTotalFee}; 34 | -------------------------------------------------------------------------------- /src/validator.test.ts: -------------------------------------------------------------------------------- 1 | import {expect, test} from "@jest/globals"; 2 | 3 | import {CONTRACT_VERSION} from "./contract/constants"; 4 | import {SupportedNetwork} from "./util/commonTypes"; 5 | import {getValidatorAppID, VALIDATOR_APP_ID} from "./validator"; 6 | 7 | describe("`getValidatorAppID`", () => { 8 | test("throws an error when one of the args is invalid", () => { 9 | expect(() => 10 | getValidatorAppID("unknown" as any, CONTRACT_VERSION.V1_1) 11 | ).toThrowError(); 12 | expect(() => getValidatorAppID("mainnet", "unknown" as any)).toThrowError(); 13 | }); 14 | 15 | test("returns the correct validator app id", () => { 16 | const networks: SupportedNetwork[] = ["mainnet", "testnet"]; 17 | const contractVersions = Object.values(CONTRACT_VERSION); 18 | 19 | for (const network of networks) { 20 | for (const contractVersion of contractVersions) { 21 | expect(getValidatorAppID(network, contractVersion)).toBe( 22 | VALIDATOR_APP_ID[contractVersion][network] 23 | ); 24 | } 25 | } 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/with-single-asset.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 3 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V2SingleAssetInAddLiquidityQuote } from "./types"; 5 | import { AssetWithIdAndAmount } from "../../util/asset/assetModels"; 6 | export * from "./common"; 7 | export declare function getQuote({ pool, assetIn, slippage, decimals }: { 8 | pool: V2PoolInfo; 9 | assetIn: AssetWithIdAndAmount; 10 | decimals: { 11 | asset1: number; 12 | asset2: number; 13 | }; 14 | slippage?: number; 15 | }): V2SingleAssetInAddLiquidityQuote; 16 | export declare function generateTxns({ client, network, poolAddress, assetIn, poolTokenId, initiatorAddr, minPoolTokenAssetAmount }: { 17 | client: Algodv2; 18 | network: SupportedNetwork; 19 | poolAddress: string; 20 | assetIn: AssetWithIdAndAmount; 21 | poolTokenId: number; 22 | initiatorAddr: string; 23 | minPoolTokenAssetAmount: bigint; 24 | }): Promise; 25 | -------------------------------------------------------------------------------- /dist/governance/rewards/storage.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | declare class RewardsAppGlobalState { 3 | tinyAssetId: number; 4 | vaultAppId: number; 5 | rewardHistoryCount: number; 6 | firstPeriodTimestamp: number; 7 | rewardPeriodCount: number; 8 | manager: string; 9 | rewardsManager: string; 10 | constructor(tinyAssetId: bigint, vaultAppId: bigint, rewardHistoryCount: bigint, firstPeriodTimestamp: bigint, rewardPeriodCount: bigint, manager: string, rewardsManager: string); 11 | } 12 | declare class RewardClaimSheet { 13 | value: Uint8Array; 14 | constructor(value: Uint8Array); 15 | } 16 | declare function getRewardPeriodBoxName(boxIndex: number): Uint8Array; 17 | declare function getAccountRewardClaimSheetBoxName(address: string, boxIndex: number): Uint8Array; 18 | declare function getRewardClaimSheet(algod: Algodv2, appId: number, address: string, accountRewardClaimSheetBoxIndex: number): Promise; 19 | export { getAccountRewardClaimSheetBoxName, getRewardClaimSheet, getRewardPeriodBoxName, RewardClaimSheet, RewardsAppGlobalState }; 20 | -------------------------------------------------------------------------------- /dist/liquid-stake/stAlgoClient.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk from "algosdk"; 2 | import { SupportedNetwork } from "../util/commonTypes"; 3 | import TinymanBaseClient from "../util/client/base/baseClient"; 4 | declare class TinymanSTAlgoClient extends TinymanBaseClient { 5 | vaultAppId: number; 6 | constructor(algod: algosdk.Algodv2, network: SupportedNetwork); 7 | increaseStake(amount: bigint, userAddress: string): Promise; 8 | decreaseStake(amount: bigint, userAddress: string): Promise; 9 | claimRewards(userAddress: string): Promise; 10 | calculateIncreaseStakeFee(accountAddress: string, minFee: bigint): Promise; 11 | calculateDecreaseStakeFee(accountAddress: string, minFee: bigint): Promise; 12 | private getUserStateBoxName; 13 | private getApplyRateChangeTxnIfNeeded; 14 | private getUserBoxPaymentTxnIfNeeded; 15 | private getUserBoxPaymentTxn; 16 | private shouldApplyRateChange; 17 | private getApplyRateChangeTxn; 18 | } 19 | export { TinymanSTAlgoClient }; 20 | -------------------------------------------------------------------------------- /dist/liquid-stake/tAlgoClient.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk from "algosdk"; 2 | import { SupportedNetwork } from "../util/commonTypes"; 3 | import TinymanBaseClient from "../util/client/base/baseClient"; 4 | declare class TinymanTAlgoClient extends TinymanBaseClient { 5 | constructor(algod: algosdk.Algodv2, network: SupportedNetwork); 6 | sync(userAddress: string): Promise; 7 | mint(amount: bigint, userAddress: string): Promise; 8 | burn(amount: bigint, userAddress: string): Promise; 9 | /** 10 | * Retrieves the current ratio of ALGO to tALGO in base units. 11 | * The ratio is calculated as (algoAmount / tAlgoAmount) * 10^12. 12 | * 13 | * @returns {Promise} The current ALGO to tALGO ratio. 14 | */ 15 | getRatio(): Promise; 16 | /** 17 | * Retrieves the circulating supply of minted tALGO in base units. 18 | * 19 | * @returns {Promise} 20 | */ 21 | getCirculatingSupply(): Promise; 22 | } 23 | export { TinymanTAlgoClient }; 24 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import {CONTRACT_VERSION} from "./contract/constants"; 2 | import {ContractVersionValue} from "./contract/types"; 3 | import {encodeString} from "./util/util"; 4 | 5 | class TinymanJSSDKConfig { 6 | /** Identifier name of the SDK user */ 7 | clientName: string; 8 | 9 | constructor() { 10 | this.clientName = "tinyman-js-sdk"; 11 | } 12 | 13 | getClientName() { 14 | return this.clientName; 15 | } 16 | 17 | setClientName(name: string) { 18 | this.clientName = name; 19 | } 20 | 21 | /** 22 | * @returns {Uint8Array} - encoded note includings version with client name 23 | */ 24 | getAppCallTxnNoteWithClientName( 25 | contractVersion: ContractVersionValue, 26 | extraData?: Record 27 | ): Uint8Array { 28 | const versionMarker = 29 | contractVersion === CONTRACT_VERSION.V1_1 ? "v1" : contractVersion; 30 | const data = JSON.stringify({origin: this.clientName, ...extraData}); 31 | 32 | return encodeString(`tinyman/${versionMarker}:j${data}`); 33 | } 34 | } 35 | 36 | export const tinymanJSSDKConfig = new TinymanJSSDKConfig(); 37 | -------------------------------------------------------------------------------- /src/governance/vault/utils.ts: -------------------------------------------------------------------------------- 1 | import {WEEK} from "../constants"; 2 | import {MAX_LOCK_TIME, TWO_TO_THE_64} from "./constants"; 3 | 4 | function getStartTimestampOfWeek(timestamp: number, isFloor = false) { 5 | const numberOfWeeks = timestamp / WEEK; 6 | 7 | return (isFloor ? Math.floor(numberOfWeeks) : Math.ceil(numberOfWeeks)) * WEEK; 8 | } 9 | 10 | function getNewTotalPowerTimestamps(oldTimeStamp: number, newTimeStamp: number) { 11 | if (oldTimeStamp > newTimeStamp) { 12 | throw new Error("Old timestamp must be less than or equal to new timestamp"); 13 | } 14 | 15 | const timestamps: number[] = []; 16 | 17 | let weekTimeStamp = getStartTimestampOfWeek(oldTimeStamp) + WEEK; 18 | 19 | while (weekTimeStamp < newTimeStamp) { 20 | timestamps.push(weekTimeStamp); 21 | 22 | weekTimeStamp += WEEK; 23 | } 24 | 25 | timestamps.push(newTimeStamp); 26 | 27 | return timestamps; 28 | } 29 | 30 | function getSlope(lockedAmount: number) { 31 | return Math.floor((lockedAmount * TWO_TO_THE_64) / MAX_LOCK_TIME); 32 | } 33 | 34 | export {getNewTotalPowerTimestamps, getStartTimestampOfWeek, getSlope}; 35 | -------------------------------------------------------------------------------- /.github/workflows/new-release.yml: -------------------------------------------------------------------------------- 1 | name: "New Release" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | if: github.repository_owner == 'tinymanorg' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 18 17 | registry-url: https://registry.npmjs.org/ 18 | - run: npm install 19 | - run: npm test 20 | - run: npm run build 21 | 22 | - id: publish-to-npm 23 | uses: JS-DevTools/npm-publish@v3 24 | with: 25 | token: ${{ secrets.NPM_TOKEN }} # This token should be added from repo settings 26 | strategy: upgrade 27 | 28 | - id: create-gh-release 29 | uses: actions/create-release@v1 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token 32 | with: 33 | tag_name: ${{ steps.publish-to-npm.outputs.version }} 34 | release_name: ${{ steps.publish-to-npm.outputs.version }} 35 | -------------------------------------------------------------------------------- /dist/governance/staking-voting/storage.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | declare class StakingDistributionProposal { 3 | index: number; 4 | creationTimestamp: number; 5 | votingStartTimestamp: number; 6 | votingEndTimestamp: number; 7 | votingPower: number; 8 | voteCount: number; 9 | isCancelled: boolean; 10 | constructor(index: number, creationTimestamp: number, votingStartTimestamp: number, votingEndTimestamp: number, votingPower: number, voteCount: number, isCancelled: boolean); 11 | } 12 | declare function getStakingDistributionProposalBoxName(proposalId: string): Uint8Array; 13 | declare function getStakingAttendanceSheetBoxName(sender: string, boxIndex: number): Uint8Array; 14 | declare function getStakingVoteBoxName(proposalIndex: number, assetId: number): Uint8Array; 15 | declare function getStakingDistributionProposal(algod: Algodv2, appId: number, proposalId: string): Promise; 16 | export { getStakingAttendanceSheetBoxName, getStakingDistributionProposal, getStakingDistributionProposalBoxName, getStakingVoteBoxName, StakingDistributionProposal }; 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Tinyman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/contract/base/contract.ts: -------------------------------------------------------------------------------- 1 | import {LogicSigAccount} from "algosdk"; 2 | 3 | import {SupportedNetwork} from "../../util/commonTypes"; 4 | import {V1_1ValidatorApp} from "../v1_1/types"; 5 | import {V2ValidatorApp} from "../v2/types"; 6 | 7 | export interface ValidatorAppSchema { 8 | numLocalInts: number; 9 | numLocalByteSlices: number; 10 | numGlobalInts: number; 11 | numGlobalByteSlices: number; 12 | } 13 | 14 | export abstract class BaseTinymanContract< 15 | ValidatorApp extends V1_1ValidatorApp | V2ValidatorApp 16 | > { 17 | schema: ValidatorAppSchema; 18 | 19 | constructor(validatorApp: ValidatorApp) { 20 | this.schema = { 21 | numLocalInts: validatorApp.local_state_schema.num_uints, 22 | numLocalByteSlices: validatorApp.local_state_schema.num_byte_slices, 23 | numGlobalInts: validatorApp.global_state_schema.num_uints, 24 | numGlobalByteSlices: validatorApp.global_state_schema.num_byte_slices 25 | }; 26 | } 27 | 28 | abstract generateLogicSigAccountForPool(params: { 29 | network: SupportedNetwork; 30 | asset1ID: number; 31 | asset2ID: number; 32 | }): LogicSigAccount; 33 | } 34 | -------------------------------------------------------------------------------- /src/util/pool/poolTypes.ts: -------------------------------------------------------------------------------- 1 | import {LogicSigAccount} from "algosdk"; 2 | 3 | import {ContractVersionValue} from "../../contract/types"; 4 | 5 | export enum PoolStatus { 6 | NOT_CREATED = "not created", 7 | BOOTSTRAP = "bootstrap", 8 | READY = "ready", 9 | ERROR = "error" 10 | } 11 | 12 | export interface V1PoolInfo { 13 | account: LogicSigAccount; 14 | contractVersion: ContractVersionValue; 15 | validatorAppID: number; 16 | asset1ID: number; 17 | asset2ID: number; 18 | status: PoolStatus; 19 | poolTokenID?: number; 20 | } 21 | 22 | export type V2PoolInfo = V1PoolInfo & { 23 | issuedPoolTokens?: bigint; 24 | asset1Reserves?: bigint; 25 | asset2Reserves?: bigint; 26 | asset1ProtocolFees?: bigint; 27 | asset2ProtocolFees?: bigint; 28 | totalFeeShare?: bigint; 29 | protocolFeeRatio?: number; 30 | cumulativePriceUpdateTimeStamp?: number; 31 | }; 32 | 33 | export interface PoolReserves { 34 | asset1: bigint; 35 | asset2: bigint; 36 | issuedLiquidity: bigint; 37 | round: bigint; 38 | } 39 | 40 | export interface PoolAssets { 41 | asset1ID: number; 42 | asset2ID: number; 43 | poolTokenID: number; 44 | } 45 | -------------------------------------------------------------------------------- /dist/util/pool/poolTypes.d.ts: -------------------------------------------------------------------------------- 1 | import { LogicSigAccount } from "algosdk"; 2 | import { ContractVersionValue } from "../../contract/types"; 3 | export declare enum PoolStatus { 4 | NOT_CREATED = "not created", 5 | BOOTSTRAP = "bootstrap", 6 | READY = "ready", 7 | ERROR = "error" 8 | } 9 | export interface V1PoolInfo { 10 | account: LogicSigAccount; 11 | contractVersion: ContractVersionValue; 12 | validatorAppID: number; 13 | asset1ID: number; 14 | asset2ID: number; 15 | status: PoolStatus; 16 | poolTokenID?: number; 17 | } 18 | export type V2PoolInfo = V1PoolInfo & { 19 | issuedPoolTokens?: bigint; 20 | asset1Reserves?: bigint; 21 | asset2Reserves?: bigint; 22 | asset1ProtocolFees?: bigint; 23 | asset2ProtocolFees?: bigint; 24 | totalFeeShare?: bigint; 25 | protocolFeeRatio?: number; 26 | cumulativePriceUpdateTimeStamp?: number; 27 | }; 28 | export interface PoolReserves { 29 | asset1: bigint; 30 | asset2: bigint; 31 | issuedLiquidity: bigint; 32 | round: bigint; 33 | } 34 | export interface PoolAssets { 35 | asset1ID: number; 36 | asset2ID: number; 37 | poolTokenID: number; 38 | } 39 | -------------------------------------------------------------------------------- /src/governance/proposal-voting/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | import {BOX_FLAT_MIN_BALANCE, BOX_BYTE_MIN_BALANCE} from "../constants"; 3 | 4 | const PROPOSAL_BOX_PREFIX = encodeString("p"); 5 | const ATTENDANCE_SHEET_BOX_PREFIX = encodeString("a"); 6 | 7 | const ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; 8 | const PROPOSAL_BOX_SIZE = 116 + 64 + 32; 9 | 10 | const PROPOSAL_BOX_COST = 11 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (60 + PROPOSAL_BOX_SIZE); 12 | const ATTENDANCE_SHEET_BOX_COST = 13 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (41 + ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE); 14 | 15 | enum ProposalVote { 16 | Against = 0, 17 | For = 1, 18 | Abstain = 2 19 | } 20 | const EXECUTION_HASH_SIZE = 34; 21 | 22 | const CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT = new Uint8Array( 23 | EXECUTION_HASH_SIZE 24 | ); 25 | 26 | export { 27 | PROPOSAL_BOX_PREFIX, 28 | PROPOSAL_BOX_SIZE, 29 | PROPOSAL_BOX_COST, 30 | ProposalVote, 31 | ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE, 32 | ATTENDANCE_SHEET_BOX_PREFIX, 33 | ATTENDANCE_SHEET_BOX_COST, 34 | EXECUTION_HASH_SIZE, 35 | CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT 36 | }; 37 | -------------------------------------------------------------------------------- /dist/util/asset/assetUtils.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction } from "../commonTypes"; 3 | export declare function generateOptIntoAssetTxns({ client, assetID, initiatorAddr }: { 4 | client: Algodv2; 5 | assetID: number; 6 | initiatorAddr: string; 7 | }): Promise; 8 | /** 9 | * @param asset_1 - Asset 1 of the pool 10 | * @param asset_2 - Asset 2 of the pool 11 | * @returns Array of assets, ordered by descending asset id 12 | */ 13 | export declare function prepareAssetPairData(asset_1: Asset, asset_2: Asset): [Omit & { 16 | id: number; 17 | }, Omit & { 18 | id: number; 19 | }]; 20 | /** 21 | * @returns Array of given asset ids, bigger first 22 | */ 23 | export declare function sortAssetIds(asset1ID: number, asset2ID: number): number[]; 24 | /** 25 | * @returns `true` if the given asset id is the ALGO asset id 26 | */ 27 | export declare function isAlgo(id: number | string): boolean; 28 | /** 29 | * @returns Asset id as a number 30 | */ 31 | export declare function getAssetId(asset: { 32 | id: string | number; 33 | }): number; 34 | -------------------------------------------------------------------------------- /src/folks-lending-pools/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility function for converting the Algorand key-value schema into a plain object. 3 | * 4 | * Algorand store keys in base64 encoding and store values as either bytes or unsigned integers depending 5 | * on the type. This function decodes this information into a more human friendly structure. 6 | * 7 | * @param kv Algorand key-value data structure to parse. 8 | * 9 | * @returns Key value dictionary parsed from the argument. 10 | */ 11 | export function parseState(kv: any) { 12 | // Transform algorand key-value schema. 13 | const res: any = {}; 14 | 15 | for (const elem of kv) { 16 | const key = new TextDecoder().decode(Buffer.from(elem.key, "base64")); 17 | let val: string | number; 18 | 19 | if (elem.value.type === 1) { 20 | val = elem.value.bytes; 21 | } else { 22 | val = elem.value.uint; 23 | } 24 | res[key] = val; 25 | } 26 | return res; 27 | } 28 | 29 | export function mulScale(n1: bigint, n2: bigint, scale: bigint): bigint { 30 | return (n1 * n2) / scale; 31 | } 32 | 33 | export function divScale(n1: bigint, n2: bigint, scale: bigint): bigint { 34 | return (n1 * scale) / n2; 35 | } 36 | -------------------------------------------------------------------------------- /src/util/error/SwapQuoteError.ts: -------------------------------------------------------------------------------- 1 | export enum SwapQuoteErrorType { 2 | SwapRouterStaleDataError = "SwapRouterStaleDataError", 3 | SwapRouterNoRouteError = "SwapRouterNoRouteError", 4 | SwapRouterLowSwapAmountError = "SwapRouterLowSwapAmountError", 5 | SwapRouterInsufficientReservesError = "SwapRouterInsufficientReservesError", 6 | SwapRouterPoolHasNoLiquidityError = "SwapRouterPoolHasNoLiquidityError", 7 | NoAvailablePoolError = "NoAvailablePoolError", 8 | OutputAmountExceedsAvailableLiquidityError = "OutputAmountExceedsAvailableLiquidityError", 9 | UnknownError = "UnknownError", 10 | LowSwapAmountError = "LowSwapAmountError", 11 | AssetDoesNotBelongToPoolError = "AssetDoesNotBelongToPoolError", 12 | InvalidSwapTypeError = "InvalidSwapTypeError" 13 | } 14 | 15 | class SwapQuoteError extends Error { 16 | type: SwapQuoteErrorType; 17 | message: string; 18 | 19 | constructor(type: SwapQuoteErrorType, message: string) { 20 | super(message); 21 | 22 | this.type = type; 23 | this.message = message; 24 | 25 | if (Error.captureStackTrace) { 26 | Error.captureStackTrace(this, SwapQuoteError); 27 | } 28 | } 29 | } 30 | 31 | export default SwapQuoteError; 32 | -------------------------------------------------------------------------------- /src/governance/transactions.ts: -------------------------------------------------------------------------------- 1 | import algosdk, {SuggestedParams} from "algosdk"; 2 | import {v4} from "uuid"; 3 | 4 | import {encodeString} from "../util/util"; 5 | 6 | function prepareBudgetIncreaseTxn({ 7 | sender, 8 | index, 9 | suggestedParams, 10 | boxes = [], 11 | extraAppArgs = [], 12 | foreignApps = [] 13 | }: { 14 | sender: string; 15 | index: number; 16 | suggestedParams: SuggestedParams; 17 | extraAppArgs?: Uint8Array[]; 18 | foreignApps?: number[]; 19 | boxes?: algosdk.BoxReference[]; 20 | }) { 21 | const emptyBoxesCount = Math.max(0, 8 - foreignApps.length - boxes.length); 22 | const emptyBoxes = Array(emptyBoxesCount).fill({ 23 | appIndex: 0, 24 | name: encodeString("") 25 | }); 26 | 27 | const increaseBudgetTxnsBoxes = [...boxes, ...emptyBoxes]; 28 | 29 | return algosdk.makeApplicationNoOpTxnFromObject({ 30 | sender, 31 | suggestedParams, 32 | appIndex: index, 33 | appArgs: [encodeString("increase_budget"), ...extraAppArgs], 34 | foreignApps, 35 | boxes: increaseBudgetTxnsBoxes, 36 | // Make transactions unique to avoid "transaction already in ledger" error 37 | note: encodeString(v4()) 38 | }); 39 | } 40 | 41 | export {prepareBudgetIncreaseTxn}; 42 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/flexible.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 3 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V2FlexibleAddLiquidityQuote } from "./types"; 5 | import { AssetWithAmountAndDecimals, AssetWithIdAndAmount } from "../../util/asset/assetModels"; 6 | export * from "./common"; 7 | /** 8 | * @returns A quote for the given asset 1 and asset 2 values. 9 | * This does not execute any transactions. 10 | */ 11 | export declare function getQuote({ pool, slippage, asset1, asset2 }: { 12 | pool: V2PoolInfo; 13 | asset1: AssetWithAmountAndDecimals; 14 | asset2: AssetWithAmountAndDecimals; 15 | slippage?: number; 16 | }): V2FlexibleAddLiquidityQuote; 17 | export declare function generateTxns({ client, network, poolAddress, asset1In, asset2In, poolTokenOut, initiatorAddr, minPoolTokenAssetAmount }: { 18 | client: Algodv2; 19 | network: SupportedNetwork; 20 | poolAddress: string; 21 | asset1In: AssetWithIdAndAmount; 22 | asset2In: AssetWithIdAndAmount; 23 | poolTokenOut: AssetWithIdAndAmount; 24 | initiatorAddr: string; 25 | minPoolTokenAssetAmount: bigint; 26 | }): Promise; 27 | -------------------------------------------------------------------------------- /dist/governance/vault/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const MAX_LOCK_TIME = 126144000; 2 | declare const MIN_LOCK_AMOUNT = 10000000; 3 | declare const MIN_LOCK_AMOUNT_INCREMENT = 10000000; 4 | declare const TWO_TO_THE_64: number; 5 | declare const ACCOUNT_STATE_BOX_SIZE = 32; 6 | declare const SLOPE_CHANGE_BOX_SIZE = 16; 7 | declare const ACCOUNT_POWER_SIZE = 48; 8 | declare const ACCOUNT_POWER_BOX_SIZE = 1008; 9 | declare const ACCOUNT_POWER_BOX_ARRAY_LEN = 21; 10 | declare const TOTAL_POWER_SIZE = 48; 11 | declare const TOTAL_POWER_BOX_SIZE = 1008; 12 | declare const TOTAL_POWER_BOX_ARRAY_LEN = 21; 13 | declare const TOTAL_POWERS: Uint8Array; 14 | declare const SLOPE_CHANGES: Uint8Array; 15 | declare const ACCOUNT_STATE_BOX_COST: number; 16 | declare const SLOPE_CHANGE_BOX_COST: number; 17 | declare const ACCOUNT_POWER_BOX_COST: number; 18 | declare const TOTAL_POWER_BOX_COST: number; 19 | export { ACCOUNT_STATE_BOX_SIZE, SLOPE_CHANGE_BOX_SIZE, ACCOUNT_POWER_SIZE, ACCOUNT_POWER_BOX_SIZE, ACCOUNT_POWER_BOX_ARRAY_LEN, TOTAL_POWER_BOX_ARRAY_LEN, TOTAL_POWER_BOX_SIZE, TOTAL_POWER_SIZE, TOTAL_POWERS, MAX_LOCK_TIME, MIN_LOCK_AMOUNT, MIN_LOCK_AMOUNT_INCREMENT, TWO_TO_THE_64, SLOPE_CHANGES, ACCOUNT_STATE_BOX_COST, SLOPE_CHANGE_BOX_COST, ACCOUNT_POWER_BOX_COST, TOTAL_POWER_BOX_COST }; 20 | -------------------------------------------------------------------------------- /src/governance/constants.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "../util/commonTypes"; 2 | 3 | const HOUR_IN_S = 60 * 60; 4 | const DAY_IN_S = 24 * HOUR_IN_S; 5 | const WEEK_IN_S = 7 * DAY_IN_S; 6 | const SECOND_IN_MS = 1000; 7 | 8 | const VAULT_APP_ID: Record = { 9 | testnet: 480164661, 10 | mainnet: 2200606875 11 | }; 12 | 13 | const STAKING_VOTING_APP_ID: Record = { 14 | testnet: 360907790, 15 | mainnet: 2200609638 16 | }; 17 | 18 | const REWARDS_APP_ID: Record = { 19 | testnet: 336189106, 20 | mainnet: 2200608153 21 | }; 22 | 23 | const PROPOSAL_VOTING_APP_ID: Record = { 24 | testnet: 383416252, 25 | mainnet: 2200608887 26 | }; 27 | 28 | const BOX_FLAT_MIN_BALANCE = 2_500; 29 | const BOX_BYTE_MIN_BALANCE = 400; 30 | 31 | const HOUR = 60 * 60; 32 | const DAY = 24 * HOUR; 33 | const WEEK = 7 * DAY; 34 | 35 | export {HOUR, DAY, WEEK}; 36 | 37 | const TWO_TO_THE_64 = 2 ** 64; 38 | 39 | export { 40 | VAULT_APP_ID, 41 | STAKING_VOTING_APP_ID, 42 | REWARDS_APP_ID, 43 | BOX_BYTE_MIN_BALANCE, 44 | BOX_FLAT_MIN_BALANCE, 45 | TWO_TO_THE_64, 46 | WEEK_IN_S, 47 | DAY_IN_S, 48 | HOUR_IN_S, 49 | SECOND_IN_MS, 50 | PROPOSAL_VOTING_APP_ID 51 | }; 52 | -------------------------------------------------------------------------------- /src/add-liquidity/v2/constants.ts: -------------------------------------------------------------------------------- 1 | export enum V2AddLiquidityType { 2 | SINGLE = "single", 3 | FLEXIBLE = "flexible", 4 | INITIAL = "initial" 5 | } 6 | 7 | export const V2AddLiquidityTxnIndices = { 8 | [V2AddLiquidityType.FLEXIBLE]: { 9 | ASSET1_IN_TXN: 0, 10 | ASSET2_IN_TXN: 1, 11 | VALIDATOR_APP_CALL_TXN: 2 12 | }, 13 | [V2AddLiquidityType.SINGLE]: { 14 | ASSET_IN_TXN: 0, 15 | VALIDATOR_APP_CALL_TXN: 1 16 | }, 17 | [V2AddLiquidityType.INITIAL]: { 18 | ASSET1_IN_TXN: 0, 19 | ASSET2_IN_TXN: 1, 20 | VALIDATOR_APP_CALL_TXN: 2 21 | } 22 | }; 23 | 24 | export const V2_ADD_LIQUIDITY_INNER_TXN_COUNT: Record = { 25 | [V2AddLiquidityType.INITIAL]: 1, 26 | [V2AddLiquidityType.SINGLE]: 2, 27 | [V2AddLiquidityType.FLEXIBLE]: 2 28 | }; 29 | 30 | /** 31 | * Number of transactions in the add liquidity transaction group (excluding inner transactions) 32 | */ 33 | export const V2_ADD_LIQUIDITY_TXN_COUNT: Record = { 34 | /** Consists of: App Call, Asset 1 In, Asset 2 In */ 35 | [V2AddLiquidityType.INITIAL]: 3, 36 | /** Consists of: App Call, Asset 1 In, Asset 2 In */ 37 | [V2AddLiquidityType.FLEXIBLE]: 3, 38 | /** Consists of: App Call, Asset In */ 39 | [V2AddLiquidityType.SINGLE]: 2 40 | }; 41 | -------------------------------------------------------------------------------- /src/bootstrap/common/utils.ts: -------------------------------------------------------------------------------- 1 | import {getContract} from "../../contract"; 2 | import {ContractVersionValue} from "../../contract/types"; 3 | import { 4 | BASE_MINIMUM_BALANCE, 5 | MINIMUM_BALANCE_REQUIRED_PER_ASSET, 6 | MINIMUM_BALANCE_REQUIRED_PER_APP, 7 | MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE, 8 | MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA 9 | } from "../../util/constant"; 10 | 11 | /** 12 | * @returns Minimum balance for a pool account 13 | */ 14 | export function getPoolAccountMinBalance( 15 | contractVersion: ContractVersionValue, 16 | isAlgoPool: boolean 17 | ) { 18 | let { 19 | schema: {numLocalInts, numLocalByteSlices} 20 | } = getContract(contractVersion); 21 | 22 | let fee = 23 | BASE_MINIMUM_BALANCE + 24 | MINIMUM_BALANCE_REQUIRED_PER_ASSET + // min balance to create asset 25 | MINIMUM_BALANCE_REQUIRED_PER_ASSET + // fee + min balance to opt into asset 1 26 | MINIMUM_BALANCE_REQUIRED_PER_APP + // min balance to opt into validator app 27 | MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE * BigInt(numLocalInts) + 28 | MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA * BigInt(numLocalByteSlices); 29 | 30 | if (!isAlgoPool) { 31 | fee += MINIMUM_BALANCE_REQUIRED_PER_ASSET; // min balance to opt into asset 2 32 | } 33 | 34 | return fee; 35 | } 36 | -------------------------------------------------------------------------------- /src/remove-liquidity/v2/types.ts: -------------------------------------------------------------------------------- 1 | import {AssetWithIdAndAmount} from "../../util/asset/assetModels"; 2 | 3 | export interface V2QuoteAssetAmount { 4 | assetId: number; 5 | amount: bigint; 6 | } 7 | 8 | /** Shape of an object containing information about a remove liquidity quote. */ 9 | export interface V2RemoveLiquidityQuote { 10 | /** The round that this quote is based on. */ 11 | round: number; 12 | asset1Out: V2QuoteAssetAmount; 13 | asset2Out: V2QuoteAssetAmount; 14 | /** input liquidity */ 15 | poolTokenIn: V2QuoteAssetAmount; 16 | } 17 | 18 | export interface V2SingleAssetRemoveLiquidityQuote { 19 | /** The round that this quote is based on. */ 20 | round: number; 21 | assetOut: V2QuoteAssetAmount; 22 | poolTokenIn: V2QuoteAssetAmount; 23 | internalSwapQuote: V2InternalSwapQuote; 24 | } 25 | 26 | interface V2InternalSwapQuote { 27 | amountIn: V2QuoteAssetAmount; 28 | amountOut: V2QuoteAssetAmount; 29 | swapFees: V2QuoteAssetAmount; 30 | priceImpact: number; 31 | } 32 | 33 | export interface V2RemoveLiquidityExecution { 34 | /** 35 | * Can be `undefined` if the execution was successful, but there was an issue while 36 | * extracting the output asset data fron the transaction response 37 | */ 38 | outputAssets: AssetWithIdAndAmount[] | undefined; 39 | txnID: string; 40 | } 41 | -------------------------------------------------------------------------------- /src/order/utils.ts: -------------------------------------------------------------------------------- 1 | import {intToBytes, joinByteArrays} from "../util/util"; 2 | 3 | function createPaddedByteArray( 4 | elements: number[], 5 | length = 8, 6 | paddingValue = 0, 7 | byteSize = 8 8 | ) { 9 | const array = new Array(length).fill(paddingValue); 10 | 11 | array.splice(0, elements.length, ...elements); 12 | 13 | return joinByteArrays(...array.map((num) => intToBytes(num, byteSize))); 14 | } 15 | 16 | // Fetch and compile the approval and clear programs 17 | async function getCompiledPrograms() { 18 | const approvalSourceResponse = await fetch( 19 | "https://raw.githubusercontent.com/tinymanorg/tinyman-order-protocol/main/contracts/order/build/order_approval.teal.tok" 20 | ); 21 | const clearSourceResponse = await fetch( 22 | "https://raw.githubusercontent.com/tinymanorg/tinyman-order-protocol/main/contracts/order/build/order_clear_state.teal.tok" 23 | ); 24 | 25 | const approvalSourceResponseBuffer = await approvalSourceResponse.arrayBuffer(); 26 | const approvalProgram = new Uint8Array(approvalSourceResponseBuffer); 27 | 28 | const clearSourceResponseBuffer = await clearSourceResponse.arrayBuffer(); 29 | const clearProgram = new Uint8Array(clearSourceResponseBuffer); 30 | 31 | return {approvalProgram, clearProgram}; 32 | } 33 | 34 | export {createPaddedByteArray, getCompiledPrograms}; 35 | -------------------------------------------------------------------------------- /dist/validator.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { ContractVersionValue } from "./contract/types"; 3 | import { SignerTransaction, SupportedNetwork } from "./util/commonTypes"; 4 | export declare const OPT_IN_VALIDATOR_APP_PROCESS_TXN_COUNT = 1; 5 | export declare const VALIDATOR_APP_ID: Record>; 6 | /** 7 | * Get the Validator App ID for a network. 8 | * 9 | * @param {SupportedNetwork} network "mainnet" | "testnet". 10 | * @param {ContractVersion} version contract version. 11 | * @returns the Validator App ID 12 | */ 13 | export declare function getValidatorAppID(network: SupportedNetwork, contractVersion: ContractVersionValue): number; 14 | export declare function generateOptIntoValidatorTxns({ client, network, contractVersion, initiatorAddr }: { 15 | client: Algodv2; 16 | network: SupportedNetwork; 17 | contractVersion: ContractVersionValue; 18 | initiatorAddr: string; 19 | }): Promise; 20 | export declare const OPT_OUT_VALIDATOR_APP_PROCESS_TXN_COUNT = 1; 21 | export declare function generateOptOutOfValidatorTxns({ client, network, contractVersion, initiatorAddr }: { 22 | client: Algodv2; 23 | network: SupportedNetwork; 24 | contractVersion: ContractVersionValue; 25 | initiatorAddr: string; 26 | }): Promise; 27 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v2/types.d.ts: -------------------------------------------------------------------------------- 1 | import { AssetWithIdAndAmount } from "../../util/asset/assetModels"; 2 | export interface V2QuoteAssetAmount { 3 | assetId: number; 4 | amount: bigint; 5 | } 6 | /** Shape of an object containing information about a remove liquidity quote. */ 7 | export interface V2RemoveLiquidityQuote { 8 | /** The round that this quote is based on. */ 9 | round: number; 10 | asset1Out: V2QuoteAssetAmount; 11 | asset2Out: V2QuoteAssetAmount; 12 | /** input liquidity */ 13 | poolTokenIn: V2QuoteAssetAmount; 14 | } 15 | export interface V2SingleAssetRemoveLiquidityQuote { 16 | /** The round that this quote is based on. */ 17 | round: number; 18 | assetOut: V2QuoteAssetAmount; 19 | poolTokenIn: V2QuoteAssetAmount; 20 | internalSwapQuote: V2InternalSwapQuote; 21 | } 22 | interface V2InternalSwapQuote { 23 | amountIn: V2QuoteAssetAmount; 24 | amountOut: V2QuoteAssetAmount; 25 | swapFees: V2QuoteAssetAmount; 26 | priceImpact: number; 27 | } 28 | export interface V2RemoveLiquidityExecution { 29 | /** 30 | * Can be `undefined` if the execution was successful, but there was an issue while 31 | * extracting the output asset data fron the transaction response 32 | */ 33 | outputAssets: AssetWithIdAndAmount[] | undefined; 34 | txnID: string; 35 | } 36 | export {}; 37 | -------------------------------------------------------------------------------- /src/util/constant.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "./commonTypes"; 2 | 3 | export const MAX_SLIPPAGE_FRACTION_DIGITS = 6; 4 | 5 | // The fee paying transaction at group index 0 should have a note value set to distinguish it from other Pay transactions in the group which might have the exact same value. 6 | export const DEFAULT_FEE_TXN_NOTE = Uint8Array.from([1]); 7 | 8 | export const BASE_MINIMUM_BALANCE = 100_000n; 9 | export const MINIMUM_BALANCE_REQUIRED_PER_ASSET = 100_000n; 10 | export const MINIMUM_BALANCE_REQUIRED_PER_APP = 100_000n; 11 | export const MINIMUM_BALANCE_REQUIRED_PER_CREATED_APP = 100_000n; 12 | export const MINIMUM_BALANCE_REQUIRED_PER_EXTRA_APP_PAGE = 100_000n; 13 | export const MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA = 50_000n; 14 | export const MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE = 28_500n; 15 | 16 | export const MINIMUM_ADD_LIQUIDITY_AMOUNT = 1000n; 17 | 18 | export const DEFAULT_WAIT_FOR_CONFIRMATION_ROUNDS = 1000; 19 | 20 | export const TINYMAN_ANALYTICS_API_BASE_URLS: Record< 21 | SupportedNetwork, 22 | {base: string; v1: string} 23 | > = { 24 | mainnet: { 25 | base: "https://mainnet.analytics.tinyman.org/api", 26 | v1: "https://mainnet.analytics.tinyman.org/api/v1" 27 | }, 28 | testnet: { 29 | base: "https://testnet.analytics.tinyman.org/api", 30 | v1: "https://testnet.analytics.tinyman.org/api/v1" 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/swap/v2/util.ts: -------------------------------------------------------------------------------- 1 | import {SwapType, DEFAULT_SWAP_FEE_RATE} from "../constants"; 2 | import {V2_SWAP_APP_CALL_INNER_TXN_COUNT, V2_SWAP_TXN_COUNT} from "./constants"; 3 | 4 | /** 5 | * @returns the total fee for the swap operation including all transactions (including inner transactions) fees 6 | */ 7 | export function getV2SwapTotalFee(mode: SwapType, minFee: bigint) { 8 | const totalTxnCount = BigInt( 9 | V2_SWAP_APP_CALL_INNER_TXN_COUNT[mode] + V2_SWAP_TXN_COUNT 10 | ); 11 | 12 | return totalTxnCount * minFee; 13 | } 14 | 15 | /** 16 | * @returns the minimum possible amount of assetIn that can be used for swap in V2 pools 17 | */ 18 | export function getV2MinSwapAssetInAmount(feeRate: number = DEFAULT_SWAP_FEE_RATE) { 19 | return Math.ceil(1 / feeRate); 20 | } 21 | 22 | /** 23 | * @returns true if the amount of assetIn is less than the minimum possible amount of assetIn that can be used for swap in V2 pools 24 | */ 25 | export function isSwapAssetInAmountLow( 26 | amount: number, 27 | feeRate: number = DEFAULT_SWAP_FEE_RATE 28 | ) { 29 | return amount < getV2MinSwapAssetInAmount(feeRate); 30 | } 31 | 32 | export function getSwapAppCallFeeAmount(swapType: SwapType, minFee: bigint) { 33 | // Add +1 to account for the outer txn fee 34 | const totalTxnCount = BigInt(V2_SWAP_APP_CALL_INNER_TXN_COUNT[swapType] + 1); 35 | 36 | return totalTxnCount * minFee; 37 | } 38 | -------------------------------------------------------------------------------- /dist/governance/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2, Transaction } from "algosdk"; 2 | declare function getRawBoxValue(algod: Algodv2, appId: number, boxName: Uint8Array): Promise; 3 | declare function doesBoxExist(algod: Algodv2, appId: number, boxName: Uint8Array): Promise; 4 | declare function getBias(slope: number, timeDelta: number): number; 5 | /** 6 | * Calculates the tiny power at a given timestamp 7 | * @param lockAmount - amount of tokens locked 8 | * @param lockEndTime - timestamp of the end of the lock, in seconds 9 | * @param timeStamp - timestamp of the time to calculate the tiny power for, in seconds 10 | * @returns tiny power at the given timestamp 11 | */ 12 | declare function calculateTinyPower(lockAmount: number, lockEndTime: number, timeStamp?: number): number; 13 | declare function getCumulativePowerDelta(bias: number, slope: number, timeDelta: number): number; 14 | declare function getGlobalState(algod: Algodv2, appId: number): Promise>; 15 | declare function generateCidFromProposalMetadata(metadata: Record): Promise; 16 | declare function combineAndRegroupTxns(...txns: Transaction[][]): Transaction[]; 17 | declare function getAllBoxNames(algod: Algodv2, appId: number): Promise; 18 | export { calculateTinyPower, combineAndRegroupTxns, doesBoxExist, generateCidFromProposalMetadata, getAllBoxNames, getBias, getCumulativePowerDelta, getGlobalState, getRawBoxValue }; 19 | -------------------------------------------------------------------------------- /dist/util/client/base/appClient.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { StructDefinition } from "./types"; 3 | import TinymanBaseClient from "./baseClient"; 4 | import { SupportedNetwork } from "../../commonTypes"; 5 | /** 6 | * Abstract client for Tinyman applications that may not have an app ID initially 7 | * This class overrides the base non-nullable properties to allow null values 8 | */ 9 | declare abstract class TinymanNullableAppClient extends TinymanBaseClient { 10 | constructor(algod: Algodv2, appId: number | null, network: SupportedNetwork, structs?: Record); 11 | /** 12 | * Helper method to check if the app ID is available 13 | */ 14 | protected isAppIdAvailable(): boolean; 15 | /** 16 | * Helper method that throws an error if the app ID is not available 17 | */ 18 | protected requireAppId(): void; 19 | /** 20 | * Override getGlobal to add null check 21 | */ 22 | protected getGlobal(key: Uint8Array, defaultValue?: any, appId?: number): Promise; 23 | /** 24 | * Override boxExists to add null check 25 | */ 26 | protected boxExists(boxName: Uint8Array, appId?: number): Promise; 27 | /** 28 | * Override getBox to add null check 29 | */ 30 | protected getBox(boxName: Uint8Array, structName: string, appId?: number): Promise; 31 | } 32 | export default TinymanNullableAppClient; 33 | -------------------------------------------------------------------------------- /dist/util/client/base/nullableBaseClient.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { StructDefinition } from "./types"; 3 | import TinymanBaseClient from "./baseClient"; 4 | import { SupportedNetwork } from "../../commonTypes"; 5 | /** 6 | * Abstract client for Tinyman applications that may not have an app ID initially 7 | * This class overrides the base non-nullable properties to allow null values 8 | */ 9 | declare abstract class TinymanNullableBaseClient extends TinymanBaseClient { 10 | constructor(algod: Algodv2, appId: number | null, network: SupportedNetwork, structs?: Record); 11 | /** 12 | * Helper method to check if the app ID is available 13 | */ 14 | protected isAppIdAvailable(): boolean; 15 | /** 16 | * Helper method that throws an error if the app ID is not available 17 | */ 18 | protected requireAppId(): void; 19 | /** 20 | * Override getGlobal to add null check 21 | */ 22 | protected getGlobal(key: Uint8Array, defaultValue?: any, appId?: number): Promise; 23 | /** 24 | * Override boxExists to add null check 25 | */ 26 | protected boxExists(boxName: Uint8Array, appId?: number): Promise; 27 | /** 28 | * Override getBox to add null check 29 | */ 30 | protected getBox(boxName: Uint8Array, structName: string, appId?: number): Promise; 31 | } 32 | export default TinymanNullableBaseClient; 33 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | root: true, 5 | parser: "@typescript-eslint/parser", 6 | plugins: ["@typescript-eslint"], 7 | env: { 8 | browser: true, 9 | jest: true, 10 | es6: true 11 | }, 12 | extends: [ 13 | "@hipo/eslint-config-base", 14 | "@hipo/eslint-config-typescript", 15 | "prettier", 16 | "plugin:import/typescript" 17 | ], 18 | parserOptions: { 19 | project: path.resolve(__dirname, "./tsconfig.json"), 20 | tsconfigRootDir: __dirname, 21 | ecmaVersion: 2018, 22 | sourceType: "module", 23 | createDefaultProgram: true 24 | }, 25 | settings: { 26 | react: { 27 | version: "detect" 28 | }, 29 | "import/resolver": { 30 | typescript: {} 31 | } 32 | }, 33 | globals: {}, 34 | rules: { 35 | "@typescript-eslint/ban-ts-comment": "off", 36 | "valid-jsdoc": "off", 37 | "no-debugger": "warn", 38 | "arrow-body-style": "off", 39 | "no-magic-numbers": "off", 40 | "line-comment-position": "off", 41 | "prefer-const": "off", 42 | "max-lines": "off", 43 | "no-continue": "off", 44 | eqeqeq: "off" 45 | }, 46 | overrides: [ 47 | { 48 | files: [".eslintrc.js"], 49 | rules: { 50 | "@typescript-eslint/no-var-requires": "off" 51 | } 52 | }, 53 | { 54 | files: ["*.d.ts"], 55 | rules: { 56 | "newline-after-var": "off" 57 | } 58 | } 59 | ] 60 | }; 61 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Tinyman JS SDK Examples 2 | 3 | This is a collection of node scripts that uses tinyman-js-sdk v2 operations. 4 | 5 | ⚠️ Please be aware that the scripts are not production-ready, and are only for testing purposes. If you plan to use the scripts in production, please make sure to test and optimize them for your use case. 6 | 7 | ### File/Folder Structure 8 | 9 | - `operation` folder includes scripts that perform operations on the pool. **If you only want to see a specific operation example, you can check the files in this folder.** 10 | - `util` folder includes helper functions or constant variables that are used in the test scripts 11 | - `index.ts` includes a `main` function that runs all of the operations in order; 12 | 1. Create an account and two assets (for testing purposes) 13 | 2. (Bootstrap) Create the pool with owned assets 14 | 3. (Add Liquidity) Adds liquidity to the pool 15 | 4. (Remove Liquidity) Take out some of the owned liquidity from the pool 16 | 5. (Swap) Swap one of the assets for the other 17 | 18 | For easier testing, on the first run, `main` function creates an account and two assets (for testing purposes). The account will initiator of the operations, and the asset pair will be used for creating the pool. 19 | 20 | ### Running the test script 21 | 22 | 1. First, install the dependencies 23 | 24 | ```sh 25 | npm install 26 | ``` 27 | 28 | 2. Then run the script: 29 | ```sh 30 | npm run start 31 | ``` 32 | -------------------------------------------------------------------------------- /dist/swap/v2/router/util.d.ts: -------------------------------------------------------------------------------- 1 | import { SupportedNetwork } from "../../../util/commonTypes"; 2 | import { SwapRouterResponse } from "../../types"; 3 | declare function getSwapRouteRate(route: Pick): number; 4 | declare function getSwapRouterAppID(network: SupportedNetwork): number; 5 | declare function getAssetOutFromSwapRoute(route: Pick): { 6 | asset: Pick; 7 | amount: bigint; 8 | }; 9 | declare function getAssetInFromSwapRoute(route: Pick): { 10 | asset: Pick; 11 | amount: bigint; 12 | }; 13 | declare function getAssetInAndOutFromSwapRoute(route: Pick): { 14 | assetIn: { 15 | asset: Pick; 16 | amount: bigint; 17 | }; 18 | assetOut: { 19 | asset: Pick; 20 | amount: bigint; 21 | }; 22 | }; 23 | export { getAssetInAndOutFromSwapRoute, getAssetInFromSwapRoute, getAssetOutFromSwapRoute, getSwapRouterAppID, getSwapRouteRate }; 24 | -------------------------------------------------------------------------------- /src/liquid-stake/constants.ts: -------------------------------------------------------------------------------- 1 | import {StructDefinition} from "../util/client/base/types"; 2 | import {SupportedNetwork} from "../util/commonTypes"; 3 | 4 | const CURRENT_REWARD_RATE_PER_TIME_END_TIMESTAMP_KEY = 5 | "current_reward_rate_per_time_end_timestamp"; 6 | 7 | const STAKE_APP_ID: Record = { 8 | testnet: 724519988, 9 | mainnet: 2537013674 10 | }; 11 | 12 | const RESTAKE_APP_ID: Record = { 13 | testnet: 724676904, 14 | mainnet: 2537022861 15 | }; 16 | 17 | const VAULT_APP_ID: Record = { 18 | testnet: 480164661, 19 | mainnet: 2200606875 20 | }; 21 | 22 | const STRUCTS: Record = { 23 | UserState: { 24 | size: 32, 25 | fields: { 26 | staked_amount: { 27 | type: "int", 28 | size: 8, 29 | offset: 0 30 | }, 31 | accumulated_rewards_per_unit_at_last_update: { 32 | type: "int", 33 | size: 8, 34 | offset: 8 35 | }, 36 | accumulated_rewards: { 37 | type: "int", 38 | size: 8, 39 | offset: 16 40 | }, 41 | timestamp: { 42 | type: "int", 43 | size: 8, 44 | offset: 24 45 | } 46 | } 47 | } 48 | }; 49 | 50 | const STAKE_RATIO_COEFFICIENT = 1_000_000_000_000; 51 | 52 | export { 53 | CURRENT_REWARD_RATE_PER_TIME_END_TIMESTAMP_KEY, 54 | RESTAKE_APP_ID, 55 | STAKE_APP_ID, 56 | STRUCTS, 57 | VAULT_APP_ID, 58 | STAKE_RATIO_COEFFICIENT 59 | }; 60 | -------------------------------------------------------------------------------- /dist/order/constants.d.ts: -------------------------------------------------------------------------------- 1 | import { StructDefinition } from "../util/client/base/types"; 2 | import { SupportedNetwork } from "../util/commonTypes"; 3 | import { OrderStruct } from "./types"; 4 | declare const TOTAL_ORDER_COUNT_KEY: Uint8Array; 5 | declare const GOVERNOR_ORDER_FEE_RATE_KEY: Uint8Array; 6 | declare const GOVERNOR_FEE_RATE_POWER_THRESHOLD_KEY: Uint8Array; 7 | declare const ORDER_FEE_RATE_KEY: Uint8Array; 8 | declare const APP_LATEST_VERSION_KEY: Uint8Array; 9 | declare const APP_VERSION_KEY: Uint8Array; 10 | declare const ORDER_STRUCTS: Record; 11 | declare const ORDER_APP_GLOBAL_SCHEMA: { 12 | numUint: number; 13 | numByteSlice: number; 14 | }; 15 | declare const ORDER_APP_LOCAL_SCHEMA: { 16 | numUint: number; 17 | numByteSlice: number; 18 | }; 19 | declare const ORDER_APP_EXTRA_PAGES = 3; 20 | declare const REGISTRY_APP_ID: Record; 21 | declare const VAULT_APP_ID: Record; 22 | declare const ROUTER_APP_ID: Record; 23 | declare const MINIMUM_BALANCE_REQUIREMENT_PER_APP = 100000; 24 | declare const MINIMUM_PUT_ORDER_TRANSACTION_COUNT = 5; 25 | export { ORDER_APP_EXTRA_PAGES, ORDER_APP_GLOBAL_SCHEMA, ORDER_APP_LOCAL_SCHEMA, REGISTRY_APP_ID, ORDER_STRUCTS, TOTAL_ORDER_COUNT_KEY, VAULT_APP_ID, MINIMUM_BALANCE_REQUIREMENT_PER_APP, GOVERNOR_ORDER_FEE_RATE_KEY, GOVERNOR_FEE_RATE_POWER_THRESHOLD_KEY, ORDER_FEE_RATE_KEY, MINIMUM_PUT_ORDER_TRANSACTION_COUNT, ROUTER_APP_ID, APP_LATEST_VERSION_KEY, APP_VERSION_KEY }; 26 | -------------------------------------------------------------------------------- /dist/util/transaction/transactionUtils.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { Algodv2 } from "algosdk"; 2 | import { AssetWithIdAndAmount } from "../asset/assetModels"; 3 | import { SignerTransaction } from "../commonTypes"; 4 | export declare function getAppCallTxnResponse(client: Algodv2, txGroup: SignerTransaction[]): Promise; 5 | /** 6 | * Tries to find the app call transaction in the group, get the response, and extract the inner txns data. 7 | * @returns the inner transactions of the app call transaction or `undefined` if no app call transaction was found. 8 | */ 9 | export declare function getAppCallInnerTxns(client: Algodv2, txGroup: SignerTransaction[]): Promise; 10 | /** 11 | * Tries to find the asset related (asset transfer / payment (i.e. ALGO transfer)) 12 | * inner transactions in the app call, and return the extracted asset data. 13 | * Useful for getting the asset data after an "execute" operation. 14 | */ 15 | export declare function getAppCallInnerAssetData(client: Algodv2, txGroup: SignerTransaction[]): Promise; 16 | /** 17 | * Combines the provided signer transaction groups into one signer transaction group, with a new group ID 18 | * @param signerTransactions - The signer transaction groups to combine 19 | * @returns the combined signer transaction groups, with a new assigned group ID 20 | */ 21 | export declare function combineAndRegroupSignerTxns(...signerTransactions: SignerTransaction[][]): SignerTransaction[]; 22 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/util.d.ts: -------------------------------------------------------------------------------- 1 | import { PoolReserves } from "../../util/pool/poolTypes"; 2 | import { V2AddLiquidityType } from "./constants"; 3 | import { AssetWithAmountAndDecimals, AssetWithIdAndAmountAndDecimals } from "../../util/asset/assetModels"; 4 | import { V2AddLiquidityInternalSwapQuote } from "./types"; 5 | export declare function calculateSubsequentAddLiquidity({ reserves, totalFeeShare, asset1, asset2 }: { 6 | totalFeeShare: number | bigint; 7 | reserves: Omit; 8 | asset1: AssetWithIdAndAmountAndDecimals; 9 | asset2: AssetWithIdAndAmountAndDecimals; 10 | }): { 11 | /** Amount of the pool tokens that will be out with the operation */ 12 | poolTokenOutAmount: bigint; 13 | /** 14 | * Data about the internal swap, which will be made by the contract, 15 | * in case the given asset values doesn't satisfy the pool ratio. 16 | */ 17 | internalSwapQuote: V2AddLiquidityInternalSwapQuote; 18 | }; 19 | /** 20 | * @returns the amount of pool tokens that should be issued for the initial add liquidity operation 21 | */ 22 | export declare function calculateV2InitialLiquidityAmount(asset1: AssetWithAmountAndDecimals, asset2: AssetWithAmountAndDecimals): bigint; 23 | /** 24 | * @returns the fee that should be assigned to the app call transaction 25 | */ 26 | export declare function getV2AddLiquidityAppCallFee(mode: V2AddLiquidityType, minFee: bigint): bigint; 27 | /** 28 | * @returns the total fee for the add liquidity operation including all transaction (including inner transactions) fees 29 | */ 30 | export declare function getV2AddLiquidityTotalFee(mode: V2AddLiquidityType, minFee: bigint): bigint; 31 | -------------------------------------------------------------------------------- /dist/governance/proposal-voting/transactions.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { SuggestedParams } from "algosdk"; 2 | import { VaultAppGlobalState } from "../vault/storage"; 3 | import { ProposalVote } from "./constants"; 4 | import { Proposal } from "./storage"; 5 | import { GenerateProposalMetadataPayload } from "./types"; 6 | export declare function generateProposalMetadata({ category, description, discussionUrl, pollUrl, title }: GenerateProposalMetadataPayload): { 7 | category: string; 8 | description: string; 9 | discussion_url: string; 10 | poll_url: string; 11 | title: string; 12 | }; 13 | export declare function prepareCreateProposalTransactions({ proposalId, proposalVotingAppId, sender, vaultAppId, vaultAppGlobalState, executionHash, executor, suggestedParams, appCallNote }: { 14 | proposalVotingAppId: number; 15 | sender: string; 16 | proposalId: string; 17 | vaultAppId: number; 18 | vaultAppGlobalState: VaultAppGlobalState; 19 | executionHash?: string; 20 | executor?: Uint8Array; 21 | suggestedParams: SuggestedParams; 22 | appCallNote?: string; 23 | }): algosdk.Transaction[]; 24 | export declare function prepareCastVoteTransactions({ accountPowerIndex, createAttendanceSheetBox, proposal, proposalId, proposalVotingAppId, sender, suggestedParams, vaultAppId, vote, appCallNote }: { 25 | proposalVotingAppId: number; 26 | vaultAppId: number; 27 | sender: string; 28 | proposalId: string; 29 | proposal: Proposal; 30 | vote: ProposalVote; 31 | accountPowerIndex: number; 32 | createAttendanceSheetBox: boolean; 33 | suggestedParams: SuggestedParams; 34 | appCallNote?: string; 35 | }): algosdk.Transaction[]; 36 | -------------------------------------------------------------------------------- /dist/folks-lending-pools/index.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk from "algosdk"; 2 | import * as AddLiquidity from "./add-liquidity"; 3 | import * as RemoveLiquidity from "./remove-liquidity"; 4 | import { getFolksWrapperAppOptInRequiredAssetIDs } from "./add-liquidity/utils"; 5 | import { FolksLendingPool } from "./types"; 6 | /** 7 | * Calculates the amount fAsset received when adding liquidity with original asset. 8 | */ 9 | declare function calculateDepositReturn({ depositAmount, depositInterestIndex, depositInterestRate, lastUpdate }: { 10 | depositAmount: bigint; 11 | depositInterestIndex: bigint; 12 | depositInterestRate: bigint; 13 | lastUpdate?: number; 14 | }): bigint; 15 | /** 16 | * Calculates the amount original asset received when removing liquidity from fAsset pool. 17 | */ 18 | declare function calculateWithdrawReturn({ withdrawAmount, depositInterestIndex, depositInterestRate, lastUpdate }: { 19 | withdrawAmount: number; 20 | depositInterestIndex: bigint; 21 | depositInterestRate: bigint; 22 | lastUpdate?: number; 23 | }): bigint; 24 | /** 25 | * Fetches Folks lending pool application info from the algod, parses the global state and builds FolksLendingPool object. 26 | */ 27 | export declare function fetchFolksLendingPool(algod: algosdk.Algodv2, appId: number): Promise; 28 | export declare const LendingPool: { 29 | AddLiquidity: typeof AddLiquidity; 30 | RemoveLiquidity: typeof RemoveLiquidity; 31 | calculateWithdrawReturn: typeof calculateWithdrawReturn; 32 | calculateDepositReturn: typeof calculateDepositReturn; 33 | getFolksWrapperAppOptInRequiredAssetIDs: typeof getFolksWrapperAppOptInRequiredAssetIDs; 34 | }; 35 | export {}; 36 | -------------------------------------------------------------------------------- /src/governance/vault/constants.ts: -------------------------------------------------------------------------------- 1 | import {encodeString} from "../../util/util"; 2 | import {BOX_FLAT_MIN_BALANCE, BOX_BYTE_MIN_BALANCE} from "../constants"; 3 | 4 | const MAX_LOCK_TIME = 126_144_000; 5 | const MIN_LOCK_AMOUNT = 10_000_000; 6 | const MIN_LOCK_AMOUNT_INCREMENT = 10_000_000; 7 | const TWO_TO_THE_64 = 2 ** 64; 8 | 9 | const ACCOUNT_STATE_BOX_SIZE = 32; 10 | const SLOPE_CHANGE_BOX_SIZE = 16; 11 | 12 | const ACCOUNT_POWER_SIZE = 48; 13 | const ACCOUNT_POWER_BOX_SIZE = 1008; 14 | const ACCOUNT_POWER_BOX_ARRAY_LEN = 21; 15 | 16 | const TOTAL_POWER_SIZE = 48; 17 | const TOTAL_POWER_BOX_SIZE = 1008; 18 | const TOTAL_POWER_BOX_ARRAY_LEN = 21; 19 | 20 | // Boxes 21 | const TOTAL_POWERS = encodeString("tp"); 22 | const SLOPE_CHANGES = encodeString("sc"); 23 | 24 | const ACCOUNT_STATE_BOX_COST = 25 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (32 + ACCOUNT_STATE_BOX_SIZE); 26 | const SLOPE_CHANGE_BOX_COST = 27 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (10 + SLOPE_CHANGE_BOX_SIZE); 28 | const ACCOUNT_POWER_BOX_COST = 29 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (40 + ACCOUNT_POWER_BOX_SIZE); 30 | const TOTAL_POWER_BOX_COST = 31 | BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (10 + TOTAL_POWER_BOX_SIZE); 32 | 33 | export { 34 | ACCOUNT_STATE_BOX_SIZE, 35 | SLOPE_CHANGE_BOX_SIZE, 36 | ACCOUNT_POWER_SIZE, 37 | ACCOUNT_POWER_BOX_SIZE, 38 | ACCOUNT_POWER_BOX_ARRAY_LEN, 39 | TOTAL_POWER_BOX_ARRAY_LEN, 40 | TOTAL_POWER_BOX_SIZE, 41 | TOTAL_POWER_SIZE, 42 | TOTAL_POWERS, 43 | MAX_LOCK_TIME, 44 | MIN_LOCK_AMOUNT, 45 | MIN_LOCK_AMOUNT_INCREMENT, 46 | TWO_TO_THE_64, 47 | SLOPE_CHANGES, 48 | ACCOUNT_STATE_BOX_COST, 49 | SLOPE_CHANGE_BOX_COST, 50 | ACCOUNT_POWER_BOX_COST, 51 | TOTAL_POWER_BOX_COST 52 | }; 53 | -------------------------------------------------------------------------------- /dist/swap/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { CONTRACT_VERSION } from "../contract/constants"; 2 | import { InitiatorSigner, SignerTransaction } from "../util/commonTypes"; 3 | import { V1PoolInfo } from "../util/pool/poolTypes"; 4 | import { SwapType } from "./constants"; 5 | import { ExecuteSwapCommonParams, GenerateSwapTxnsParams, GetSwapQuoteBySwapTypeParams, GetSwapQuoteParams, SwapQuote } from "./types"; 6 | /** 7 | * Gets the best quote for swap from the pools and swap router and returns the best option. 8 | */ 9 | export declare function getQuote(params: GetSwapQuoteParams): Promise; 10 | /** 11 | * Gets quotes for fixed input swap the pools and swap router, 12 | * and returns the best quote (with the highest rate). 13 | */ 14 | export declare function getFixedInputSwapQuote(params: GetSwapQuoteBySwapTypeParams): Promise; 15 | /** 16 | * Gets quotes for fixed output swap from the pools and swap router, 17 | * and returns the best quote (with the highest rate). 18 | */ 19 | export declare function getFixedOutputSwapQuote(params: GetSwapQuoteBySwapTypeParams): Promise; 20 | export declare function generateTxns(params: GenerateSwapTxnsParams): Promise; 21 | export declare function signTxns(params: { 22 | quote: SwapQuote; 23 | txGroup: SignerTransaction[]; 24 | initiatorSigner: InitiatorSigner; 25 | }): Promise; 26 | export declare function execute(params: ({ 27 | contractVersion: typeof CONTRACT_VERSION.V1_1; 28 | initiatorAddr: string; 29 | pool: V1PoolInfo; 30 | swapType: SwapType; 31 | } | { 32 | contractVersion: typeof CONTRACT_VERSION.V2; 33 | quote: SwapQuote; 34 | }) & ExecuteSwapCommonParams): Promise | Promise; 35 | -------------------------------------------------------------------------------- /dist/util/pool/common/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SupportedNetwork } from "../../commonTypes"; 3 | import { V1PoolInfo, V2PoolInfo, PoolReserves } from "../poolTypes"; 4 | /** 5 | * @param {bigint} totalLiquidity Total amount of issued liquidity within a pool 6 | * @param {bigint} ownedLiquidity Amount of liquidity tokens within an account 7 | * @returns Percentage of liquidity that the account holds 8 | */ 9 | export declare function getPoolShare(totalLiquidity: bigint, ownedLiquidity: bigint): number; 10 | /** 11 | * Calculates the pair ratio for the pool reserves 12 | */ 13 | export declare function getPoolPairRatio(reserves: null | Pick): null | number; 14 | /** 15 | * Checks if the pool is empty 16 | * 17 | * @param poolReserves - Pool reserves 18 | * @returns true if pool is empty, otherwise returns false 19 | */ 20 | export declare function isPoolEmpty(poolReserves: undefined | null | Pick): boolean; 21 | /** 22 | * @param pool - Pool info 23 | * @returns true if pool's status is NOT_CREATED, otherwise returns false 24 | */ 25 | export declare function isPoolNotCreated(pool: undefined | null | V1PoolInfo | V2PoolInfo): boolean; 26 | /** 27 | * @param pool - Pool info 28 | * @returns true if pool's status is READY, otherwise returns false 29 | */ 30 | export declare function isPoolReady(pool: undefined | null | V1PoolInfo | V2PoolInfo): boolean; 31 | /** 32 | * @returns {PoolInfo[]} - Pool info for the given asset pair for all contract versions 33 | */ 34 | export declare function getPoolsForPair(params: { 35 | client: Algodv2; 36 | network: SupportedNetwork; 37 | asset1ID: number; 38 | asset2ID: number; 39 | }): Promise<[V1PoolInfo, V2PoolInfo]>; 40 | -------------------------------------------------------------------------------- /dist/bootstrap/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { ContractVersionValue } from "../contract/types"; 3 | import { CONTRACT_VERSION } from "../contract/constants"; 4 | import { TinymanAnalyticsApiAsset } from "../util/asset/assetModels"; 5 | import { SupportedNetwork, SignerTransaction, InitiatorSigner } from "../util/commonTypes"; 6 | import { V1PoolInfo, V2PoolInfo } from "../util/pool/poolTypes"; 7 | import { BootstrapV1_1 } from "./v1_1"; 8 | import { BootstrapV2 } from "./v2"; 9 | export declare function generateTxns(params: { 10 | client: Algodv2; 11 | network: SupportedNetwork; 12 | contractVersion: ContractVersionValue; 13 | asset_1: Pick; 14 | asset_2: Pick; 15 | initiatorAddr: string; 16 | }): Promise; 17 | export declare function signTxns(params: { 18 | contractVersion: ContractVersionValue; 19 | txGroup: SignerTransaction[]; 20 | network: SupportedNetwork; 21 | initiatorSigner: InitiatorSigner; 22 | asset1ID: number; 23 | asset2ID: number; 24 | }): Promise<{ 25 | signedTxns: Uint8Array[]; 26 | txnIDs: string[]; 27 | }>; 28 | export declare function execute(params: (Parameters[0] & { 29 | contractVersion: typeof CONTRACT_VERSION.V2; 30 | }) | (Parameters[0] & { 31 | contractVersion: typeof CONTRACT_VERSION.V1_1; 32 | })): Promise; 33 | /** 34 | * Calculates the amount of funding txn for creating a pool 35 | */ 36 | export declare function calculateBootstrapFundingTxnAmount({ contractVersion, isAlgoPool, minFee }: { 37 | contractVersion: ContractVersionValue; 38 | isAlgoPool: boolean; 39 | minFee: bigint; 40 | }): bigint; 41 | -------------------------------------------------------------------------------- /src/add-liquidity/v1_1/types.ts: -------------------------------------------------------------------------------- 1 | /** An object containing information about an add liquidity quote. */ 2 | export interface V1_1AddLiquidityQuote { 3 | /** The round that this quote is based on. */ 4 | round: number; 5 | /** The ID of the first input asset in this quote. */ 6 | asset1ID: number; 7 | /** The quantity of the first input asset in this quote. */ 8 | asset1In: bigint; 9 | /** The ID of the second input asset in this quote. */ 10 | asset2ID: number; 11 | /** The quantity of the second input asset in this quote. */ 12 | asset2In: bigint; 13 | /** The ID of the pool token output in this quote. */ 14 | poolTokenID: number; 15 | /** The amount of the pool token output in this quote. */ 16 | poolTokenOut: bigint; 17 | /** The share of the total liquidity in this quote. */ 18 | share: number; 19 | } 20 | 21 | /** An object containing information about a successfully executed add liquidity transaction. */ 22 | export interface V1_1AddLiquidityExecution { 23 | /** The round that the add liquidity occurred in. */ 24 | round: number; 25 | /** 26 | * The total amount of transaction fees that were spent (in microAlgos) to execute the add liquidity and, 27 | * if applicable, redeem transactions. 28 | */ 29 | fees: number; 30 | /** The ID of the output pool token asset. */ 31 | poolTokenID: number; 32 | /** The quantity of the output pool token asset. */ 33 | poolTokenOut?: bigint; 34 | excessAmount?: { 35 | /** Excess amount for the current add liquidity */ 36 | excessAmountForAddingLiquidity: bigint; 37 | /** Total excess amount accumulated for the pool asset */ 38 | totalExcessAmount: bigint; 39 | }; 40 | /** The ID of the transaction. */ 41 | txnID: string; 42 | /** The group ID for the transaction group. */ 43 | groupID: string; 44 | } 45 | -------------------------------------------------------------------------------- /dist/add-liquidity/v1_1/types.d.ts: -------------------------------------------------------------------------------- 1 | /** An object containing information about an add liquidity quote. */ 2 | export interface V1_1AddLiquidityQuote { 3 | /** The round that this quote is based on. */ 4 | round: number; 5 | /** The ID of the first input asset in this quote. */ 6 | asset1ID: number; 7 | /** The quantity of the first input asset in this quote. */ 8 | asset1In: bigint; 9 | /** The ID of the second input asset in this quote. */ 10 | asset2ID: number; 11 | /** The quantity of the second input asset in this quote. */ 12 | asset2In: bigint; 13 | /** The ID of the pool token output in this quote. */ 14 | poolTokenID: number; 15 | /** The amount of the pool token output in this quote. */ 16 | poolTokenOut: bigint; 17 | /** The share of the total liquidity in this quote. */ 18 | share: number; 19 | } 20 | /** An object containing information about a successfully executed add liquidity transaction. */ 21 | export interface V1_1AddLiquidityExecution { 22 | /** The round that the add liquidity occurred in. */ 23 | round: number; 24 | /** 25 | * The total amount of transaction fees that were spent (in microAlgos) to execute the add liquidity and, 26 | * if applicable, redeem transactions. 27 | */ 28 | fees: number; 29 | /** The ID of the output pool token asset. */ 30 | poolTokenID: number; 31 | /** The quantity of the output pool token asset. */ 32 | poolTokenOut?: bigint; 33 | excessAmount?: { 34 | /** Excess amount for the current add liquidity */ 35 | excessAmountForAddingLiquidity: bigint; 36 | /** Total excess amount accumulated for the pool asset */ 37 | totalExcessAmount: bigint; 38 | }; 39 | /** The ID of the transaction. */ 40 | txnID: string; 41 | /** The group ID for the transaction group. */ 42 | groupID: string; 43 | } 44 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v1_1/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, InitiatorSigner } from "../../util/commonTypes"; 3 | import { PoolReserves, V1PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V1_1RemoveLiquidityQuote, V1_1RemoveLiquidityExecution } from "./types"; 5 | /** 6 | * Get a quote for how many of assets 1 and 2 a deposit of `poolTokenIn` is worth 7 | * at this moment. This does not execute any transactions. 8 | */ 9 | export declare function getQuote({ pool, reserves, poolTokenIn }: { 10 | pool: V1PoolInfo; 11 | reserves: PoolReserves; 12 | /** 13 | * The amount of the pool token being deposited. 14 | */ 15 | poolTokenIn: bigint; 16 | }): V1_1RemoveLiquidityQuote; 17 | declare function generateTxns({ client, pool, poolTokenIn, asset1Out, asset2Out, slippage, initiatorAddr }: { 18 | client: Algodv2; 19 | pool: V1PoolInfo; 20 | poolTokenIn: bigint; 21 | asset1Out: bigint; 22 | asset2Out: bigint; 23 | slippage: number; 24 | initiatorAddr: string; 25 | }): Promise; 26 | declare function signTxns({ pool, txGroup, initiatorSigner }: { 27 | pool: V1PoolInfo; 28 | txGroup: SignerTransaction[]; 29 | initiatorSigner: InitiatorSigner; 30 | }): Promise; 31 | declare function execute({ client, pool, txGroup, signedTxns, initiatorAddr }: { 32 | client: Algodv2; 33 | pool: V1PoolInfo; 34 | txGroup: SignerTransaction[]; 35 | signedTxns: Uint8Array[]; 36 | /** 37 | * The address of the account performing the burn operation. 38 | */ 39 | initiatorAddr: string; 40 | }): Promise; 41 | export declare const RemoveLiquidityV1_1: { 42 | generateTxns: typeof generateTxns; 43 | getQuote: typeof getQuote; 44 | signTxns: typeof signTxns; 45 | execute: typeof execute; 46 | }; 47 | export {}; 48 | -------------------------------------------------------------------------------- /src/swap/v2/router/util.ts: -------------------------------------------------------------------------------- 1 | import {SupportedNetwork} from "../../../util/commonTypes"; 2 | import {convertFromBaseUnits} from "../../../util/util"; 3 | import {SwapRouterResponse} from "../../types"; 4 | import {SWAP_ROUTER_APP_ID} from "./constants"; 5 | 6 | function getSwapRouteRate( 7 | route: Pick< 8 | SwapRouterResponse, 9 | "asset_in" | "asset_out" | "input_amount" | "output_amount" 10 | > 11 | ) { 12 | const {assetIn, assetOut} = getAssetInAndOutFromSwapRoute(route); 13 | 14 | return ( 15 | convertFromBaseUnits(assetOut.asset.decimals, Number(assetOut.amount)) / 16 | convertFromBaseUnits(assetIn.asset.decimals, Number(assetIn.amount)) 17 | ); 18 | } 19 | 20 | function getSwapRouterAppID(network: SupportedNetwork) { 21 | const id = SWAP_ROUTER_APP_ID[network]; 22 | 23 | if (!id) { 24 | throw new Error(`Unknown network or network not supported: ${network}`); 25 | } 26 | 27 | return id; 28 | } 29 | 30 | function getAssetOutFromSwapRoute( 31 | route: Pick 32 | ) { 33 | return { 34 | asset: route.asset_out, 35 | amount: BigInt(route.output_amount ?? 0) 36 | }; 37 | } 38 | 39 | function getAssetInFromSwapRoute( 40 | route: Pick 41 | ) { 42 | return { 43 | asset: route.asset_in, 44 | amount: BigInt(route.input_amount ?? 0) 45 | }; 46 | } 47 | 48 | function getAssetInAndOutFromSwapRoute( 49 | route: Pick< 50 | SwapRouterResponse, 51 | "asset_in" | "asset_out" | "input_amount" | "output_amount" 52 | > 53 | ) { 54 | return { 55 | assetIn: getAssetInFromSwapRoute(route), 56 | assetOut: getAssetOutFromSwapRoute(route) 57 | }; 58 | } 59 | 60 | export { 61 | getAssetInAndOutFromSwapRoute, 62 | getAssetInFromSwapRoute, 63 | getAssetOutFromSwapRoute, 64 | getSwapRouterAppID, 65 | getSwapRouteRate 66 | }; 67 | -------------------------------------------------------------------------------- /src/util/asset/assetUtils.test.ts: -------------------------------------------------------------------------------- 1 | import {describe, expect, test} from "@jest/globals"; 2 | 3 | import {ALGO_ASSET_ID} from "./assetConstants"; 4 | import {isAlgo, prepareAssetPairData, sortAssetIds} from "./assetUtils"; 5 | 6 | test("`sortAssetIds` returns an array with bigger id first", () => { 7 | expect(sortAssetIds(0, 1)).toStrictEqual([1, 0]); 8 | expect(sortAssetIds(1, 0)).toStrictEqual([1, 0]); 9 | }); 10 | 11 | test("`isAlgo` returns correct value", () => { 12 | expect(isAlgo(ALGO_ASSET_ID)).toBe(true); 13 | expect(isAlgo(ALGO_ASSET_ID + 1)).toBe(false); 14 | }); 15 | 16 | describe("`prepareAssetPairData`", () => { 17 | test("returns an array of asset objects, with asset with bigger id first", () => { 18 | const assetWithBiggerId = {id: 1, name: "asset 1"}; 19 | const assetWithSmallerId = {id: 0, name: "asset 2"}; 20 | const expectedSortedResult = [assetWithBiggerId, assetWithSmallerId]; 21 | 22 | expect(prepareAssetPairData(assetWithBiggerId, assetWithSmallerId)).toStrictEqual( 23 | expectedSortedResult 24 | ); 25 | expect(prepareAssetPairData(assetWithSmallerId, assetWithBiggerId)).toStrictEqual( 26 | expectedSortedResult 27 | ); 28 | }); 29 | 30 | test("returns an array of asset objects, with asset with bigger id first, and converts id to number", () => { 31 | const assetWithBiggerId = {id: "1", name: "asset 1"}; 32 | const assetWithSmallerId = {id: "0", name: "asset 2"}; 33 | const expectedSortedResult = [ 34 | {...assetWithBiggerId, id: Number(assetWithBiggerId.id)}, 35 | {...assetWithSmallerId, id: Number(assetWithSmallerId.id)} 36 | ]; 37 | 38 | expect(prepareAssetPairData(assetWithBiggerId, assetWithSmallerId)).toStrictEqual( 39 | expectedSortedResult 40 | ); 41 | expect(prepareAssetPairData(assetWithSmallerId, assetWithBiggerId)).toStrictEqual( 42 | expectedSortedResult 43 | ); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /dist/util/client/base/baseClient.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { Algodv2, Transaction } from "algosdk"; 2 | import { SignerTransaction, SupportedNetwork } from "../../commonTypes"; 3 | import { StructDefinition } from "./types"; 4 | import { Struct } from "./utils"; 5 | declare abstract class TinymanBaseClient { 6 | protected algod: Algodv2; 7 | protected applicationAddress: AppAddress; 8 | protected network: SupportedNetwork; 9 | appId: AppId; 10 | readonly structs: Record | undefined; 11 | constructor(algod: Algodv2, appId: AppId, network: SupportedNetwork, structs?: Record); 12 | protected setupTxnFeeAndAssignGroupId({ txns, additionalFeeCount }: { 13 | txns: algosdk.Transaction[]; 14 | additionalFeeCount?: number; 15 | }): algosdk.Transaction[]; 16 | protected getGlobal(key: Uint8Array, defaultValue?: any, appId?: number): Promise; 17 | protected calculateMinBalance({ accounts, assets, boxes }: { 18 | accounts?: number; 19 | assets?: number; 20 | boxes?: Record; 21 | }): number; 22 | protected boxExists(boxName: Uint8Array, appId?: number): Promise; 23 | protected getBox(boxName: Uint8Array, structName: string, appId?: number, structs?: Record): Promise; 24 | protected getOptinTxnIfNeeded(sender: string, assetId: number): Promise; 25 | protected isOptedIn(accountAddress: string | algosdk.Address, assetId: number): Promise; 26 | protected getSuggestedParams(): Promise; 27 | convertStandardTransactionsToSignerTransactions(txns: Transaction[], signer: string | string[]): SignerTransaction[]; 28 | } 29 | export default TinymanBaseClient; 30 | -------------------------------------------------------------------------------- /src/remove-liquidity/v1_1/types.ts: -------------------------------------------------------------------------------- 1 | /** An object containing information about a burn quote. */ 2 | export interface V1_1RemoveLiquidityQuote { 3 | /** The round that this quote is based on. */ 4 | round: number; 5 | /** The ID of the first output asset in this quote. */ 6 | asset1ID: number; 7 | /** The quantity of the first output asset in this quote. */ 8 | asset1Out: bigint; 9 | /** The ID of the second output asset in this quote. */ 10 | asset2ID: number; 11 | /** The quantity of the second output asset in this quote. */ 12 | asset2Out: bigint; 13 | /** The ID of the input liquidity token asset in this quote. */ 14 | poolTokenID: number; 15 | /** The quantity of the input liquidity token asset in this quote. */ 16 | poolTokenIn: bigint; 17 | } 18 | 19 | /** An object containing information about a successfully executed burn transaction. */ 20 | export interface V1_1RemoveLiquidityExecution { 21 | /** The round that the burn occurred in. */ 22 | round: number; 23 | /** 24 | * The total amount of transaction fees that were spent (in microAlgos) to execute the burn and, 25 | * if applicable, redeem transactions. 26 | */ 27 | fees: number; 28 | /** The ID of the first output asset. */ 29 | asset1ID: number; 30 | /** The quantity of the first output asset. */ 31 | asset1Out: bigint; 32 | /** The ID of the second output asset. */ 33 | asset2ID: number; 34 | /** The quantity of the second output asset. */ 35 | asset2Out: bigint; 36 | /** The ID of the liquidity token input asset. */ 37 | poolTokenID: number; 38 | /** The quantity of the liquidity token input asset. */ 39 | poolTokenIn: bigint; 40 | /** Excess amount details for the pool assets */ 41 | excessAmounts: { 42 | assetID: number; 43 | excessAmountForBurning: bigint; 44 | totalExcessAmount: bigint; 45 | }[]; 46 | /** The ID of the transaction. */ 47 | txnID: string; 48 | /** The group ID for the transaction group. */ 49 | groupID: string; 50 | } 51 | -------------------------------------------------------------------------------- /examples/src/util/account.ts: -------------------------------------------------------------------------------- 1 | import {Account, generateAccount, modelsv2} from "algosdk"; 2 | import {writeFileSync, readFileSync} from "fs"; 3 | 4 | import {algodClient} from "./client"; 5 | import {assertAccountHasBalance} from "./other"; 6 | 7 | export const ACCOUNT_FILENAME = "account.json"; 8 | 9 | /** 10 | * @returns existing account if exists, otherwise generates a new account 11 | */ 12 | export async function getAccount(): Promise { 13 | let account: Account | undefined = tryGetAccountFromJson(); 14 | 15 | if (!account) { 16 | account = generateAccount(); 17 | 18 | console.log(`✅ Account generated: ${account.addr}`); 19 | console.log(`✅ Account data saved to: ${ACCOUNT_FILENAME}`); 20 | 21 | writeFileSync(ACCOUNT_FILENAME, JSON.stringify(account)); 22 | } 23 | 24 | try { 25 | await assertAccountHasBalance(account.addr.toString()); 26 | } catch (error) { 27 | console.log(error); 28 | } 29 | 30 | return account; 31 | } 32 | 33 | /** tries to read and return account data from the local json file */ 34 | function tryGetAccountFromJson() { 35 | try { 36 | const parsedAccount = JSON.parse(readFileSync(ACCOUNT_FILENAME).toString()) as { 37 | addr: Account["addr"]; 38 | sk: Record; 39 | }; 40 | const account: Account = { 41 | ...parsedAccount, 42 | // This is needed since byte array can't be serialized correctly 43 | sk: new Uint8Array(Object.values(parsedAccount.sk)) 44 | }; 45 | 46 | return account; 47 | } catch (_e) { 48 | return undefined; 49 | } 50 | } 51 | 52 | /** 53 | * @returns the amount of the asset (with the given `assetId`) owned by the account 54 | */ 55 | export async function getOwnedAssetAmount(accountAddress: string, assetId: bigint) { 56 | const {assets} = (await algodClient 57 | .accountInformation(accountAddress) 58 | .do()) as modelsv2.Account; 59 | 60 | return assets?.find((asset) => asset.assetId === assetId)?.amount || 0n; 61 | } 62 | -------------------------------------------------------------------------------- /dist/bootstrap/v2/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { TinymanAnalyticsApiAsset } from "../../util/asset/assetModels"; 3 | import { SupportedNetwork, SignerTransaction, InitiatorSigner } from "../../util/commonTypes"; 4 | import { V2PoolInfo } from "../../util/pool/poolTypes"; 5 | declare function getTotalCost(isAlgoPool: boolean, minFee: bigint): bigint; 6 | declare function generateTxns({ client, network, asset_1, asset_2, initiatorAddr }: { 7 | client: Algodv2; 8 | network: SupportedNetwork; 9 | asset_1: Pick; 10 | asset_2: Pick; 11 | initiatorAddr: string; 12 | }): Promise; 13 | declare function getBootstrapFundingTxnAmount(isAlgoPool: boolean, minFee: bigint): bigint; 14 | declare function signTxns({ txGroup, network, initiatorSigner, asset1ID, asset2ID }: { 15 | txGroup: SignerTransaction[]; 16 | network: SupportedNetwork; 17 | initiatorSigner: InitiatorSigner; 18 | asset1ID: number; 19 | asset2ID: number; 20 | }): Promise<{ 21 | signedTxns: Uint8Array[]; 22 | txnIDs: string[]; 23 | }>; 24 | /** 25 | * Create an pool for an asset pair if it does not already exist. The initiator will provide 26 | * funding to create the pool and pay for the creation transaction fees. 27 | */ 28 | declare function execute({ client, network, pool: { asset1ID, asset2ID }, txGroup, signedTxns }: { 29 | client: Algodv2; 30 | network: SupportedNetwork; 31 | pool: { 32 | asset1ID: number; 33 | asset2ID: number; 34 | }; 35 | txGroup: SignerTransaction[]; 36 | signedTxns: Uint8Array[]; 37 | }): Promise; 38 | export declare const BootstrapV2: { 39 | generateTxns: typeof generateTxns; 40 | signTxns: typeof signTxns; 41 | execute: typeof execute; 42 | getBootstrapFundingTxnAmount: typeof getBootstrapFundingTxnAmount; 43 | getTotalCost: typeof getTotalCost; 44 | }; 45 | export {}; 46 | -------------------------------------------------------------------------------- /examples/src/operation/bootstrap/bootstrapPool.ts: -------------------------------------------------------------------------------- 1 | import {Bootstrap, poolUtils, SupportedNetwork} from "@tinymanorg/tinyman-js-sdk"; 2 | import {Account} from "algosdk"; 3 | 4 | import {algodClient} from "../../util/client"; 5 | import signerWithSecretKey from "../../util/initiatorSigner"; 6 | 7 | /** 8 | * Creates (i.e. "Bootstraps") a pool with an owned asset pair 9 | */ 10 | export async function bootstrapPool({ 11 | account, 12 | asset_1, 13 | asset_2 14 | }: { 15 | account: Account; 16 | asset_1: {id: string; unit_name: string}; 17 | asset_2: {id: string; unit_name: string}; 18 | }) { 19 | const initiatorAddr = account.addr; 20 | const poolInfo = await poolUtils.v2.getPoolInfo({ 21 | network: "testnet" as SupportedNetwork, 22 | client: algodClient, 23 | asset1ID: Number(asset_1.id), 24 | asset2ID: Number(asset_2.id) 25 | }); 26 | 27 | const bootstrapTxns = await Bootstrap.v2.generateTxns({ 28 | network: "testnet" as SupportedNetwork, 29 | client: algodClient, 30 | asset_1, 31 | asset_2, 32 | initiatorAddr: initiatorAddr.toString() 33 | }); 34 | 35 | const signedTxns = await Bootstrap.v2.signTxns({ 36 | network: "testnet" as SupportedNetwork, 37 | txGroup: bootstrapTxns, 38 | initiatorSigner: signerWithSecretKey(account), 39 | asset1ID: Number(asset_1.id), 40 | asset2ID: Number(asset_2.id) 41 | }); 42 | 43 | const bootstrapExecutionResponse = await Bootstrap.v2.execute({ 44 | network: "testnet" as SupportedNetwork, 45 | client: algodClient, 46 | pool: poolInfo, 47 | txGroup: bootstrapTxns, 48 | ...signedTxns 49 | }); 50 | 51 | const poolAddress = bootstrapExecutionResponse.account.address(); 52 | 53 | console.log("✅ Pool bootstrapped!"); 54 | console.log(`✅ Pool address: ${poolAddress}`); 55 | console.log(`✅ Pool token ID: ${bootstrapExecutionResponse.poolTokenID}`); 56 | console.log( 57 | "✅ See pool account on AlgoExplorer: " + 58 | `https://testnet.algoexplorer.io/address/${poolAddress}` 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /src/add-liquidity/v2/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AssetWithIdAndAmount, 3 | AssetWithIdAndAmountAndDecimals 4 | } from "../../util/asset/assetModels"; 5 | 6 | export interface V2InitialAddLiquidityQuote { 7 | asset1In: {id: number; amount: bigint}; 8 | asset2In: {id: number; amount: bigint}; 9 | poolTokenOut: {id: number; amount: bigint}; 10 | slippage: number; 11 | } 12 | 13 | export interface V2FlexibleAddLiquidityQuote { 14 | asset1In: {id: number; amount: bigint}; 15 | asset2In: {id: number; amount: bigint}; 16 | poolTokenOut: {id: number; amount: bigint}; 17 | share: number; 18 | slippage: number; 19 | internalSwapQuote: V2AddLiquidityInternalSwapQuote; 20 | minPoolTokenAssetAmountWithSlippage: bigint; 21 | } 22 | 23 | export interface V2SingleAssetInAddLiquidityQuote { 24 | assetIn: {id: number; amount: bigint}; 25 | poolTokenOut: {id: number; amount: bigint}; 26 | share: number; 27 | slippage: number; 28 | internalSwapQuote: V2AddLiquidityInternalSwapQuote; 29 | minPoolTokenAssetAmountWithSlippage: bigint; 30 | } 31 | 32 | export interface V2AddLiquidityInternalSwapQuote { 33 | assetIn: AssetWithIdAndAmountAndDecimals; 34 | assetOut: AssetWithIdAndAmountAndDecimals; 35 | swapFees: bigint; 36 | priceImpact: number; 37 | } 38 | 39 | export interface V2AddLiquidityExecution { 40 | /** The round that the add liquidity occurred in. */ 41 | round: number; 42 | /** The ID of the transaction. */ 43 | txnID: string; 44 | /** 45 | * The total amount of transaction fees that were spent (in microAlgos) to execute the add liquidity and, 46 | * if applicable, redeem transactions. 47 | */ 48 | fees: number; 49 | /** The ID of the output pool token asset. */ 50 | poolTokenID: number; 51 | /** The group ID for the transaction group. */ 52 | groupID: string; 53 | /** 54 | * Can be `undefined` if the execution was successful, but there was an issue while 55 | * extracting the output asset data fron the transaction response 56 | */ 57 | assetOut: AssetWithIdAndAmount | undefined; 58 | } 59 | -------------------------------------------------------------------------------- /dist/bootstrap/v1_1/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { InitiatorSigner, SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; 3 | import { V1PoolInfo } from "../../util/pool/poolTypes"; 4 | import { TinymanAnalyticsApiAsset } from "../../util/asset/assetModels"; 5 | declare function generateTxns({ client, network, asset_1, asset_2, initiatorAddr }: { 6 | client: Algodv2; 7 | network: SupportedNetwork; 8 | asset_1: Pick; 9 | asset_2: Pick; 10 | initiatorAddr: string; 11 | }): Promise; 12 | /** 13 | * To get the total Bootstrap fee, one extra transaction fee (1000) can be added 14 | * to the result of this function. 15 | * @returns the bootstrap funding txn amount 16 | */ 17 | declare function getBootstrapFundingTxnAmount(isAlgoPool: boolean): 960000n | 859000n; 18 | declare function signTxns({ txGroup, network, initiatorSigner, asset1ID, asset2ID }: { 19 | txGroup: SignerTransaction[]; 20 | network: SupportedNetwork; 21 | initiatorSigner: InitiatorSigner; 22 | asset1ID: number; 23 | asset2ID: number; 24 | }): Promise<{ 25 | signedTxns: Uint8Array[]; 26 | txnIDs: string[]; 27 | }>; 28 | /** 29 | * Create an pool for an asset pair if it does not already exist. The initiator will provide 30 | * funding to create the pool and pay for the creation transaction fees. 31 | */ 32 | declare function execute({ client, network, pool: { asset1ID, asset2ID }, signedTxns, txnIDs }: { 33 | client: Algodv2; 34 | network: SupportedNetwork; 35 | pool: { 36 | asset1ID: number; 37 | asset2ID: number; 38 | }; 39 | signedTxns: Uint8Array[]; 40 | txnIDs: string[]; 41 | }): Promise; 42 | export declare const BootstrapV1_1: { 43 | generateTxns: typeof generateTxns; 44 | signTxns: typeof signTxns; 45 | execute: typeof execute; 46 | getBootstrapFundingTxnAmount: typeof getBootstrapFundingTxnAmount; 47 | }; 48 | export {}; 49 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v1_1/types.d.ts: -------------------------------------------------------------------------------- 1 | /** An object containing information about a burn quote. */ 2 | export interface V1_1RemoveLiquidityQuote { 3 | /** The round that this quote is based on. */ 4 | round: number; 5 | /** The ID of the first output asset in this quote. */ 6 | asset1ID: number; 7 | /** The quantity of the first output asset in this quote. */ 8 | asset1Out: bigint; 9 | /** The ID of the second output asset in this quote. */ 10 | asset2ID: number; 11 | /** The quantity of the second output asset in this quote. */ 12 | asset2Out: bigint; 13 | /** The ID of the input liquidity token asset in this quote. */ 14 | poolTokenID: number; 15 | /** The quantity of the input liquidity token asset in this quote. */ 16 | poolTokenIn: bigint; 17 | } 18 | /** An object containing information about a successfully executed burn transaction. */ 19 | export interface V1_1RemoveLiquidityExecution { 20 | /** The round that the burn occurred in. */ 21 | round: number; 22 | /** 23 | * The total amount of transaction fees that were spent (in microAlgos) to execute the burn and, 24 | * if applicable, redeem transactions. 25 | */ 26 | fees: number; 27 | /** The ID of the first output asset. */ 28 | asset1ID: number; 29 | /** The quantity of the first output asset. */ 30 | asset1Out: bigint; 31 | /** The ID of the second output asset. */ 32 | asset2ID: number; 33 | /** The quantity of the second output asset. */ 34 | asset2Out: bigint; 35 | /** The ID of the liquidity token input asset. */ 36 | poolTokenID: number; 37 | /** The quantity of the liquidity token input asset. */ 38 | poolTokenIn: bigint; 39 | /** Excess amount details for the pool assets */ 40 | excessAmounts: { 41 | assetID: number; 42 | excessAmountForBurning: bigint; 43 | totalExcessAmount: bigint; 44 | }[]; 45 | /** The ID of the transaction. */ 46 | txnID: string; 47 | /** The group ID for the transaction group. */ 48 | groupID: string; 49 | } 50 | -------------------------------------------------------------------------------- /dist/governance/proposal-voting/storage.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | export declare class Proposal { 3 | index: number; 4 | creationTimestamp: number; 5 | votingStartTimestamp: number; 6 | votingEndTimestamp: number; 7 | snapshotTotalVotingPower: number; 8 | voteCount: number; 9 | quorumNumerator: number; 10 | againstVotingPower: number; 11 | forVotingPower: number; 12 | abstainVotingPower: number; 13 | isApproved: boolean; 14 | isCancelled: boolean; 15 | isExecuted: boolean; 16 | isQuorumReached: boolean; 17 | proposerAddress: string; 18 | executionHash: string; 19 | executorAddress: string; 20 | constructor(index: number, creationTimestamp: number, votingStartTimestamp: number, votingEndTimestamp: number, snapshotTotalVotingPower: number, voteCount: number, quorumNumerator: number, againstVotingPower: number, forVotingPower: number, abstainVotingPower: number, isApproved: boolean, isCancelled: boolean, isExecuted: boolean, isQuorumReached: boolean, proposerAddress: string, executionHash: string, executorAddress: string); 21 | get snapshotTimestamp(): number; 22 | } 23 | export declare class ProposalVotingAppGlobalState { 24 | vaultAppId: number; 25 | proposalIndexCounter: number; 26 | votingDelay: number; 27 | votingDuration: number; 28 | proposalThreshold: number; 29 | proposalThresholdNumerator: number; 30 | quorumThreshold: number; 31 | approvalRequirement: number; 32 | manager: string; 33 | proposalManager: Uint8Array; 34 | constructor(vaultAppId: bigint, proposalIndexCounter: bigint, votingDelay: bigint, votingDuration: bigint, proposalThreshold: bigint, proposalThresholdNumerator: bigint, quorumThreshold: bigint, approvalRequirement: bigint, manager: string, proposalManager: Uint8Array); 35 | } 36 | export declare function getProposalBoxName(proposalId: string): Uint8Array; 37 | export declare function getAttendanceSheetBoxName(address: string, boxIndex: number): Uint8Array; 38 | export declare function getProposal(client: Algodv2, appId: number, proposalId: string): Promise; 39 | -------------------------------------------------------------------------------- /dist/redeem.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { InitiatorSigner, SignerTransaction } from "./util/commonTypes"; 3 | import { V1PoolInfo } from "./util/pool/poolTypes"; 4 | /** 5 | * Execute a redeem operation to collect excess assets from previous operations. 6 | * 7 | * @param params.client An Algodv2 client. 8 | * @param params.pool Information for the pool. 9 | * @param params.initiatorSigner A function that will sign transactions from the initiator's 10 | * account. 11 | */ 12 | export declare function redeemExcessAsset({ client, pool, txGroup, initiatorSigner }: { 13 | client: Algodv2; 14 | pool: V1PoolInfo; 15 | txGroup: SignerTransaction[]; 16 | initiatorSigner: InitiatorSigner; 17 | }): Promise<{ 18 | fees: number; 19 | confirmedRound: number; 20 | groupID: string; 21 | txnID: string; 22 | }>; 23 | /** 24 | * Execute redeem operations to collect all excess assets from previous operations. 25 | * 26 | * @param params.client An Algodv2 client. 27 | * @param params.data.pool Information for the pool. 28 | * @param params.data.assetID The ID of the asset being redeemed. Must match one of the pool's 29 | * asset1ID, asset2ID, or poolTokenID. 30 | * @param params.data.assetOut The quantity of the asset being redeemed. 31 | * @param params.initiatorAddr The address of the account performing the redeem operation. 32 | * @param params.initiatorSigner A function that will sign transactions from the initiator's 33 | * account. 34 | */ 35 | export declare function redeemAllExcessAsset({ client, data, initiatorSigner }: { 36 | client: Algodv2; 37 | data: { 38 | pool: V1PoolInfo; 39 | txGroup: SignerTransaction[]; 40 | }[]; 41 | initiatorSigner: InitiatorSigner; 42 | }): Promise<{ 43 | fees: number; 44 | confirmedRound: number; 45 | groupID: string; 46 | txnID: string; 47 | }[]>; 48 | export declare const REDEEM_PROCESS_TXN_COUNT = 3; 49 | export declare function generateRedeemTxns({ client, pool, assetID, assetOut, initiatorAddr }: { 50 | client: Algodv2; 51 | pool: V1PoolInfo; 52 | assetID: number; 53 | assetOut: bigint; 54 | initiatorAddr: string; 55 | }): Promise; 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | 73 | # dotenv environment variables file 74 | .env 75 | .env.test 76 | 77 | # parcel-bundler cache (https://parceljs.org/) 78 | .cache 79 | 80 | # Next.js build output 81 | .next 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | 107 | # VSCode settings 108 | .vscode 109 | -------------------------------------------------------------------------------- /dist/governance/vault/transactions.d.ts: -------------------------------------------------------------------------------- 1 | import algosdk, { Algodv2, SuggestedParams } from "algosdk"; 2 | import { AccountState, SlopeChange, VaultAppGlobalState } from "./storage"; 3 | import { SupportedNetwork } from "../../util/commonTypes"; 4 | declare function prepareCreateLockTransactions({ accountState, lockEndTime, lockedAmount, network, sender, vaultAppGlobalState, suggestedParams, slopeChangeAtLockEndTime, appCallNote }: { 5 | network: SupportedNetwork; 6 | sender: string; 7 | lockedAmount: number; 8 | lockEndTime: number; 9 | vaultAppGlobalState: VaultAppGlobalState; 10 | suggestedParams: SuggestedParams; 11 | accountState?: AccountState | null; 12 | slopeChangeAtLockEndTime?: SlopeChange | null; 13 | appCallNote?: Uint8Array; 14 | }): algosdk.Transaction[]; 15 | declare function prepareIncreaseLockAmountTransactions({ accountState, lockedAmount, network, sender, vaultAppGlobalState, suggestedParams, appCallNote }: { 16 | network: SupportedNetwork; 17 | sender: string; 18 | lockedAmount: number; 19 | vaultAppGlobalState: VaultAppGlobalState; 20 | accountState: AccountState; 21 | suggestedParams: SuggestedParams; 22 | appCallNote?: Uint8Array; 23 | }): algosdk.Transaction[]; 24 | declare function prepareExtendLockEndTimeTransactions({ accountState, network, newLockEndTime, slopeChangeAtNewLockEndTime, sender, vaultAppGlobalState, suggestedParams, appCallNote }: { 25 | network: SupportedNetwork; 26 | sender: string; 27 | newLockEndTime: number; 28 | vaultAppGlobalState: VaultAppGlobalState; 29 | accountState: AccountState; 30 | slopeChangeAtNewLockEndTime?: number; 31 | suggestedParams: SuggestedParams; 32 | appCallNote?: Uint8Array; 33 | }): algosdk.Transaction[]; 34 | declare function prepareWithdrawTransactions({ accountState, network, sender, suggestedParams, appCallNote }: { 35 | network: SupportedNetwork; 36 | client: Algodv2; 37 | sender: string; 38 | accountState: AccountState; 39 | suggestedParams: SuggestedParams; 40 | appCallNote?: Uint8Array; 41 | }): algosdk.Transaction[]; 42 | export { prepareCreateLockTransactions, prepareIncreaseLockAmountTransactions, prepareExtendLockEndTimeTransactions, prepareWithdrawTransactions }; 43 | -------------------------------------------------------------------------------- /dist/swap/common/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { CONTRACT_VERSION } from "../../contract/constants"; 2 | import { ContractVersionValue } from "../../contract/types"; 3 | import { AssetWithAmountAndDecimals, AssetWithIdAndAmount } from "../../util/asset/assetModels"; 4 | import { SwapType } from "../constants"; 5 | import { SwapQuote } from "../types"; 6 | declare function calculateSwapRate({ assetIn, assetOut }: { 7 | assetIn: AssetWithAmountAndDecimals; 8 | assetOut: AssetWithAmountAndDecimals; 9 | }): number; 10 | declare function calculatePriceImpact({ inputSupply, outputSupply, assetIn, assetOut }: { 11 | inputSupply: bigint; 12 | outputSupply: bigint; 13 | assetIn: AssetWithAmountAndDecimals; 14 | assetOut: AssetWithAmountAndDecimals; 15 | }): number; 16 | declare function getSwapQuotePriceImpact(quote: SwapQuote): number; 17 | declare function getAssetInFromSwapQuote(quote: SwapQuote): AssetWithIdAndAmount; 18 | declare function getAssetOutFromSwapQuote(quote: SwapQuote): AssetWithIdAndAmount; 19 | declare function getAssetInAndAssetOutFromSwapQuote(quote: SwapQuote): { 20 | assetIn: AssetWithIdAndAmount; 21 | assetOut: AssetWithIdAndAmount; 22 | }; 23 | declare function getSwapQuoteContractVersion(quote: SwapQuote): ContractVersionValue; 24 | /** 25 | * @returns the total fee that will be paid by the user 26 | * for the swap transaction with given parameters 27 | */ 28 | declare function getSwapTotalFee(params: { 29 | minFee: bigint; 30 | } & ({ 31 | version: typeof CONTRACT_VERSION.V1_1; 32 | } | { 33 | version: typeof CONTRACT_VERSION.V2; 34 | type: SwapType; 35 | })): bigint; 36 | /** 37 | * @returns The asset amount ratio for the given quote 38 | */ 39 | declare function getSwapQuoteRate(quote: SwapQuote): number; 40 | /** 41 | * Compares the given quotes and returns the best one (with the highest rate). 42 | */ 43 | declare function getBestQuote(quotes: SwapQuote[]): SwapQuote; 44 | declare function isSwapQuoteErrorCausedByAmount(error: Error): boolean; 45 | export { calculatePriceImpact, calculateSwapRate, getAssetInAndAssetOutFromSwapQuote, getAssetInFromSwapQuote, getAssetOutFromSwapQuote, getBestQuote, getSwapQuoteContractVersion, getSwapQuotePriceImpact, getSwapQuoteRate, getSwapTotalFee, isSwapQuoteErrorCausedByAmount }; 46 | -------------------------------------------------------------------------------- /dist/add-liquidity/v1_1/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, InitiatorSigner, SupportedNetwork } from "../../util/commonTypes"; 3 | import { PoolReserves, V1PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V1_1AddLiquidityQuote, V1_1AddLiquidityExecution } from "./types"; 5 | import { AssetWithIdAndAmount } from "../../util/asset/assetModels"; 6 | /** 7 | * Get a quote for how many liquidity tokens a deposit of asset1In and asset2In is worth at this 8 | * moment. This does not execute any transactions. 9 | * 10 | * @param params.pool Information for the pool. 11 | * @param params.reserves Pool reserves. 12 | * @param params.asset1In The quantity of the first asset being deposited. 13 | * @param params.asset2In The quantity of the second asset being deposited. 14 | */ 15 | export declare function getQuote({ pool, reserves, asset1In, asset2In }: { 16 | pool: V1PoolInfo; 17 | reserves: PoolReserves; 18 | asset1In: bigint; 19 | asset2In: bigint; 20 | }): V1_1AddLiquidityQuote; 21 | export declare function generateTxns({ client, network, poolAddress, asset1In, asset2In, poolTokenOut, slippage, initiatorAddr }: { 22 | client: Algodv2; 23 | network: SupportedNetwork; 24 | poolAddress: string; 25 | asset1In: AssetWithIdAndAmount; 26 | asset2In: AssetWithIdAndAmount; 27 | poolTokenOut: AssetWithIdAndAmount; 28 | slippage: number; 29 | initiatorAddr: string; 30 | }): Promise; 31 | export declare function signTxns({ pool, txGroup, initiatorSigner }: { 32 | pool: V1PoolInfo; 33 | txGroup: SignerTransaction[]; 34 | initiatorSigner: InitiatorSigner; 35 | }): Promise; 36 | /** 37 | * Execute adding liquidity operation with the desired quantities. 38 | * 39 | * @param params.client An Algodv2 client. 40 | * @param params.pool Information for the pool. 41 | * @param params.initiatorAddr The address of the account performing the add liquidity operation. 42 | */ 43 | export declare function execute({ client, pool, txGroup, signedTxns, initiatorAddr }: { 44 | client: Algodv2; 45 | pool: V1PoolInfo; 46 | txGroup: SignerTransaction[]; 47 | signedTxns: Uint8Array[]; 48 | initiatorAddr: string; 49 | }): Promise; 50 | -------------------------------------------------------------------------------- /examples/src/index.ts: -------------------------------------------------------------------------------- 1 | import {addFlexibleLiquidity} from "./operation/add-liquidity/addFlexibleLiquidity"; 2 | import {addInitialLiquidity} from "./operation/add-liquidity/addInitialLiquidity"; 3 | import {addSingleAssetLiquidity} from "./operation/add-liquidity/addSingleAssetLiquidity"; 4 | import {bootstrapPool} from "./operation/bootstrap/bootstrapPool"; 5 | import {removeLiquidity} from "./operation/remove-liquidity/removeLiquidity"; 6 | import {removeLiquidityWithSingleAssetOut} from "./operation/remove-liquidity/removeLiquidityWithSingleAssetOut"; 7 | import {fixedInputSwap} from "./operation/swap/fixedInputSwap"; 8 | import {fixedOutputSwap} from "./operation/swap/fixedOutputSwap"; 9 | import {getAccount} from "./util/account"; 10 | import {getAssetParams} from "./util/asset"; 11 | 12 | /** 13 | * Will run all the operations in the order they are defined 14 | * - You can remove `account.json` and `assets.json` files to start from scratch 15 | * - You can simply comment out the operations you don't want to run 16 | */ 17 | async function main() { 18 | // Initialize account and asset data 19 | const account = await getAccount(); 20 | const {asset_1, asset_2} = await getAssetParams(); 21 | 22 | // Create the pool with the owned assets 23 | // await bootstrapPool({ account, asset_1, asset_2 }); 24 | 25 | // Add some initial liquidity to the pool 26 | await addInitialLiquidity({account, asset_1, asset_2}); 27 | 28 | // Add subsequent liquidity to the pool using the flexible mode 29 | await addFlexibleLiquidity({account, asset_1, asset_2}); 30 | 31 | // Add subsequent liquidity to the pool using the single asset mode 32 | await addSingleAssetLiquidity({account, asset_1, asset_2}); 33 | 34 | // Remove some of the owned liquidity from the pool 35 | await removeLiquidity({account, asset_1, asset_2}); 36 | 37 | // Remove some of the owned liquidity from the pool, but only one asset 38 | await removeLiquidityWithSingleAssetOut({account, asset_1, asset_2}); 39 | 40 | // Swap assets with fixed input 41 | await fixedInputSwap({account, asset_1, asset_2}); 42 | 43 | // Swap assets with fixed output 44 | await fixedOutputSwap({account, asset_1, asset_2}); 45 | 46 | console.log("✅ All operations completed successfully"); 47 | } 48 | 49 | main(); 50 | -------------------------------------------------------------------------------- /dist/add-liquidity/v2/types.d.ts: -------------------------------------------------------------------------------- 1 | import { AssetWithIdAndAmount, AssetWithIdAndAmountAndDecimals } from "../../util/asset/assetModels"; 2 | export interface V2InitialAddLiquidityQuote { 3 | asset1In: { 4 | id: number; 5 | amount: bigint; 6 | }; 7 | asset2In: { 8 | id: number; 9 | amount: bigint; 10 | }; 11 | poolTokenOut: { 12 | id: number; 13 | amount: bigint; 14 | }; 15 | slippage: number; 16 | } 17 | export interface V2FlexibleAddLiquidityQuote { 18 | asset1In: { 19 | id: number; 20 | amount: bigint; 21 | }; 22 | asset2In: { 23 | id: number; 24 | amount: bigint; 25 | }; 26 | poolTokenOut: { 27 | id: number; 28 | amount: bigint; 29 | }; 30 | share: number; 31 | slippage: number; 32 | internalSwapQuote: V2AddLiquidityInternalSwapQuote; 33 | minPoolTokenAssetAmountWithSlippage: bigint; 34 | } 35 | export interface V2SingleAssetInAddLiquidityQuote { 36 | assetIn: { 37 | id: number; 38 | amount: bigint; 39 | }; 40 | poolTokenOut: { 41 | id: number; 42 | amount: bigint; 43 | }; 44 | share: number; 45 | slippage: number; 46 | internalSwapQuote: V2AddLiquidityInternalSwapQuote; 47 | minPoolTokenAssetAmountWithSlippage: bigint; 48 | } 49 | export interface V2AddLiquidityInternalSwapQuote { 50 | assetIn: AssetWithIdAndAmountAndDecimals; 51 | assetOut: AssetWithIdAndAmountAndDecimals; 52 | swapFees: bigint; 53 | priceImpact: number; 54 | } 55 | export interface V2AddLiquidityExecution { 56 | /** The round that the add liquidity occurred in. */ 57 | round: number; 58 | /** The ID of the transaction. */ 59 | txnID: string; 60 | /** 61 | * The total amount of transaction fees that were spent (in microAlgos) to execute the add liquidity and, 62 | * if applicable, redeem transactions. 63 | */ 64 | fees: number; 65 | /** The ID of the output pool token asset. */ 66 | poolTokenID: number; 67 | /** The group ID for the transaction group. */ 68 | groupID: string; 69 | /** 70 | * Can be `undefined` if the execution was successful, but there was an issue while 71 | * extracting the output asset data fron the transaction response 72 | */ 73 | assetOut: AssetWithIdAndAmount | undefined; 74 | } 75 | -------------------------------------------------------------------------------- /src/contract/v2/contract.ts: -------------------------------------------------------------------------------- 1 | import * as ascJson_v2 from "./asc.json"; 2 | 3 | import {encodeUint64, LogicSigAccount} from "algosdk"; 4 | 5 | import {SupportedNetwork} from "../../util/commonTypes"; 6 | import {getValidatorAppID} from "../../validator"; 7 | import {BaseTinymanContract} from "../base/contract"; 8 | import {CONTRACT_VERSION} from "../constants"; 9 | import {V2PoolLogicSig, V2ValidatorApp} from "./types"; 10 | import {sortAssetIds} from "../../util/asset/assetUtils"; 11 | 12 | export class TinymanContractV2 extends BaseTinymanContract { 13 | private poolLogicSigContractTemplate: string; 14 | 15 | constructor(validatorApp: V2ValidatorApp, poolLogicSig: V2PoolLogicSig) { 16 | super(validatorApp); 17 | 18 | this.poolLogicSigContractTemplate = poolLogicSig.logic.bytecode; 19 | } 20 | 21 | generateLogicSigAccountForPool(params: { 22 | network: SupportedNetwork; 23 | asset1ID: number; 24 | asset2ID: number; 25 | }): LogicSigAccount { 26 | if (params.asset1ID === params.asset2ID) { 27 | throw new Error("Assets are the same"); 28 | } 29 | 30 | const {network} = params; 31 | const validatorAppID = getValidatorAppID(network, CONTRACT_VERSION.V2); 32 | const [asset1ID, asset2ID] = sortAssetIds(params.asset1ID, params.asset2ID); 33 | 34 | // Encode required values, and convert them to byte arrays 35 | const encodedByteArrays = { 36 | bytes: Array.from(Buffer.from(this.poolLogicSigContractTemplate, "base64")), 37 | validatorAppId: Array.from(encodeUint64(validatorAppID)), 38 | asset1ID: Array.from(encodeUint64(asset1ID)), 39 | asset2ID: Array.from(encodeUint64(asset2ID)) 40 | }; 41 | 42 | // Concat byte arrays (we're required to insert validatorAppID and assetIDs in the middle of the byte array) 43 | const finalProgramArray = [ 44 | ...encodedByteArrays.bytes.slice(0, 3), 45 | ...encodedByteArrays.validatorAppId.slice(0, 8), 46 | ...encodedByteArrays.asset1ID.slice(0, 8), 47 | ...encodedByteArrays.asset2ID.slice(0, 8), 48 | ...encodedByteArrays.bytes.slice(27) 49 | ]; 50 | 51 | // Finally, create the logic signature account using the final byte array 52 | return new LogicSigAccount(new Uint8Array(finalProgramArray)); 53 | } 54 | } 55 | 56 | export const tinymanContract_v2 = new TinymanContractV2( 57 | ascJson_v2.contracts.validator_app, 58 | ascJson_v2.contracts.pool_logicsig 59 | ); 60 | -------------------------------------------------------------------------------- /src/util/asset/assetUtils.ts: -------------------------------------------------------------------------------- 1 | import algosdk, {Algodv2} from "algosdk"; 2 | 3 | import {SignerTransaction} from "../commonTypes"; 4 | import TinymanError from "../error/TinymanError"; 5 | import {ALGO_ASSET_ID} from "./assetConstants"; 6 | 7 | export async function generateOptIntoAssetTxns({ 8 | client, 9 | assetID, 10 | initiatorAddr 11 | }: { 12 | client: Algodv2; 13 | assetID: number; 14 | initiatorAddr: string; 15 | }): Promise { 16 | try { 17 | const suggestedParams = await client.getTransactionParams().do(); 18 | 19 | const optInTxn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({ 20 | sender: initiatorAddr, 21 | receiver: initiatorAddr, 22 | assetIndex: assetID, 23 | amount: 0, 24 | suggestedParams 25 | }); 26 | 27 | return [{txn: optInTxn, signers: [initiatorAddr]}]; 28 | } catch (error: any) { 29 | throw new TinymanError( 30 | error, 31 | "We encountered something unexpected while opting into this asset. Try again later." 32 | ); 33 | } 34 | } 35 | 36 | /** 37 | * @param asset_1 - Asset 1 of the pool 38 | * @param asset_2 - Asset 2 of the pool 39 | * @returns Array of assets, ordered by descending asset id 40 | */ 41 | 42 | export function prepareAssetPairData( 43 | asset_1: Asset, 44 | asset_2: Asset 45 | ): [Omit & {id: number}, Omit & {id: number}] { 46 | const asset1ID = Number(asset_1.id); 47 | const asset2ID = Number(asset_2.id); 48 | 49 | // Make sure first asset has greater ID 50 | return asset1ID > asset2ID 51 | ? [ 52 | {...asset_1, id: asset1ID}, 53 | {...asset_2, id: asset2ID} 54 | ] 55 | : [ 56 | {...asset_2, id: asset2ID}, 57 | {...asset_1, id: asset1ID} 58 | ]; 59 | } 60 | 61 | /** 62 | * @returns Array of given asset ids, bigger first 63 | */ 64 | export function sortAssetIds(asset1ID: number, asset2ID: number): number[] { 65 | const assets = [asset1ID, asset2ID]; 66 | 67 | return [Math.max(...assets), Math.min(...assets)]; 68 | } 69 | 70 | /** 71 | * @returns `true` if the given asset id is the ALGO asset id 72 | */ 73 | export function isAlgo(id: number | string) { 74 | return Number(id) === ALGO_ASSET_ID; 75 | } 76 | 77 | /** 78 | * @returns Asset id as a number 79 | */ 80 | export function getAssetId(asset: {id: string | number}): number { 81 | return Number(asset.id); 82 | } 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tinymanorg/tinyman-js-sdk", 3 | "version": "5.1.3", 4 | "description": "Tinyman JS SDK", 5 | "author": "Tinyman Core Team", 6 | "license": "MIT", 7 | "main": "dist/index.js", 8 | "types": "dist/index.d.ts", 9 | "directories": { 10 | "dist": "dist" 11 | }, 12 | "scripts": { 13 | "prepare": "husky install", 14 | "prettify": "prettier --config ./.prettierrc.js --write \"src/**/*\"", 15 | "eslint": "eslint --ext .jsx,.js,.tsx,.ts src/", 16 | "type-check": "tsc --noEmit", 17 | "dev": "npm run type-check -- --watch", 18 | "build:types": "tsc --emitDeclarationOnly", 19 | "build:js": "rollup -c", 20 | "build": "npm run build:types && npm run build:js", 21 | "test": "jest" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/tinymanorg/tinyman-js-sdk.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/tinymanorg/tinyman-js-sdk/issues" 29 | }, 30 | "homepage": "https://github.com/tinymanorg/tinyman-js-sdk#readme", 31 | "keywords": [ 32 | "tinyman", 33 | "algorand", 34 | "typescript", 35 | "javascript" 36 | ], 37 | "devDependencies": { 38 | "@babel/preset-env": "^7.26.9", 39 | "@babel/preset-typescript": "^7.27.0", 40 | "@hipo/eslint-config-base": "^4.3.0", 41 | "@hipo/eslint-config-typescript": "^1.2.0", 42 | "@rollup/plugin-babel": "^6.0.4", 43 | "@rollup/plugin-commonjs": "^24.0.1", 44 | "@rollup/plugin-json": "^6.0.0", 45 | "@rollup/plugin-node-resolve": "^15.0.1", 46 | "@rollup/plugin-terser": "0.4.0", 47 | "@types/jest": "^29.5.0", 48 | "@types/node": "^18.15.5", 49 | "@typescript-eslint/eslint-plugin": "^5.56.0", 50 | "@typescript-eslint/parser": "^5.56.0", 51 | "eslint": "^8.36.0", 52 | "eslint-config-prettier": "^8.8.0", 53 | "eslint-import-resolver-typescript": "^2.7.1", 54 | "eslint-plugin-import": "^2.27.5", 55 | "husky": "^8.0.3", 56 | "jest": "^29.5.0", 57 | "js-sha512": "^0.8.0", 58 | "lint-staged": "^13.2.0", 59 | "prettier": "^2.8.6", 60 | "rollup": "^3.20.0", 61 | "rollup-plugin-eslint": "^7.0.0", 62 | "typescript": "^5.0.2", 63 | "@types/uuid": "^10.0.0" 64 | }, 65 | "dependencies": { 66 | "algosdk": "^3.2.0", 67 | "base64-js": "^1.5.1", 68 | "multiformats": "^13.2.2", 69 | "uuid": "^10.0.0" 70 | }, 71 | "lint-staged": { 72 | "src/**/*.{ts,md}": "prettier --write", 73 | "src/**/*.ts": "eslint" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/src/operation/add-liquidity/addInitialLiquidity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AddLiquidity, 3 | combineAndRegroupSignerTxns, 4 | generateOptIntoAssetTxns, 5 | poolUtils, 6 | SupportedNetwork 7 | } from "@tinymanorg/tinyman-js-sdk"; 8 | import {Account} from "algosdk"; 9 | 10 | import {algodClient} from "../../util/client"; 11 | import signerWithSecretKey from "../../util/initiatorSigner"; 12 | 13 | /** 14 | * Adds initial liquidity to a pool 15 | */ 16 | export async function addInitialLiquidity({ 17 | account, 18 | asset_1, 19 | asset_2 20 | }: { 21 | account: Account; 22 | asset_1: {id: string; unit_name: string}; 23 | asset_2: {id: string; unit_name: string}; 24 | }) { 25 | const initiatorAddr = account.addr.toString(); 26 | const poolInfo = await poolUtils.v2.getPoolInfo({ 27 | network: "testnet" as SupportedNetwork, 28 | client: algodClient, 29 | asset1ID: Number(asset_1.id), 30 | asset2ID: Number(asset_2.id) 31 | }); 32 | 33 | // Get a quote for the desired add amount 34 | const quote = AddLiquidity.v2.initial.getQuote({ 35 | pool: poolInfo, 36 | asset1: { 37 | amount: 10_000_000n, 38 | decimals: 6 39 | }, 40 | asset2: { 41 | amount: 25_000_000n, 42 | decimals: 6 43 | } 44 | }); 45 | 46 | let addInitialLiqTxns = await AddLiquidity.v2.initial.generateTxns({ 47 | network: "testnet" as SupportedNetwork, 48 | client: algodClient, 49 | pool: poolInfo, 50 | initiatorAddr, 51 | asset1In: quote.asset1In, 52 | asset2In: quote.asset2In, 53 | poolAddress: poolInfo.account.address().toString(), 54 | poolTokenId: poolInfo.poolTokenID! 55 | }); 56 | 57 | /** 58 | * We assume the account is not opted-in to pool token asset, 59 | * so we add asset opt in txn to the txn group 60 | */ 61 | addInitialLiqTxns = combineAndRegroupSignerTxns( 62 | await generateOptIntoAssetTxns({ 63 | client: algodClient, 64 | assetID: poolInfo.poolTokenID!, 65 | initiatorAddr 66 | }), 67 | addInitialLiqTxns 68 | ); 69 | 70 | const signedTxns = await AddLiquidity.v2.initial.signTxns({ 71 | txGroup: addInitialLiqTxns, 72 | initiatorSigner: signerWithSecretKey(account) 73 | }); 74 | 75 | const executionResponse = await AddLiquidity.v2.initial.execute({ 76 | client: algodClient, 77 | txGroup: addInitialLiqTxns, 78 | signedTxns, 79 | pool: poolInfo 80 | }); 81 | 82 | console.log("✅ Add Initial Liquidity executed successfully!"); 83 | console.log({txnID: executionResponse.txnID}); 84 | } 85 | -------------------------------------------------------------------------------- /src/bootstrap/utils.ts: -------------------------------------------------------------------------------- 1 | import {Algodv2} from "algosdk"; 2 | 3 | import {ContractVersionValue} from "../contract/types"; 4 | import {CONTRACT_VERSION} from "../contract/constants"; 5 | import {TinymanAnalyticsApiAsset} from "../util/asset/assetModels"; 6 | import {SupportedNetwork, SignerTransaction, InitiatorSigner} from "../util/commonTypes"; 7 | import {V1PoolInfo, V2PoolInfo} from "../util/pool/poolTypes"; 8 | import {BootstrapV1_1} from "./v1_1"; 9 | import {BootstrapV2} from "./v2"; 10 | 11 | export function generateTxns(params: { 12 | client: Algodv2; 13 | network: SupportedNetwork; 14 | contractVersion: ContractVersionValue; 15 | asset_1: Pick; 16 | asset_2: Pick; 17 | initiatorAddr: string; 18 | }): Promise { 19 | if (params.contractVersion === CONTRACT_VERSION.V1_1) { 20 | return BootstrapV1_1.generateTxns(params); 21 | } 22 | 23 | return BootstrapV2.generateTxns(params); 24 | } 25 | 26 | export function signTxns(params: { 27 | contractVersion: ContractVersionValue; 28 | txGroup: SignerTransaction[]; 29 | network: SupportedNetwork; 30 | initiatorSigner: InitiatorSigner; 31 | asset1ID: number; 32 | asset2ID: number; 33 | }): Promise<{signedTxns: Uint8Array[]; txnIDs: string[]}> { 34 | if (params.contractVersion === CONTRACT_VERSION.V1_1) { 35 | return BootstrapV1_1.signTxns(params); 36 | } 37 | 38 | return BootstrapV2.signTxns(params); 39 | } 40 | 41 | export function execute( 42 | params: 43 | | (Parameters[0] & { 44 | contractVersion: typeof CONTRACT_VERSION.V2; 45 | }) 46 | | (Parameters[0] & { 47 | contractVersion: typeof CONTRACT_VERSION.V1_1; 48 | }) 49 | ): Promise { 50 | if (params.contractVersion === CONTRACT_VERSION.V1_1) { 51 | return BootstrapV1_1.execute(params); 52 | } 53 | 54 | return BootstrapV2.execute(params); 55 | } 56 | 57 | /** 58 | * Calculates the amount of funding txn for creating a pool 59 | */ 60 | export function calculateBootstrapFundingTxnAmount({ 61 | contractVersion, 62 | isAlgoPool, 63 | minFee 64 | }: { 65 | contractVersion: ContractVersionValue; 66 | isAlgoPool: boolean; 67 | minFee: bigint; 68 | }): bigint { 69 | if (contractVersion === CONTRACT_VERSION.V1_1) { 70 | return BootstrapV1_1.getBootstrapFundingTxnAmount(isAlgoPool); 71 | } 72 | 73 | return BootstrapV2.getBootstrapFundingTxnAmount(isAlgoPool, minFee); 74 | } 75 | -------------------------------------------------------------------------------- /src/add-liquidity/v2/common.ts: -------------------------------------------------------------------------------- 1 | import {Algodv2} from "algosdk"; 2 | 3 | import {AssetWithIdAndAmount} from "../../util/asset/assetModels"; 4 | import {InitiatorSigner, SignerTransaction} from "../../util/commonTypes"; 5 | import TinymanError from "../../util/error/TinymanError"; 6 | import {V2PoolInfo} from "../../util/pool/poolTypes"; 7 | import {getAppCallInnerAssetData} from "../../util/transaction/transactionUtils"; 8 | import {getTxnGroupID, sendAndWaitRawTransaction, sumUpTxnFees} from "../../util/util"; 9 | import {V2AddLiquidityExecution} from "./types"; 10 | 11 | export function signTxns({ 12 | txGroup, 13 | initiatorSigner 14 | }: { 15 | txGroup: SignerTransaction[]; 16 | initiatorSigner: InitiatorSigner; 17 | }): Promise { 18 | return initiatorSigner([txGroup]); 19 | } 20 | 21 | /** 22 | * Execute an add liquidity operation with the desired quantities. 23 | * 24 | * @param params.client An Algodv2 client. 25 | * @param params.pool Information for the pool. 26 | * @param params.txGroup The transaction group to execute. 27 | */ 28 | export async function execute({ 29 | client, 30 | pool, 31 | txGroup, 32 | signedTxns 33 | }: { 34 | client: Algodv2; 35 | pool: V2PoolInfo; 36 | txGroup: SignerTransaction[]; 37 | signedTxns: Uint8Array[]; 38 | }): Promise { 39 | try { 40 | const [{confirmedRound, txnID}] = await sendAndWaitRawTransaction(client, [ 41 | signedTxns 42 | ]); 43 | 44 | let assetOut: AssetWithIdAndAmount | undefined; 45 | 46 | try { 47 | assetOut = (await getAppCallInnerAssetData(client, txGroup))?.find( 48 | // Output asset is the pool token for add liquidity 49 | ({id}) => id === pool.poolTokenID 50 | ); 51 | } catch (_error) { 52 | // We can ignore this error since the main execution was successful 53 | } 54 | 55 | return { 56 | round: confirmedRound, 57 | assetOut, 58 | fees: sumUpTxnFees(txGroup), 59 | poolTokenID: pool.poolTokenID!, 60 | txnID, 61 | groupID: getTxnGroupID(txGroup) 62 | }; 63 | } catch (error: any) { 64 | const parsedError = new TinymanError( 65 | error, 66 | "We encountered something unexpected while adding liquidity. Try again later." 67 | ); 68 | 69 | if (parsedError.type === "SlippageTolerance") { 70 | parsedError.setMessage( 71 | "Adding liquidity failed due to too much slippage in the price. Please adjust the slippage tolerance and try again." 72 | ); 73 | } 74 | 75 | throw parsedError; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /dist/util/account/accountUtils.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2, modelsv2 } from "algosdk"; 2 | import { ContractVersionValue } from "../../contract/types"; 3 | import { V1PoolInfo } from "../pool/poolTypes"; 4 | import { AccountExcess, AccountExcessWithinPool } from "./accountTypes"; 5 | /** 6 | * @returns the decoded application local state object (both keys and values are decoded) 7 | */ 8 | export declare function getDecodedAccountApplicationLocalState(accountInfo: Pick, validatorAppID: number): Record | null; 9 | export declare function hasSufficientMinimumBalance(accountData: Pick): boolean; 10 | /** 11 | * Finds the excess amounts accumulated for an account within a pool 12 | * @param params.client An Algodv2 client. 13 | * @param params.pool Pool info. 14 | * @param params.validatorAppID Validator APP ID 15 | * @returns The excess amounts accumulated for an account within the pool 16 | */ 17 | export declare function getAccountExcessWithinPool({ client, pool, accountAddr }: { 18 | client: Algodv2; 19 | pool: V1PoolInfo; 20 | accountAddr: string; 21 | }): Promise; 22 | /** 23 | * Generates a list of excess amounts accumulated within an account. 24 | * @param params.client An Algodv2 client. 25 | * @param params.accountAddr The address of the account. 26 | * @param params.validatorAppID Validator APP ID 27 | * @returns List of excess amounts 28 | */ 29 | export declare function getAccountExcess({ client, accountAddr, validatorAppID }: { 30 | client: Algodv2; 31 | accountAddr: string; 32 | validatorAppID: bigint; 33 | }): Promise; 34 | /** 35 | * Checks if an account is opted into an app. 36 | * 37 | * @param params.appID The ID of the App. 38 | * @param params.accountAppsLocalState Array of app local states for an account. 39 | * @returns True if and only if the indicated account has opted into the App. 40 | */ 41 | export declare function isAccountOptedIntoApp({ appID, accountAppsLocalState }: { 42 | appID: number; 43 | accountAppsLocalState: modelsv2.Account["appsLocalState"]; 44 | }): boolean; 45 | /** 46 | * @returns the minimum balance required to opt in to an app or asset (decided by `type`) 47 | */ 48 | export declare function getMinRequiredBalanceToOptIn(params: ({ 49 | type: "app-opt-in"; 50 | contractVersion: ContractVersionValue; 51 | } | { 52 | type: "asset-opt-in"; 53 | }) & { 54 | currentMinumumBalanceForAccount: bigint; 55 | suggestedTransactionFee?: bigint; 56 | }): bigint; 57 | -------------------------------------------------------------------------------- /examples/src/operation/remove-liquidity/removeLiquidity.ts: -------------------------------------------------------------------------------- 1 | import {poolUtils, RemoveLiquidity, SupportedNetwork} from "@tinymanorg/tinyman-js-sdk"; 2 | import {Account} from "algosdk"; 3 | 4 | import {getOwnedAssetAmount} from "../../util/account"; 5 | import {algodClient} from "../../util/client"; 6 | import signerWithSecretKey from "../../util/initiatorSigner"; 7 | 8 | /** 9 | * Removes a portion of owned liquidity from a pool 10 | */ 11 | export async function removeLiquidity({ 12 | account, 13 | asset_1, 14 | asset_2 15 | }: { 16 | account: Account; 17 | asset_1: {id: string; unit_name: string}; 18 | asset_2: {id: string; unit_name: string}; 19 | }) { 20 | const initiatorAddr = account.addr.toString(); 21 | const poolInfo = await poolUtils.v2.getPoolInfo({ 22 | network: "testnet" as SupportedNetwork, 23 | client: algodClient, 24 | asset1ID: Number(asset_1.id), 25 | asset2ID: Number(asset_2.id) 26 | }); 27 | const poolReserves = await poolUtils.v2.getPoolReserves(algodClient, poolInfo); 28 | 29 | // Get the owned pool token amount, so we can decide how much to remove 30 | const ownedPoolTokenAssetAmount = await getOwnedAssetAmount( 31 | initiatorAddr, 32 | BigInt(poolInfo.poolTokenID!) 33 | ); 34 | 35 | /** 36 | * For testing purposes, we will remove 1/4 of the owned pool tokens, 37 | * it can be any amount that is lower than the owned amount 38 | */ 39 | const poolTokenAmountToBeRemoved = ownedPoolTokenAssetAmount / 4n; 40 | 41 | // Get a quote for the desired removal amount 42 | const quote = RemoveLiquidity.v2.getQuote({ 43 | pool: poolInfo, 44 | reserves: poolReserves, 45 | poolTokenIn: poolTokenAmountToBeRemoved 46 | }); 47 | 48 | const removeLiquidityTxns = await RemoveLiquidity.v2.generateTxns({ 49 | client: algodClient, 50 | pool: poolInfo, 51 | initiatorAddr, 52 | poolTokenIn: quote.poolTokenIn.amount, 53 | minAsset1Amount: quote.asset1Out.amount, 54 | minAsset2Amount: quote.asset2Out.amount, 55 | slippage: 0.05 56 | }); 57 | 58 | const signedTxns = await RemoveLiquidity.v2.signTxns({ 59 | txGroup: removeLiquidityTxns, 60 | initiatorSigner: signerWithSecretKey(account) 61 | }); 62 | 63 | const executionResponse = await RemoveLiquidity.v2.execute({ 64 | client: algodClient, 65 | txGroup: removeLiquidityTxns, 66 | signedTxns 67 | }); 68 | 69 | console.log("✅ Remove Liquidity executed successfully!"); 70 | console.log({ 71 | outputAssets: JSON.stringify(executionResponse.outputAssets), 72 | txnID: executionResponse.txnID 73 | }); 74 | } 75 | -------------------------------------------------------------------------------- /src/contract/v1_1/asc.json: -------------------------------------------------------------------------------- 1 | { 2 | "repo": "https://github.com/tinymanorg/tinyman-contracts-v1", 3 | "ref": "dc9ab40c58b85c15d58f63a1507e18be76720dbb", 4 | "contracts": { 5 | "pool_logicsig": { 6 | "type": "logicsig", 7 | "logic": { 8 | "bytecode": "BCAIAQCBgICAgICAgPABgICAgICAgIDwAQMEBQYlJA1EMQkyAxJEMRUyAxJEMSAyAxJEMgQiDUQzAQAxABJEMwEQIQcSRDMBGIGCgICAgICAgPABEkQzARkiEjMBGyEEEhA3ARoAgAlib290c3RyYXASEEAAXDMBGSMSRDMBG4ECEjcBGgCABHN3YXASEEACOzMBGyISRDcBGgCABG1pbnQSQAE7NwEaAIAEYnVybhJAAZg3ARoAgAZyZWRlZW0SQAJbNwEaAIAEZmVlcxJAAnkAIQYhBSQjEk0yBBJENwEaARclEjcBGgIXJBIQRDMCADEAEkQzAhAhBBJEMwIhIxJEMwIiIxwSRDMCIyEHEkQzAiQjEkQzAiWACFRNUE9PTDExEkQzAiZRAA+AD1RpbnltYW5Qb29sMS4xIBJEMwIngBNodHRwczovL3RpbnltYW4ub3JnEkQzAikyAxJEMwIqMgMSRDMCKzIDEkQzAiwyAxJEMwMAMQASRDMDECEFEkQzAxElEkQzAxQxABJEMwMSIxJEJCMTQAAQMwEBMwIBCDMDAQg1AUIBsTMEADEAEkQzBBAhBRJEMwQRJBJEMwQUMQASRDMEEiMSRDMBATMCAQgzAwEIMwQBCDUBQgF8MgQhBhJENwEcATEAE0Q3ARwBMwQUEkQzAgAxABNEMwIUMQASRDMDADMCABJEMwIRJRJEMwMUMwMHMwMQIhJNMQASRDMDESMzAxAiEk0kEkQzBAAxABJEMwQUMwIAEkQzAQEzBAEINQFCAREyBCEGEkQ3ARwBMQATRDcBHAEzAhQSRDMDFDMDBzMDECISTTcBHAESRDMCADEAEkQzAhQzBAASRDMCESUSRDMDADEAEkQzAxQzAwczAxAiEk0zBAASRDMDESMzAxAiEk0kEkQzBAAxABNEMwQUMQASRDMBATMCAQgzAwEINQFCAJAyBCEFEkQ3ARwBMQATRDMCADcBHAESRDMCADEAE0QzAwAxABJEMwIUMwIHMwIQIhJNMQASRDMDFDMDBzMDECISTTMCABJEMwEBMwMBCDUBQgA+MgQhBBJENwEcATEAE0QzAhQzAgczAhAiEk03ARwBEkQzAQEzAgEINQFCABIyBCEEEkQzAQEzAgEINQFCAAAzAAAxABNEMwAHMQASRDMACDQBD0M=", 9 | "address": "ABUKAXTANWR6K6ZYV75DWJEPVWWOU6SFUVRI6QHO44E4SIDLHBTD2CZ64A", 10 | "size": 881, 11 | "variables": [ 12 | { 13 | "name": "TMPL_ASSET_ID_1", 14 | "type": "int", 15 | "index": 15, 16 | "length": 10 17 | }, 18 | { 19 | "name": "TMPL_ASSET_ID_2", 20 | "type": "int", 21 | "index": 5, 22 | "length": 10 23 | }, 24 | { 25 | "name": "TMPL_VALIDATOR_APP_ID", 26 | "type": "int", 27 | "index": 74, 28 | "length": 10 29 | } 30 | ], 31 | "source": "https://github.com/tinymanorg/tinyman-contracts-v1/tree/dc9ab40c58b85c15d58f63a1507e18be76720dbb/contracts/pool_logicsig.teal.tmpl" 32 | }, 33 | "name": "pool_logicsig" 34 | }, 35 | "validator_app": { 36 | "type": "app", 37 | "global_state_schema": { 38 | "num_uints": 0, 39 | "num_byte_slices": 0 40 | }, 41 | "local_state_schema": { 42 | "num_uints": 16, 43 | "num_byte_slices": 0 44 | }, 45 | "name": "validator_app" 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/util/pool/common/index.ts: -------------------------------------------------------------------------------- 1 | import {Algodv2} from "algosdk"; 2 | 3 | import {SupportedNetwork} from "../../commonTypes"; 4 | import {V1PoolInfo, V2PoolInfo, PoolReserves, PoolStatus} from "../poolTypes"; 5 | import {getPoolInfo as getV1_1PoolInfo} from "../v1_1"; 6 | import {getPoolInfo as getV2PoolInfo} from "../v2"; 7 | 8 | /** 9 | * @param {bigint} totalLiquidity Total amount of issued liquidity within a pool 10 | * @param {bigint} ownedLiquidity Amount of liquidity tokens within an account 11 | * @returns Percentage of liquidity that the account holds 12 | */ 13 | export function getPoolShare(totalLiquidity: bigint, ownedLiquidity: bigint) { 14 | let share = Number(ownedLiquidity) / Number(totalLiquidity); 15 | 16 | if (!Number.isFinite(share)) { 17 | share = 0; 18 | } 19 | 20 | return share; 21 | } 22 | 23 | /** 24 | * Calculates the pair ratio for the pool reserves 25 | */ 26 | export function getPoolPairRatio( 27 | reserves: null | Pick 28 | ): null | number { 29 | const isEmpty = isPoolEmpty(reserves); 30 | let pairRatio: null | number = null; 31 | 32 | if (reserves && !isEmpty && reserves.asset1 && reserves.asset2) { 33 | pairRatio = Number(reserves.asset1) / Number(reserves.asset2); 34 | } 35 | 36 | return pairRatio; 37 | } 38 | 39 | /** 40 | * Checks if the pool is empty 41 | * 42 | * @param poolReserves - Pool reserves 43 | * @returns true if pool is empty, otherwise returns false 44 | */ 45 | export function isPoolEmpty( 46 | poolReserves: undefined | null | Pick 47 | ): boolean { 48 | return Boolean(poolReserves && !(poolReserves.asset1 + poolReserves.asset2)); 49 | } 50 | 51 | /** 52 | * @param pool - Pool info 53 | * @returns true if pool's status is NOT_CREATED, otherwise returns false 54 | */ 55 | export function isPoolNotCreated(pool: undefined | null | V1PoolInfo | V2PoolInfo) { 56 | return pool?.status === PoolStatus.NOT_CREATED; 57 | } 58 | 59 | /** 60 | * @param pool - Pool info 61 | * @returns true if pool's status is READY, otherwise returns false 62 | */ 63 | export function isPoolReady(pool: undefined | null | V1PoolInfo | V2PoolInfo) { 64 | return pool?.status === PoolStatus.READY; 65 | } 66 | 67 | /** 68 | * @returns {PoolInfo[]} - Pool info for the given asset pair for all contract versions 69 | */ 70 | export function getPoolsForPair(params: { 71 | client: Algodv2; 72 | network: SupportedNetwork; 73 | asset1ID: number; 74 | asset2ID: number; 75 | }): Promise<[V1PoolInfo, V2PoolInfo]> { 76 | return Promise.all([getV1_1PoolInfo(params), getV2PoolInfo(params)]); 77 | } 78 | -------------------------------------------------------------------------------- /dist/remove-liquidity/v2/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Algodv2 } from "algosdk"; 2 | import { SignerTransaction, InitiatorSigner } from "../../util/commonTypes"; 3 | import { PoolReserves, V2PoolInfo } from "../../util/pool/poolTypes"; 4 | import { V2RemoveLiquidityExecution, V2RemoveLiquidityQuote, V2SingleAssetRemoveLiquidityQuote } from "./types"; 5 | /** 6 | * Get a quote for how many of assets 1 and 2 a deposit of `poolTokenIn` is worth at this moment. This 7 | * does not execute any transactions. 8 | */ 9 | declare function getQuote({ pool, reserves, poolTokenIn }: { 10 | pool: V2PoolInfo; 11 | reserves: PoolReserves; 12 | poolTokenIn: bigint; 13 | }): V2RemoveLiquidityQuote; 14 | declare function getSingleAssetRemoveLiquidityQuote({ pool, reserves, poolTokenIn, assetOutID, decimals }: { 15 | pool: V2PoolInfo; 16 | reserves: PoolReserves; 17 | poolTokenIn: bigint; 18 | assetOutID: number; 19 | decimals: { 20 | assetIn: number; 21 | assetOut: number; 22 | }; 23 | }): V2SingleAssetRemoveLiquidityQuote; 24 | /** 25 | * Generates transactions for multiple asset out remove liquidity operation 26 | */ 27 | declare function generateTxns({ client, pool, poolTokenIn, initiatorAddr, minAsset1Amount, minAsset2Amount, slippage }: { 28 | client: Algodv2; 29 | pool: V2PoolInfo; 30 | poolTokenIn: number | bigint; 31 | initiatorAddr: string; 32 | minAsset1Amount: bigint; 33 | minAsset2Amount: bigint; 34 | slippage: number; 35 | }): Promise; 36 | /** 37 | * Generates transactions for single asset out remove liquidity operation 38 | */ 39 | declare function generateSingleAssetOutTxns({ client, pool, initiatorAddr, poolTokenIn, outputAssetId, minOutputAssetAmount, slippage }: { 40 | client: Algodv2; 41 | pool: V2PoolInfo; 42 | outputAssetId: number; 43 | poolTokenIn: bigint; 44 | initiatorAddr: string; 45 | minOutputAssetAmount: bigint; 46 | slippage: number; 47 | }): Promise; 48 | declare function signTxns({ txGroup, initiatorSigner }: { 49 | txGroup: SignerTransaction[]; 50 | initiatorSigner: InitiatorSigner; 51 | }): Promise; 52 | declare function execute({ client, txGroup, signedTxns }: { 53 | client: Algodv2; 54 | txGroup: SignerTransaction[]; 55 | signedTxns: Uint8Array[]; 56 | }): Promise; 57 | export declare const RemoveLiquidityV2: { 58 | getQuote: typeof getQuote; 59 | getSingleAssetRemoveLiquidityQuote: typeof getSingleAssetRemoveLiquidityQuote; 60 | generateTxns: typeof generateTxns; 61 | generateSingleAssetOutTxns: typeof generateSingleAssetOutTxns; 62 | signTxns: typeof signTxns; 63 | execute: typeof execute; 64 | }; 65 | export {}; 66 | -------------------------------------------------------------------------------- /examples/src/operation/add-liquidity/addFlexibleLiquidity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AddLiquidity, 3 | combineAndRegroupSignerTxns, 4 | generateOptIntoAssetTxns, 5 | poolUtils, 6 | SupportedNetwork 7 | } from "@tinymanorg/tinyman-js-sdk"; 8 | import {Account} from "algosdk"; 9 | 10 | import {getIsAccountOptedIntoAsset} from "../../util/asset"; 11 | import {algodClient} from "../../util/client"; 12 | import signerWithSecretKey from "../../util/initiatorSigner"; 13 | 14 | /** 15 | * Adds liquidity to an existent pool using the flexible mode 16 | */ 17 | export async function addFlexibleLiquidity({ 18 | account, 19 | asset_1, 20 | asset_2 21 | }: { 22 | account: Account; 23 | asset_1: {id: string; unit_name: string}; 24 | asset_2: {id: string; unit_name: string}; 25 | }) { 26 | const initiatorAddr = account.addr.toString(); 27 | const poolInfo = await poolUtils.v2.getPoolInfo({ 28 | network: "testnet" as SupportedNetwork, 29 | client: algodClient, 30 | asset1ID: Number(asset_1.id), 31 | asset2ID: Number(asset_2.id) 32 | }); 33 | 34 | // Get a quote for the desired add amount 35 | const quote = AddLiquidity.v2.flexible.getQuote({ 36 | pool: poolInfo, 37 | asset1: { 38 | amount: 25_000_000n, 39 | decimals: 6 40 | }, 41 | asset2: { 42 | amount: 75_000_000n, 43 | decimals: 6 44 | } 45 | }); 46 | 47 | let addFlexibleLiqTxns = await AddLiquidity.v2.flexible.generateTxns({ 48 | network: "testnet" as SupportedNetwork, 49 | client: algodClient, 50 | initiatorAddr, 51 | poolAddress: poolInfo.account.address().toString(), 52 | asset1In: quote.asset1In, 53 | asset2In: quote.asset2In, 54 | poolTokenOut: quote.poolTokenOut, 55 | minPoolTokenAssetAmount: quote.minPoolTokenAssetAmountWithSlippage 56 | }); 57 | 58 | if (!getIsAccountOptedIntoAsset(initiatorAddr, poolInfo.poolTokenID!)) { 59 | /** 60 | * Insert opt-in transaction to the txn group 61 | * if the account is not opted-in to the pool token 62 | */ 63 | addFlexibleLiqTxns = combineAndRegroupSignerTxns( 64 | await generateOptIntoAssetTxns({ 65 | client: algodClient, 66 | assetID: poolInfo.poolTokenID!, 67 | initiatorAddr 68 | }), 69 | addFlexibleLiqTxns 70 | ); 71 | } 72 | 73 | const signedTxns = await AddLiquidity.v2.flexible.signTxns({ 74 | txGroup: addFlexibleLiqTxns, 75 | initiatorSigner: signerWithSecretKey(account) 76 | }); 77 | 78 | const executionResponse = await AddLiquidity.v2.flexible.execute({ 79 | client: algodClient, 80 | txGroup: addFlexibleLiqTxns, 81 | signedTxns, 82 | pool: poolInfo 83 | }); 84 | 85 | console.log("✅ Add Flexible Liquidity executed successfully!"); 86 | console.log({txnID: executionResponse.txnID}); 87 | } 88 | -------------------------------------------------------------------------------- /examples/src/operation/add-liquidity/addSingleAssetLiquidity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AddLiquidity, 3 | combineAndRegroupSignerTxns, 4 | generateOptIntoAssetTxns, 5 | poolUtils, 6 | SupportedNetwork 7 | } from "@tinymanorg/tinyman-js-sdk"; 8 | import {Account} from "algosdk"; 9 | 10 | import {getIsAccountOptedIntoAsset} from "../../util/asset"; 11 | import {algodClient} from "../../util/client"; 12 | import signerWithSecretKey from "../../util/initiatorSigner"; 13 | 14 | /** 15 | * Adds liquidity to an existent pool using only a single asset 16 | */ 17 | export async function addSingleAssetLiquidity({ 18 | account, 19 | asset_1, 20 | asset_2 21 | }: { 22 | account: Account; 23 | asset_1: {id: string; unit_name: string}; 24 | asset_2: {id: string; unit_name: string}; 25 | }) { 26 | const initiatorAddr = account.addr.toString(); 27 | const poolInfo = await poolUtils.v2.getPoolInfo({ 28 | network: "testnet" as SupportedNetwork, 29 | client: algodClient, 30 | asset1ID: Number(asset_1.id), 31 | asset2ID: Number(asset_2.id) 32 | }); 33 | 34 | // Get a quote for the desired add amount 35 | const quote = AddLiquidity.v2.withSingleAsset.getQuote({ 36 | pool: poolInfo, 37 | assetIn: { 38 | // Add liquidity only using asset1 39 | id: Number(asset_1.id), 40 | amount: 25_000_000n 41 | }, 42 | decimals: { 43 | asset1: 6, 44 | asset2: 6 45 | } 46 | }); 47 | 48 | let addLiqTxns = await AddLiquidity.v2.withSingleAsset.generateTxns({ 49 | network: "testnet" as SupportedNetwork, 50 | client: algodClient, 51 | initiatorAddr, 52 | poolAddress: poolInfo.account.address().toString(), 53 | assetIn: quote.assetIn, 54 | poolTokenId: poolInfo.poolTokenID!, 55 | minPoolTokenAssetAmount: quote.minPoolTokenAssetAmountWithSlippage 56 | }); 57 | 58 | if (!getIsAccountOptedIntoAsset(initiatorAddr, poolInfo.poolTokenID!)) { 59 | /** 60 | * Insert opt-in transaction to the txn group 61 | * if the account is not opted-in to the pool token 62 | */ 63 | addLiqTxns = combineAndRegroupSignerTxns( 64 | await generateOptIntoAssetTxns({ 65 | client: algodClient, 66 | assetID: poolInfo.poolTokenID!, 67 | initiatorAddr 68 | }), 69 | addLiqTxns 70 | ); 71 | } 72 | 73 | const signedTxns = await AddLiquidity.v2.withSingleAsset.signTxns({ 74 | txGroup: addLiqTxns, 75 | initiatorSigner: signerWithSecretKey(account) 76 | }); 77 | 78 | const executionResponse = await AddLiquidity.v2.withSingleAsset.execute({ 79 | client: algodClient, 80 | txGroup: addLiqTxns, 81 | signedTxns, 82 | pool: poolInfo 83 | }); 84 | 85 | console.log("✅ Add Liquidity with Single Asset executed successfully!"); 86 | console.log({txnID: executionResponse.txnID}); 87 | } 88 | --------------------------------------------------------------------------------