diff --git a/dist/governance/client.d.ts b/dist/governance/client.d.ts new file mode 100644 index 00000000..715cce12 --- /dev/null +++ b/dist/governance/client.d.ts @@ -0,0 +1,72 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import { SuggestedParams, Transaction } from "algosdk"; +import { VaultAppGlobalState } from "./vault/storage"; +import { RewardsAppGlobalState } from "./rewards/storage"; +import { ProposalVotingAppGlobalState } from "./proposal-voting/storage"; +import { ProposalVote } from "./proposal-voting/constants"; +import { GetRawBoxValueCacheProps } from "./types"; +import { SupportedNetwork } from "../util/commonTypes"; +declare class TinymanGovernanceClient { + private algodClient; + private userAddress; + private network; + constructor(algodClient: AlgodClient, userAddress: string, network: SupportedNetwork); + getTinyPower(timeStamp?: number, cacheProps?: GetRawBoxValueCacheProps): Promise; + getTotalTinyPower(timeStamp?: number, cacheProps?: GetRawBoxValueCacheProps): Promise; + getCumulativeTinyPower(cacheProps?: GetRawBoxValueCacheProps, timeStamp?: number): Promise; + fetchVaultAppGlobalState(): Promise; + generateCreateLockTransactions({ lockedAmount, lockEndTime, userAddress }: { + lockedAmount: number; + lockEndTime: number; + userAddress?: string; + }): Promise; + generateIncreaseLockAmountTransactions({ lockedAmount, userAddress }: { + lockedAmount: number; + userAddress?: string; + }): Promise; + generateExtendLockTimeTransactions({ newLockEndTime, userAddress }: { + newLockEndTime: number; + userAddress?: string; + }): Promise; + generateIncreaseLockAmountAndExtendLockEndTimeTransactions({ lockAmount, lockEndTime, userAddress }: { + lockAmount: number; + lockEndTime: number; + userAddress?: string; + }): Promise; + generateWithdrawTransactions(userAddress?: string, shouldOptIntoTINY?: boolean): Promise; + fetchAccountState(): Promise; + fetchStakingDistributionProposal(proposalId: string): Promise; + generateCastVoteForStakingDistributionProposalTransactions({ proposalId, votes, assetIds, userAddress, suggestedParams }: { + proposalId: string; + votes: number[]; + assetIds: number[]; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + fetchRewardsAppGlobalState(): Promise; + generateClaimRewardTransactions({ periodIndexStart, periodCount, userAddress, suggestedParams, shouldOptIntoTINY }: { + periodIndexStart: number; + periodCount: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + shouldOptIntoTINY?: boolean; + }): Promise; + fetchProposal(proposalId: string): Promise; + uploadProposalMetadata(proposalId: string, metadata: any): Promise; + generateCreateProposalTransactions({ proposalId, userAddress, suggestedParams, executionHash, executor }: { + proposalId: string; + userAddress?: string; + suggestedParams?: SuggestedParams; + executionHash?: string; + executor?: string; + }): Promise; + generateCastVoteTransactions({ proposalId, suggestedParams, vote, userAddress }: { + proposalId: string; + vote: ProposalVote; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + fetchProposalVotingAppGlobalState(): Promise; + getRequiredTinyPowerToCreateProposal(): Promise; +} +export { TinymanGovernanceClient }; diff --git a/dist/governance/constants.d.ts b/dist/governance/constants.d.ts new file mode 100644 index 00000000..4edd9043 --- /dev/null +++ b/dist/governance/constants.d.ts @@ -0,0 +1,16 @@ +import { SupportedNetwork } from "../util/commonTypes"; +declare const HOUR_IN_S: number; +declare const DAY_IN_S: number; +declare const WEEK_IN_S: number; +declare const VAULT_APP_ID: Record; +declare const STAKING_VOTING_APP_ID: Record; +declare const REWARDS_APP_ID: Record; +declare const PROPOSAL_VOTING_APP_ID: Record; +declare const BOX_FLAT_MIN_BALANCE = 2500; +declare const BOX_BYTE_MIN_BALANCE = 400; +declare const HOUR: number; +declare const DAY: number; +declare const WEEK: number; +export { HOUR, DAY, WEEK }; +declare const TWO_TO_THE_64: number; +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, PROPOSAL_VOTING_APP_ID }; diff --git a/dist/governance/index.d.ts b/dist/governance/index.d.ts new file mode 100644 index 00000000..45a24f7b --- /dev/null +++ b/dist/governance/index.d.ts @@ -0,0 +1,76 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import { SuggestedParams, Transaction } from "algosdk"; +import { VaultAppGlobalState } from "./vault/storage"; +import { RewardsAppGlobalState } from "./rewards/storage"; +import { ProposalVotingAppGlobalState } from "./proposal-voting/storage"; +import { ProposalVote } from "./proposal-voting/constants"; +import { GetRawBoxValueCacheProps } from "./types"; +import { SupportedNetwork } from "../util/commonTypes"; +declare class TinymanGovernanceClient { + private algodClient; + private userAddress; + private network; + constructor(algodClient: AlgodClient, userAddress: string, network: SupportedNetwork); + getTinyPower(timeStamp?: number, cacheProps?: GetRawBoxValueCacheProps): Promise; + getTotalTinyPower(timeStamp?: number, cacheProps?: GetRawBoxValueCacheProps): Promise; + getCumulativeTinyPower(cacheProps?: GetRawBoxValueCacheProps, timeStamp?: number): Promise; + fetchVaultAppGlobalState(): Promise; + generateCreateLockTransactions({ lockedAmount, lockEndTime, userAddress, suggestedParams }: { + lockedAmount: number; + lockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + generateIncreaseLockAmountTransactions({ lockedAmount, userAddress, suggestedParams }: { + lockedAmount: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + generateExtendLockTimeTransactions({ newLockEndTime, userAddress, suggestedParams }: { + newLockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + generateIncreaseLockAmountAndExtendLockEndTimeTransactions({ lockAmount, lockEndTime, userAddress, suggestedParams }: { + lockAmount: number; + lockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + generateWithdrawTransactions(userAddress?: string, shouldOptIntoTINY?: boolean, suggestedParams?: SuggestedParams): Promise; + fetchAccountState(): Promise; + fetchStakingDistributionProposal(proposalId: string): Promise; + generateCastVoteForStakingDistributionProposalTransactions({ proposalId, votes, assetIds, userAddress, suggestedParams }: { + proposalId: string; + votes: number[]; + assetIds: number[]; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + fetchRewardsAppGlobalState(): Promise; + generateClaimRewardTransactions({ periodIndexStart, periodCount, userAddress, suggestedParams, shouldOptIntoTINY }: { + periodIndexStart: number; + periodCount: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + shouldOptIntoTINY?: boolean; + }): Promise; + fetchProposal(proposalId: string): Promise; + uploadProposalMetadata(proposalId: string, metadata: any): Promise; + generateCreateProposalTransactions({ proposalId, userAddress, suggestedParams, executionHash, executor }: { + proposalId: string; + userAddress?: string; + suggestedParams?: SuggestedParams; + executionHash?: string; + executor?: string; + }): Promise; + generateCastVoteTransactions({ proposalId, suggestedParams, vote, userAddress }: { + proposalId: string; + vote: ProposalVote; + userAddress?: string; + suggestedParams?: SuggestedParams; + }): Promise; + fetchProposalVotingAppGlobalState(): Promise; + getRequiredTinyPowerToCreateProposal(): Promise; +} +export { TinymanGovernanceClient }; diff --git a/dist/governance/proposal-voting/constants.d.ts b/dist/governance/proposal-voting/constants.d.ts new file mode 100644 index 00000000..92d9e360 --- /dev/null +++ b/dist/governance/proposal-voting/constants.d.ts @@ -0,0 +1,15 @@ +declare const PROPOSAL_BOX_PREFIX: Uint8Array; +declare const ATTENDANCE_SHEET_BOX_PREFIX: Uint8Array; +declare const ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; +declare const PROPOSAL_BOX_SIZE: number; +declare const PROPOSAL_BOX_COST: number; +declare const ATTENDANCE_SHEET_BOX_COST: number; +declare enum ProposalVote { + Against = 0, + For = 1, + Abstain = 2 +} +declare const EXECUTION_HASH_SIZE = 34; +declare const CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT: Uint8Array; +declare const EXECUTOR_FALLBACK_ADDRESS = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"; +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, EXECUTOR_FALLBACK_ADDRESS }; diff --git a/dist/governance/proposal-voting/storage.d.ts b/dist/governance/proposal-voting/storage.d.ts new file mode 100644 index 00000000..f47bf61a --- /dev/null +++ b/dist/governance/proposal-voting/storage.d.ts @@ -0,0 +1,38 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +export declare class Proposal { + 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; + 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); + get snapshotTimestamp(): number; +} +export declare class ProposalVotingAppGlobalState { + vaultAppId: number; + proposalIndexCounter: number; + votingDelay: number; + votingDuration: number; + proposalThreshold: number; + proposalThresholdNumerator: number; + quorumThreshold: number; + approvalRequirement: number; + manager: string; + proposalManager: Uint8Array; + constructor(vaultAppId: number, proposalIndexCounter: number, votingDelay: number, votingDuration: number, proposalThreshold: number, proposalThresholdNumerator: number, quorumThreshold: number, approvalRequirement: number, manager: string, proposalManager: Uint8Array); +} +export declare function getProposalBoxName(proposalId: string): Uint8Array; +export declare function getAttendanceSheetBoxName(address: string, boxIndex: number): Uint8Array; +export declare function getProposal(client: AlgodClient, appId: number, proposalId: string): Promise; diff --git a/dist/governance/proposal-voting/transactions.d.ts b/dist/governance/proposal-voting/transactions.d.ts new file mode 100644 index 00000000..70fb68d0 --- /dev/null +++ b/dist/governance/proposal-voting/transactions.d.ts @@ -0,0 +1,35 @@ +import algosdk, { SuggestedParams } from "algosdk"; +import { VaultAppGlobalState } from "../vault/storage"; +import { ProposalVote } from "./constants"; +import { Proposal } from "./storage"; +import { GenerateProposalMetadataPayload } from "./types"; +export declare function generateProposalMetadata({ category, description, discussionUrl, pollUrl, title }: GenerateProposalMetadataPayload): { + category: string; + description: string; + discussion_url: string; + poll_url: string; + title: string; +}; +export declare function prepareCreateProposalTransactions({ proposalId, proposalVotingAppId, sender, vaultAppId, vaultAppGlobalState, executionHash, executor, suggestedParams, appCallNote }: { + proposalVotingAppId: number; + sender: string; + proposalId: string; + vaultAppId: number; + vaultAppGlobalState: VaultAppGlobalState; + executionHash?: string; + executor?: Uint8Array; + suggestedParams: SuggestedParams; + appCallNote?: string; +}): algosdk.Transaction[]; +export declare function prepareCastVoteTransactions({ accountPowerIndex, createAttendanceSheetBox, proposal, proposalId, proposalVotingAppId, sender, suggestedParams, vaultAppId, vote, appCallNote }: { + proposalVotingAppId: number; + vaultAppId: number; + sender: string; + proposalId: string; + proposal: Proposal; + vote: ProposalVote; + accountPowerIndex: number; + createAttendanceSheetBox: boolean; + suggestedParams: SuggestedParams; + appCallNote?: string; +}): algosdk.Transaction[]; diff --git a/dist/governance/proposal-voting/types.d.ts b/dist/governance/proposal-voting/types.d.ts new file mode 100644 index 00000000..9f8ee028 --- /dev/null +++ b/dist/governance/proposal-voting/types.d.ts @@ -0,0 +1,8 @@ +interface GenerateProposalMetadataPayload { + title: string; + description: string; + category: string; + discussionUrl: string; + pollUrl: string; +} +export type { GenerateProposalMetadataPayload }; diff --git a/dist/governance/rewards/constants.d.ts b/dist/governance/rewards/constants.d.ts new file mode 100644 index 00000000..00abe061 --- /dev/null +++ b/dist/governance/rewards/constants.d.ts @@ -0,0 +1,8 @@ +declare const REWARD_PERIOD_BOX_PREFIX: Uint8Array; +declare const REWARD_CLAIM_SHEET_BOX_SIZE = 1012; +declare const REWARD_CLAIM_SHEET_BOX_PREFIX: Uint8Array; +declare const REWARD_PERIOD_SIZE = 24; +declare const REWARD_PERIOD_BOX_SIZE = 1008; +declare const REWARD_PERIOD_BOX_ARRAY_LEN = 42; +declare const REWARD_CLAIM_SHEET_BOX_COST: number; +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 }; diff --git a/dist/governance/rewards/storage.d.ts b/dist/governance/rewards/storage.d.ts new file mode 100644 index 00000000..298bcbb2 --- /dev/null +++ b/dist/governance/rewards/storage.d.ts @@ -0,0 +1,19 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +declare class RewardsAppGlobalState { + tinyAssetId: number; + vaultAppId: number; + rewardHistoryCount: number; + firstPeriodTimestamp: number; + rewardPeriodCount: number; + manager: string; + rewardsManager: string; + constructor(tinyAssetId: number, vaultAppId: number, rewardHistoryCount: number, firstPeriodTimestamp: number, rewardPeriodCount: number, manager: string, rewardsManager: string); +} +declare class RewardClaimSheet { + value: Uint8Array; + constructor(value: Uint8Array); +} +declare function getRewardPeriodBoxName(boxIndex: number): Uint8Array; +declare function getAccountRewardClaimSheetBoxName(address: string, boxIndex: number): Uint8Array; +declare function getRewardClaimSheet(algod: AlgodClient, appId: number, address: string, accountRewardClaimSheetBoxIndex: number): Promise; +export { RewardClaimSheet, RewardsAppGlobalState, getRewardPeriodBoxName, getAccountRewardClaimSheetBoxName, getRewardClaimSheet }; diff --git a/dist/governance/rewards/transactions.d.ts b/dist/governance/rewards/transactions.d.ts new file mode 100644 index 00000000..83e6f819 --- /dev/null +++ b/dist/governance/rewards/transactions.d.ts @@ -0,0 +1,14 @@ +import { SuggestedParams, Transaction } from "algosdk"; +declare function prepareClaimRewardsTransactions({ rewardsAppId, vaultAppId, tinyAssetId, sender, periodIndexStart, periodCount, accountPowerIndexes, suggestedParams, createRewardClaimSheet, appCallNote }: { + rewardsAppId: number; + vaultAppId: number; + tinyAssetId: number; + sender: string; + periodIndexStart: number; + periodCount: number; + accountPowerIndexes: number[]; + suggestedParams: SuggestedParams; + createRewardClaimSheet: boolean; + appCallNote?: string; +}): Transaction[]; +export { prepareClaimRewardsTransactions }; diff --git a/dist/governance/staking-voting/constants.d.ts b/dist/governance/staking-voting/constants.d.ts new file mode 100644 index 00000000..a67c3a6b --- /dev/null +++ b/dist/governance/staking-voting/constants.d.ts @@ -0,0 +1,7 @@ +declare const STAKING_VOTE_MAX_OPTION_COUNT = 8; +declare const PROPOSAL_BOX_PREFIX: Uint8Array; +declare const STAKING_ATTENDANCE_BOX_PREFIX: Uint8Array; +declare const STAKING_VOTE_BOX_PREFIX: Uint8Array; +declare const STAKING_ATTENDANCE_BOX_COST: number; +declare const STAKING_VOTE_BOX_COST: number; +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 }; diff --git a/dist/governance/staking-voting/storage.d.ts b/dist/governance/staking-voting/storage.d.ts new file mode 100644 index 00000000..47ae53ea --- /dev/null +++ b/dist/governance/staking-voting/storage.d.ts @@ -0,0 +1,16 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +declare class StakingDistributionProposal { + index: number; + creationTimestamp: number; + votingStartTimestamp: number; + votingEndTimestamp: number; + votingPower: number; + voteCount: number; + isCancelled: boolean; + constructor(index: number, creationTimestamp: number, votingStartTimestamp: number, votingEndTimestamp: number, votingPower: number, voteCount: number, isCancelled: boolean); +} +declare function getStakingDistributionProposalBoxName(proposalId: string): Uint8Array; +declare function getStakingAttendanceSheetBoxName(sender: string, boxIndex: number): Uint8Array; +declare function getStakingVoteBoxName(proposalIndex: number, assetId: number): Uint8Array; +declare function getStakingDistributionProposal(algod: AlgodClient, appId: number, proposalId: string): Promise; +export { StakingDistributionProposal, getStakingDistributionProposalBoxName, getStakingAttendanceSheetBoxName, getStakingVoteBoxName, getStakingDistributionProposal }; diff --git a/dist/governance/staking-voting/transactions.d.ts b/dist/governance/staking-voting/transactions.d.ts new file mode 100644 index 00000000..611b3868 --- /dev/null +++ b/dist/governance/staking-voting/transactions.d.ts @@ -0,0 +1,16 @@ +import { SuggestedParams } from "algosdk"; +import { StakingDistributionProposal } from "./storage"; +declare function prepareCastVoteForStakingDistributionProposalTransactions({ stakingVotingAppId, vaultAppId, sender, proposalId, proposal, votes, assetIds, accountPowerIndex, appBoxNames, suggestedParams, appCallNote }: { + stakingVotingAppId: number; + vaultAppId: number; + sender: string; + proposalId: string; + proposal: StakingDistributionProposal; + votes: number[]; + assetIds: number[]; + accountPowerIndex: number; + appBoxNames: Uint8Array[]; + suggestedParams: SuggestedParams; + appCallNote: string | null; +}): import("algosdk").Transaction[]; +export { prepareCastVoteForStakingDistributionProposalTransactions }; diff --git a/dist/governance/transactions.d.ts b/dist/governance/transactions.d.ts new file mode 100644 index 00000000..e1909326 --- /dev/null +++ b/dist/governance/transactions.d.ts @@ -0,0 +1,10 @@ +import algosdk, { SuggestedParams } from "algosdk"; +declare function prepareBudgetIncreaseTxn({ sender, index, suggestedParams, boxes, extraAppArgs, foreignApps }: { + sender: string; + index: number; + suggestedParams: SuggestedParams; + extraAppArgs?: Uint8Array[]; + foreignApps?: number[]; + boxes?: algosdk.BoxReference[]; +}): algosdk.Transaction; +export { prepareBudgetIncreaseTxn }; diff --git a/dist/governance/types.d.ts b/dist/governance/types.d.ts new file mode 100644 index 00000000..26248284 --- /dev/null +++ b/dist/governance/types.d.ts @@ -0,0 +1,7 @@ +export interface RawBoxCacheValue { + [key: string]: Uint8Array; +} +export interface GetRawBoxValueCacheProps { + onCacheUpdate: (cacheData: RawBoxCacheValue) => void; + cacheData: RawBoxCacheValue | null; +} diff --git a/dist/governance/util/utils.d.ts b/dist/governance/util/utils.d.ts new file mode 100644 index 00000000..83375063 --- /dev/null +++ b/dist/governance/util/utils.d.ts @@ -0,0 +1,4 @@ +export declare function intToBytes(num: number, length?: number): Uint8Array; +export declare function areBuffersEqual(buf1: Uint8Array, buf2: Uint8Array): boolean; +export declare function bytesToInt(buffer: Uint8Array): number; +export declare function sum(values: number[]): number; diff --git a/dist/governance/utils.d.ts b/dist/governance/utils.d.ts new file mode 100644 index 00000000..26468232 --- /dev/null +++ b/dist/governance/utils.d.ts @@ -0,0 +1,21 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import { Transaction } from "algosdk"; +import { GetRawBoxValueCacheProps } from "./types"; +declare function getRawBoxValue(algod: AlgodClient, appId: number, boxName: Uint8Array, cacheProps?: GetRawBoxValueCacheProps): Promise; +declare function doesBoxExist(algod: AlgodClient, appId: number, boxName: Uint8Array): Promise; +declare function getBias(slope: number, timeDelta: number): number; +/** + * Calculates the tiny power at a given timestamp + * @param lockAmount - amount of tokens locked + * @param lockEndTime - timestamp of the end of the lock, in seconds + * @param timeStamp - timestamp of the time to calculate the tiny power for, in seconds + * @returns tiny power at the given timestamp + */ +declare function calculateTinyPower(lockAmount: number, lockEndTime: number, timeStamp?: number): number; +declare function getCumulativePowerDelta(bias: number, slope: number, timeDelta: number): number; +declare function getGlobalState(algod: AlgodClient, appId: number): Promise>; +declare function concatUint8Arrays(...arrays: Uint8Array[]): Uint8Array; +declare function generateCidFromProposalMetadata(metadata: Record): Promise; +declare function combineAndRegroupTxns(...txns: Transaction[][]): Transaction[]; +declare function getAllBoxNames(algod: AlgodClient, appId: number): Promise; +export { getRawBoxValue, getCumulativePowerDelta, getBias, getGlobalState, concatUint8Arrays, doesBoxExist, getAllBoxNames, generateCidFromProposalMetadata, combineAndRegroupTxns, calculateTinyPower }; diff --git a/dist/governance/vault/constants.d.ts b/dist/governance/vault/constants.d.ts new file mode 100644 index 00000000..3c17fee9 --- /dev/null +++ b/dist/governance/vault/constants.d.ts @@ -0,0 +1,19 @@ +declare const MAX_LOCK_TIME = 126144000; +declare const MIN_LOCK_AMOUNT = 10000000; +declare const MIN_LOCK_AMOUNT_INCREMENT = 10000000; +declare const TWO_TO_THE_64: number; +declare const ACCOUNT_STATE_BOX_SIZE = 32; +declare const SLOPE_CHANGE_BOX_SIZE = 16; +declare const ACCOUNT_POWER_SIZE = 48; +declare const ACCOUNT_POWER_BOX_SIZE = 1008; +declare const ACCOUNT_POWER_BOX_ARRAY_LEN = 21; +declare const TOTAL_POWER_SIZE = 48; +declare const TOTAL_POWER_BOX_SIZE = 1008; +declare const TOTAL_POWER_BOX_ARRAY_LEN = 21; +declare const TOTAL_POWERS: Uint8Array; +declare const SLOPE_CHANGES: Uint8Array; +declare const ACCOUNT_STATE_BOX_COST: number; +declare const SLOPE_CHANGE_BOX_COST: number; +declare const ACCOUNT_POWER_BOX_COST: number; +declare const TOTAL_POWER_BOX_COST: number; +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 }; diff --git a/dist/governance/vault/storage.d.ts b/dist/governance/vault/storage.d.ts new file mode 100644 index 00000000..ee12045d --- /dev/null +++ b/dist/governance/vault/storage.d.ts @@ -0,0 +1,53 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import { GetRawBoxValueCacheProps } from "../types"; +declare class AccountState { + lockedAmount: number; + lockEndTime: number; + powerCount: number; + deletedPowerCount: number; + constructor(lockedAmount: number, lockEndTime: number, powerCount: number, deletedPowerCount: number); + get freeAccountPowerSpaceCount(): number; + get lastAccountPowerBoxIndex(): number; + get lastAccountPowerArrayIndex(): number; +} +declare class AccountPower { + bias: number; + timestamp: number; + slope: number; + cumulativePower: number; + constructor(bias: number, timestamp: number, slope: number, cumulativePower: number); + get lockEndTimestamp(): number; + cumulativePowerAt(timestamp: number): number; +} +declare class TotalPower { + bias: number; + timestamp: number; + slope: number; + cumulativePower: number; + constructor(bias: number, timestamp: number, slope: number, cumulativePower: number); +} +declare class SlopeChange { + slopeDelta?: number; + constructor(slopeDelta?: number); +} +declare class VaultAppGlobalState { + tinyAssetId: number; + totalLockedAmount: number; + totalPowerCount: number; + lastTotalPowerTimestamp: number; + constructor(tinyAssetId: number, totalLockedAmount: number, totalPowerCount: number, lastTotalPowerTimestamp: number); + get freeTotalPowerSpaceCount(): number; + get lastTotalPowerBoxIndex(): number; + get lastTotalPowerArrayIndex(): number; +} +declare function getAccountState(algodClient: AlgodClient, appId: number, address: string): Promise; +declare function getAccountStateBoxName(address: string): Uint8Array; +declare function getTotalPowerBoxName(boxIndex: number): Uint8Array; +declare function getLastAccountPowerBoxIndexes(powerCount: number): [number, number]; +declare function getAccountPowerBoxName(address: string, boxIndex: number): Uint8Array; +declare function getSlopeChange(algod: AlgodClient, appId: number, timeStamp: number): Promise; +declare function getSlopeChangeBoxName(timestamp: number): Uint8Array; +declare function getAllTotalPowers(algodClient: AlgodClient, appId: number, totalPowerCount: number, cacheProps?: GetRawBoxValueCacheProps): Promise; +declare function getAccountPowers(algodClient: AlgodClient, address: string, appId: number, powerCount?: number | null, cacheProps?: GetRawBoxValueCacheProps): Promise; +declare function getPowerIndexAt(powers: AccountPower[] | TotalPower[], timestamp: number): number | null; +export { AccountState, AccountPower, TotalPower, VaultAppGlobalState, SlopeChange, getAccountState, getAccountPowers, getAccountPowerBoxName, getAccountStateBoxName, getLastAccountPowerBoxIndexes, getPowerIndexAt, getTotalPowerBoxName, getSlopeChangeBoxName, getSlopeChange, getAllTotalPowers }; diff --git a/dist/governance/vault/transactions.d.ts b/dist/governance/vault/transactions.d.ts new file mode 100644 index 00000000..7069d657 --- /dev/null +++ b/dist/governance/vault/transactions.d.ts @@ -0,0 +1,43 @@ +import algosdk, { SuggestedParams } from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import { AccountState, SlopeChange, VaultAppGlobalState } from "./storage"; +import { SupportedNetwork } from "../../util/commonTypes"; +declare function prepareCreateLockTransactions({ accountState, lockEndTime, lockedAmount, network, sender, vaultAppGlobalState, suggestedParams, slopeChangeAtLockEndTime, appCallNote }: { + network: SupportedNetwork; + sender: string; + lockedAmount: number; + lockEndTime: number; + vaultAppGlobalState: VaultAppGlobalState; + suggestedParams: SuggestedParams; + accountState?: AccountState | null; + slopeChangeAtLockEndTime?: SlopeChange | null; + appCallNote?: Uint8Array; +}): algosdk.Transaction[]; +declare function prepareIncreaseLockAmountTransactions({ accountState, lockedAmount, network, sender, vaultAppGlobalState, suggestedParams, appCallNote }: { + network: SupportedNetwork; + sender: string; + lockedAmount: number; + vaultAppGlobalState: VaultAppGlobalState; + accountState: AccountState; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}): algosdk.Transaction[]; +declare function prepareExtendLockEndTimeTransactions({ accountState, network, newLockEndTime, slopeChangeAtNewLockEndTime, sender, vaultAppGlobalState, suggestedParams, appCallNote }: { + network: SupportedNetwork; + sender: string; + newLockEndTime: number; + vaultAppGlobalState: VaultAppGlobalState; + accountState: AccountState; + slopeChangeAtNewLockEndTime?: number; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}): algosdk.Transaction[]; +declare function prepareWithdrawTransactions({ accountState, network, sender, suggestedParams, appCallNote }: { + network: SupportedNetwork; + client: AlgodClient; + sender: string; + accountState: AccountState; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}): algosdk.Transaction[]; +export { prepareCreateLockTransactions, prepareIncreaseLockAmountTransactions, prepareExtendLockEndTimeTransactions, prepareWithdrawTransactions }; diff --git a/dist/governance/vault/utils.d.ts b/dist/governance/vault/utils.d.ts new file mode 100644 index 00000000..d6df728b --- /dev/null +++ b/dist/governance/vault/utils.d.ts @@ -0,0 +1,4 @@ +declare function getStartTimestampOfWeek(value: number): number; +declare function getNewTotalPowerTimestamps(oldTimeStamp: number, newTimeStamp: number): number[]; +declare function getSlope(lockedAmount: number): number; +export { getNewTotalPowerTimestamps, getStartTimestampOfWeek, getSlope }; diff --git a/dist/index.d.ts b/dist/index.d.ts index 04649633..85b89555 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -6,7 +6,7 @@ export * from "./swap/common/utils"; export { applySlippageToAmount, ASSET_OPT_IN_PROCESS_TXN_COUNT, convertFromBaseUnits, convertToBaseUnits, sendAndWaitRawTransaction, getTxnGroupID, sumUpTxnFees } from "./util/util"; export { generateOptIntoAssetTxns } from "./util/asset/assetUtils"; export type { AccountAsset, TinymanAnalyticsApiAsset, IndexerAssetInformation } from "./util/asset/assetModels"; -export { ALGO_ASSET, ALGO_ASSET_ID, POOL_TOKEN_UNIT_NAME } from "./util/asset/assetConstants"; +export { ALGO_ASSET, ALGO_ASSET_ID, POOL_TOKEN_UNIT_NAME, TINY_ASSET_ID } from "./util/asset/assetConstants"; export { getAccountInformation, calculateAccountMinimumRequiredBalance, hasSufficientMinimumBalance, isAccountOptedIntoApp, getAccountExcessWithinPool, getAccountExcess, getMinRequiredBalanceToOptIn } from "./util/account/accountUtils"; export type { AccountInformationData } from "./util/account/accountTypes"; export type { ContractVersionValue } from "./contract/types"; @@ -42,3 +42,12 @@ export type { FolksLendingPool } from "./folks-lending-pools/types"; export { prepareCommitTransactions, getStakingAppID } from "./stake"; export { tinymanJSSDKConfig } from "./config"; export { combineAndRegroupSignerTxns } from "./util/transaction/transactionUtils"; +export { TinymanGovernanceClient } from "./governance"; +export type { GetRawBoxValueCacheProps, RawBoxCacheValue } from "./governance/types"; +export { AccountState } from "./governance/vault/storage"; +export { getStartTimestampOfWeek } from "./governance/vault/utils"; +export { ProposalVote } from "./governance/proposal-voting/constants"; +export { generateProposalMetadata } from "./governance/proposal-voting/transactions"; +export type { GenerateProposalMetadataPayload } from "./governance/proposal-voting/types"; +export { intToBytes } from "./governance/util/utils"; +export { generateCidFromProposalMetadata, calculateTinyPower, combineAndRegroupTxns, concatUint8Arrays } from "./governance/utils"; diff --git a/dist/index.js b/dist/index.js index 428ba7df..2b5c26e3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1 +1 @@ -"use strict";var t=require("algosdk"),e=require("base64-js");function n(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function r(t){for(var e=1;e=0;--a){var s=this.tryEntries[a],o=s.completion;if("root"===s.tryLoc)return r("end");if(s.tryLoc<=this.prev){var i=n.call(s,"catchLoc"),u=n.call(s,"finallyLoc");if(i&&u){if(this.prev=0;--r){var a=this.tryEntries[r];if(a.tryLoc<=this.prev&&n.call(a,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),b(n),d}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var a=r.arg;b(n)}return a}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:D(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=void 0),d}},t}function s(t,e,n,r,a,s,o){try{var i=t[s](o),u=i.value}catch(t){return void n(t)}i.done?e(u):Promise.resolve(u).then(r,a)}function o(t){return function(){var e=this,n=arguments;return new Promise((function(r,a){var o=t.apply(e,n);function i(t){s(o,r,a,i,u,"next",t)}function u(t){s(o,r,a,i,u,"throw",t)}i(void 0)}))}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function u(t,e){for(var n=0;nt.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,o=!0,i=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return o=t.done,t},e:function(t){i=!0,s=t},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw s}}}}function _(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var r=n.call(t,e||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}var b=function(t){return t.SwapRouterStaleDataError="SwapRouterStaleDataError",t.SwapRouterNoRouteError="SwapRouterNoRouteError",t.SwapRouterLowSwapAmountError="SwapRouterLowSwapAmountError",t.SwapRouterInsufficientReservesError="SwapRouterInsufficientReservesError",t.SwapRouterPoolHasNoLiquidityError="SwapRouterPoolHasNoLiquidityError",t.NoAvailablePoolError="NoAvailablePoolError",t.OutputAmountExceedsAvailableLiquidityError="OutputAmountExceedsAvailableLiquidityError",t.UnknownError="UnknownError",t.LowSwapAmountError="LowSwapAmountError",t.AssetDoesNotBelongToPoolError="AssetDoesNotBelongToPoolError",t.InvalidSwapTypeError="InvalidSwapTypeError",t}({}),E=function(t){l(n,A(Error));var e=x(n);function n(t,r){var a;return i(this,n),(a=e.call(this,r)).type=t,a.message=r,Error.captureStackTrace&&Error.captureStackTrace(I(a),n),a}return c(n)}(),D=Uint8Array.from([1]),S=1e5,O=1e5,N=1e5,P=1e5,k=1e5,L=5e4,F=28500,R=1e3,B=1e3,M={mainnet:{base:"https://mainnet.analytics.tinyman.org/api",v1:"https://mainnet.analytics.tinyman.org/api/v1"},testnet:{base:"https://testnet.analytics.tinyman.org/api",v1:"https://testnet.analytics.tinyman.org/api/v1"}},C={V1_1:"v1_1",V2:"v2"},j=0,X={id:"".concat(j),name:"Algorand",unit_name:"ALGO",decimals:6,url:"https://algorand.org",is_liquidity_token:!1,total_amount:"6615503326932151",clawback_address:""},V={V1:"TM1POOL",V1_1:"TMPOOL11",V2:"TMPOOL2"},U="- would result negative",Q="logic eval error:",q="exceeds schema integer count",G=/transaction \w+:/,W=function(t){l(n,A(Error));var e=x(n);function n(t,r){var a;i(this,n);for(var s=arguments.length,o=new Array(s>2?s-2:0),u=2;ua?[r(r({},t),{},{id:n}),r(r({},e),{},{id:a})]:[r(r({},e),{},{id:a}),r(r({},t),{},{id:n})]}function Y(t,e){var n=[t,e];return[Math.max.apply(Math,n),Math.min.apply(Math,n)]}function K(t){return Number(t)===j}function H(t){return Number(t.id)}function Z(t){var e,n=t.stateArray,r=void 0===n?[]:n,a=t.shouldDecodeKeys,s=void 0!==a&&a,o={},i=w(r);try{for(i.s();!(e=i.n()).done;){var u=e.value,c=u.key,p=void 0;if(1==u.value.type)p=u.value.bytes;else{if(2!=u.value.type)throw new Error("Unexpected state type: ".concat(u.value.type));p=u.value.uint}o[s?atob(c):c]=p}}catch(t){i.e(t)}finally{i.f()}return o}function $(t){var e,n=t.reduce((function(t,e){return t+e.length}),0),r=new Uint8Array(n),a=0,s=w(t);try{for(s.s();!(e=s.n()).done;){var o=e.value;r.set(o,a),a+=o.length}}catch(t){s.e(t)}finally{s.f()}return r}var tt=100000n,et=100000n,nt=100000n,rt=25000n+25000n,at=25000n+3500n;function st(t){var e=t["apps-total-schema"],n=0n,r=0n;e&&(e["num-byte-slice"]&&(n=e["num-byte-slice"]),e["num-uint"]&&(r=e["num-uint"]));var a=t["apps-local-state"]||[],s=t["created-apps"]||[],o=t.assets||[];return tt+et*BigInt(o.length)+nt*BigInt(s.length+a.length)+at*r+rt*n}function ot(t){return new Promise((function(e){setTimeout((function(){e(null)}),t)}))}function it(t,e){return ut.apply(this,arguments)}function ut(){return(ut=o(a().mark((function t(e,n){var r;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=3,ot(1e3);case 3:return r=null,t.prev=4,t.next=7,e.pendingTransactionInformation(n).do();case 7:r=t.sent,t.next=12;break;case 10:t.prev=10,t.t0=t.catch(4);case 12:if(!r){t.next=17;break}if(!r["confirmed-round"]){t.next=15;break}return t.abrupt("return",r);case 15:if(!r["pool-error"]){t.next=17;break}throw new Error("Transaction Rejected: ".concat(r["pool-error"]));case 17:t.next=0;break;case 19:case"end":return t.stop()}}),t,null,[[4,10]])})))).apply(this,arguments)}function ct(t,e,n){if(e>1||e<0)throw new Error("Invalid slippage value. Must be between 0 and 1, got ".concat(e));var r;try{var a="negative"===t?1-e:1+e;r=BigInt(Math.floor(Number(n)*a))}catch(t){throw new Error(t.message)}return r}function pt(t,e){var n=Number(t);return lt({decimalPlaces:n},Math.pow(10,-n)*Number(e))}function lt(t,e){var n=t.decimalPlaces,r=void 0===n?0:n;if(r>0){var a=h(ft(e),2),s=a[0],o=a[1],i=h(ft(Math.round(Number(dt(s,o+r)))),2),u=i[0],c=i[1];return Number(dt(u,c-r))}return Math.round(e)}function dt(t,e){return t+(e<0?"e".concat(e):"e+".concat(e))}function ft(t){if(t.toString().includes("e")){var e=t.toString().split("e");return[parseFloat(e[0]),parseFloat(e[1])]}return[t,0]}function mt(t,e){return gt.apply(this,arguments)}function gt(){return(gt=o(a().mark((function t(e,n){var r,s,o,i,u,c,p,l;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:t.prev=0,r=[],s=w(n),t.prev=3,s.s();case 5:if((o=s.n()).done){t.next=18;break}return i=o.value,t.next=9,e.sendRawTransaction(i).do();case 9:return u=t.sent,c=u.txId,t.next=13,it(e,c);case 13:p=t.sent,l=p["confirmed-round"],r.push({confirmedRound:l,txnID:c});case 16:t.next=5;break;case 18:t.next=23;break;case 20:t.prev=20,t.t0=t.catch(3),s.e(t.t0);case 23:return t.prev=23,s.f(),t.finish(23);case 26:return t.abrupt("return",r);case 29:throw t.prev=29,t.t1=t.catch(0),new W(t.t1,"We encountered an error while processing this transaction. Try again later.");case 32:case"end":return t.stop()}}),t,null,[[0,29],[3,20,23,26]])})))).apply(this,arguments)}function At(t){return t.reduce((function(t,e){return t+e.txn.fee}),0)}function It(t){return(e=t[0].txn.group)?Buffer.from(e).toString("base64"):"";var e}function xt(t){for(var e=[];;){var n=Number(t&BigInt(127));if(!(t>>=BigInt(7))){e.push(n);break}e.push(128|n)}return e}function ht(t){return(new TextEncoder).encode(t)}var vt,Tt=new(function(){function t(){i(this,t),this.clientName="tinyman-js-sdk"}return c(t,[{key:"getClientName",value:function(){return this.clientName}},{key:"setClientName",value:function(t){this.clientName=t}},{key:"getAppCallTxnNoteWithClientName",value:function(t){var e=t===C.V1_1?"v1":t;return ht("tinyman/".concat(e,':j{"origin":"').concat(this.clientName,'"}'))}}]),t}()),yt=(p(vt={},C.V1_1,{testnet:62368684,mainnet:552635992}),p(vt,C.V2,{testnet:148607e3,mainnet:1002541853}),vt);function wt(t,e){var n=yt[e][t];if(!n)throw new Error("No Validator App exists for ".concat(t," network with ").concat(e," contract version"));return n}function _t(){return(_t=o(a().mark((function e(n){var r,s,o,i,u,c;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.contractVersion,i=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return u=e.sent,c=t.makeApplicationOptInTxnFromObject({from:i,appIndex:wt(s,o),note:Tt.getAppCallTxnNoteWithClientName(o),suggestedParams:u}),e.abrupt("return",[{txn:c,signers:[i]}]);case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function bt(){return(bt=o(a().mark((function e(n){var r,s,o,i,u,c;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.contractVersion,i=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return u=e.sent,c=t.makeApplicationClearStateTxnFromObject({from:i,appIndex:wt(s,o),note:Tt.getAppCallTxnNoteWithClientName(o),suggestedParams:u}),e.abrupt("return",[{txn:c,signers:[i]}]);case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var Et,Dt,St,Ot=function(t){return t.FixedInput="fixed-input",t.FixedOutput="fixed-output",t}({}),Nt=.003,Pt=function(t){return t[t.INPUT_TXN=0]="INPUT_TXN",t[t.APP_CALL_TXN=1]="APP_CALL_TXN",t}({}),kt=(p(Et={},Ot.FixedInput,1),p(Et,Ot.FixedOutput,2),Et),Lt=2,Ft=ht("swap"),Rt=(p(Dt={},Ot.FixedInput,ht("fixed-input")),p(Dt,Ot.FixedOutput,ht("fixed-output")),Dt),Bt={ASSET_OPT_IN:ht("asset_opt_in")},Mt={testnet:184778019,mainnet:1083651166},Ct=(p(St={},Ot.FixedInput,7),p(St,Ot.FixedOutput,8),St);function jt(t){var e=Qt(t),n=e.assetIn,r=e.assetOut;return pt(r.asset.decimals,Number(r.amount))/pt(n.asset.decimals,Number(n.amount))}function Xt(t){var e=Mt[t];if(!e)throw new Error("Unknown network or network not supported: ".concat(t));return e}function Vt(t){return t[t.length-1].quote.amount_out}function Ut(t){return t[0].quote.amount_in}function Qt(t){return{assetIn:Ut(t),assetOut:Vt(t)}}function qt(t){return Gt.apply(this,arguments)}function Gt(){return(Gt=o(a().mark((function e(n){var r,s,o,i,u,c,p;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.routerAppID,o=n.assetIDs,i=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return u=e.sent,c=t.makeApplicationNoOpTxnFromObject({from:i,appIndex:s,appArgs:[Bt.ASSET_OPT_IN],foreignAssets:o,suggestedParams:u}),p=o.length,c.fee=t.ALGORAND_MIN_TX_FEE*(p+1),e.abrupt("return",c);case 8:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Wt(t){return zt.apply(this,arguments)}function zt(){return(zt=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,h,v,T,y,w,_,b,E,D,S,O,N;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.initiatorAddr,s=n.client,o=n.network,i=n.swapType,u=n.route,c=n.slippage,e.next=3,s.getTransactionParams().do();case 3:return p=e.sent,l=[H(u[0].quote.amount_in.asset),H(u[0].quote.amount_out.asset),H(u[1].quote.amount_out.asset)],d=l[0],f=l[1],m=l[2],g=[Number(Ut(u).amount),Number(Vt(u).amount)],A=g[0],I=g[1],x=[u[0].pool.address,u[1].pool.address],h=x[0],v=x[1],T=i===Ot.FixedInput?A:ct("positive",c,A),y=i===Ot.FixedOutput?I:ct("negative",c,I),w=K(d),_=Xt(o),b=w?t.makePaymentTxnWithSuggestedParamsFromObject({from:r,to:t.getApplicationAddress(_),amount:T,suggestedParams:p}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:r,to:t.getApplicationAddress(_),amount:T,assetIndex:d,suggestedParams:p}),(E=t.makeApplicationNoOpTxnFromObject({from:r,appIndex:_,appArgs:[Ft,Rt[i],t.encodeUint64(y)],foreignApps:[wt(o,C.V2)],foreignAssets:[d,f,m],accounts:[h,v],suggestedParams:p,note:Tt.getAppCallTxnNoteWithClientName(C.V2)})).fee=t.ALGORAND_MIN_TX_FEE*(Ct[i]+1),D=[b,E],e.next=17,Jt({client:s,network:o,assetIDs:[d,f,m]});case 17:if(!((S=e.sent).length>0)){e.next=23;break}return e.next=21,qt({client:s,initiatorAddr:r,assetIDs:S,routerAppID:_});case 21:O=e.sent,D.unshift(O);case 23:return N=t.assignGroupID(D),e.abrupt("return",N.map((function(t){return{txn:t,signers:[r]}})));case 25:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Jt(t){return Yt.apply(this,arguments)}function Yt(){return(Yt=o(a().mark((function e(n){var r,s,o,i,u,c;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.assetIDs,i=t.getApplicationAddress(Xt(s)),e.next=4,r.accountInformation(i).do();case 4:return u=e.sent,c=u.assets.map((function(t){return t["asset-id"]})),e.abrupt("return",o.filter((function(t){return t!==j&&!c.includes(t)})));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Kt(t){return Ht.apply(this,arguments)}function Ht(){return(Ht=o(a().mark((function t(e){var n,r,s,o,i,u,c,p;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.amount,r=e.assetInID,s=e.assetOutID,o=e.swapType,i=e.network,u={asset_in_id:String(r),asset_out_id:String(s),swap_type:o,amount:String(n)},t.next=4,fetch("".concat(M[i].v1,"/swap-router/quotes/"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}).catch((function(){throw new Error("Network error")}));case 4:return c=t.sent,t.next=7,c.json();case 7:if(p=t.sent,c.ok){t.next=14;break}if(a=p,!Boolean(a)||void 0===a.fallback_message){t.next=13;break}throw new E(p.type,p.fallback_message);case 13:throw new E(b.UnknownError,"There was an error while getting a quote from Swap Router");case 14:if(!(p.route.length<2)){t.next=16;break}throw new E(b.SwapRouterNoRouteError,"Swap router couldn't find a route for this swap.");case 16:return t.abrupt("return",p);case 17:case"end":return t.stop()}var a}),t)})))).apply(this,arguments)}var Zt=function(t){return t.Direct="direct",t.Router="router",t}({}),$t=4*t.ALGORAND_MIN_TX_FEE;function te(e){return(kt[e]+Lt)*t.ALGORAND_MIN_TX_FEE}function ee(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Nt;return Math.ceil(1/t)}function ne(t){return t1&&void 0!==arguments[1]?arguments[1]:Nt)}function re(e){return(kt[e]+1)*t.ALGORAND_MIN_TX_FEE}function ae(t){var e=t.assetIn,n=t.assetOut;return pt(n.decimals,Number(n.amount))/pt(e.decimals,Number(e.amount))}function se(t){var e=t.inputSupply,n=t.outputSupply,r=t.assetIn,a=t.assetOut,s=ae({assetIn:r,assetOut:a}),o=pt(a.decimals,Number(n))/pt(r.decimals,Number(e));return lt({decimalPlaces:5},Math.abs(s/o-1))}function oe(t){if(t.type===Zt.Router){var e=Ut(t.data.route);return{id:H(e.asset),amount:Number(e.amount)}}return{id:t.data.quote.assetInID,amount:t.data.quote.assetInAmount}}function ie(t){if(t.type===Zt.Router){var e=Vt(t.data.route);return{id:H(e.asset),amount:Number(e.amount)}}return{id:t.data.quote.assetOutID,amount:t.data.quote.assetOutAmount}}function ue(t){return t.type===Zt.Direct?t.data.pool.contractVersion:C.V2}function ce(t){return t.type===Zt.Direct?t.data.quote.rate:jt(t.data.route)}function pe(t){for(var e=t[0],n=ce(e),r=1;rn&&(e=a,n=s)}return e}function le(t){return t instanceof E&&[b.SwapRouterInsufficientReservesError,b.SwapRouterLowSwapAmountError,b.OutputAmountExceedsAvailableLiquidityError,b.LowSwapAmountError].includes(t.type)}var de={type:"logicsig",logic:{bytecode:"BCAIAQCBgICAgICAgPABgICAgICAgIDwAQMEBQYlJA1EMQkyAxJEMRUyAxJEMSAyAxJEMgQiDUQzAQAxABJEMwEQIQcSRDMBGIGCgICAgICAgPABEkQzARkiEjMBGyEEEhA3ARoAgAlib290c3RyYXASEEAAXDMBGSMSRDMBG4ECEjcBGgCABHN3YXASEEACOzMBGyISRDcBGgCABG1pbnQSQAE7NwEaAIAEYnVybhJAAZg3ARoAgAZyZWRlZW0SQAJbNwEaAIAEZmVlcxJAAnkAIQYhBSQjEk0yBBJENwEaARclEjcBGgIXJBIQRDMCADEAEkQzAhAhBBJEMwIhIxJEMwIiIxwSRDMCIyEHEkQzAiQjEkQzAiWACFRNUE9PTDExEkQzAiZRAA+AD1RpbnltYW5Qb29sMS4xIBJEMwIngBNodHRwczovL3RpbnltYW4ub3JnEkQzAikyAxJEMwIqMgMSRDMCKzIDEkQzAiwyAxJEMwMAMQASRDMDECEFEkQzAxElEkQzAxQxABJEMwMSIxJEJCMTQAAQMwEBMwIBCDMDAQg1AUIBsTMEADEAEkQzBBAhBRJEMwQRJBJEMwQUMQASRDMEEiMSRDMBATMCAQgzAwEIMwQBCDUBQgF8MgQhBhJENwEcATEAE0Q3ARwBMwQUEkQzAgAxABNEMwIUMQASRDMDADMCABJEMwIRJRJEMwMUMwMHMwMQIhJNMQASRDMDESMzAxAiEk0kEkQzBAAxABJEMwQUMwIAEkQzAQEzBAEINQFCAREyBCEGEkQ3ARwBMQATRDcBHAEzAhQSRDMDFDMDBzMDECISTTcBHAESRDMCADEAEkQzAhQzBAASRDMCESUSRDMDADEAEkQzAxQzAwczAxAiEk0zBAASRDMDESMzAxAiEk0kEkQzBAAxABNEMwQUMQASRDMBATMCAQgzAwEINQFCAJAyBCEFEkQ3ARwBMQATRDMCADcBHAESRDMCADEAE0QzAwAxABJEMwIUMwIHMwIQIhJNMQASRDMDFDMDBzMDECISTTMCABJEMwEBMwMBCDUBQgA+MgQhBBJENwEcATEAE0QzAhQzAgczAhAiEk03ARwBEkQzAQEzAgEINQFCABIyBCEEEkQzAQEzAgEINQFCAAAzAAAxABNEMwAHMQASRDMACDQBD0M=",address:"ABUKAXTANWR6K6ZYV75DWJEPVWWOU6SFUVRI6QHO44E4SIDLHBTD2CZ64A",size:881,variables:[{name:"TMPL_ASSET_ID_1",type:"int",index:15,length:10},{name:"TMPL_ASSET_ID_2",type:"int",index:5,length:10},{name:"TMPL_VALIDATOR_APP_ID",type:"int",index:74,length:10}],source:"https://github.com/tinymanorg/tinyman-contracts-v1/tree/dc9ab40c58b85c15d58f63a1507e18be76720dbb/contracts/pool_logicsig.teal.tmpl"},name:"pool_logicsig"},fe={type:"app",global_state_schema:{num_uints:0,num_byte_slices:0},local_state_schema:{num_uints:16,num_byte_slices:0},name:"validator_app"},me=c((function t(e){i(this,t),this.schema={numLocalInts:e.local_state_schema.num_uints,numLocalByteSlices:e.local_state_schema.num_byte_slices,numGlobalInts:e.global_state_schema.num_uints,numGlobalByteSlices:e.global_state_schema.num_byte_slices}})),ge=new(function(n){l(a,me);var r=x(a);function a(t,e){var n;return i(this,a),(n=r.call(this,t)).poolLogicSigContractTemplate=e.logic.bytecode,n.templateVariables=e.logic.variables,n}return c(a,[{key:"generateLogicSigAccountForPool",value:function(n){if(n.asset1ID===n.asset2ID)throw new Error("Assets are the same");var r=wt(n.network,C.V1_1),a=h(Y(n.asset1ID,n.asset2ID),2),s=a[0],o=a[1],i=Array.from(e.toByteArray(this.poolLogicSigContractTemplate)),u={asset_id_1:s,asset_id_2:o,validator_app_id:r},c=0;this.templateVariables.sort((function(t,e){return t.index-e.index}));for(var p=0;p2&&void 0!==arguments[2]?arguments[2]:t.IntDecoding.DEFAULT;return new Promise(function(){var t=o(a().mark((function t(o,i){var u;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,e.accountInformation(n).setIntDecoding(s).do();case 3:u=t.sent,o(r(r({},u),{},{minimum_required_balance:ye(u)})),t.next=10;break;case 7:t.prev=7,t.t0=t.catch(0),i(new Error(t.t0.message||"Failed to fetch account information"));case 10:case"end":return t.stop()}}),t,null,[[0,7]])})));return function(e,n){return t.apply(this,arguments)}}())}function Te(t,e){var n=t["apps-local-state"].find((function(t){return t.id===e}));return n?Z({stateArray:n["key-value"],shouldDecodeKeys:!0}):null}function ye(t){var e=t["apps-total-schema"];return S+O*(t.assets||[]).length+P*(t["created-apps"]||[]).length+N*(t["apps-local-state"]||[]).length+L*Number(e&&e["num-byte-slice"]||0)+F*Number(e&&e["num-uint"]||0)+k*(t["apps-total-extra-pages"]||0)}var we=ht("e");function _e(t){return be.apply(this,arguments)}function be(){return(be=o(a().mark((function n(r){var s,o,i,u,c,p,l,d,f,m,g,A,I,x,h,v,T,y,_,b,E;return a().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return s=r.client,o=r.pool,i=r.accountAddr,n.next=3,s.accountInformation(i).setIntDecoding(t.IntDecoding.BIGINT).do();case 3:u=n.sent,c=u["apps-local-state"]||[],p=0n,l=0n,d=0n,f=o.account.address(),m=w(c),n.prev=10,m.s();case 12:if((g=m.n()).done){n.next=31;break}if((A=g.value).id==o.validatorAppID){n.next=16;break}return n.abrupt("continue",29);case 16:if(I=A["key-value"]){n.next=19;break}return n.abrupt("break",31);case 19:x=Z({stateArray:I}),h=e.fromByteArray($([t.decodeAddress(f).publicKey,we,t.encodeUint64(o.asset1ID)])),v=e.fromByteArray($([t.decodeAddress(f).publicKey,we,t.encodeUint64(o.asset2ID)])),T=e.fromByteArray($([t.decodeAddress(f).publicKey,we,t.encodeUint64(o.poolTokenID)])),y=x[h],_=x[v],b=x[T],"bigint"==typeof y&&(p=y),"bigint"==typeof _&&(l=_),"bigint"==typeof b&&(d=b);case 29:n.next=12;break;case 31:n.next=36;break;case 33:n.prev=33,n.t0=n.catch(10),m.e(n.t0);case 36:return n.prev=36,m.f(),n.finish(36);case 39:if(!((E={excessAsset1:p,excessAsset2:l,excessPoolTokens:d}).excessAsset1<0n||E.excessAsset2<0n||E.excessPoolTokens<0n)){n.next=42;break}throw new Error("Invalid account excess: ".concat(E));case 42:return n.abrupt("return",E);case 43:case"end":return n.stop()}}),n,null,[[10,33,36,39]])})))).apply(this,arguments)}function Ee(){return(Ee=o(a().mark((function n(r){var s,o,i,u,c,p,l,d,f,m,g,A,I,x,v;return a().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return s=r.client,o=r.accountAddr,i=r.validatorAppID,n.next=3,s.accountInformation(o).setIntDecoding(t.IntDecoding.BIGINT).do();case 3:if(u=n.sent,c=u["apps-local-state"]||[],p=c.find((function(t){return t.id==i})),l=[],p&&p["key-value"])for(d=Z({stateArray:p["key-value"]}),f=0,m=Object.entries(d);fke)){n.next=48;break}throw new Error("Issued liquidity value is out of the expected range ([0n, ".concat(ke,"]): ").concat(k.issuedLiquidity));case 48:return n.abrupt("return",k);case 49:case"end":return n.stop()}}),n,null,[[8,31,34,37]])})))).apply(this,arguments)}function Be(){return Be=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d=arguments;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(n=e.client,r=e.address,s=e.network,!(o=d.length>1&&void 0!==d[1]?d[1]:{})[r]){t.next=4;break}return t.abrupt("return",o[r]);case 4:return t.next=6,ve(n,r);case 6:return i=t.sent,u=Te(i,wt(s,C.V1_1)),c=null,u&&(l=i["created-assets"][0],p=l.index,c={asset1ID:u[Oe[C.V1_1].asset1],asset2ID:u[Oe[C.V1_1].asset2],poolTokenID:p},o[r]=c),t.abrupt("return",c);case 11:case"end":return t.stop()}}),t)}))),Be.apply(this,arguments)}var Me=Object.freeze({__proto__:null,getPoolAssets:function(t){return Be.apply(this,arguments)},getPoolInfo:Le,getPoolReserves:function(t,e){return Re.apply(this,arguments)}});function Ce(t){return je.apply(this,arguments)}function je(){return(je=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d,f,m;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.network,s=e.asset1ID,o=e.asset2ID,i=he(C.V2),u=i.generateLogicSigAccountForPool(e),c=wt(r,C.V2),p=u.address(),l=Y(s,o),t.next=8,ve(n,p);case 8:return d=t.sent,f=Te(d,c),m={account:u,validatorAppID:c,asset1ID:l[0],asset2ID:l[1],status:f?Se.READY:Se.NOT_CREATED,contractVersion:C.V2},f&&(m.asset1ProtocolFees=BigInt(f[Oe.v2.asset1ProtocolFees]),m.asset2ProtocolFees=BigInt(f[Oe.v2.asset2ProtocolFees]),m.asset1Reserves=BigInt(f[Oe.v2.asset1Reserves]),m.asset2Reserves=BigInt(f[Oe.v2.asset2Reserves]),m.issuedPoolTokens=BigInt(f[Oe.v2.issuedPoolTokens]),m.cumulativePriceUpdateTimeStamp=Number(f[Oe.v2.cumulativePriceUpdateTimeStamp]),m.protocolFeeRatio=Number(f[Oe.v2.protocolFeeRatio]),m.totalFeeShare=BigInt(f[Oe.v2.totalFeeShare]),m.poolTokenID=Number(f[Oe.v2.poolTokenID]),m.asset1ID=Number(f[Oe.v2.asset1]),m.asset2ID=Number(f[Oe.v2.asset2])),t.abrupt("return",m);case 13:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Xe(){return(Xe=o(a().mark((function t(e,n){var r,s,o;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,ve(e,n.account.address());case 2:return r=t.sent,s=Te(r,n.validatorAppID),o={asset1:0n,asset2:0n,issuedLiquidity:0n,round:r.round},s&&(o.asset1=BigInt(s[Oe.v2.asset1Reserves]),o.asset2=BigInt(s[Oe.v2.asset2Reserves]),o.issuedLiquidity=BigInt(s[Oe.v2.issuedPoolTokens])),t.abrupt("return",o);case 7:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Ve(){return(Ve=o(a().mark((function t(e){var n,r,s,o,i,u;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.address,s=e.network,t.next=3,ve(n,r);case 3:return o=t.sent,i=Te(o,wt(s,C.V2)),u=null,i&&(u={asset1ID:i[Oe[C.V2].asset1],asset2ID:i[Oe[C.V2].asset2],poolTokenID:i[Oe[C.V2].poolTokenID]}),t.abrupt("return",u);case 8:case"end":return t.stop()}}),t)})))).apply(this,arguments)}var Ue=Object.freeze({__proto__:null,getPoolAssets:function(t){return Ve.apply(this,arguments)},getPoolInfo:Ce,getPoolReserves:function(t,e){return Xe.apply(this,arguments)}});function Qe(t){return Boolean(t&&!(t.asset1+t.asset2))}var qe,Ge=Object.freeze({__proto__:null,getPoolPairRatio:function(t){var e=Qe(t),n=null;return t&&!e&&t.asset1&&t.asset2&&(n=Number(t.asset1)/Number(t.asset2)),n},getPoolShare:function(t,e){var n=Number(e)/Number(t);return Number.isFinite(n)||(n=0),n},getPoolsForPair:function(t){return Promise.all([Le(t),Ce(t)])},isPoolEmpty:Qe,isPoolNotCreated:function(t){return(null==t?void 0:t.status)===Se.NOT_CREATED},isPoolReady:function(t){return(null==t?void 0:t.status)===Se.READY}}),We=r((p(qe={},C.V1_1,r(r({},Me),Ge)),p(qe,C.V2,r(r({},Ue),Ge)),qe),Ge),ze=function(t){return t[t.FUNDING_TXN=0]="FUNDING_TXN",t[t.VALIDATOR_APP_CALL=1]="VALIDATOR_APP_CALL",t[t.POOL_TOKEN_CREATE=2]="POOL_TOKEN_CREATE",t[t.ASSET1_OPT_IN=3]="ASSET1_OPT_IN",t[t.ASSET2_OPT_IN=4]="ASSET2_OPT_IN",t}({}),Je={ASA_ALGO:96e4,ASA_ASA:859e3};function Ye(){return(Ye=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,v,T,y,w,_,b,E,D,S,O;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.asset_1,i=n.asset_2,u=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return c=e.sent,p=J(o,i),l=h(p,2),d=l[0],f=d.id,m=d.unit_name,g=l[1],A=g.id,I=g.unit_name,x=K(A),v=wt(s,C.V1_1),T=ge.generateLogicSigAccountForPool({network:s,asset1ID:f,asset2ID:A}),y=T.address(),w=t.makeApplicationOptInTxnFromObject({from:y,appIndex:v,note:Tt.getAppCallTxnNoteWithClientName(C.V1_1),appArgs:[ht("bootstrap"),t.encodeUint64(f),t.encodeUint64(A)],foreignAssets:x?[f]:[A],suggestedParams:c}),_=t.makeAssetCreateTxnWithSuggestedParamsFromObject({from:y,total:0xffffffffffffffffn,decimals:6,defaultFrozen:!1,unitName:V.V1_1,assetName:"TinymanPool1.1 ".concat(m,"-").concat(I),assetURL:"https://tinyman.org",suggestedParams:c}),b=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:y,to:y,assetIndex:f,amount:0,suggestedParams:c}),E=t.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:y,amount:Ke(x),suggestedParams:c}),(D=[])[ze.FUNDING_TXN]=E,D[ze.VALIDATOR_APP_CALL]=w,D[ze.POOL_TOKEN_CREATE]=_,D[ze.ASSET1_OPT_IN]=b,x||(D[ze.ASSET2_OPT_IN]=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:y,to:y,assetIndex:A,amount:0,suggestedParams:c})),S=t.assignGroupID(D),O=[{txn:S[ze.FUNDING_TXN],signers:[u]},{txn:S[ze.VALIDATOR_APP_CALL],signers:[y]},{txn:S[ze.POOL_TOKEN_CREATE],signers:[y]},{txn:S[ze.ASSET1_OPT_IN],signers:[y]}],S[ze.ASSET2_OPT_IN]&&O.push({txn:S[ze.ASSET2_OPT_IN],signers:[y]}),e.abrupt("return",O);case 23:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Ke(t){return t?Je.ASA_ALGO:Je.ASA_ASA}function He(){return(He=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.txGroup,s=n.network,o=n.initiatorSigner,i=n.asset1ID,u=n.asset2ID,e.next=3,o([r]);case 3:return c=e.sent,p=h(c,1),l=p[0],d=Y(i,u),f=h(d,2),m=f[0],g=f[1],A=ge.generateLogicSigAccountForPool({network:s,asset1ID:m,asset2ID:g}),I=[],x=r.map((function(e,n){if(n===ze.FUNDING_TXN)return I.push(e.txn.txID().toString()),l;var r=t.signLogicSigTransactionObject(e.txn,A),a=r.txID,s=r.blob;return I.push(a),s})),e.abrupt("return",{signedTxns:x,txnIDs:I});case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Ze(t){return $e.apply(this,arguments)}function $e(){return($e=o(a().mark((function t(e){var n,r,s,o,i;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.signedTxns,s=e.txnIDs,t.prev=1,t.next=4,n.sendRawTransaction(r).do();case 4:return t.next=6,it(n,s[ze.POOL_TOKEN_CREATE]);case 6:if(o=t.sent,"number"==typeof(i=o["asset-index"])){t.next=10;break}throw new Error("Generated ID is not valid: got ".concat(i));case 10:return t.abrupt("return",{poolTokenID:i});case 13:throw t.prev=13,t.t0=t.catch(1),new W(t.t0,"We encountered something unexpected while bootstraping the pool. Try again later.");case 16:case"end":return t.stop()}}),t,null,[[1,13]])})))).apply(this,arguments)}function tn(){return(tn=o(a().mark((function t(e){var n,r,s,o,i,u,c;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.network,s=e.pool,o=s.asset1ID,i=s.asset2ID,u=e.signedTxns,c=e.txnIDs,t.next=3,Ze({client:n,signedTxns:u,txnIDs:c});case 3:return t.abrupt("return",We.v1_1.getPoolInfo({client:n,network:r,asset1ID:o,asset2ID:i}));case 4:case"end":return t.stop()}}),t)})))).apply(this,arguments)}var en={generateTxns:function(t){return Ye.apply(this,arguments)},signTxns:function(t){return He.apply(this,arguments)},execute:function(t){return tn.apply(this,arguments)},getBootstrapFundingTxnAmount:Ke};var nn=function(t){return t[t.FUNDING_TXN=0]="FUNDING_TXN",t[t.VALIDATOR_APP_CALL=1]="VALIDATOR_APP_CALL",t}({}),rn={ASA_ALGO:5,ASA_ASA:6};function an(t,e){return sn.apply(this,arguments)}function sn(){return(sn=o(a().mark((function e(n,r){var s,o,i;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!(o=null===(s=r.find((function(t){return"appl"===t.txn.type})))||void 0===s?void 0:s.txn.txID())){e.next=7;break}return e.next=4,t.waitForConfirmation(n,o,B);case 4:e.t0=e.sent,e.next=8;break;case 7:e.t0=void 0;case 8:return i=e.t0,e.abrupt("return",i);case 10:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function on(t,e){return un.apply(this,arguments)}function un(){return(un=o(a().mark((function t(e,n){var r;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,an(e,n);case 2:return r=t.sent,t.abrupt("return",null==r?void 0:r["inner-txns"]);case 4:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function cn(t,e){return pn.apply(this,arguments)}function pn(){return(pn=o(a().mark((function e(n,r){var s,o;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,on(n,r);case 2:return s=e.sent,a=r[0].txn,o=t.encodeAddress(a.from.publicKey),e.abrupt("return",null==s?void 0:s.reduce((function(e,n){var r=e,a=n.txn.txn;return a.type===t.TransactionType.axfer&&t.encodeAddress(a.arcv)===o?r.push({id:a.xaid,amount:a.aamt}):a.type===t.TransactionType.pay&&t.encodeAddress(a.rcv)===o&&r.push({id:j,amount:a.amt}),r}),[]));case 5:case"end":return e.stop()}var a}),e)})))).apply(this,arguments)}function ln(){return(ln=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,v,T,y,w,_;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.asset_1,i=n.asset_2,u=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return c=e.sent,p=wt(s,C.V2),l=t.getApplicationAddress(p),d=J(o,i),f=h(d,2),m=f[0].id,g=f[1].id,e.next=9,We.v2.getPoolInfo({client:r,network:s,asset1ID:m,asset2ID:g});case 9:if(e.sent.status!==Se.READY){e.next=12;break}throw new Error("Pool for ".concat(o.unit_name,"-").concat(i.unit_name," already exists"));case 12:return A=xe.generateLogicSigAccountForPool({network:s,asset1ID:m,asset2ID:g}),I=A.address(),x=K(g),(v=t.makeApplicationOptInTxnFromObject({from:I,appIndex:p,appArgs:[ht("bootstrap")],note:Tt.getAppCallTxnNoteWithClientName(C.V2),foreignAssets:[m,g],rekeyTo:l,suggestedParams:c})).fee=fn(x),T=t.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:I,amount:dn(x),suggestedParams:c}),(y=[])[nn.FUNDING_TXN]=T,y[nn.VALIDATOR_APP_CALL]=v,w=t.assignGroupID(y),(_=[])[nn.FUNDING_TXN]={txn:w[nn.FUNDING_TXN],signers:[u]},_[nn.VALIDATOR_APP_CALL]={txn:w[nn.VALIDATOR_APP_CALL],signers:[I]},e.abrupt("return",_);case 26:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function dn(t){return function(t,e){var n=he(t).schema,r=n.numLocalInts,a=n.numLocalByteSlices,s=S+O+O+N+F*r+L*a;return e||(s+=O),s}(C.V2,t)+fn(t)+O}function fn(e){return((e?rn.ASA_ALGO:rn.ASA_ASA)+1)*t.ALGORAND_MIN_TX_FEE}function mn(){return(mn=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.txGroup,s=n.network,o=n.initiatorSigner,i=n.asset1ID,u=n.asset2ID,e.next=3,o([r]);case 3:return c=e.sent,p=h(c,1),l=p[0],d=Y(i,u),f=h(d,2),m=f[0],g=f[1],A=xe.generateLogicSigAccountForPool({network:s,asset1ID:m,asset2ID:g}),I=[],x=r.map((function(e,n){if(n===nn.FUNDING_TXN)return I.push(e.txn.txID().toString()),l;var r=t.signLogicSigTransactionObject(e.txn,A),a=r.txID,s=r.blob;return I.push(a),s})),e.abrupt("return",{signedTxns:x,txnIDs:I});case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function gn(){return(gn=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d,f;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.network,s=e.pool,o=s.asset1ID,i=s.asset2ID,u=e.txGroup,c=e.signedTxns,t.prev=1,t.next=4,n.sendRawTransaction(c).do();case 4:return t.next=6,an(n,u);case 6:if(t.t1=p=t.sent,t.t0=null===t.t1,t.t0){t.next=10;break}t.t0=void 0===p;case 10:if(!t.t0){t.next=14;break}t.t2=void 0,t.next=15;break;case 14:t.t2=null===(l=p["local-state-delta"][0].delta)||void 0===l||null===(d=l.find((function(t){return t.key===btoa(Oe.v2.poolTokenID)})))||void 0===d?void 0:d.value.uint;case 15:if("number"==typeof(f=t.t2)){t.next=18;break}throw new Error("Generated ID is not valid: got ".concat(f));case 18:return t.abrupt("return",We.v2.getPoolInfo({client:n,network:r,asset1ID:o,asset2ID:i}));case 21:throw t.prev=21,t.t3=t.catch(1),new W(t.t3,"We encountered something unexpected while bootstraping the pool. Try again later.");case 24:case"end":return t.stop()}}),t,null,[[1,21]])})))).apply(this,arguments)}var An,In={generateTxns:function(t){return ln.apply(this,arguments)},signTxns:function(t){return mn.apply(this,arguments)},execute:function(t){return gn.apply(this,arguments)},getBootstrapFundingTxnAmount:dn,getTotalCost:function(e){return t.ALGORAND_MIN_TX_FEE+dn(e)}};var xn,hn,vn,Tn,yn=(p(An={},C.V1_1,en),p(An,C.V2,In),p(An,"generateTxns",(function(t){return t.contractVersion===C.V1_1?en.generateTxns(t):In.generateTxns(t)})),p(An,"signTxns",(function(t){return t.contractVersion===C.V1_1?en.signTxns(t):In.signTxns(t)})),p(An,"execute",(function(t){return t.contractVersion===C.V1_1?en.execute(t):In.execute(t)})),p(An,"calculateBootstrapFundingTxnAmount",(function(t){var e=t.contractVersion,n=t.isAlgoPool;return e===C.V1_1?en.getBootstrapFundingTxnAmount(n):In.getBootstrapFundingTxnAmount(n)})),An),wn=function(t){return t[t.FEE_TXN=0]="FEE_TXN",t[t.VALIDATOR_APP_CALL_TXN=1]="VALIDATOR_APP_CALL_TXN",t[t.ASSET1_IN_TXN=2]="ASSET1_IN_TXN",t[t.ASSET2_IN_TXN=3]="ASSET2_IN_TXN",t[t.LIQUDITY_OUT_TXN=4]="LIQUDITY_OUT_TXN",t}({}),_n=5*t.ALGORAND_MIN_TX_FEE,bn=function(t){return t.SINGLE="single",t.FLEXIBLE="flexible",t.INITIAL="initial",t}({}),En=(p(xn={},bn.FLEXIBLE,{ASSET1_IN_TXN:0,ASSET2_IN_TXN:1,VALIDATOR_APP_CALL_TXN:2}),p(xn,bn.SINGLE,{ASSET_IN_TXN:0,VALIDATOR_APP_CALL_TXN:1}),p(xn,bn.INITIAL,{ASSET1_IN_TXN:0,ASSET2_IN_TXN:1,VALIDATOR_APP_CALL_TXN:2}),xn),Dn=(p(hn={},bn.INITIAL,1),p(hn,bn.SINGLE,2),p(hn,bn.FLEXIBLE,2),hn),Sn=(p(vn={},bn.INITIAL,3),p(vn,bn.FLEXIBLE,3),p(vn,bn.SINGLE,2),vn);function On(t){var e,n,r,a=t.reserves,s=t.totalFeeShare,o=t.asset1,i=t.asset2,u=a.asset1*a.asset2,c=a.asset1+BigInt(o.amount),p=a.asset2+BigInt(i.amount),l=c*p,d=BigInt(parseInt(String(Math.sqrt(Number(l*a.issuedLiquidity*a.issuedLiquidity/u))))),f=d-a.issuedLiquidity,m=f*c/d,g=f*p/d,A=BigInt(o.amount)-m,I=BigInt(i.amount)-g;if(A>I){var x=A;r=Pn(x,s),e={id:o.id,amount:x+r,decimals:o.decimals,reserves:a.asset1},n={id:i.id,amount:BigInt(Math.abs(Math.min(Number(I),0))),decimals:i.decimals,reserves:a.asset2},f-=r*d/(c*BigInt(2))}else{var h=I;r=Pn(h,s),e={id:i.id,amount:h+r,decimals:i.decimals,reserves:a.asset2},n={id:o.id,amount:BigInt(Math.abs(Math.min(Number(A),0))),decimals:o.decimals,reserves:a.asset1},f-=r*d/(p*BigInt(2))}return{poolTokenOutAmount:f,internalSwapQuote:{assetIn:e,assetOut:n,swapFees:r,priceImpact:se({inputSupply:e.reserves,outputSupply:n.reserves,assetIn:e,assetOut:n})}}}function Nn(t,e){if(!t.amount||!e.amount)throw new Error("Both assets are required for the initial add liquidity");return BigInt(Math.floor(Math.abs(Math.sqrt(Number(t.amount)*Number(e.amount))-Ne)))}function Pn(t,e){return t*BigInt(e)/(BigInt(1e4)-BigInt(e))}function kn(e){return(Dn[e]+1)*t.ALGORAND_MIN_TX_FEE}var Ln=ht("add_liquidity"),Fn=(p(Tn={},C.V1_1,[ht("mint")]),p(Tn,C.V2,{INITIAL_LIQUIDITY:[ht("add_initial_liquidity")],SINGLE_ASSET_MODE:[Ln,ht("single")],FLEXIBLE_MODE:[Ln,ht("flexible")]}),Tn);function Rn(){return(Rn=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,h;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.poolAddress,i=n.asset1In,u=n.asset2In,c=n.poolTokenOut,p=n.slippage,l=n.initiatorAddr,d=ct("negative",p,c.amount),e.next=4,r.getTransactionParams().do();case 4:return f=e.sent,m=t.makeApplicationNoOpTxnFromObject({from:o,appIndex:wt(s,C.V1_1),appArgs:Fn.v1_1,accounts:[l],note:Tt.getAppCallTxnNoteWithClientName(C.V1_1),foreignAssets:u.id==j?[i.id,c.id]:[i.id,u.id,c.id],suggestedParams:f}),g=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:o,assetIndex:i.id,amount:i.amount,suggestedParams:f}),A=u.id===j?t.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:o,amount:u.amount,suggestedParams:f}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:o,assetIndex:u.id,amount:u.amount,suggestedParams:f}),I=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:o,to:l,assetIndex:c.id,amount:d,suggestedParams:f}),x=t.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:o,amount:m.fee+I.fee,note:D,suggestedParams:f}),h=t.assignGroupID([x,m,g,A,I]),e.abrupt("return",[{txn:h[0],signers:[l]},{txn:h[1],signers:[o]},{txn:h[2],signers:[l]},{txn:h[3],signers:[l]},{txn:h[4],signers:[o]}]);case 12:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Bn(){return(Bn=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.pool,s=n.txGroup,o=n.initiatorSigner,i=r.account,e.next=4,o([s]);case 4:return u=e.sent,c=h(u,3),p=c[0],l=c[1],d=c[2],f=s.map((function(e,n){return n===wn.FEE_TXN?p:n===wn.ASSET1_IN_TXN?l:n===wn.ASSET2_IN_TXN?d:t.signLogicSigTransactionObject(e.txn,i).blob})),e.abrupt("return",f);case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Mn(){return(Mn=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,v;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.pool,s=e.txGroup,o=e.signedTxns,i=e.initiatorAddr,t.prev=1,u=BigInt(s[wn.LIQUDITY_OUT_TXN].txn.amount),t.next=5,_e({client:n,pool:r,accountAddr:i});case 5:return c=t.sent,t.next=8,mt(n,[o]);case 8:return p=t.sent,l=h(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,g=At(s),A=It(s),t.next=17,_e({client:n,pool:r,accountAddr:i});case 17:return I=t.sent,(x=I.excessPoolTokens-c.excessPoolTokens)<0n&&(x=0n),t.abrupt("return",{round:f,fees:g,poolTokenID:r.poolTokenID,poolTokenOut:u+x,excessAmount:{excessAmountForAddingLiquidity:x,totalExcessAmount:I.excessPoolTokens},txnID:m,groupID:A});case 23:throw t.prev=23,t.t0=t.catch(1),"SlippageTolerance"===(v=new W(t.t0,"We encountered something unexpected while adding liquidity. Try again later.")).type&&v.setMessage("Adding liquidity failed due to too much slippage in the price. Please adjust the slippage tolerance and try again."),v;case 28:case"end":return t.stop()}}),t,null,[[1,23]])})))).apply(this,arguments)}var Cn=Object.freeze({__proto__:null,execute:function(t){return Mn.apply(this,arguments)},generateTxns:function(t){return Rn.apply(this,arguments)},getQuote:function(t){var e=t.pool,n=t.reserves,r=t.asset1In,a=t.asset2In;if(0n===n.issuedLiquidity){var s=BigInt(Math.floor(Math.sqrt(Number(r)*Number(a))));if(s<=BigInt(R))throw new Error("Initial liquidity amount is too small. The amount must be greater than ".concat(R,", this quote is for ").concat(s,"."));return{round:n.round,asset1ID:e.asset1ID,asset1In:BigInt(r),asset2ID:e.asset2ID,asset2In:BigInt(a),poolTokenID:e.poolTokenID,poolTokenOut:s-BigInt(R),share:1}}var o=BigInt(r)*n.issuedLiquidity/n.asset1,i=BigInt(a)*n.issuedLiquidity/n.asset2,u=oo)throw new E(b.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");if(ne(Number(e)))throw new E(b.LowSwapAmountError,"Swap amount is too low.");return{assetInID:i,assetInAmount:l,assetOutID:c,assetOutAmount:m,swapFee:Number(g),rate:pt(p,Number(m))/pt(u,Number(l)),priceImpact:A}}function lr(t){var e=t.amount,n=t.assetIn,r=t.assetOut,a=t.pool;if(!a||!We.isPoolReady(a))throw new E(b.NoAvailablePoolError,"There is not an available pool for this asset pair");var s,o,i=n.id,u=n.decimals,c=r.id,p=r.decimals,l=BigInt(e),d=a.totalFeeShare;if(c===a.asset1ID)s=a.asset2Reserves,o=a.asset1Reserves;else{if(c!==a.asset2ID)throw new E(b.AssetDoesNotBelongToPoolError,"Output asset (#".concat(c,") doesn't belong to the pool ").concat(a.account.address(),"."));s=a.asset1Reserves,o=a.asset2Reserves}var f=function(t){var e=t.inputSupply,n=t.outputSupply,r=t.swapOutputAmount,a=t.totalFeeShare,s=t.decimals,o=function(t){var e=t.inputSupply,n=t.outputSupply,r=t.outputAmount,a=e*n,s=BigInt(a/(n-r))-e;return s+=BigInt(1),s}({inputSupply:e,outputSupply:n,outputAmount:r}),i=function(t){var e=t.swapAmount,n=t.totalFeeShare,r=Math.floor(Number(e*BigInt(1e4)/(BigInt(1e4)-BigInt(n)))),a=BigInt(r)-e;return a}({swapAmount:o,totalFeeShare:a}),u=o+i,c=se({inputSupply:e,outputSupply:n,assetIn:{amount:u,decimals:s.assetIn},assetOut:{amount:r,decimals:s.assetOut}});return{swapInputAmount:u,totalFeeAmount:i,priceImpact:c}}({inputSupply:s,outputSupply:o,swapOutputAmount:l,totalFeeShare:d,decimals:{assetIn:u,assetOut:p}}),m=f.swapInputAmount,g=f.totalFeeAmount,A=f.priceImpact;if(l>o)throw new E(b.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");if(ne(Number(m)))throw new E(b.LowSwapAmountError,"Swap amount is too low.");return{type:Zt.Direct,data:{pool:a,quote:{assetInID:i,assetInAmount:m,assetOutID:c,assetOutAmount:l,swapFee:Number(g),rate:pt(p,Number(l))/pt(u,Number(m)),priceImpact:A}}}}function dr(t){return fr.apply(this,arguments)}function fr(){return(fr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.amount,r=e.assetIn,s=e.assetOut,o=e.isSwapRouterEnabled,i=e.network,u=e.pool,c=[],u?c.push(new Promise((function(t,e){try{var a=pr({amount:n,assetIn:r,assetOut:s,pool:u});t({type:Zt.Direct,data:{pool:u,quote:a}})}catch(t){e(t)}}))):c.push(Promise.reject(new E(b.NoAvailablePoolError,"There is not an available pool for this asset pair"))),o&&c.push(Kt({amount:n,assetInID:r.id,assetOutID:s.id,swapType:Ot.FixedInput,network:i}).then((function(t){return{type:Zt.Router,data:t}}))),t.next=6,cr(c);case 6:return p=t.sent,t.abrupt("return",pe(p));case 8:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function mr(t){return gr.apply(this,arguments)}function gr(){return(gr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.amount,r=e.assetIn,s=e.assetOut,o=e.isSwapRouterEnabled,i=e.network,u=e.pool,c=[new Promise((function(t,e){try{t(lr({amount:n,assetIn:r,assetOut:s,pool:u}))}catch(t){e(t)}}))],o&&c.push(Kt({amount:n,assetInID:r.id,assetOutID:s.id,swapType:Ot.FixedOutput,network:i}).then((function(t){return{type:Zt.Router,data:t}}))),t.next=5,cr(c);case 5:return p=t.sent,t.abrupt("return",pe(p));case 7:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Ar(t){var e=t.inputSupply,n=t.outputSupply,r=t.swapInputAmount,a=t.totalFeeShare,s=t.decimals,o=BigInt(function(t){var e=t.inputAmount,n=t.totalFeeShare;return Math.floor(Number(e*BigInt(n))/1e4)}({inputAmount:r,totalFeeShare:a})),i=function(t){var e=t.inputSupply,n=t.outputSupply,r=t.swapAmount,a=e*n,s=n-BigInt(a/(e+BigInt(r)));return s-=BigInt(1)}({inputSupply:e,outputSupply:n,swapAmount:r-o});return{swapOutputAmount:i,totalFeeAmount:o,priceImpact:se({inputSupply:e,outputSupply:n,assetIn:{amount:r,decimals:s.assetIn},assetOut:{amount:i,decimals:s.assetOut}})}}var Ir={getQuote:function(t){return ur.apply(this,arguments)},getFixedInputSwapQuote:dr,getFixedInputDirectSwapQuote:pr,getFixedOutputDirectSwapQuote:lr,getFixedOutputSwapQuote:mr,generateTxns:function(t){return or.apply(this,arguments)},signTxns:function(t){var e=t.txGroup;return(0,t.initiatorSigner)([e])},execute:function(t){return ir.apply(this,arguments)},calculateFixedInputSwap:Ar};function xr(t,e){var n,r,a=BigInt(t),s=e.issuedLiquidity;return s>a+BigInt(Ne)?(n=a*e.asset1/s,r=a*e.asset2/s):(n=e.asset1,r=e.asset2),{asset1OutputAmount:n,asset2OutputAmount:r}}function hr(){return(hr=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.pool,o=n.poolTokenIn,i=n.initiatorAddr,u=n.minAsset1Amount,c=n.minAsset2Amount,p=n.slippage,e.next=3,r.getTransactionParams().do();case 3:if(l=e.sent,d=s.account.address(),f=s.poolTokenID){e.next=8;break}throw new Error("Pool token asset ID is missing");case 8:return m=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:i,to:d,assetIndex:f,amount:o,suggestedParams:l}),(g=t.makeApplicationNoOpTxnFromObject({from:i,appIndex:s.validatorAppID,note:Tt.getAppCallTxnNoteWithClientName(C.V2),appArgs:[tr,t.encodeUint64(ct("negative",p,u)),t.encodeUint64(ct("negative",p,c))],accounts:[d],foreignAssets:[s.asset1ID,s.asset2ID],suggestedParams:l})).fee=($n+1)*t.ALGORAND_MIN_TX_FEE,(A=[])[er.ASSET_TRANSFER_TXN]=m,A[er.APP_CALL_TXN]=g,I=t.assignGroupID(A),e.abrupt("return",[{txn:I[er.ASSET_TRANSFER_TXN],signers:[i]},{txn:I[er.APP_CALL_TXN],signers:[i]}]);case 16:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function vr(){return(vr=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,h,v,T,y;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.pool,o=n.initiatorAddr,i=n.poolTokenIn,u=n.outputAssetId,c=n.minOutputAssetAmount,p=n.slippage,e.next=3,r.getTransactionParams().do();case 3:if(l=e.sent,d=s.asset1ID,f=s.asset2ID,m=s.account.address(),g=s.poolTokenID){e.next=9;break}throw new Error("Pool token asset ID is missing");case 9:if(A=0,I=0,x=ct("negative",p,c),u!==d){e.next=17;break}A=x,I=0,e.next=23;break;case 17:if(u!==f){e.next=22;break}A=0,I=x,e.next=23;break;case 22:throw new Error("Invalid output asset id. It doesn't match with pool assets");case 23:return h=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:o,to:m,assetIndex:g,amount:i,suggestedParams:l}),(v=t.makeApplicationNoOpTxnFromObject({from:o,appIndex:s.validatorAppID,note:Tt.getAppCallTxnNoteWithClientName(C.V2),appArgs:[tr,t.encodeUint64(A),t.encodeUint64(I)],accounts:[m],foreignAssets:[u],suggestedParams:l})).fee=($n+1)*t.ALGORAND_MIN_TX_FEE,(T=[])[er.ASSET_TRANSFER_TXN]=h,T[er.APP_CALL_TXN]=v,y=t.assignGroupID(T),e.abrupt("return",[{txn:y[er.ASSET_TRANSFER_TXN],signers:[o]},{txn:y[er.APP_CALL_TXN],signers:[o]}]);case 31:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Tr(){return(Tr=o(a().mark((function t(e){var n,r,s,o,i,u,c;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.txGroup,s=e.signedTxns,t.next=3,mt(n,[s]);case 3:return o=t.sent,i=h(o,1),u=i[0].txnID,t.prev=6,t.next=9,cn(n,r);case 9:c=t.sent,t.next=14;break;case 12:t.prev=12,t.t0=t.catch(6);case 14:return t.abrupt("return",{outputAssets:c,txnID:u});case 15:case"end":return t.stop()}}),t,null,[[6,12]])})))).apply(this,arguments)}var yr,wr={getQuote:function(t){var e=t.pool,n=t.reserves,r=t.poolTokenIn,a=BigInt(r),s=xr(a,n),o=s.asset1OutputAmount,i=s.asset2OutputAmount;return{round:n.round,asset1Out:{assetId:e.asset1ID,amount:o},asset2Out:{assetId:e.asset2ID,amount:i},poolTokenIn:{assetId:e.poolTokenID,amount:a}}},getSingleAssetRemoveLiquidityQuote:function(t){var e,n=t.pool,r=t.reserves,a=t.poolTokenIn,s=t.assetOutID,o=t.decimals,i=BigInt(a),u=xr(i,r),c=u.asset1OutputAmount,p=u.asset2OutputAmount,l=n.totalFeeShare;if(s===n.asset1ID){var d=Ir.calculateFixedInputSwap({inputSupply:r.asset2-p,outputSupply:r.asset1-c,swapInputAmount:p,totalFeeShare:l,decimals:o}),f=d.swapOutputAmount,m=d.totalFeeAmount,g=d.priceImpact;e={round:r.round,assetOut:{assetId:s,amount:c+f},poolTokenIn:{assetId:n.poolTokenID,amount:i},internalSwapQuote:{amountIn:{assetId:n.asset2ID,amount:p},amountOut:{assetId:n.asset1ID,amount:f},swapFees:{assetId:n.asset2ID,amount:m},priceImpact:g}}}else{if(s!==n.asset2ID)throw new Error("assetOutID must be one of the pool assets");var A=Ir.calculateFixedInputSwap({inputSupply:r.asset1-c,outputSupply:r.asset2-p,swapInputAmount:c,totalFeeShare:l,decimals:o}),I=A.swapOutputAmount,x=A.totalFeeAmount,h=A.priceImpact;e={round:r.round,assetOut:{assetId:s,amount:p+I},poolTokenIn:{assetId:n.poolTokenID,amount:i},internalSwapQuote:{amountIn:{assetId:n.asset2ID,amount:p},amountOut:{assetId:n.asset1ID,amount:I},swapFees:{assetId:n.asset2ID,amount:x},priceImpact:h}}}return e},generateTxns:function(t){return hr.apply(this,arguments)},generateSingleAssetOutTxns:function(t){return vr.apply(this,arguments)},signTxns:function(t){var e=t.txGroup;return(0,t.initiatorSigner)([e])},execute:function(t){return Tr.apply(this,arguments)}},_r=(p(yr={},C.V1_1,sr),p(yr,C.V2,wr),yr),br=3n,Er=1000n,Dr=function(t){return t[t.FEE_TXN_INDEX=0]="FEE_TXN_INDEX",t[t.VALIDATOR_APP_CALL_TXN_INDEX=1]="VALIDATOR_APP_CALL_TXN_INDEX",t[t.ASSET_IN_TXN_INDEX=2]="ASSET_IN_TXN_INDEX",t[t.ASSET_OUT_TXN_INDEX=3]="ASSET_OUT_TXN_INDEX",t}(Dr||{});function Sr(){return(Sr=o(a().mark((function e(n){var r,s,o,i,u,c,p,l;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.pool,s=n.txGroup,o=n.initiatorSigner,e.next=3,o([s]);case 3:return i=e.sent,u=h(i,2),c=u[0],p=u[1],l=s.map((function(e,n){return n===Dr.FEE_TXN_INDEX?c:n===Dr.ASSET_IN_TXN_INDEX?p:t.signLogicSigTransactionObject(e.txn,r.account.lsig).blob})),e.abrupt("return",l);case 9:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Or(){return(Or=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,h,v,T,y,w;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(r=n.client,s=n.quoteAndPool,o=n.swapType,i=n.slippage,u=n.initiatorAddr,c=s.pool,p=s.quote,l=p.assetInID,d=p.assetOutID,f=c.account.address(),(m=[c.asset1ID,c.asset2ID]).includes(l)&&m.includes(d)&&l!==d){e.next=7;break}throw new W({pool:c,quote:p},"Input asset (#".concat(l,") and output asset (#").concat(d,") provided to generate transactions do not belong to the pool ").concat(f,"."));case 7:return e.next=9,r.getTransactionParams().do();case 9:return g=e.sent,A=[ht("swap"),o===Ot.FixedInput?ht("fi"):ht("fo")],I=t.makeApplicationNoOpTxnFromObject({from:f,appIndex:c.validatorAppID,appArgs:A,accounts:[u],note:Tt.getAppCallTxnNoteWithClientName(C.V1_1),foreignAssets:c.asset2ID==j?[c.asset1ID,c.poolTokenID]:[c.asset1ID,c.asset2ID,c.poolTokenID],suggestedParams:g}),x=o===Ot.FixedOutput?ct("positive",i,p.assetInAmount):p.assetInAmount,h=l===j?t.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:f,amount:x,suggestedParams:g}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:u,to:f,assetIndex:l,amount:x,suggestedParams:g}),v=o===Ot.FixedInput?ct("negative",i,p.assetOutAmount):p.assetOutAmount,T=d===j?t.makePaymentTxnWithSuggestedParamsFromObject({from:f,to:u,amount:v,suggestedParams:g}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:f,to:u,assetIndex:d,amount:v,suggestedParams:g}),y=t.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:f,amount:I.fee+T.fee,note:D,suggestedParams:g}),w=t.assignGroupID([y,I,h,T]),e.abrupt("return",[{txn:w[0],signers:[u]},{txn:w[1],signers:[f]},{txn:w[2],signers:[u]},{txn:w[3],signers:[f]}]);case 19:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Nr(t){var e=t.pool,n=t.reserves,a=t.assetIn,s=t.decimals;if(e.status!==Se.READY)throw new E(b.NoAvailablePoolError,"There is not an available pool for this asset pair");var o,i,u,c=BigInt(a.amount);if(a.id===e.asset1ID)o=e.asset2ID,i=n.asset1,u=n.asset2;else{if(a.id!==e.asset2ID)throw new E(b.AssetDoesNotBelongToPoolError,"Input asset (#".concat(a.id,") doesn't belong to the pool ").concat(e.account.address(),"."));o=e.asset1ID,i=n.asset2,u=n.asset1}var p=c*br/Er,l=u-i*u/(i+(c-p));if(l>u)throw new E(b.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");var d={assetIn:{amount:c,decimals:s.assetIn},assetOut:{amount:l,decimals:s.assetOut}},f={round:n.round,assetInID:a.id,assetInAmount:c,assetOutID:o,assetOutAmount:l,swapFee:Number(p),rate:ae(d),priceImpact:se(r({inputSupply:i,outputSupply:u},d))};return{type:Zt.Direct,data:{pool:e,quote:f}}}function Pr(t){return kr.apply(this,arguments)}function kr(){return(kr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d,f,m,g,A,I,x;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.pool,s=e.signedTxns,o=e.assetIn,i=e.assetOut,u=e.initiatorAddr,t.next=3,_e({client:n,pool:r,accountAddr:u});case 3:return c=t.sent,t.next=6,mt(n,[s]);case 6:return p=t.sent,l=h(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,t.next=13,_e({client:n,pool:r,accountAddr:u});case 13:return g=t.sent,i.id===r.asset1ID?(A=c.excessAsset1,I=g.excessAsset1):(A=c.excessAsset2,I=g.excessAsset2),(x=I-A)<0n&&(x=0n),t.abrupt("return",{round:f,assetInID:o.id,assetInAmount:BigInt(o.amount),assetOutID:i.id,assetOutAmount:BigInt(i.amount)+x,excessAmount:{assetID:i.id,excessAmountForSwap:x,totalExcessAmount:I},txnID:m});case 18:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Lr(t){var e=t.pool,n=t.reserves,r=t.assetOut,a=t.decimals;if(e.status!==Se.READY)throw new E(b.NoAvailablePoolError,"There is not an available pool for this asset pair");var s,o,i,u=BigInt(r.amount);if(r.id===e.asset1ID)s=e.asset2ID,o=n.asset2,i=n.asset1;else{if(r.id!==e.asset2ID)throw new E(b.AssetDoesNotBelongToPoolError,"Output asset (#".concat(r.id,") doesn't belong to the pool ").concat(e.account.address(),"."));s=e.asset1ID,o=n.asset1,i=n.asset2}if(u>i)throw new E(b.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");var c=o*i/(i-u)-o,p=c*Er/(Er-br),l=p-c,d=pt(a.assetOut,Number(u))/pt(a.assetIn,Number(p)),f=pt(a.assetOut,Number(i))/pt(a.assetIn,Number(o)),m=lt({decimalPlaces:5},Math.abs(d/f-1)),g={round:n.round,assetInID:s,assetInAmount:p,assetOutID:r.id,assetOutAmount:u,swapFee:Number(l),rate:d,priceImpact:m};return{type:Zt.Direct,data:{pool:e,quote:g}}}function Fr(t){return Rr.apply(this,arguments)}function Rr(){return(Rr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d,f,m,g,A,I,x;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.pool,s=e.signedTxns,o=e.assetIn,i=e.assetOut,u=e.initiatorAddr,t.next=3,_e({client:n,pool:r,accountAddr:u});case 3:return c=t.sent,t.next=6,mt(n,[s]);case 6:return p=t.sent,l=h(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,t.next=13,_e({client:n,pool:r,accountAddr:u});case 13:return g=t.sent,o.id===r.asset1ID?(A=c.excessAsset1,I=g.excessAsset1):(A=c.excessAsset2,I=g.excessAsset2),(x=I-A)<0n&&(x=0n),t.abrupt("return",{round:f,assetInID:o.id,assetInAmount:BigInt(o.amount)-x,assetOutID:i.id,assetOutAmount:BigInt(i.amount),excessAmount:{assetID:o.id,excessAmountForSwap:x,totalExcessAmount:I},txnID:m});case 18:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Br(){return(Br=o(a().mark((function t(e){var n,s,o,i,u,c,p,l,d,f;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(n=e.client,s=e.pool,o=e.swapType,i=e.txGroup,u=e.signedTxns,c=e.initiatorAddr,s.status===Se.READY){t.next=3;break}throw new W({pool:s,swapType:o,txGroup:i},"There is not an available pool for this asset pair");case 3:if(t.prev=3,p={id:i[Dr.ASSET_IN_TXN_INDEX].txn.assetIndex||j,amount:i[Dr.ASSET_IN_TXN_INDEX].txn.amount},l={id:i[Dr.ASSET_OUT_TXN_INDEX].txn.assetIndex||j,amount:i[Dr.ASSET_OUT_TXN_INDEX].txn.amount},o!==Ot.FixedInput){t.next=12;break}return t.next=9,Pr({client:n,pool:s,signedTxns:u,assetIn:p,assetOut:l,initiatorAddr:c});case 9:d=t.sent,t.next=15;break;case 12:return t.next=14,Fr({client:n,pool:s,signedTxns:u,assetIn:p,assetOut:l,initiatorAddr:c});case 14:d=t.sent;case 15:return t.abrupt("return",r(r({},d),{},{groupID:It(i),fees:At(i)}));case 18:throw t.prev=18,t.t0=t.catch(3),"SlippageTolerance"===(f=new W(t.t0,"We encountered something unexpected while swapping. Try again later.")).type&&f.setMessage("The swap failed due to too much slippage in the price. Please adjust the slippage tolerance and try again."),f;case 23:case"end":return t.stop()}}),t,null,[[3,18]])})))).apply(this,arguments)}var Mr,Cr={getQuote:function(t,e,n,r,a){return t===Ot.FixedInput?Nr({pool:e,reserves:n,assetIn:r,decimals:a}):Lr({pool:e,reserves:n,assetOut:r,decimals:a})},getFixedInputSwapQuote:Nr,getFixedOutputSwapQuote:Lr,generateTxns:function(t){return Or.apply(this,arguments)},signTxns:function(t){return Sr.apply(this,arguments)},execute:function(t){return Br.apply(this,arguments)},executeFixedOutputSwap:Fr};function jr(t){return Promise.allSettled(t).then((function(t){if(t.every((function(t){return"rejected"===t.status}))){var e=h(t.map((function(t){return t.reason})),2),n=e[0],r=e[1];if(le(n)&&!le(r))throw n;throw r}return t.filter((function(t){return"fulfilled"===t.status&&t.value})).map((function(t){return t.value}))}))}function Xr(){return(Xr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=e.amount,s=e.assetIn,o=e.assetOut,i=e.isSwapRouterEnabled,u=e.pools,c=[],(p=u.find((function(t){return t.info.contractVersion===C.V1_1})))?c.push(new Promise((function(t,e){try{t(Cr.getFixedInputSwapQuote({pool:p.info,assetIn:{amount:r,id:Number(s.id)},decimals:{assetIn:s.decimals,assetOut:o.decimals},reserves:p.reserves}))}catch(t){e(t)}}))):c.push(Promise.reject(new E(b.NoAvailablePoolError,"Trying to swap from non-existent pool"))),l=u.find((function(t){return t.info.contractVersion===C.V2})),c.push(Ir.getFixedInputSwapQuote({amount:r,assetIn:{id:H(s),decimals:s.decimals},assetOut:{id:H(o),decimals:o.decimals},pool:null!==(n=null==l?void 0:l.info)&&void 0!==n?n:null,isSwapRouterEnabled:i,network:e.network})),t.next=8,jr(c);case 8:return d=t.sent,t.abrupt("return",pe(d));case 10:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Vr(){return(Vr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=e.amount,s=e.assetIn,o=e.assetOut,i=e.pools,u=e.isSwapRouterEnabled,c=[],(p=i.find((function(t){return t.info.contractVersion===C.V1_1})))?c.push(new Promise((function(t,e){try{t(Cr.getFixedOutputSwapQuote({pool:p.info,assetOut:{amount:r,id:Number(o.id)},decimals:{assetIn:s.decimals,assetOut:o.decimals},reserves:p.reserves}))}catch(t){e(t)}}))):c.push(Promise.reject(new E(b.NoAvailablePoolError,"Trying to swap from non-existent pool"))),l=i.find((function(t){return t.info.contractVersion===C.V2})),c.push(Ir.getFixedOutputSwapQuote({amount:r,assetIn:{id:H(s),decimals:s.decimals},assetOut:{id:H(o),decimals:o.decimals},pool:null!==(n=null==l?void 0:l.info)&&void 0!==n?n:null,isSwapRouterEnabled:u,network:e.network})),t.next=8,jr(c);case 8:return d=t.sent,t.abrupt("return",pe(d));case 10:case"end":return t.stop()}}),t)})))).apply(this,arguments)}var Ur=(p(Mr={},C.V1_1,Cr),p(Mr,C.V2,Ir),p(Mr,"getQuote",(function(t){var e=t.type;if(e===Ot.FixedInput)return function(t){return Xr.apply(this,arguments)}(t);if(e===Ot.FixedOutput)return function(t){return Vr.apply(this,arguments)}(t);throw new E(b.InvalidSwapTypeError,"Invalid swap type")})),p(Mr,"generateTxns",(function(t){return t.quote.type===Zt.Direct&&ue(t.quote)===C.V1_1?Cr.generateTxns(r(r({},t),{},{quoteAndPool:t.quote.data})):Ir.generateTxns(t)})),p(Mr,"signTxns",(function(t){if(t.quote.type===Zt.Direct&&ue(t.quote)===C.V1_1){var e=t.quote.data.pool;return Cr.signTxns(r(r({},t),{},{pool:e}))}return Ir.signTxns(t)})),p(Mr,"execute",(function(t){return t.contractVersion===C.V1_1?Cr.execute(t):Ir.execute(t)})),Mr);function Qr(){return(Qr=o(a().mark((function t(e){var n,r,s,o,i,u,c,p,l,d;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=e.client,r=e.pool,s=e.txGroup,o=e.initiatorSigner,t.prev=1,t.next=4,qr({txGroup:s,pool:r,initiatorSigner:o});case 4:return i=t.sent,t.next=7,mt(n,[i]);case 7:return u=t.sent,c=h(u,1),p=c[0],l=p.txnID,d=p.confirmedRound,t.abrupt("return",{fees:At(s),confirmedRound:d,txnID:l,groupID:It(s)});case 15:throw t.prev=15,t.t0=t.catch(1),new W(t.t0,"We encountered something unexpected while redeeming. Try again later.");case 18:case"end":return t.stop()}}),t,null,[[1,15]])})))).apply(this,arguments)}function qr(t){return Gr.apply(this,arguments)}function Gr(){return(Gr=o(a().mark((function e(n){var r,s,o,i,u,c,p,l;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.txGroup,s=n.pool,o=n.initiatorSigner,e.next=3,o([r]);case 3:return i=e.sent,u=h(i,1),c=u[0],p=s.account.lsig,l=r.map((function(e,n){return 0===n?c:t.signLogicSigTransactionObject(e.txn,p).blob})),e.abrupt("return",l);case 9:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Wr(){return Wr=o(a().mark((function e(n){var r,s,i,u,c,p;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.data,i=n.initiatorSigner,e.prev=1,u=s.map((function(t){var e=t.txGroup,n=t.pool;return{txns:e,txnFees:At(e),groupID:It(e),lsig:n.account.lsig}})),e.next=5,i(u.map((function(t){return t.txns})));case 5:return c=e.sent,p=Promise.all(u.map((function(e,n){return new Promise(function(){var s=o(a().mark((function s(o,i){var u,p,l,d,f,m;return a().wrap((function(a){for(;;)switch(a.prev=a.next){case 0:return a.prev=0,u=e.txns.map((function(r,a){return 0===a?c[n]:t.signLogicSigTransactionObject(r.txn,e.lsig).blob})),a.next=4,mt(r,[u]);case 4:p=a.sent,l=h(p,1),d=l[0],f=d.txnID,m=d.confirmedRound,o({fees:e.txnFees,groupID:e.groupID,txnID:f,confirmedRound:m}),a.next=15;break;case 12:a.prev=12,a.t0=a.catch(0),i(a.t0);case 15:case"end":return a.stop()}}),s,null,[[0,12]])})));return function(t,e){return s.apply(this,arguments)}}())}))),e.abrupt("return",p);case 10:throw e.prev=10,e.t0=e.catch(1),new W(e.t0,"We encountered something unexpected while redeeming. Try again later.");case 13:case"end":return e.stop()}}),e,null,[[1,10]])}))),Wr.apply(this,arguments)}function zr(){return(zr=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.pool,o=n.assetID,i=n.assetOut,u=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:return c=e.sent,p=s.account.address(),l=t.makeApplicationNoOpTxnFromObject({from:p,appIndex:s.validatorAppID,appArgs:[ht("redeem")],note:Tt.getAppCallTxnNoteWithClientName(s.contractVersion),accounts:[u],foreignAssets:0==s.asset2ID?[s.asset1ID,s.poolTokenID]:[s.asset1ID,s.asset2ID,s.poolTokenID],suggestedParams:c}),d=0===o?t.makePaymentTxnWithSuggestedParamsFromObject({from:p,to:u,amount:BigInt(i),suggestedParams:c}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:p,to:u,assetIndex:o,amount:BigInt(i),suggestedParams:c}),f=t.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:p,amount:l.fee+d.fee,note:D,suggestedParams:c}),m=t.assignGroupID([f,l,d]),e.abrupt("return",[{txn:m[0],signers:[u]},{txn:m[1],signers:[p]},{txn:m[2],signers:[p]}]);case 10:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Jr(t){var e,n={},r=w(t);try{for(r.s();!(e=r.n()).done;){var a=e.value,s=(new TextDecoder).decode(Buffer.from(a.key,"base64")),o=void 0;o=1===a.value.type?a.value.bytes:a.value.uint,n[s]=o}}catch(t){r.e(t)}finally{r.f()}return n}function Yr(t,e,n){return t*e/n}var Kr=BigInt(31536e3),Hr=BigInt(1e14),Zr=BigInt(1e16),$r={testnet:548587153,mainnet:1385499515},ta=14;function ea(t){return na.apply(this,arguments)}function na(){return(na=o(a().mark((function e(n){var r,s,o,i,u;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.assetIDs,i=t.getApplicationAddress($r[s]),e.next=4,ve(r,i);case 4:return u=e.sent.assets.map((function(t){return t["asset-id"]})),e.abrupt("return",o.filter((function(t){return t!==j&&!u.includes(t)})));case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function ra(){return(ra=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,T,y,w,_,b,E,D,S;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.network,o=n.poolAddress,i=n.poolTokenId,u=n.lendingManagerId,c=n.asset1In,p=n.asset2In,l=n.initiatorAddr,d=t.getApplicationAddress($r[s]),e.next=4,r.getTransactionParams().do();case 4:return f=e.sent,m=[c,p].sort((function(t,e){return e.fAssetId-t.fAssetId})),g=h(m,2),A=g[0],I=g[1],x=K(I.id),T=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:d,assetIndex:A.id,amount:A.amount,suggestedParams:f}),y=x?t.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:d,amount:I.amount,suggestedParams:f}):t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:d,assetIndex:I.id,amount:I.amount,suggestedParams:f}),(w=t.makeApplicationNoOpTxnFromObject({from:l,appIndex:$r[s],appArgs:[ht("add_liquidity"),t.decodeAddress(o).publicKey,t.encodeUint64(A.lendingAppId),t.encodeUint64(I.lendingAppId)],foreignAssets:[A.id,I.id,A.fAssetId,I.fAssetId],foreignApps:[A.lendingAppId,I.lendingAppId,u],accounts:[o],suggestedParams:f})).fee=t.ALGORAND_MIN_TX_FEE*(ta+1),_=wt(s,C.V2),b=t.makeApplicationNoOpTxnFromObject({from:l,appIndex:$r[s],appArgs:[ht("noop")],foreignAssets:[i],foreignApps:[_],accounts:[o],suggestedParams:f}),E=[T,y,w,b],e.next=16,ea({client:r,network:s,assetIDs:[A.id,I.id,A.fAssetId,I.fAssetId,i]});case 16:return(D=e.sent).length&&((S=[t.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:d,amount:O*D.length,suggestedParams:f}),t.makeApplicationNoOpTxnFromObject({from:l,appIndex:$r[s],appArgs:[ht("asset_optin")].concat(v(D.map((function(e){return t.encodeUint64(e)})))),foreignAssets:v(D),suggestedParams:f})])[1].fee=(D.length+1)*t.ALGORAND_MIN_TX_FEE,E.unshift.apply(E,S)),e.abrupt("return",t.assignGroupID(E).map((function(t){return{txn:t,signers:[l]}})));case 19:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function aa(){return(aa=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m,g,A,I,x,h,v;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.pool,o=n.poolTokenIn,i=n.initiatorAddr,u=n.asset1Out,c=n.asset2Out,p=n.lendingManagerId,l=n.network,d=t.getApplicationAddress($r[l]),e.next=4,r.getTransactionParams().do();case 4:if(f=e.sent,m=s.account.address(),g=s.poolTokenID){e.next=9;break}throw new Error("Pool token asset ID is missing");case 9:return A=t.makeAssetTransferTxnWithSuggestedParamsFromObject({from:i,to:d,assetIndex:g,amount:o,suggestedParams:f}),(I=t.makeApplicationNoOpTxnFromObject({from:i,appIndex:$r[l],appArgs:[ht("remove_liquidity"),t.decodeAddress(m).publicKey,t.encodeUint64(u.lendingAppId),t.encodeUint64(c.lendingAppId)],accounts:[m],foreignAssets:[u.id,c.id,u.fAssetId,c.fAssetId],foreignApps:[u.lendingAppId,c.lendingAppId,p],suggestedParams:f})).fee=t.ALGORAND_MIN_TX_FEE*(ta+1),x=wt(l,C.V2),h=t.makeApplicationNoOpTxnFromObject({from:i,appIndex:$r[l],appArgs:[ht("noop")],accounts:[m],foreignAssets:[g,u.fAssetId,c.fAssetId],foreignApps:[x],suggestedParams:f}),v=t.assignGroupID([A,I,h]),e.abrupt("return",v.map((function(t){return{txn:t,signers:[i]}})));case 16:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function sa(t,e,n){var r=BigInt(Math.floor((new Date).getTime()/1e3)-function(t){return null!=t?t:Math.floor((new Date).getTime()/1e3)}(n));return Yr(t,Zr+e*r/Kr,Zr)}function oa(){return(oa=o(a().mark((function t(e,n){var r,s,o,i,u,c,p,l;return a().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,e.getApplicationByID(n).do();case 2:return r=t.sent,s=r.params["global-state"],o=Jr(s),i=Number(Buffer.from(o.pm,"base64").readBigUInt64BE(0)),u=Buffer.from(o.i,"base64"),c=u.readBigUInt64BE(32),p=u.readBigUInt64BE(40),l=Number(u.readBigUInt64BE(48)),t.abrupt("return",{appId:n,managerAppId:i,depositInterestRate:c,depositInterestIndex:p,lastUpdate:l});case 11:case"end":return t.stop()}}),t)})))).apply(this,arguments)}var ia={AddLiquidity:Object.freeze({__proto__:null,generateTxns:function(t){return ra.apply(this,arguments)},getAddLiquidityTotalFee:function(e){return t.ALGORAND_MIN_TX_FEE*(4+ta)+(e?(e+1)*t.ALGORAND_MIN_TX_FEE+e*O:0)}}),RemoveLiquidity:Object.freeze({__proto__:null,generateTxns:function(t){return aa.apply(this,arguments)},getRemoveLiquidityTotalFee:function(){return t.ALGORAND_MIN_TX_FEE*(3+ta)}}),calculateWithdrawReturn:function(t){var e=t.withdrawAmount,n=sa(t.depositInterestIndex,t.depositInterestRate,t.lastUpdate);return Yr(BigInt(e),n,Hr)},calculateDepositReturn:function(t){var e=t.depositAmount,n=sa(t.depositInterestIndex,t.depositInterestRate,t.lastUpdate);return BigInt(e)*Hr/n},getFolksWrapperAppOptInRequiredAssetIDs:ea};function ua(e){var n=e.suggestedParams,r=e.stakingAppID,a=e.initiatorAddr,s=e.liquidityAssetID,o=e.program,i=e.amount,u=t.encodeUint64(i),c=t.encodeUint64(o.id);return t.makeApplicationNoOpTxnFromObject({appIndex:r,from:a,suggestedParams:n,foreignAssets:[s],accounts:[o.accountAddress],appArgs:[ht("commit"),u],note:$([ht("tinymanStaking/v1:b"),c,t.encodeUint64(s),u])})}function ca(){return(ca=o(a().mark((function e(n){var r,s,o,i,u,c,p,l,d,f,m;return a().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=n.client,s=n.stakingAppID,o=n.program,i=n.requiredAssetID,u=n.liquidityAssetID,c=n.amount,p=n.initiatorAddr,e.next=3,r.getTransactionParams().do();case 3:if(l=e.sent,d=ua({suggestedParams:l,stakingAppID:s,program:o,liquidityAssetID:u,initiatorAddr:p,amount:c}),f=[d],"number"!=typeof i){e.next=10;break}return m=t.makeApplicationNoOpTxnFromObject({appIndex:s,from:p,suggestedParams:l,foreignAssets:[i],accounts:[o.accountAddress],appArgs:[ht("log_balance")]}),f=t.assignGroupID([d,m]),e.abrupt("return",[{txn:f[0],signers:[p]},{txn:f[1],signers:[p]}]);case 10:return e.abrupt("return",[{txn:f[0],signers:[p]}]);case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}exports.ALGO_ASSET=X,exports.ALGO_ASSET_ID=j,exports.ASSET_OPT_IN_PROCESS_TXN_COUNT=1,exports.AddLiquidity=Kn,exports.BASE_MINIMUM_BALANCE=S,exports.Bootstrap=yn,exports.CONTRACT_VERSION=C,exports.LendingPool=ia,exports.MINIMUM_ADD_LIQUIDITY_AMOUNT=R,exports.MINIMUM_BALANCE_REQUIRED_PER_APP=N,exports.MINIMUM_BALANCE_REQUIRED_PER_ASSET=O,exports.MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA=L,exports.MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE=F,exports.OPT_IN_VALIDATOR_APP_PROCESS_TXN_COUNT=1,exports.OPT_OUT_VALIDATOR_APP_PROCESS_TXN_COUNT=1,exports.POOL_TOKEN_UNIT_NAME=V,exports.PoolStatus=Se,exports.REDEEM_PROCESS_TXN_COUNT=3,exports.RemoveLiquidity=_r,exports.Swap=Ur,exports.SwapQuoteError=E,exports.SwapQuoteErrorType=b,exports.SwapQuoteType=Zt,exports.SwapType=Ot,exports.V1_1AddLiquidityTxnIndices=wn,exports.V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT=5,exports.V1_1_REMOVE_LIQUIDITY_TXN_COUNT=Zn,exports.V2AddLiquidityTxnIndices=En,exports.V2AddLiquidityType=bn,exports.V2_REMOVE_LIQUIDITY_APP_CALL_INNER_TXN_COUNT=$n,exports.applySlippageToAmount=ct,exports.calculateAccountMinimumRequiredBalance=ye,exports.calculatePriceImpact=se,exports.calculateSwapRate=ae,exports.combineAndRegroupSignerTxns=function(){for(var e=arguments.length,n=new Array(e),a=0;a=t.minimum_required_balance},exports.isAccountOptedIntoApp=function(t){var e=t.appID;return t.accountAppsLocalState.some((function(t){return t.id===e}))},exports.isSwapAssetInAmountLow=ne,exports.isSwapQuoteErrorCausedByAmount=le,exports.poolUtils=We,exports.prepareCommitTransactions=function(t){return ca.apply(this,arguments)},exports.redeemAllExcessAsset=function(t){return Wr.apply(this,arguments)},exports.redeemExcessAsset=function(t){return Qr.apply(this,arguments)},exports.sendAndWaitRawTransaction=mt,exports.sumUpTxnFees=At,exports.tinymanContract_v1_1=ge,exports.tinymanContract_v2=xe,exports.tinymanJSSDKConfig=Tt; +"use strict";var e=require("algosdk"),t=require("base64-js"),n=require("crypto");function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0;--a){var s=this.tryEntries[a],o=s.completion;if("root"===s.tryLoc)return r("end");if(s.tryLoc<=this.prev){var i=n.call(s,"catchLoc"),u=n.call(s,"finallyLoc");if(i&&u){if(this.prev=0;--r){var a=this.tryEntries[r];if(a.tryLoc<=this.prev&&n.call(a,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),k(n),d}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var a=r.arg;k(n)}return a}}throw new Error("illegal catch attempt")},delegateYield:function(e,t,n){return this.delegate={iterator:E(e),resultName:t,nextLoc:n},"next"===this.method&&(this.arg=void 0),d}},e}function o(e,t,n,r,a,s,o){try{var i=e[s](o),u=i.value}catch(e){return void n(e)}i.done?t(u):Promise.resolve(u).then(r,a)}function i(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var s=e.apply(t,n);function i(e){o(s,r,a,i,u,"next",e)}function u(e){o(s,r,a,i,u,"throw",e)}i(void 0)}))}}function u(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function c(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,o=!0,i=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){i=!0,s=e},f:function(){try{o||null==n.return||n.return()}finally{if(i)throw s}}}}function k(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}var _=function(e){return e.SwapRouterStaleDataError="SwapRouterStaleDataError",e.SwapRouterNoRouteError="SwapRouterNoRouteError",e.SwapRouterLowSwapAmountError="SwapRouterLowSwapAmountError",e.SwapRouterInsufficientReservesError="SwapRouterInsufficientReservesError",e.SwapRouterPoolHasNoLiquidityError="SwapRouterPoolHasNoLiquidityError",e.NoAvailablePoolError="NoAvailablePoolError",e.OutputAmountExceedsAvailableLiquidityError="OutputAmountExceedsAvailableLiquidityError",e.UnknownError="UnknownError",e.LowSwapAmountError="LowSwapAmountError",e.AssetDoesNotBelongToPoolError="AssetDoesNotBelongToPoolError",e.InvalidSwapTypeError="InvalidSwapTypeError",e}({}),E=function(e){d(n,A(Error));var t=I(n);function n(e,r){var a;return u(this,n),(a=t.call(this,r)).type=e,a.message=r,Error.captureStackTrace&&Error.captureStackTrace(x(a),n),a}return p(n)}(),P=Uint8Array.from([1]),S=1e5,D=1e5,O=1e5,N=1e5,L=1e5,B=5e4,C=28500,F=1e3,R=1e3,M={mainnet:{base:"https://mainnet.analytics.tinyman.org/api",v1:"https://mainnet.analytics.tinyman.org/api/v1"},testnet:{base:"https://testnet.analytics.tinyman.org/api",v1:"https://testnet.analytics.tinyman.org/api/v1"}},U={V1_1:"v1_1",V2:"v2"},j=0,V={id:"".concat(j),name:"Algorand",unit_name:"ALGO",decimals:6,url:"https://algorand.org",is_liquidity_token:!1,total_amount:"6615503326932151",clawback_address:""},X={V1:"TM1POOL",V1_1:"TMPOOL11",V2:"TMPOOL2"},G={testnet:258703304,mainnet:22e8},q="- would result negative",Q="logic eval error:",W="exceeds schema integer count",z=/transaction \w+:/,J=function(e){d(n,A(Error));var t=I(n);function n(e,r){var a;u(this,n);for(var s=arguments.length,o=new Array(s>2?s-2:0),i=2;ir?[a(a({},e),{},{id:n}),a(a({},t),{},{id:r})]:[a(a({},t),{},{id:r}),a(a({},e),{},{id:n})]}function $(e,t){var n=[e,t];return[Math.max.apply(Math,n),Math.min.apply(Math,n)]}function Z(e){return Number(e)===j}function ee(e){return Number(e.id)}function te(e){var t,n=e.stateArray,r=void 0===n?[]:n,a=e.shouldDecodeKeys,s=void 0!==a&&a,o={},i=T(r);try{for(i.s();!(t=i.n()).done;){var u=t.value,c=u.key,p=void 0;if(1==u.value.type)p=u.value.bytes;else{if(2!=u.value.type)throw new Error("Unexpected state type: ".concat(u.value.type));p=u.value.uint}o[s?atob(c):c]=p}}catch(e){i.e(e)}finally{i.f()}return o}function ne(e){var t,n=e.reduce((function(e,t){return e+t.length}),0),r=new Uint8Array(n),a=0,s=T(e);try{for(s.s();!(t=s.n()).done;){var o=t.value;r.set(o,a),a+=o.length}}catch(e){s.e(e)}finally{s.f()}return r}var re=100000n,ae=100000n,se=100000n,oe=25000n+25000n,ie=25000n+3500n;function ue(e){var t=e["apps-total-schema"],n=0n,r=0n;t&&(t["num-byte-slice"]&&(n=t["num-byte-slice"]),t["num-uint"]&&(r=t["num-uint"]));var a=e["apps-local-state"]||[],s=e["created-apps"]||[],o=e.assets||[];return re+ae*BigInt(o.length)+se*BigInt(s.length+a.length)+ie*r+oe*n}function ce(e){return new Promise((function(t){setTimeout((function(){t(null)}),e)}))}function pe(e,t){return le.apply(this,arguments)}function le(){return(le=i(s().mark((function e(t,n){var r;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=3,ce(1e3);case 3:return r=null,e.prev=4,e.next=7,t.pendingTransactionInformation(n).do();case 7:r=e.sent,e.next=12;break;case 10:e.prev=10,e.t0=e.catch(4);case 12:if(!r){e.next=17;break}if(!r["confirmed-round"]){e.next=15;break}return e.abrupt("return",r);case 15:if(!r["pool-error"]){e.next=17;break}throw new Error("Transaction Rejected: ".concat(r["pool-error"]));case 17:e.next=0;break;case 19:case"end":return e.stop()}}),e,null,[[4,10]])})))).apply(this,arguments)}function de(e,t,n){if(t>1||t<0)throw new Error("Invalid slippage value. Must be between 0 and 1, got ".concat(t));var r;try{var a="negative"===e?1-t:1+t;r=BigInt(Math.floor(Number(n)*a))}catch(e){throw new Error(e.message)}return r}function fe(e,t){var n=Number(e);return me({decimalPlaces:n},Math.pow(10,-n)*Number(t))}function me(e,t){var n=e.decimalPlaces,r=void 0===n?0:n;if(r>0){var a=v(ge(t),2),s=a[0],o=a[1],i=v(ge(Math.round(Number(he(s,o+r)))),2),u=i[0],c=i[1];return Number(he(u,c-r))}return Math.round(t)}function he(e,t){return e+(t<0?"e".concat(t):"e+".concat(t))}function ge(e){if(e.toString().includes("e")){var t=e.toString().split("e");return[parseFloat(t[0]),parseFloat(t[1])]}return[e,0]}function Ae(e,t){return xe.apply(this,arguments)}function xe(){return(xe=i(s().mark((function e(t,n){var r,a,o,i,u,c,p,l;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:e.prev=0,r=[],a=T(n),e.prev=3,a.s();case 5:if((o=a.n()).done){e.next=18;break}return i=o.value,e.next=9,t.sendRawTransaction(i).do();case 9:return u=e.sent,c=u.txId,e.next=13,pe(t,c);case 13:p=e.sent,l=p["confirmed-round"],r.push({confirmedRound:l,txnID:c});case 16:e.next=5;break;case 18:e.next=23;break;case 20:e.prev=20,e.t0=e.catch(3),a.e(e.t0);case 23:return e.prev=23,a.f(),e.finish(23);case 26:return e.abrupt("return",r);case 29:throw e.prev=29,e.t1=e.catch(0),new J(e.t1,"We encountered an error while processing this transaction. Try again later.");case 32:case"end":return e.stop()}}),e,null,[[0,29],[3,20,23,26]])})))).apply(this,arguments)}function Ie(e){return e.reduce((function(e,t){return e+t.txn.fee}),0)}function ve(e){return(t=e[0].txn.group)?Buffer.from(t).toString("base64"):"";var t}function we(e){for(var t=[];;){var n=Number(e&BigInt(127));if(!(e>>=BigInt(7))){t.push(n);break}t.push(128|n)}return t}function ye(e){return(new TextEncoder).encode(e)}var be,Te=new(function(){function e(){u(this,e),this.clientName="tinyman-js-sdk"}return p(e,[{key:"getClientName",value:function(){return this.clientName}},{key:"setClientName",value:function(e){this.clientName=e}},{key:"getAppCallTxnNoteWithClientName",value:function(e){var t=e===U.V1_1?"v1":e;return ye("tinyman/".concat(t,':j{"origin":"').concat(this.clientName,'"}'))}}]),e}()),ke=(l(be={},U.V1_1,{testnet:62368684,mainnet:552635992}),l(be,U.V2,{testnet:148607e3,mainnet:1002541853}),be);function _e(e,t){var n=ke[t][e];if(!n)throw new Error("No Validator App exists for ".concat(e," network with ").concat(t," contract version"));return n}function Ee(){return(Ee=i(s().mark((function t(n){var r,a,o,i,u,c;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.contractVersion,i=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return u=t.sent,c=e.makeApplicationOptInTxnFromObject({from:i,appIndex:_e(a,o),note:Te.getAppCallTxnNoteWithClientName(o),suggestedParams:u}),t.abrupt("return",[{txn:c,signers:[i]}]);case 6:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Pe(){return(Pe=i(s().mark((function t(n){var r,a,o,i,u,c;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.contractVersion,i=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return u=t.sent,c=e.makeApplicationClearStateTxnFromObject({from:i,appIndex:_e(a,o),note:Te.getAppCallTxnNoteWithClientName(o),suggestedParams:u}),t.abrupt("return",[{txn:c,signers:[i]}]);case 6:case"end":return t.stop()}}),t)})))).apply(this,arguments)}var Se,De,Oe,Ne=function(e){return e.FixedInput="fixed-input",e.FixedOutput="fixed-output",e}({}),Le=.003,Be=function(e){return e[e.INPUT_TXN=0]="INPUT_TXN",e[e.APP_CALL_TXN=1]="APP_CALL_TXN",e}({}),Ce=(l(Se={},Ne.FixedInput,1),l(Se,Ne.FixedOutput,2),Se),Fe=2,Re=ye("swap"),Me=(l(De={},Ne.FixedInput,ye("fixed-input")),l(De,Ne.FixedOutput,ye("fixed-output")),De),Ue={ASSET_OPT_IN:ye("asset_opt_in")},je={testnet:184778019,mainnet:1083651166},Ve=(l(Oe={},Ne.FixedInput,7),l(Oe,Ne.FixedOutput,8),Oe);function Xe(e){var t=We(e),n=t.assetIn,r=t.assetOut;return fe(r.asset.decimals,Number(r.amount))/fe(n.asset.decimals,Number(n.amount))}function Ge(e){var t=je[e];if(!t)throw new Error("Unknown network or network not supported: ".concat(e));return t}function qe(e){return e[e.length-1].quote.amount_out}function Qe(e){return e[0].quote.amount_in}function We(e){return{assetIn:Qe(e),assetOut:qe(e)}}function ze(e){return Je.apply(this,arguments)}function Je(){return(Je=i(s().mark((function t(n){var r,a,o,i,u,c,p;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.routerAppID,o=n.assetIDs,i=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return u=t.sent,c=e.makeApplicationNoOpTxnFromObject({from:i,appIndex:a,appArgs:[Ue.ASSET_OPT_IN],foreignAssets:o,suggestedParams:u}),p=o.length,c.fee=e.ALGORAND_MIN_TX_FEE*(p+1),t.abrupt("return",c);case 8:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Ye(e){return Ke.apply(this,arguments)}function Ke(){return(Ke=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w,y,b,T,k,_,E,P,S,D;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.initiatorAddr,a=n.client,o=n.network,i=n.swapType,u=n.route,c=n.slippage,t.next=3,a.getTransactionParams().do();case 3:return p=t.sent,l=[ee(u[0].quote.amount_in.asset),ee(u[0].quote.amount_out.asset),ee(u[1].quote.amount_out.asset)],d=l[0],f=l[1],m=l[2],h=[Number(Qe(u).amount),Number(qe(u).amount)],g=h[0],A=h[1],x=[u[0].pool.address,u[1].pool.address],I=x[0],v=x[1],w=i===Ne.FixedInput?g:de("positive",c,g),y=i===Ne.FixedOutput?A:de("negative",c,A),b=Z(d),T=Ge(o),k=b?e.makePaymentTxnWithSuggestedParamsFromObject({from:r,to:e.getApplicationAddress(T),amount:w,suggestedParams:p}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:r,to:e.getApplicationAddress(T),amount:w,assetIndex:d,suggestedParams:p}),(_=e.makeApplicationNoOpTxnFromObject({from:r,appIndex:T,appArgs:[Re,Me[i],e.encodeUint64(y)],foreignApps:[_e(o,U.V2)],foreignAssets:[d,f,m],accounts:[I,v],suggestedParams:p,note:Te.getAppCallTxnNoteWithClientName(U.V2)})).fee=e.ALGORAND_MIN_TX_FEE*(Ve[i]+1),E=[k,_],t.next=17,He({client:a,network:o,assetIDs:[d,f,m]});case 17:if(!((P=t.sent).length>0)){t.next=23;break}return t.next=21,ze({client:a,initiatorAddr:r,assetIDs:P,routerAppID:T});case 21:S=t.sent,E.unshift(S);case 23:return D=e.assignGroupID(E),t.abrupt("return",D.map((function(e){return{txn:e,signers:[r]}})));case 25:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function He(e){return $e.apply(this,arguments)}function $e(){return($e=i(s().mark((function t(n){var r,a,o,i,u,c;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.assetIDs,i=e.getApplicationAddress(Ge(a)),t.next=4,r.accountInformation(i).do();case 4:return u=t.sent,c=u.assets.map((function(e){return e["asset-id"]})),t.abrupt("return",o.filter((function(e){return e!==j&&!c.includes(e)})));case 7:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Ze(e){return et.apply(this,arguments)}function et(){return(et=i(s().mark((function e(t){var n,r,a,o,i,u,c,p;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.amount,r=t.assetInID,a=t.assetOutID,o=t.swapType,i=t.network,u={asset_in_id:String(r),asset_out_id:String(a),swap_type:o,amount:String(n)},e.next=4,fetch("".concat(M[i].v1,"/swap-router/quotes/"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}).catch((function(){throw new Error("Network error")}));case 4:return c=e.sent,e.next=7,c.json();case 7:if(p=e.sent,c.ok){e.next=14;break}if(s=p,!Boolean(s)||void 0===s.fallback_message){e.next=13;break}throw new E(p.type,p.fallback_message);case 13:throw new E(_.UnknownError,"There was an error while getting a quote from Swap Router");case 14:if(!(p.route.length<2)){e.next=16;break}throw new E(_.SwapRouterNoRouteError,"Swap router couldn't find a route for this swap.");case 16:return e.abrupt("return",p);case 17:case"end":return e.stop()}var s}),e)})))).apply(this,arguments)}var tt=function(e){return e.Direct="direct",e.Router="router",e}({}),nt=4*e.ALGORAND_MIN_TX_FEE;function rt(t){return(Ce[t]+Fe)*e.ALGORAND_MIN_TX_FEE}function at(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Le;return Math.ceil(1/e)}function st(e){return e1&&void 0!==arguments[1]?arguments[1]:Le)}function ot(t){return(Ce[t]+1)*e.ALGORAND_MIN_TX_FEE}function it(e){var t=e.assetIn,n=e.assetOut;return fe(n.decimals,Number(n.amount))/fe(t.decimals,Number(t.amount))}function ut(e){var t=e.inputSupply,n=e.outputSupply,r=e.assetIn,a=e.assetOut,s=it({assetIn:r,assetOut:a}),o=fe(a.decimals,Number(n))/fe(r.decimals,Number(t));return me({decimalPlaces:5},Math.abs(s/o-1))}function ct(e){if(e.type===tt.Router){var t=Qe(e.data.route);return{id:ee(t.asset),amount:Number(t.amount)}}return{id:e.data.quote.assetInID,amount:e.data.quote.assetInAmount}}function pt(e){if(e.type===tt.Router){var t=qe(e.data.route);return{id:ee(t.asset),amount:Number(t.amount)}}return{id:e.data.quote.assetOutID,amount:e.data.quote.assetOutAmount}}function lt(e){return e.type===tt.Direct?e.data.pool.contractVersion:U.V2}function dt(e){return e.type===tt.Direct?e.data.quote.rate:Xe(e.data.route)}function ft(e){for(var t=e[0],n=dt(t),r=1;rn&&(t=a,n=s)}return t}function mt(e){return e instanceof E&&[_.SwapRouterInsufficientReservesError,_.SwapRouterLowSwapAmountError,_.OutputAmountExceedsAvailableLiquidityError,_.LowSwapAmountError].includes(e.type)}var ht={type:"logicsig",logic:{bytecode:"BCAIAQCBgICAgICAgPABgICAgICAgIDwAQMEBQYlJA1EMQkyAxJEMRUyAxJEMSAyAxJEMgQiDUQzAQAxABJEMwEQIQcSRDMBGIGCgICAgICAgPABEkQzARkiEjMBGyEEEhA3ARoAgAlib290c3RyYXASEEAAXDMBGSMSRDMBG4ECEjcBGgCABHN3YXASEEACOzMBGyISRDcBGgCABG1pbnQSQAE7NwEaAIAEYnVybhJAAZg3ARoAgAZyZWRlZW0SQAJbNwEaAIAEZmVlcxJAAnkAIQYhBSQjEk0yBBJENwEaARclEjcBGgIXJBIQRDMCADEAEkQzAhAhBBJEMwIhIxJEMwIiIxwSRDMCIyEHEkQzAiQjEkQzAiWACFRNUE9PTDExEkQzAiZRAA+AD1RpbnltYW5Qb29sMS4xIBJEMwIngBNodHRwczovL3RpbnltYW4ub3JnEkQzAikyAxJEMwIqMgMSRDMCKzIDEkQzAiwyAxJEMwMAMQASRDMDECEFEkQzAxElEkQzAxQxABJEMwMSIxJEJCMTQAAQMwEBMwIBCDMDAQg1AUIBsTMEADEAEkQzBBAhBRJEMwQRJBJEMwQUMQASRDMEEiMSRDMBATMCAQgzAwEIMwQBCDUBQgF8MgQhBhJENwEcATEAE0Q3ARwBMwQUEkQzAgAxABNEMwIUMQASRDMDADMCABJEMwIRJRJEMwMUMwMHMwMQIhJNMQASRDMDESMzAxAiEk0kEkQzBAAxABJEMwQUMwIAEkQzAQEzBAEINQFCAREyBCEGEkQ3ARwBMQATRDcBHAEzAhQSRDMDFDMDBzMDECISTTcBHAESRDMCADEAEkQzAhQzBAASRDMCESUSRDMDADEAEkQzAxQzAwczAxAiEk0zBAASRDMDESMzAxAiEk0kEkQzBAAxABNEMwQUMQASRDMBATMCAQgzAwEINQFCAJAyBCEFEkQ3ARwBMQATRDMCADcBHAESRDMCADEAE0QzAwAxABJEMwIUMwIHMwIQIhJNMQASRDMDFDMDBzMDECISTTMCABJEMwEBMwMBCDUBQgA+MgQhBBJENwEcATEAE0QzAhQzAgczAhAiEk03ARwBEkQzAQEzAgEINQFCABIyBCEEEkQzAQEzAgEINQFCAAAzAAAxABNEMwAHMQASRDMACDQBD0M=",address:"ABUKAXTANWR6K6ZYV75DWJEPVWWOU6SFUVRI6QHO44E4SIDLHBTD2CZ64A",size:881,variables:[{name:"TMPL_ASSET_ID_1",type:"int",index:15,length:10},{name:"TMPL_ASSET_ID_2",type:"int",index:5,length:10},{name:"TMPL_VALIDATOR_APP_ID",type:"int",index:74,length:10}],source:"https://github.com/tinymanorg/tinyman-contracts-v1/tree/dc9ab40c58b85c15d58f63a1507e18be76720dbb/contracts/pool_logicsig.teal.tmpl"},name:"pool_logicsig"},gt={type:"app",global_state_schema:{num_uints:0,num_byte_slices:0},local_state_schema:{num_uints:16,num_byte_slices:0},name:"validator_app"},At=p((function e(t){u(this,e),this.schema={numLocalInts:t.local_state_schema.num_uints,numLocalByteSlices:t.local_state_schema.num_byte_slices,numGlobalInts:t.global_state_schema.num_uints,numGlobalByteSlices:t.global_state_schema.num_byte_slices}})),xt=function(n){d(a,At);var r=I(a);function a(e,t){var n;return u(this,a),(n=r.call(this,e)).poolLogicSigContractTemplate=t.logic.bytecode,n.templateVariables=t.logic.variables,n}return p(a,[{key:"generateLogicSigAccountForPool",value:function(n){if(n.asset1ID===n.asset2ID)throw new Error("Assets are the same");var r=_e(n.network,U.V1_1),a=v($(n.asset1ID,n.asset2ID),2),s=a[0],o=a[1],i=Array.from(t.toByteArray(this.poolLogicSigContractTemplate)),u={asset_id_1:s,asset_id_2:o,validator_app_id:r},c=0;this.templateVariables.sort((function(e,t){return e.index-t.index}));for(var p=0;p2&&void 0!==arguments[2]?arguments[2]:e.IntDecoding.DEFAULT;return new Promise(function(){var e=i(s().mark((function e(o,i){var u;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,t.accountInformation(n).setIntDecoding(r).do();case 3:u=e.sent,o(a(a({},u),{},{minimum_required_balance:_t(u)})),e.next=10;break;case 7:e.prev=7,e.t0=e.catch(0),i(new Error(e.t0.message||"Failed to fetch account information"));case 10:case"end":return e.stop()}}),e,null,[[0,7]])})));return function(t,n){return e.apply(this,arguments)}}())}function kt(e,t){var n=e["apps-local-state"].find((function(e){return e.id===t}));return n?te({stateArray:n["key-value"],shouldDecodeKeys:!0}):null}function _t(e){var t=e["apps-total-schema"];return S+D*(e.assets||[]).length+N*(e["created-apps"]||[]).length+O*(e["apps-local-state"]||[]).length+B*Number(t&&t["num-byte-slice"]||0)+C*Number(t&&t["num-uint"]||0)+L*(e["apps-total-extra-pages"]||0)}var Et=ye("e");function Pt(e){return St.apply(this,arguments)}function St(){return(St=i(s().mark((function n(r){var a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w,y,b,k,_;return s().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return a=r.client,o=r.pool,i=r.accountAddr,n.next=3,a.accountInformation(i).setIntDecoding(e.IntDecoding.BIGINT).do();case 3:u=n.sent,c=u["apps-local-state"]||[],p=0n,l=0n,d=0n,f=o.account.address(),m=T(c),n.prev=10,m.s();case 12:if((h=m.n()).done){n.next=31;break}if((g=h.value).id==o.validatorAppID){n.next=16;break}return n.abrupt("continue",29);case 16:if(A=g["key-value"]){n.next=19;break}return n.abrupt("break",31);case 19:x=te({stateArray:A}),I=t.fromByteArray(ne([e.decodeAddress(f).publicKey,Et,e.encodeUint64(o.asset1ID)])),v=t.fromByteArray(ne([e.decodeAddress(f).publicKey,Et,e.encodeUint64(o.asset2ID)])),w=t.fromByteArray(ne([e.decodeAddress(f).publicKey,Et,e.encodeUint64(o.poolTokenID)])),y=x[I],b=x[v],k=x[w],"bigint"==typeof y&&(p=y),"bigint"==typeof b&&(l=b),"bigint"==typeof k&&(d=k);case 29:n.next=12;break;case 31:n.next=36;break;case 33:n.prev=33,n.t0=n.catch(10),m.e(n.t0);case 36:return n.prev=36,m.f(),n.finish(36);case 39:if(!((_={excessAsset1:p,excessAsset2:l,excessPoolTokens:d}).excessAsset1<0n||_.excessAsset2<0n||_.excessPoolTokens<0n)){n.next=42;break}throw new Error("Invalid account excess: ".concat(_));case 42:return n.abrupt("return",_);case 43:case"end":return n.stop()}}),n,null,[[10,33,36,39]])})))).apply(this,arguments)}function Dt(){return(Dt=i(s().mark((function n(r){var a,o,i,u,c,p,l,d,f,m,h,g,A,x,I;return s().wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return a=r.client,o=r.accountAddr,i=r.validatorAppID,n.next=3,a.accountInformation(o).setIntDecoding(e.IntDecoding.BIGINT).do();case 3:if(u=n.sent,c=u["apps-local-state"]||[],p=c.find((function(e){return e.id==i})),l=[],p&&p["key-value"])for(d=te({stateArray:p["key-value"]}),f=0,m=Object.entries(d);fFt)){n.next=48;break}throw new Error("Issued liquidity value is out of the expected range ([0n, ".concat(Ft,"]): ").concat(N.issuedLiquidity));case 48:return n.abrupt("return",N);case 49:case"end":return n.stop()}}),n,null,[[8,31,34,37]])})))).apply(this,arguments)}function jt(){return jt=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.client,r=t.address,a=t.network,!(o=d.length>1&&void 0!==d[1]?d[1]:{})[r]){e.next=4;break}return e.abrupt("return",o[r]);case 4:return e.next=6,Tt(n,r);case 6:return i=e.sent,u=kt(i,_e(a,U.V1_1)),c=null,u&&(l=i["created-assets"][0],p=l.index,c={asset1ID:u[Lt[U.V1_1].asset1],asset2ID:u[Lt[U.V1_1].asset2],poolTokenID:p},o[r]=c),e.abrupt("return",c);case 11:case"end":return e.stop()}}),e)}))),jt.apply(this,arguments)}var Vt=Object.freeze({__proto__:null,getPoolAssets:function(e){return jt.apply(this,arguments)},getPoolInfo:Rt,getPoolReserves:function(e,t){return Ut.apply(this,arguments)}});function Xt(e){return Gt.apply(this,arguments)}function Gt(){return(Gt=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.network,a=t.asset1ID,o=t.asset2ID,i=bt(U.V2),u=i.generateLogicSigAccountForPool(t),c=_e(r,U.V2),p=u.address(),l=$(a,o),e.next=8,Tt(n,p);case 8:return d=e.sent,f=kt(d,c),m={account:u,validatorAppID:c,asset1ID:l[0],asset2ID:l[1],status:f?Nt.READY:Nt.NOT_CREATED,contractVersion:U.V2},f&&(m.asset1ProtocolFees=BigInt(f[Lt.v2.asset1ProtocolFees]),m.asset2ProtocolFees=BigInt(f[Lt.v2.asset2ProtocolFees]),m.asset1Reserves=BigInt(f[Lt.v2.asset1Reserves]),m.asset2Reserves=BigInt(f[Lt.v2.asset2Reserves]),m.issuedPoolTokens=BigInt(f[Lt.v2.issuedPoolTokens]),m.cumulativePriceUpdateTimeStamp=Number(f[Lt.v2.cumulativePriceUpdateTimeStamp]),m.protocolFeeRatio=Number(f[Lt.v2.protocolFeeRatio]),m.totalFeeShare=BigInt(f[Lt.v2.totalFeeShare]),m.poolTokenID=Number(f[Lt.v2.poolTokenID]),m.asset1ID=Number(f[Lt.v2.asset1]),m.asset2ID=Number(f[Lt.v2.asset2])),e.abrupt("return",m);case 13:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function qt(){return(qt=i(s().mark((function e(t,n){var r,a,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Tt(t,n.account.address());case 2:return r=e.sent,a=kt(r,n.validatorAppID),o={asset1:0n,asset2:0n,issuedLiquidity:0n,round:r.round},a&&(o.asset1=BigInt(a[Lt.v2.asset1Reserves]),o.asset2=BigInt(a[Lt.v2.asset2Reserves]),o.issuedLiquidity=BigInt(a[Lt.v2.issuedPoolTokens])),e.abrupt("return",o);case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Qt(){return(Qt=i(s().mark((function e(t){var n,r,a,o,i,u;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.address,a=t.network,e.next=3,Tt(n,r);case 3:return o=e.sent,i=kt(o,_e(a,U.V2)),u=null,i&&(u={asset1ID:i[Lt[U.V2].asset1],asset2ID:i[Lt[U.V2].asset2],poolTokenID:i[Lt[U.V2].poolTokenID]}),e.abrupt("return",u);case 8:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var Wt=Object.freeze({__proto__:null,getPoolAssets:function(e){return Qt.apply(this,arguments)},getPoolInfo:Xt,getPoolReserves:function(e,t){return qt.apply(this,arguments)}});function zt(e){return Boolean(e&&!(e.asset1+e.asset2))}var Jt,Yt=Object.freeze({__proto__:null,getPoolPairRatio:function(e){var t=zt(e),n=null;return e&&!t&&e.asset1&&e.asset2&&(n=Number(e.asset1)/Number(e.asset2)),n},getPoolShare:function(e,t){var n=Number(t)/Number(e);return Number.isFinite(n)||(n=0),n},getPoolsForPair:function(e){return Promise.all([Rt(e),Xt(e)])},isPoolEmpty:zt,isPoolNotCreated:function(e){return(null==e?void 0:e.status)===Nt.NOT_CREATED},isPoolReady:function(e){return(null==e?void 0:e.status)===Nt.READY}}),Kt=a((l(Jt={},U.V1_1,a(a({},Vt),Yt)),l(Jt,U.V2,a(a({},Wt),Yt)),Jt),Yt),Ht=function(e){return e[e.FUNDING_TXN=0]="FUNDING_TXN",e[e.VALIDATOR_APP_CALL=1]="VALIDATOR_APP_CALL",e[e.POOL_TOKEN_CREATE=2]="POOL_TOKEN_CREATE",e[e.ASSET1_OPT_IN=3]="ASSET1_OPT_IN",e[e.ASSET2_OPT_IN=4]="ASSET2_OPT_IN",e}({}),$t={ASA_ALGO:96e4,ASA_ASA:859e3};function Zt(){return(Zt=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,w,y,b,T,k,_,E,P,S;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.asset_1,i=n.asset_2,u=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return c=t.sent,p=H(o,i),l=v(p,2),d=l[0],f=d.id,m=d.unit_name,h=l[1],g=h.id,A=h.unit_name,x=Z(g),I=_e(a,U.V1_1),w=It.generateLogicSigAccountForPool({network:a,asset1ID:f,asset2ID:g}),y=w.address(),b=e.makeApplicationOptInTxnFromObject({from:y,appIndex:I,note:Te.getAppCallTxnNoteWithClientName(U.V1_1),appArgs:[ye("bootstrap"),e.encodeUint64(f),e.encodeUint64(g)],foreignAssets:x?[f]:[g],suggestedParams:c}),T=e.makeAssetCreateTxnWithSuggestedParamsFromObject({from:y,total:0xffffffffffffffffn,decimals:6,defaultFrozen:!1,unitName:X.V1_1,assetName:"TinymanPool1.1 ".concat(m,"-").concat(A),assetURL:"https://tinyman.org",suggestedParams:c}),k=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:y,to:y,assetIndex:f,amount:0,suggestedParams:c}),_=e.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:y,amount:en(x),suggestedParams:c}),(E=[])[Ht.FUNDING_TXN]=_,E[Ht.VALIDATOR_APP_CALL]=b,E[Ht.POOL_TOKEN_CREATE]=T,E[Ht.ASSET1_OPT_IN]=k,x||(E[Ht.ASSET2_OPT_IN]=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:y,to:y,assetIndex:g,amount:0,suggestedParams:c})),P=e.assignGroupID(E),S=[{txn:P[Ht.FUNDING_TXN],signers:[u]},{txn:P[Ht.VALIDATOR_APP_CALL],signers:[y]},{txn:P[Ht.POOL_TOKEN_CREATE],signers:[y]},{txn:P[Ht.ASSET1_OPT_IN],signers:[y]}],P[Ht.ASSET2_OPT_IN]&&S.push({txn:P[Ht.ASSET2_OPT_IN],signers:[y]}),t.abrupt("return",S);case 23:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function en(e){return e?$t.ASA_ALGO:$t.ASA_ASA}function tn(){return(tn=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.txGroup,a=n.network,o=n.initiatorSigner,i=n.asset1ID,u=n.asset2ID,t.next=3,o([r]);case 3:return c=t.sent,p=v(c,1),l=p[0],d=$(i,u),f=v(d,2),m=f[0],h=f[1],g=It.generateLogicSigAccountForPool({network:a,asset1ID:m,asset2ID:h}),A=[],x=r.map((function(t,n){if(n===Ht.FUNDING_TXN)return A.push(t.txn.txID().toString()),l;var r=e.signLogicSigTransactionObject(t.txn,g),a=r.txID,s=r.blob;return A.push(a),s})),t.abrupt("return",{signedTxns:x,txnIDs:A});case 11:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function nn(e){return rn.apply(this,arguments)}function rn(){return(rn=i(s().mark((function e(t){var n,r,a,o,i;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.signedTxns,a=t.txnIDs,e.prev=1,e.next=4,n.sendRawTransaction(r).do();case 4:return e.next=6,pe(n,a[Ht.POOL_TOKEN_CREATE]);case 6:if(o=e.sent,"number"==typeof(i=o["asset-index"])){e.next=10;break}throw new Error("Generated ID is not valid: got ".concat(i));case 10:return e.abrupt("return",{poolTokenID:i});case 13:throw e.prev=13,e.t0=e.catch(1),new J(e.t0,"We encountered something unexpected while bootstraping the pool. Try again later.");case 16:case"end":return e.stop()}}),e,null,[[1,13]])})))).apply(this,arguments)}function an(){return(an=i(s().mark((function e(t){var n,r,a,o,i,u,c;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.network,a=t.pool,o=a.asset1ID,i=a.asset2ID,u=t.signedTxns,c=t.txnIDs,e.next=3,nn({client:n,signedTxns:u,txnIDs:c});case 3:return e.abrupt("return",Kt.v1_1.getPoolInfo({client:n,network:r,asset1ID:o,asset2ID:i}));case 4:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var sn={generateTxns:function(e){return Zt.apply(this,arguments)},signTxns:function(e){return tn.apply(this,arguments)},execute:function(e){return an.apply(this,arguments)},getBootstrapFundingTxnAmount:en};var on=function(e){return e[e.FUNDING_TXN=0]="FUNDING_TXN",e[e.VALIDATOR_APP_CALL=1]="VALIDATOR_APP_CALL",e}({}),un={ASA_ALGO:5,ASA_ASA:6};function cn(e,t){return pn.apply(this,arguments)}function pn(){return(pn=i(s().mark((function t(n,r){var a,o,i;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!(o=null===(a=r.find((function(e){return"appl"===e.txn.type})))||void 0===a?void 0:a.txn.txID())){t.next=7;break}return t.next=4,e.waitForConfirmation(n,o,R);case 4:t.t0=t.sent,t.next=8;break;case 7:t.t0=void 0;case 8:return i=t.t0,t.abrupt("return",i);case 10:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function ln(e,t){return dn.apply(this,arguments)}function dn(){return(dn=i(s().mark((function e(t,n){var r;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,cn(t,n);case 2:return r=e.sent,e.abrupt("return",null==r?void 0:r["inner-txns"]);case 4:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function fn(e,t){return mn.apply(this,arguments)}function mn(){return(mn=i(s().mark((function t(n,r){var a,o;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,ln(n,r);case 2:return a=t.sent,s=r[0].txn,o=e.encodeAddress(s.from.publicKey),t.abrupt("return",null==a?void 0:a.reduce((function(t,n){var r=t,a=n.txn.txn;return a.type===e.TransactionType.axfer&&e.encodeAddress(a.arcv)===o?r.push({id:a.xaid,amount:a.aamt}):a.type===e.TransactionType.pay&&e.encodeAddress(a.rcv)===o&&r.push({id:j,amount:a.amt}),r}),[]));case 5:case"end":return t.stop()}var s}),t)})))).apply(this,arguments)}function hn(){return(hn=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,w,y,b,T;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.asset_1,i=n.asset_2,u=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return c=t.sent,p=_e(a,U.V2),l=e.getApplicationAddress(p),d=H(o,i),f=v(d,2),m=f[0].id,h=f[1].id,t.next=9,Kt.v2.getPoolInfo({client:r,network:a,asset1ID:m,asset2ID:h});case 9:if(t.sent.status!==Nt.READY){t.next=12;break}throw new Error("Pool for ".concat(o.unit_name,"-").concat(i.unit_name," already exists"));case 12:return g=yt.generateLogicSigAccountForPool({network:a,asset1ID:m,asset2ID:h}),A=g.address(),x=Z(h),(I=e.makeApplicationOptInTxnFromObject({from:A,appIndex:p,appArgs:[ye("bootstrap")],note:Te.getAppCallTxnNoteWithClientName(U.V2),foreignAssets:[m,h],rekeyTo:l,suggestedParams:c})).fee=An(x),w=e.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:A,amount:gn(x),suggestedParams:c}),(y=[])[on.FUNDING_TXN]=w,y[on.VALIDATOR_APP_CALL]=I,b=e.assignGroupID(y),(T=[])[on.FUNDING_TXN]={txn:b[on.FUNDING_TXN],signers:[u]},T[on.VALIDATOR_APP_CALL]={txn:b[on.VALIDATOR_APP_CALL],signers:[A]},t.abrupt("return",T);case 26:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function gn(e){return function(e,t){var n=bt(e).schema,r=n.numLocalInts,a=n.numLocalByteSlices,s=S+D+D+O+C*r+B*a;return t||(s+=D),s}(U.V2,e)+An(e)+D}function An(t){return((t?un.ASA_ALGO:un.ASA_ASA)+1)*e.ALGORAND_MIN_TX_FEE}function xn(){return(xn=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.txGroup,a=n.network,o=n.initiatorSigner,i=n.asset1ID,u=n.asset2ID,t.next=3,o([r]);case 3:return c=t.sent,p=v(c,1),l=p[0],d=$(i,u),f=v(d,2),m=f[0],h=f[1],g=yt.generateLogicSigAccountForPool({network:a,asset1ID:m,asset2ID:h}),A=[],x=r.map((function(t,n){if(n===on.FUNDING_TXN)return A.push(t.txn.txID().toString()),l;var r=e.signLogicSigTransactionObject(t.txn,g),a=r.txID,s=r.blob;return A.push(a),s})),t.abrupt("return",{signedTxns:x,txnIDs:A});case 11:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function In(){return(In=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.network,a=t.pool,o=a.asset1ID,i=a.asset2ID,u=t.txGroup,c=t.signedTxns,e.prev=1,e.next=4,n.sendRawTransaction(c).do();case 4:return e.next=6,cn(n,u);case 6:if(e.t1=p=e.sent,e.t0=null===e.t1,e.t0){e.next=10;break}e.t0=void 0===p;case 10:if(!e.t0){e.next=14;break}e.t2=void 0,e.next=15;break;case 14:e.t2=null===(l=p["local-state-delta"][0].delta)||void 0===l||null===(d=l.find((function(e){return e.key===btoa(Lt.v2.poolTokenID)})))||void 0===d?void 0:d.value.uint;case 15:if("number"==typeof(f=e.t2)){e.next=18;break}throw new Error("Generated ID is not valid: got ".concat(f));case 18:return e.abrupt("return",Kt.v2.getPoolInfo({client:n,network:r,asset1ID:o,asset2ID:i}));case 21:throw e.prev=21,e.t3=e.catch(1),new J(e.t3,"We encountered something unexpected while bootstraping the pool. Try again later.");case 24:case"end":return e.stop()}}),e,null,[[1,21]])})))).apply(this,arguments)}var vn,wn={generateTxns:function(e){return hn.apply(this,arguments)},signTxns:function(e){return xn.apply(this,arguments)},execute:function(e){return In.apply(this,arguments)},getBootstrapFundingTxnAmount:gn,getTotalCost:function(t){return e.ALGORAND_MIN_TX_FEE+gn(t)}};var yn,bn,Tn,kn,_n=(l(vn={},U.V1_1,sn),l(vn,U.V2,wn),l(vn,"generateTxns",(function(e){return e.contractVersion===U.V1_1?sn.generateTxns(e):wn.generateTxns(e)})),l(vn,"signTxns",(function(e){return e.contractVersion===U.V1_1?sn.signTxns(e):wn.signTxns(e)})),l(vn,"execute",(function(e){return e.contractVersion===U.V1_1?sn.execute(e):wn.execute(e)})),l(vn,"calculateBootstrapFundingTxnAmount",(function(e){var t=e.contractVersion,n=e.isAlgoPool;return t===U.V1_1?sn.getBootstrapFundingTxnAmount(n):wn.getBootstrapFundingTxnAmount(n)})),vn),En=function(e){return e[e.FEE_TXN=0]="FEE_TXN",e[e.VALIDATOR_APP_CALL_TXN=1]="VALIDATOR_APP_CALL_TXN",e[e.ASSET1_IN_TXN=2]="ASSET1_IN_TXN",e[e.ASSET2_IN_TXN=3]="ASSET2_IN_TXN",e[e.LIQUDITY_OUT_TXN=4]="LIQUDITY_OUT_TXN",e}({}),Pn=5*e.ALGORAND_MIN_TX_FEE,Sn=function(e){return e.SINGLE="single",e.FLEXIBLE="flexible",e.INITIAL="initial",e}({}),Dn=(l(yn={},Sn.FLEXIBLE,{ASSET1_IN_TXN:0,ASSET2_IN_TXN:1,VALIDATOR_APP_CALL_TXN:2}),l(yn,Sn.SINGLE,{ASSET_IN_TXN:0,VALIDATOR_APP_CALL_TXN:1}),l(yn,Sn.INITIAL,{ASSET1_IN_TXN:0,ASSET2_IN_TXN:1,VALIDATOR_APP_CALL_TXN:2}),yn),On=(l(bn={},Sn.INITIAL,1),l(bn,Sn.SINGLE,2),l(bn,Sn.FLEXIBLE,2),bn),Nn=(l(Tn={},Sn.INITIAL,3),l(Tn,Sn.FLEXIBLE,3),l(Tn,Sn.SINGLE,2),Tn);function Ln(e){var t,n,r,a=e.reserves,s=e.totalFeeShare,o=e.asset1,i=e.asset2,u=a.asset1*a.asset2,c=a.asset1+BigInt(o.amount),p=a.asset2+BigInt(i.amount),l=c*p,d=BigInt(parseInt(String(Math.sqrt(Number(l*a.issuedLiquidity*a.issuedLiquidity/u))))),f=d-a.issuedLiquidity,m=f*c/d,h=f*p/d,g=BigInt(o.amount)-m,A=BigInt(i.amount)-h;if(g>A){var x=g;r=Cn(x,s),t={id:o.id,amount:x+r,decimals:o.decimals,reserves:a.asset1},n={id:i.id,amount:BigInt(Math.abs(Math.min(Number(A),0))),decimals:i.decimals,reserves:a.asset2},f-=r*d/(c*BigInt(2))}else{var I=A;r=Cn(I,s),t={id:i.id,amount:I+r,decimals:i.decimals,reserves:a.asset2},n={id:o.id,amount:BigInt(Math.abs(Math.min(Number(g),0))),decimals:o.decimals,reserves:a.asset1},f-=r*d/(p*BigInt(2))}return{poolTokenOutAmount:f,internalSwapQuote:{assetIn:t,assetOut:n,swapFees:r,priceImpact:ut({inputSupply:t.reserves,outputSupply:n.reserves,assetIn:t,assetOut:n})}}}function Bn(e,t){if(!e.amount||!t.amount)throw new Error("Both assets are required for the initial add liquidity");return BigInt(Math.floor(Math.abs(Math.sqrt(Number(e.amount)*Number(t.amount))-Bt)))}function Cn(e,t){return e*BigInt(t)/(BigInt(1e4)-BigInt(t))}function Fn(t){return(On[t]+1)*e.ALGORAND_MIN_TX_FEE}var Rn=ye("add_liquidity"),Mn=(l(kn={},U.V1_1,[ye("mint")]),l(kn,U.V2,{INITIAL_LIQUIDITY:[ye("add_initial_liquidity")],SINGLE_ASSET_MODE:[Rn,ye("single")],FLEXIBLE_MODE:[Rn,ye("flexible")]}),kn);function Un(){return(Un=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.poolAddress,i=n.asset1In,u=n.asset2In,c=n.poolTokenOut,p=n.slippage,l=n.initiatorAddr,d=de("negative",p,c.amount),t.next=4,r.getTransactionParams().do();case 4:return f=t.sent,m=e.makeApplicationNoOpTxnFromObject({from:o,appIndex:_e(a,U.V1_1),appArgs:Mn.v1_1,accounts:[l],note:Te.getAppCallTxnNoteWithClientName(U.V1_1),foreignAssets:u.id==j?[i.id,c.id]:[i.id,u.id,c.id],suggestedParams:f}),h=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:o,assetIndex:i.id,amount:i.amount,suggestedParams:f}),g=u.id===j?e.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:o,amount:u.amount,suggestedParams:f}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:o,assetIndex:u.id,amount:u.amount,suggestedParams:f}),A=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:o,to:l,assetIndex:c.id,amount:d,suggestedParams:f}),x=e.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:o,amount:m.fee+A.fee,note:P,suggestedParams:f}),I=e.assignGroupID([x,m,h,g,A]),t.abrupt("return",[{txn:I[0],signers:[l]},{txn:I[1],signers:[o]},{txn:I[2],signers:[l]},{txn:I[3],signers:[l]},{txn:I[4],signers:[o]}]);case 12:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function jn(){return(jn=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.pool,a=n.txGroup,o=n.initiatorSigner,i=r.account,t.next=4,o([a]);case 4:return u=t.sent,c=v(u,3),p=c[0],l=c[1],d=c[2],f=a.map((function(t,n){return n===En.FEE_TXN?p:n===En.ASSET1_IN_TXN?l:n===En.ASSET2_IN_TXN?d:e.signLogicSigTransactionObject(t.txn,i).blob})),t.abrupt("return",f);case 11:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Vn(){return(Vn=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.pool,a=t.txGroup,o=t.signedTxns,i=t.initiatorAddr,e.prev=1,u=BigInt(a[En.LIQUDITY_OUT_TXN].txn.amount),e.next=5,Pt({client:n,pool:r,accountAddr:i});case 5:return c=e.sent,e.next=8,Ae(n,[o]);case 8:return p=e.sent,l=v(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,h=Ie(a),g=ve(a),e.next=17,Pt({client:n,pool:r,accountAddr:i});case 17:return A=e.sent,(x=A.excessPoolTokens-c.excessPoolTokens)<0n&&(x=0n),e.abrupt("return",{round:f,fees:h,poolTokenID:r.poolTokenID,poolTokenOut:u+x,excessAmount:{excessAmountForAddingLiquidity:x,totalExcessAmount:A.excessPoolTokens},txnID:m,groupID:g});case 23:throw e.prev=23,e.t0=e.catch(1),"SlippageTolerance"===(I=new J(e.t0,"We encountered something unexpected while adding liquidity. Try again later.")).type&&I.setMessage("Adding liquidity failed due to too much slippage in the price. Please adjust the slippage tolerance and try again."),I;case 28:case"end":return e.stop()}}),e,null,[[1,23]])})))).apply(this,arguments)}var Xn=Object.freeze({__proto__:null,execute:function(e){return Vn.apply(this,arguments)},generateTxns:function(e){return Un.apply(this,arguments)},getQuote:function(e){var t=e.pool,n=e.reserves,r=e.asset1In,a=e.asset2In;if(0n===n.issuedLiquidity){var s=BigInt(Math.floor(Math.sqrt(Number(r)*Number(a))));if(s<=BigInt(F))throw new Error("Initial liquidity amount is too small. The amount must be greater than ".concat(F,", this quote is for ").concat(s,"."));return{round:n.round,asset1ID:t.asset1ID,asset1In:BigInt(r),asset2ID:t.asset2ID,asset2In:BigInt(a),poolTokenID:t.poolTokenID,poolTokenOut:s-BigInt(F),share:1}}var o=BigInt(r)*n.issuedLiquidity/n.asset1,i=BigInt(a)*n.issuedLiquidity/n.asset2,u=oo)throw new E(_.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");if(st(Number(t)))throw new E(_.LowSwapAmountError,"Swap amount is too low.");return{assetInID:i,assetInAmount:l,assetOutID:c,assetOutAmount:m,swapFee:Number(h),rate:fe(p,Number(m))/fe(u,Number(l)),priceImpact:g}}function hr(e){var t=e.amount,n=e.assetIn,r=e.assetOut,a=e.pool;if(!a||!Kt.isPoolReady(a))throw new E(_.NoAvailablePoolError,"There is not an available pool for this asset pair");var s,o,i=n.id,u=n.decimals,c=r.id,p=r.decimals,l=BigInt(t),d=a.totalFeeShare;if(c===a.asset1ID)s=a.asset2Reserves,o=a.asset1Reserves;else{if(c!==a.asset2ID)throw new E(_.AssetDoesNotBelongToPoolError,"Output asset (#".concat(c,") doesn't belong to the pool ").concat(a.account.address(),"."));s=a.asset1Reserves,o=a.asset2Reserves}var f=function(e){var t=e.inputSupply,n=e.outputSupply,r=e.swapOutputAmount,a=e.totalFeeShare,s=e.decimals,o=function(e){var t=e.inputSupply,n=e.outputSupply,r=e.outputAmount,a=t*n,s=BigInt(a/(n-r))-t;return s+=BigInt(1),s}({inputSupply:t,outputSupply:n,outputAmount:r}),i=function(e){var t=e.swapAmount,n=e.totalFeeShare,r=Math.floor(Number(t*BigInt(1e4)/(BigInt(1e4)-BigInt(n)))),a=BigInt(r)-t;return a}({swapAmount:o,totalFeeShare:a}),u=o+i,c=ut({inputSupply:t,outputSupply:n,assetIn:{amount:u,decimals:s.assetIn},assetOut:{amount:r,decimals:s.assetOut}});return{swapInputAmount:u,totalFeeAmount:i,priceImpact:c}}({inputSupply:s,outputSupply:o,swapOutputAmount:l,totalFeeShare:d,decimals:{assetIn:u,assetOut:p}}),m=f.swapInputAmount,h=f.totalFeeAmount,g=f.priceImpact;if(l>o)throw new E(_.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");if(st(Number(m)))throw new E(_.LowSwapAmountError,"Swap amount is too low.");return{type:tt.Direct,data:{pool:a,quote:{assetInID:i,assetInAmount:m,assetOutID:c,assetOutAmount:l,swapFee:Number(h),rate:fe(p,Number(l))/fe(u,Number(m)),priceImpact:g}}}}function gr(e){return Ar.apply(this,arguments)}function Ar(){return(Ar=i(s().mark((function e(t){var n,r,a,o,i,u,c,p;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.amount,r=t.assetIn,a=t.assetOut,o=t.isSwapRouterEnabled,i=t.network,u=t.pool,c=[],u?c.push(new Promise((function(e,t){try{var s=mr({amount:n,assetIn:r,assetOut:a,pool:u});e({type:tt.Direct,data:{pool:u,quote:s}})}catch(e){t(e)}}))):c.push(Promise.reject(new E(_.NoAvailablePoolError,"There is not an available pool for this asset pair"))),o&&c.push(Ze({amount:n,assetInID:r.id,assetOutID:a.id,swapType:Ne.FixedInput,network:i}).then((function(e){return{type:tt.Router,data:e}}))),e.next=6,fr(c);case 6:return p=e.sent,e.abrupt("return",ft(p));case 8:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function xr(e){return Ir.apply(this,arguments)}function Ir(){return(Ir=i(s().mark((function e(t){var n,r,a,o,i,u,c,p;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.amount,r=t.assetIn,a=t.assetOut,o=t.isSwapRouterEnabled,i=t.network,u=t.pool,c=[new Promise((function(e,t){try{e(hr({amount:n,assetIn:r,assetOut:a,pool:u}))}catch(e){t(e)}}))],o&&c.push(Ze({amount:n,assetInID:r.id,assetOutID:a.id,swapType:Ne.FixedOutput,network:i}).then((function(e){return{type:tt.Router,data:e}}))),e.next=5,fr(c);case 5:return p=e.sent,e.abrupt("return",ft(p));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function vr(e){var t=e.inputSupply,n=e.outputSupply,r=e.swapInputAmount,a=e.totalFeeShare,s=e.decimals,o=BigInt(function(e){var t=e.inputAmount,n=e.totalFeeShare;return Math.floor(Number(t*BigInt(n))/1e4)}({inputAmount:r,totalFeeShare:a})),i=function(e){var t=e.inputSupply,n=e.outputSupply,r=e.swapAmount,a=t*n,s=n-BigInt(a/(t+BigInt(r)));return s-=BigInt(1)}({inputSupply:t,outputSupply:n,swapAmount:r-o});return{swapOutputAmount:i,totalFeeAmount:o,priceImpact:ut({inputSupply:t,outputSupply:n,assetIn:{amount:r,decimals:s.assetIn},assetOut:{amount:i,decimals:s.assetOut}})}}var wr={getQuote:function(e){return dr.apply(this,arguments)},getFixedInputSwapQuote:gr,getFixedInputDirectSwapQuote:mr,getFixedOutputDirectSwapQuote:hr,getFixedOutputSwapQuote:xr,generateTxns:function(e){return pr.apply(this,arguments)},signTxns:function(e){var t=e.txGroup;return(0,e.initiatorSigner)([t])},execute:function(e){return lr.apply(this,arguments)},calculateFixedInputSwap:vr};function yr(e,t){var n,r,a=BigInt(e),s=t.issuedLiquidity;return s>a+BigInt(Bt)?(n=a*t.asset1/s,r=a*t.asset2/s):(n=t.asset1,r=t.asset2),{asset1OutputAmount:n,asset2OutputAmount:r}}function br(){return(br=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.pool,o=n.poolTokenIn,i=n.initiatorAddr,u=n.minAsset1Amount,c=n.minAsset2Amount,p=n.slippage,t.next=3,r.getTransactionParams().do();case 3:if(l=t.sent,d=a.account.address(),f=a.poolTokenID){t.next=8;break}throw new Error("Pool token asset ID is missing");case 8:return m=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:i,to:d,assetIndex:f,amount:o,suggestedParams:l}),(h=e.makeApplicationNoOpTxnFromObject({from:i,appIndex:a.validatorAppID,note:Te.getAppCallTxnNoteWithClientName(U.V2),appArgs:[ar,e.encodeUint64(de("negative",p,u)),e.encodeUint64(de("negative",p,c))],accounts:[d],foreignAssets:[a.asset1ID,a.asset2ID],suggestedParams:l})).fee=(rr+1)*e.ALGORAND_MIN_TX_FEE,(g=[])[sr.ASSET_TRANSFER_TXN]=m,g[sr.APP_CALL_TXN]=h,A=e.assignGroupID(g),t.abrupt("return",[{txn:A[sr.ASSET_TRANSFER_TXN],signers:[i]},{txn:A[sr.APP_CALL_TXN],signers:[i]}]);case 16:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Tr(){return(Tr=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w,y;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.pool,o=n.initiatorAddr,i=n.poolTokenIn,u=n.outputAssetId,c=n.minOutputAssetAmount,p=n.slippage,t.next=3,r.getTransactionParams().do();case 3:if(l=t.sent,d=a.asset1ID,f=a.asset2ID,m=a.account.address(),h=a.poolTokenID){t.next=9;break}throw new Error("Pool token asset ID is missing");case 9:if(g=0,A=0,x=de("negative",p,c),u!==d){t.next=17;break}g=x,A=0,t.next=23;break;case 17:if(u!==f){t.next=22;break}g=0,A=x,t.next=23;break;case 22:throw new Error("Invalid output asset id. It doesn't match with pool assets");case 23:return I=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:o,to:m,assetIndex:h,amount:i,suggestedParams:l}),(v=e.makeApplicationNoOpTxnFromObject({from:o,appIndex:a.validatorAppID,note:Te.getAppCallTxnNoteWithClientName(U.V2),appArgs:[ar,e.encodeUint64(g),e.encodeUint64(A)],accounts:[m],foreignAssets:[u],suggestedParams:l})).fee=(rr+1)*e.ALGORAND_MIN_TX_FEE,(w=[])[sr.ASSET_TRANSFER_TXN]=I,w[sr.APP_CALL_TXN]=v,y=e.assignGroupID(w),t.abrupt("return",[{txn:y[sr.ASSET_TRANSFER_TXN],signers:[o]},{txn:y[sr.APP_CALL_TXN],signers:[o]}]);case 31:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function kr(){return(kr=i(s().mark((function e(t){var n,r,a,o,i,u,c;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.txGroup,a=t.signedTxns,e.next=3,Ae(n,[a]);case 3:return o=e.sent,i=v(o,1),u=i[0].txnID,e.prev=6,e.next=9,fn(n,r);case 9:c=e.sent,e.next=14;break;case 12:e.prev=12,e.t0=e.catch(6);case 14:return e.abrupt("return",{outputAssets:c,txnID:u});case 15:case"end":return e.stop()}}),e,null,[[6,12]])})))).apply(this,arguments)}var _r,Er={getQuote:function(e){var t=e.pool,n=e.reserves,r=e.poolTokenIn,a=BigInt(r),s=yr(a,n),o=s.asset1OutputAmount,i=s.asset2OutputAmount;return{round:n.round,asset1Out:{assetId:t.asset1ID,amount:o},asset2Out:{assetId:t.asset2ID,amount:i},poolTokenIn:{assetId:t.poolTokenID,amount:a}}},getSingleAssetRemoveLiquidityQuote:function(e){var t,n=e.pool,r=e.reserves,a=e.poolTokenIn,s=e.assetOutID,o=e.decimals,i=BigInt(a),u=yr(i,r),c=u.asset1OutputAmount,p=u.asset2OutputAmount,l=n.totalFeeShare;if(s===n.asset1ID){var d=wr.calculateFixedInputSwap({inputSupply:r.asset2-p,outputSupply:r.asset1-c,swapInputAmount:p,totalFeeShare:l,decimals:o}),f=d.swapOutputAmount,m=d.totalFeeAmount,h=d.priceImpact;t={round:r.round,assetOut:{assetId:s,amount:c+f},poolTokenIn:{assetId:n.poolTokenID,amount:i},internalSwapQuote:{amountIn:{assetId:n.asset2ID,amount:p},amountOut:{assetId:n.asset1ID,amount:f},swapFees:{assetId:n.asset2ID,amount:m},priceImpact:h}}}else{if(s!==n.asset2ID)throw new Error("assetOutID must be one of the pool assets");var g=wr.calculateFixedInputSwap({inputSupply:r.asset1-c,outputSupply:r.asset2-p,swapInputAmount:c,totalFeeShare:l,decimals:o}),A=g.swapOutputAmount,x=g.totalFeeAmount,I=g.priceImpact;t={round:r.round,assetOut:{assetId:s,amount:p+A},poolTokenIn:{assetId:n.poolTokenID,amount:i},internalSwapQuote:{amountIn:{assetId:n.asset2ID,amount:p},amountOut:{assetId:n.asset1ID,amount:A},swapFees:{assetId:n.asset2ID,amount:x},priceImpact:I}}}return t},generateTxns:function(e){return br.apply(this,arguments)},generateSingleAssetOutTxns:function(e){return Tr.apply(this,arguments)},signTxns:function(e){var t=e.txGroup;return(0,e.initiatorSigner)([t])},execute:function(e){return kr.apply(this,arguments)}},Pr=(l(_r={},U.V1_1,cr),l(_r,U.V2,Er),_r),Sr=3n,Dr=1000n,Or=function(e){return e[e.FEE_TXN_INDEX=0]="FEE_TXN_INDEX",e[e.VALIDATOR_APP_CALL_TXN_INDEX=1]="VALIDATOR_APP_CALL_TXN_INDEX",e[e.ASSET_IN_TXN_INDEX=2]="ASSET_IN_TXN_INDEX",e[e.ASSET_OUT_TXN_INDEX=3]="ASSET_OUT_TXN_INDEX",e}(Or||{});function Nr(){return(Nr=i(s().mark((function t(n){var r,a,o,i,u,c,p,l;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.pool,a=n.txGroup,o=n.initiatorSigner,t.next=3,o([a]);case 3:return i=t.sent,u=v(i,2),c=u[0],p=u[1],l=a.map((function(t,n){return n===Or.FEE_TXN_INDEX?c:n===Or.ASSET_IN_TXN_INDEX?p:e.signLogicSigTransactionObject(t.txn,r.account.lsig).blob})),t.abrupt("return",l);case 9:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Lr(){return(Lr=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w,y,b;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(r=n.client,a=n.quoteAndPool,o=n.swapType,i=n.slippage,u=n.initiatorAddr,c=a.pool,p=a.quote,l=p.assetInID,d=p.assetOutID,f=c.account.address(),(m=[c.asset1ID,c.asset2ID]).includes(l)&&m.includes(d)&&l!==d){t.next=7;break}throw new J({pool:c,quote:p},"Input asset (#".concat(l,") and output asset (#").concat(d,") provided to generate transactions do not belong to the pool ").concat(f,"."));case 7:return t.next=9,r.getTransactionParams().do();case 9:return h=t.sent,g=[ye("swap"),o===Ne.FixedInput?ye("fi"):ye("fo")],A=e.makeApplicationNoOpTxnFromObject({from:f,appIndex:c.validatorAppID,appArgs:g,accounts:[u],note:Te.getAppCallTxnNoteWithClientName(U.V1_1),foreignAssets:c.asset2ID==j?[c.asset1ID,c.poolTokenID]:[c.asset1ID,c.asset2ID,c.poolTokenID],suggestedParams:h}),x=o===Ne.FixedOutput?de("positive",i,p.assetInAmount):p.assetInAmount,I=l===j?e.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:f,amount:x,suggestedParams:h}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:u,to:f,assetIndex:l,amount:x,suggestedParams:h}),v=o===Ne.FixedInput?de("negative",i,p.assetOutAmount):p.assetOutAmount,w=d===j?e.makePaymentTxnWithSuggestedParamsFromObject({from:f,to:u,amount:v,suggestedParams:h}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:f,to:u,assetIndex:d,amount:v,suggestedParams:h}),y=e.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:f,amount:A.fee+w.fee,note:P,suggestedParams:h}),b=e.assignGroupID([y,A,I,w]),t.abrupt("return",[{txn:b[0],signers:[u]},{txn:b[1],signers:[f]},{txn:b[2],signers:[u]},{txn:b[3],signers:[f]}]);case 19:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Br(e){var t=e.pool,n=e.reserves,r=e.assetIn,s=e.decimals;if(t.status!==Nt.READY)throw new E(_.NoAvailablePoolError,"There is not an available pool for this asset pair");var o,i,u,c=BigInt(r.amount);if(r.id===t.asset1ID)o=t.asset2ID,i=n.asset1,u=n.asset2;else{if(r.id!==t.asset2ID)throw new E(_.AssetDoesNotBelongToPoolError,"Input asset (#".concat(r.id,") doesn't belong to the pool ").concat(t.account.address(),"."));o=t.asset1ID,i=n.asset2,u=n.asset1}var p=c*Sr/Dr,l=u-i*u/(i+(c-p));if(l>u)throw new E(_.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");var d={assetIn:{amount:c,decimals:s.assetIn},assetOut:{amount:l,decimals:s.assetOut}},f={round:n.round,assetInID:r.id,assetInAmount:c,assetOutID:o,assetOutAmount:l,swapFee:Number(p),rate:it(d),priceImpact:ut(a({inputSupply:i,outputSupply:u},d))};return{type:tt.Direct,data:{pool:t,quote:f}}}function Cr(e){return Fr.apply(this,arguments)}function Fr(){return(Fr=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m,h,g,A,x;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.pool,a=t.signedTxns,o=t.assetIn,i=t.assetOut,u=t.initiatorAddr,e.next=3,Pt({client:n,pool:r,accountAddr:u});case 3:return c=e.sent,e.next=6,Ae(n,[a]);case 6:return p=e.sent,l=v(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,e.next=13,Pt({client:n,pool:r,accountAddr:u});case 13:return h=e.sent,i.id===r.asset1ID?(g=c.excessAsset1,A=h.excessAsset1):(g=c.excessAsset2,A=h.excessAsset2),(x=A-g)<0n&&(x=0n),e.abrupt("return",{round:f,assetInID:o.id,assetInAmount:BigInt(o.amount),assetOutID:i.id,assetOutAmount:BigInt(i.amount)+x,excessAmount:{assetID:i.id,excessAmountForSwap:x,totalExcessAmount:A},txnID:m});case 18:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Rr(e){var t=e.pool,n=e.reserves,r=e.assetOut,a=e.decimals;if(t.status!==Nt.READY)throw new E(_.NoAvailablePoolError,"There is not an available pool for this asset pair");var s,o,i,u=BigInt(r.amount);if(r.id===t.asset1ID)s=t.asset2ID,o=n.asset2,i=n.asset1;else{if(r.id!==t.asset2ID)throw new E(_.AssetDoesNotBelongToPoolError,"Output asset (#".concat(r.id,") doesn't belong to the pool ").concat(t.account.address(),"."));s=t.asset1ID,o=n.asset1,i=n.asset2}if(u>i)throw new E(_.OutputAmountExceedsAvailableLiquidityError,"Output amount exceeds available liquidity.");var c=o*i/(i-u)-o,p=c*Dr/(Dr-Sr),l=p-c,d=fe(a.assetOut,Number(u))/fe(a.assetIn,Number(p)),f=fe(a.assetOut,Number(i))/fe(a.assetIn,Number(o)),m=me({decimalPlaces:5},Math.abs(d/f-1)),h={round:n.round,assetInID:s,assetInAmount:p,assetOutID:r.id,assetOutAmount:u,swapFee:Number(l),rate:d,priceImpact:m};return{type:tt.Direct,data:{pool:t,quote:h}}}function Mr(e){return Ur.apply(this,arguments)}function Ur(){return(Ur=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m,h,g,A,x;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.pool,a=t.signedTxns,o=t.assetIn,i=t.assetOut,u=t.initiatorAddr,e.next=3,Pt({client:n,pool:r,accountAddr:u});case 3:return c=e.sent,e.next=6,Ae(n,[a]);case 6:return p=e.sent,l=v(p,1),d=l[0],f=d.confirmedRound,m=d.txnID,e.next=13,Pt({client:n,pool:r,accountAddr:u});case 13:return h=e.sent,o.id===r.asset1ID?(g=c.excessAsset1,A=h.excessAsset1):(g=c.excessAsset2,A=h.excessAsset2),(x=A-g)<0n&&(x=0n),e.abrupt("return",{round:f,assetInID:o.id,assetInAmount:BigInt(o.amount)-x,assetOutID:i.id,assetOutAmount:BigInt(i.amount),excessAmount:{assetID:o.id,excessAmountForSwap:x,totalExcessAmount:A},txnID:m});case 18:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function jr(){return(jr=i(s().mark((function e(t){var n,r,o,i,u,c,p,l,d,f;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.client,r=t.pool,o=t.swapType,i=t.txGroup,u=t.signedTxns,c=t.initiatorAddr,r.status===Nt.READY){e.next=3;break}throw new J({pool:r,swapType:o,txGroup:i},"There is not an available pool for this asset pair");case 3:if(e.prev=3,p={id:i[Or.ASSET_IN_TXN_INDEX].txn.assetIndex||j,amount:i[Or.ASSET_IN_TXN_INDEX].txn.amount},l={id:i[Or.ASSET_OUT_TXN_INDEX].txn.assetIndex||j,amount:i[Or.ASSET_OUT_TXN_INDEX].txn.amount},o!==Ne.FixedInput){e.next=12;break}return e.next=9,Cr({client:n,pool:r,signedTxns:u,assetIn:p,assetOut:l,initiatorAddr:c});case 9:d=e.sent,e.next=15;break;case 12:return e.next=14,Mr({client:n,pool:r,signedTxns:u,assetIn:p,assetOut:l,initiatorAddr:c});case 14:d=e.sent;case 15:return e.abrupt("return",a(a({},d),{},{groupID:ve(i),fees:Ie(i)}));case 18:throw e.prev=18,e.t0=e.catch(3),"SlippageTolerance"===(f=new J(e.t0,"We encountered something unexpected while swapping. Try again later.")).type&&f.setMessage("The swap failed due to too much slippage in the price. Please adjust the slippage tolerance and try again."),f;case 23:case"end":return e.stop()}}),e,null,[[3,18]])})))).apply(this,arguments)}var Vr,Xr={getQuote:function(e,t,n,r,a){return e===Ne.FixedInput?Br({pool:t,reserves:n,assetIn:r,decimals:a}):Rr({pool:t,reserves:n,assetOut:r,decimals:a})},getFixedInputSwapQuote:Br,getFixedOutputSwapQuote:Rr,generateTxns:function(e){return Lr.apply(this,arguments)},signTxns:function(e){return Nr.apply(this,arguments)},execute:function(e){return jr.apply(this,arguments)},executeFixedOutputSwap:Mr};function Gr(e){return Promise.allSettled(e).then((function(e){if(e.every((function(e){return"rejected"===e.status}))){var t=v(e.map((function(e){return e.reason})),2),n=t[0],r=t[1];if(mt(n)&&!mt(r))throw n;throw r}return e.filter((function(e){return"fulfilled"===e.status&&e.value})).map((function(e){return e.value}))}))}function qr(){return(qr=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=t.amount,a=t.assetIn,o=t.assetOut,i=t.isSwapRouterEnabled,u=t.pools,c=[],(p=u.find((function(e){return e.info.contractVersion===U.V1_1})))?c.push(new Promise((function(e,t){try{e(Xr.getFixedInputSwapQuote({pool:p.info,assetIn:{amount:r,id:Number(a.id)},decimals:{assetIn:a.decimals,assetOut:o.decimals},reserves:p.reserves}))}catch(e){t(e)}}))):c.push(Promise.reject(new E(_.NoAvailablePoolError,"Trying to swap from non-existent pool"))),l=u.find((function(e){return e.info.contractVersion===U.V2})),c.push(wr.getFixedInputSwapQuote({amount:r,assetIn:{id:ee(a),decimals:a.decimals},assetOut:{id:ee(o),decimals:o.decimals},pool:null!==(n=null==l?void 0:l.info)&&void 0!==n?n:null,isSwapRouterEnabled:i,network:t.network})),e.next=8,Gr(c);case 8:return d=e.sent,e.abrupt("return",ft(d));case 10:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Qr(){return(Qr=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=t.amount,a=t.assetIn,o=t.assetOut,i=t.pools,u=t.isSwapRouterEnabled,c=[],(p=i.find((function(e){return e.info.contractVersion===U.V1_1})))?c.push(new Promise((function(e,t){try{e(Xr.getFixedOutputSwapQuote({pool:p.info,assetOut:{amount:r,id:Number(o.id)},decimals:{assetIn:a.decimals,assetOut:o.decimals},reserves:p.reserves}))}catch(e){t(e)}}))):c.push(Promise.reject(new E(_.NoAvailablePoolError,"Trying to swap from non-existent pool"))),l=i.find((function(e){return e.info.contractVersion===U.V2})),c.push(wr.getFixedOutputSwapQuote({amount:r,assetIn:{id:ee(a),decimals:a.decimals},assetOut:{id:ee(o),decimals:o.decimals},pool:null!==(n=null==l?void 0:l.info)&&void 0!==n?n:null,isSwapRouterEnabled:u,network:t.network})),e.next=8,Gr(c);case 8:return d=e.sent,e.abrupt("return",ft(d));case 10:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var Wr=(l(Vr={},U.V1_1,Xr),l(Vr,U.V2,wr),l(Vr,"getQuote",(function(e){var t=e.type;if(t===Ne.FixedInput)return function(e){return qr.apply(this,arguments)}(e);if(t===Ne.FixedOutput)return function(e){return Qr.apply(this,arguments)}(e);throw new E(_.InvalidSwapTypeError,"Invalid swap type")})),l(Vr,"generateTxns",(function(e){return e.quote.type===tt.Direct&<(e.quote)===U.V1_1?Xr.generateTxns(a(a({},e),{},{quoteAndPool:e.quote.data})):wr.generateTxns(e)})),l(Vr,"signTxns",(function(e){if(e.quote.type===tt.Direct&<(e.quote)===U.V1_1){var t=e.quote.data.pool;return Xr.signTxns(a(a({},e),{},{pool:t}))}return wr.signTxns(e)})),l(Vr,"execute",(function(e){return e.contractVersion===U.V1_1?Xr.execute(e):wr.execute(e)})),Vr);function zr(){return(zr=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.client,r=t.pool,a=t.txGroup,o=t.initiatorSigner,e.prev=1,e.next=4,Jr({txGroup:a,pool:r,initiatorSigner:o});case 4:return i=e.sent,e.next=7,Ae(n,[i]);case 7:return u=e.sent,c=v(u,1),p=c[0],l=p.txnID,d=p.confirmedRound,e.abrupt("return",{fees:Ie(a),confirmedRound:d,txnID:l,groupID:ve(a)});case 15:throw e.prev=15,e.t0=e.catch(1),new J(e.t0,"We encountered something unexpected while redeeming. Try again later.");case 18:case"end":return e.stop()}}),e,null,[[1,15]])})))).apply(this,arguments)}function Jr(e){return Yr.apply(this,arguments)}function Yr(){return(Yr=i(s().mark((function t(n){var r,a,o,i,u,c,p,l;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.txGroup,a=n.pool,o=n.initiatorSigner,t.next=3,o([r]);case 3:return i=t.sent,u=v(i,1),c=u[0],p=a.account.lsig,l=r.map((function(t,n){return 0===n?c:e.signLogicSigTransactionObject(t.txn,p).blob})),t.abrupt("return",l);case 9:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function Kr(){return Kr=i(s().mark((function t(n){var r,a,o,u,c,p;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.data,o=n.initiatorSigner,t.prev=1,u=a.map((function(e){var t=e.txGroup,n=e.pool;return{txns:t,txnFees:Ie(t),groupID:ve(t),lsig:n.account.lsig}})),t.next=5,o(u.map((function(e){return e.txns})));case 5:return c=t.sent,p=Promise.all(u.map((function(t,n){return new Promise(function(){var a=i(s().mark((function a(o,i){var u,p,l,d,f,m;return s().wrap((function(a){for(;;)switch(a.prev=a.next){case 0:return a.prev=0,u=t.txns.map((function(r,a){return 0===a?c[n]:e.signLogicSigTransactionObject(r.txn,t.lsig).blob})),a.next=4,Ae(r,[u]);case 4:p=a.sent,l=v(p,1),d=l[0],f=d.txnID,m=d.confirmedRound,o({fees:t.txnFees,groupID:t.groupID,txnID:f,confirmedRound:m}),a.next=15;break;case 12:a.prev=12,a.t0=a.catch(0),i(a.t0);case 15:case"end":return a.stop()}}),a,null,[[0,12]])})));return function(e,t){return a.apply(this,arguments)}}())}))),t.abrupt("return",p);case 10:throw t.prev=10,t.t0=t.catch(1),new J(t.t0,"We encountered something unexpected while redeeming. Try again later.");case 13:case"end":return t.stop()}}),t,null,[[1,10]])}))),Kr.apply(this,arguments)}function Hr(){return(Hr=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.pool,o=n.assetID,i=n.assetOut,u=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:return c=t.sent,p=a.account.address(),l=e.makeApplicationNoOpTxnFromObject({from:p,appIndex:a.validatorAppID,appArgs:[ye("redeem")],note:Te.getAppCallTxnNoteWithClientName(a.contractVersion),accounts:[u],foreignAssets:0==a.asset2ID?[a.asset1ID,a.poolTokenID]:[a.asset1ID,a.asset2ID,a.poolTokenID],suggestedParams:c}),d=0===o?e.makePaymentTxnWithSuggestedParamsFromObject({from:p,to:u,amount:BigInt(i),suggestedParams:c}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:p,to:u,assetIndex:o,amount:BigInt(i),suggestedParams:c}),f=e.makePaymentTxnWithSuggestedParamsFromObject({from:u,to:p,amount:l.fee+d.fee,note:P,suggestedParams:c}),m=e.assignGroupID([f,l,d]),t.abrupt("return",[{txn:m[0],signers:[u]},{txn:m[1],signers:[p]},{txn:m[2],signers:[p]}]);case 10:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function $r(e){var t,n={},r=T(e);try{for(r.s();!(t=r.n()).done;){var a=t.value,s=(new TextDecoder).decode(Buffer.from(a.key,"base64")),o=void 0;o=1===a.value.type?a.value.bytes:a.value.uint,n[s]=o}}catch(e){r.e(e)}finally{r.f()}return n}function Zr(e,t,n){return e*t/n}var ea=BigInt(31536e3),ta=BigInt(1e14),na=BigInt(1e16),ra={testnet:548587153,mainnet:1385499515},aa=14;function sa(e){return oa.apply(this,arguments)}function oa(){return(oa=i(s().mark((function t(n){var r,a,o,i,u;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.assetIDs,i=e.getApplicationAddress(ra[a]),t.next=4,Tt(r,i);case 4:return u=t.sent.assets.map((function(e){return e["asset-id"]})),t.abrupt("return",o.filter((function(e){return e!==j&&!u.includes(e)})));case 6:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function ia(){return(ia=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,y,b,T,k,_,E,P;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.network,o=n.poolAddress,i=n.poolTokenId,u=n.lendingManagerId,c=n.asset1In,p=n.asset2In,l=n.initiatorAddr,d=e.getApplicationAddress(ra[a]),t.next=4,r.getTransactionParams().do();case 4:return f=t.sent,m=[c,p].sort((function(e,t){return t.fAssetId-e.fAssetId})),h=v(m,2),g=h[0],A=h[1],x=Z(A.id),I=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:d,assetIndex:g.id,amount:g.amount,suggestedParams:f}),y=x?e.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:d,amount:A.amount,suggestedParams:f}):e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:l,to:d,assetIndex:A.id,amount:A.amount,suggestedParams:f}),(b=e.makeApplicationNoOpTxnFromObject({from:l,appIndex:ra[a],appArgs:[ye("add_liquidity"),e.decodeAddress(o).publicKey,e.encodeUint64(g.lendingAppId),e.encodeUint64(A.lendingAppId)],foreignAssets:[g.id,A.id,g.fAssetId,A.fAssetId],foreignApps:[g.lendingAppId,A.lendingAppId,u],accounts:[o],suggestedParams:f})).fee=e.ALGORAND_MIN_TX_FEE*(aa+1),T=_e(a,U.V2),k=e.makeApplicationNoOpTxnFromObject({from:l,appIndex:ra[a],appArgs:[ye("noop")],foreignAssets:[i],foreignApps:[T],accounts:[o],suggestedParams:f}),_=[I,y,b,k],t.next=16,sa({client:r,network:a,assetIDs:[g.id,A.id,g.fAssetId,A.fAssetId,i]});case 16:return(E=t.sent).length&&((P=[e.makePaymentTxnWithSuggestedParamsFromObject({from:l,to:d,amount:D*E.length,suggestedParams:f}),e.makeApplicationNoOpTxnFromObject({from:l,appIndex:ra[a],appArgs:[ye("asset_optin")].concat(w(E.map((function(t){return e.encodeUint64(t)})))),foreignAssets:w(E),suggestedParams:f})])[1].fee=(E.length+1)*e.ALGORAND_MIN_TX_FEE,_.unshift.apply(_,P)),t.abrupt("return",e.assignGroupID(_).map((function(e){return{txn:e,signers:[l]}})));case 19:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function ua(){return(ua=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.pool,o=n.poolTokenIn,i=n.initiatorAddr,u=n.asset1Out,c=n.asset2Out,p=n.lendingManagerId,l=n.network,d=e.getApplicationAddress(ra[l]),t.next=4,r.getTransactionParams().do();case 4:if(f=t.sent,m=a.account.address(),h=a.poolTokenID){t.next=9;break}throw new Error("Pool token asset ID is missing");case 9:return g=e.makeAssetTransferTxnWithSuggestedParamsFromObject({from:i,to:d,assetIndex:h,amount:o,suggestedParams:f}),(A=e.makeApplicationNoOpTxnFromObject({from:i,appIndex:ra[l],appArgs:[ye("remove_liquidity"),e.decodeAddress(m).publicKey,e.encodeUint64(u.lendingAppId),e.encodeUint64(c.lendingAppId)],accounts:[m],foreignAssets:[u.id,c.id,u.fAssetId,c.fAssetId],foreignApps:[u.lendingAppId,c.lendingAppId,p],suggestedParams:f})).fee=e.ALGORAND_MIN_TX_FEE*(aa+1),x=_e(l,U.V2),I=e.makeApplicationNoOpTxnFromObject({from:i,appIndex:ra[l],appArgs:[ye("noop")],accounts:[m],foreignAssets:[h,u.fAssetId,c.fAssetId],foreignApps:[x],suggestedParams:f}),v=e.assignGroupID([g,A,I]),t.abrupt("return",v.map((function(e){return{txn:e,signers:[i]}})));case 16:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function ca(e,t,n){var r=BigInt(Math.floor((new Date).getTime()/1e3)-function(e){return null!=e?e:Math.floor((new Date).getTime()/1e3)}(n));return Zr(e,na+t*r/ea,na)}function pa(){return(pa=i(s().mark((function e(t,n){var r,a,o,i,u,c,p,l;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.getApplicationByID(n).do();case 2:return r=e.sent,a=r.params["global-state"],o=$r(a),i=Number(Buffer.from(o.pm,"base64").readBigUInt64BE(0)),u=Buffer.from(o.i,"base64"),c=u.readBigUInt64BE(32),p=u.readBigUInt64BE(40),l=Number(u.readBigUInt64BE(48)),e.abrupt("return",{appId:n,managerAppId:i,depositInterestRate:c,depositInterestIndex:p,lastUpdate:l});case 11:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var la={AddLiquidity:Object.freeze({__proto__:null,generateTxns:function(e){return ia.apply(this,arguments)},getAddLiquidityTotalFee:function(t){return e.ALGORAND_MIN_TX_FEE*(4+aa)+(t?(t+1)*e.ALGORAND_MIN_TX_FEE+t*D:0)}}),RemoveLiquidity:Object.freeze({__proto__:null,generateTxns:function(e){return ua.apply(this,arguments)},getRemoveLiquidityTotalFee:function(){return e.ALGORAND_MIN_TX_FEE*(3+aa)}}),calculateWithdrawReturn:function(e){var t=e.withdrawAmount,n=ca(e.depositInterestIndex,e.depositInterestRate,e.lastUpdate);return Zr(BigInt(t),n,ta)},calculateDepositReturn:function(e){var t=e.depositAmount,n=ca(e.depositInterestIndex,e.depositInterestRate,e.lastUpdate);return BigInt(t)*ta/n},getFolksWrapperAppOptInRequiredAssetIDs:sa};function da(t){var n=t.suggestedParams,r=t.stakingAppID,a=t.initiatorAddr,s=t.liquidityAssetID,o=t.program,i=t.amount,u=e.encodeUint64(i),c=e.encodeUint64(o.id);return e.makeApplicationNoOpTxnFromObject({appIndex:r,from:a,suggestedParams:n,foreignAssets:[s],accounts:[o.accountAddress],appArgs:[ye("commit"),u],note:ne([ye("tinymanStaking/v1:b"),c,e.encodeUint64(s),u])})}function fa(){return(fa=i(s().mark((function t(n){var r,a,o,i,u,c,p,l,d,f,m;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return r=n.client,a=n.stakingAppID,o=n.program,i=n.requiredAssetID,u=n.liquidityAssetID,c=n.amount,p=n.initiatorAddr,t.next=3,r.getTransactionParams().do();case 3:if(l=t.sent,d=da({suggestedParams:l,stakingAppID:a,program:o,liquidityAssetID:u,initiatorAddr:p,amount:c}),f=[d],"number"!=typeof i){t.next=10;break}return m=e.makeApplicationNoOpTxnFromObject({appIndex:a,from:p,suggestedParams:l,foreignAssets:[i],accounts:[o.accountAddress],appArgs:[ye("log_balance")]}),f=e.assignGroupID([d,m]),t.abrupt("return",[{txn:f[0],signers:[p]},{txn:f[1],signers:[p]}]);case 10:return t.abrupt("return",[{txn:f[0],signers:[p]}]);case 11:case"end":return t.stop()}}),t)})))).apply(this,arguments)}function ma(e){if(e instanceof Uint8Array&&"Uint8Array"===e.constructor.name)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Unknown type, must be binary type")}var ha=function(e,t){if(e.length>=255)throw new TypeError("Alphabet too long");for(var n=new Uint8Array(256),r=0;r>>0,o=new Uint8Array(s);e[t];){var p=n[e.charCodeAt(t)];if(255===p)return;for(var l=0,d=s-1;(0!==p||l>>0,o[d]=p%256>>>0,p=p/256>>>0;if(0!==p)throw new Error("Non-zero carry");a=l,t++}if(" "!==e[t]){for(var f=s-a;f!==s&&0===o[f];)f++;for(var m=new Uint8Array(r+(s-f)),h=r;f!==s;)m[h++]=o[f++];return m}}}return{encode:function(t){if(t instanceof Uint8Array||(ArrayBuffer.isView(t)?t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength):Array.isArray(t)&&(t=Uint8Array.from(t))),!(t instanceof Uint8Array))throw new TypeError("Expected Uint8Array");if(0===t.length)return"";for(var n=0,r=0,a=0,s=t.length;a!==s&&0===t[a];)a++,n++;for(var o=(s-a)*p+1>>>0,c=new Uint8Array(o);a!==s;){for(var l=t[a],d=0,f=o-1;(0!==l||d>>0,c[f]=l%i>>>0,l=l/i>>>0;if(0!==l)throw new Error("Non-zero carry");r=d,a++}for(var m=o-r;m!==o&&0===c[m];)m++;for(var h=u.repeat(n);mma(a(e))})}function Ta({name:e,prefix:t,bitsPerChar:n,alphabet:r}){return ya({prefix:t,name:e,encode:e=>function(e,t,n){const r="="===t[t.length-1],a=(1<n;)o-=n,s+=t[a&i>>o];if(0!==o&&(s+=t[a&i<function(e,t,n,r){const a={};for(let e=0;e=8&&(i-=8,o[c++]=255&u>>i)}if(i>=n||0!=(255&u<<8-i))throw new SyntaxError("Unexpected end of data");return o}(t,r,n,e)})}const ka=Ta({prefix:"b",name:"base32",alphabet:"abcdefghijklmnopqrstuvwxyz234567",bitsPerChar:5});Ta({prefix:"B",name:"base32upper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",bitsPerChar:5}),Ta({prefix:"c",name:"base32pad",alphabet:"abcdefghijklmnopqrstuvwxyz234567=",bitsPerChar:5}),Ta({prefix:"C",name:"base32padupper",alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",bitsPerChar:5}),Ta({prefix:"v",name:"base32hex",alphabet:"0123456789abcdefghijklmnopqrstuv",bitsPerChar:5}),Ta({prefix:"V",name:"base32hexupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV",bitsPerChar:5}),Ta({prefix:"t",name:"base32hexpad",alphabet:"0123456789abcdefghijklmnopqrstuv=",bitsPerChar:5}),Ta({prefix:"T",name:"base32hexpadupper",alphabet:"0123456789ABCDEFGHIJKLMNOPQRSTUV=",bitsPerChar:5}),Ta({prefix:"h",name:"base32z",alphabet:"ybndrfg8ejkmcpqxot1uwisza345h769",bitsPerChar:5});const _a=ba({name:"base58btc",prefix:"z",alphabet:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"});ba({name:"base58flickr",prefix:"Z",alphabet:"123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"});var Ea=function e(t,n,r){n=n||[];var a=r=r||0;for(;t>=Da;)n[r++]=255&t|Pa,t/=128;for(;t&Sa;)n[r++]=255&t|Pa,t>>>=7;return n[r]=0|t,e.bytes=r-a+1,n},Pa=128,Sa=-128,Da=Math.pow(2,31);var Oa=function e(t,n){var r,a=0,s=0,o=n=n||0,i=t.length;do{if(o>=i)throw e.bytes=0,new RangeError("Could not decode varint");r=t[o++],a+=s<28?(r&La)<=Na);return e.bytes=o-n,a},Na=128,La=127;var Ba=Math.pow(2,7),Ca=Math.pow(2,14),Fa=Math.pow(2,21),Ra=Math.pow(2,28),Ma=Math.pow(2,35),Ua=Math.pow(2,42),ja=Math.pow(2,49),Va=Math.pow(2,56),Xa=Math.pow(2,63),Ga={encode:Ea,decode:Oa,encodingLength:function(e){return e{const[n,r]=qa(e.subarray(t));return t+=r,n};let r=n(),a=Za;if(18===r?(r=0,t=0):a=n(),0!==r&&1!==r)throw new RangeError(`Invalid CID version ${r}`);const s=t,o=n(),i=n(),u=t+i;return{version:r,codec:a,multihashCode:o,digestSize:i,multihashSize:u-s,size:u}}static parse(e,t){const[n,r]=function(e,t){switch(e[0]){case"Q":{const n=t??_a;return[_a.prefix,n.decode(`${_a.prefix}${e}`)]}case _a.prefix:{const n=t??_a;return[_a.prefix,n.decode(e)]}case ka.prefix:{const n=t??ka;return[ka.prefix,n.decode(e)]}default:if(null==t)throw Error("To parse non base32 or base58btc encoded CID multibase decoder must be provided");return[e[0],t.decode(e)]}}(e,t),a=$a.decode(r);if(0===a.version&&"Q"!==e[0])throw Error("Version 0 CID string must not include multibase prefix");return Ha(a).set(n,e),a}}const Za=112,es=18;function ts(e,t,n){const r=Wa(e),a=r+Wa(t),s=new Uint8Array(a+n.byteLength);return Qa(e,s,0),Qa(t,s,r),s.set(n,a),s}const ns=Symbol.for("@ipld/js-cid/CID");class rs{name;code;encode;constructor(e,t,n){this.name=e,this.code=t,this.encode=n}digest(e){if(e instanceof Uint8Array){const t=this.encode(e);return t instanceof Uint8Array?za(this.code,t):t.then((e=>za(this.code,e)))}throw Error("Unknown type, must be binary type")}}const as=function({name:e,code:t,encode:n}){return new rs(e,t,n)}({name:"sha2-256",code:18,encode:e=>ma(n.createHash("sha256").update(e).digest())}),ss=85;var os=604800,is={testnet:480164661,mainnet:2200606875},us={testnet:360907790,mainnet:2200609638},cs={testnet:336189106,mainnet:2200608153},ps={testnet:383416252,mainnet:2200608887},ls=2500,ds=400,fs=604800,ms=126144e3,hs=1e7,gs=Math.pow(2,64),As=48,xs=21,Is=48,vs=ye("tp"),ws=ye("sc"),ys=28100,bs=12900,Ts=421700,ks=409700;function _s(e){return Math.floor(e/fs)*fs}function Es(e,t){if(e>t)throw new Error("Old timestamp must be less than or equal to new timestamp");for(var n=[],r=_s(e)+fs;re?r=t?e*e*gs/(2*t):0:r=(e+(e-r))*n/2;return r}function Bs(e,t){return Cs.apply(this,arguments)}function Cs(){return(Cs=i(s().mark((function e(t,n){var r;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,t.getApplicationByID(n).do();case 2:return r=e.sent,e.abrupt("return",Fs(r));case 4:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Fs(e){var t,n={},r=T(e.params["global-state"]);try{for(r.s();!(t=r.n()).done;){var a=t.value,s=Buffer.from(a.key,"base64").toString(),o=void 0;o=1===a.value.type?Buffer.from(a.value.bytes||"","base64"):a.value.uint||0,n[s]=o}}catch(e){r.e(e)}finally{r.f()}return n}function Rs(){for(var e=arguments.length,t=new Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:8,n=new Uint8Array(t),r=e,a=t-1;a>=0;a--)n[a]=255&r,r>>=8;return n}function Gs(e,t){return 0===Buffer.compare(e,t)}function qs(e){for(var t=0,n=0;n0?xs-e:0}},{key:"lastAccountPowerBoxIndex",get:function(){return eo(this.powerCount)[0]}},{key:"lastAccountPowerArrayIndex",get:function(){return eo(this.powerCount)[1]}}]),e}(),Ws=function(){function e(t,n,r,a){u(this,e),this.bias=t,this.timestamp=n,this.slope=r,this.cumulativePower=a}return p(e,[{key:"lockEndTimestamp",get:function(){var e=this.bias*Math.pow(2,64)/this.slope;return this.timestamp+e}},{key:"cumulativePowerAt",value:function(e){var t=e-this.timestamp;if(t<0)throw new Error("Time delta must be greater than or equal to 0");return this.cumulativePower+Ls(this.bias,this.slope,t)}}]),e}(),zs=p((function e(t,n,r,a){u(this,e),this.bias=t,this.timestamp=n,this.slope=r,this.cumulativePower=a})),Js=p((function e(t){u(this,e),this.slopeDelta=t})),Ys=function(){function e(t,n,r,a){u(this,e),this.tinyAssetId=t,this.totalLockedAmount=n,this.totalPowerCount=r,this.lastTotalPowerTimestamp=a}return p(e,[{key:"freeTotalPowerSpaceCount",get:function(){var e=this.totalPowerCount%xs;return e>0?xs-e:0}},{key:"lastTotalPowerBoxIndex",get:function(){return eo(this.totalPowerCount)[0]}},{key:"lastTotalPowerArrayIndex",get:function(){return eo(this.totalPowerCount)[1]}}]),e}();function Ks(){return(Ks=i(s().mark((function e(t,n,r){var a,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=$s(r),e.prev=1,e.next=4,Ps(t,n,a);case 4:if(!(o=e.sent)){e.next=7;break}return e.abrupt("return",Hs(o));case 7:return e.abrupt("return",null);case 10:return e.prev=10,e.t0=e.catch(1),console.log(e.t0),e.abrupt("return",null);case 14:case"end":return e.stop()}}),e,null,[[1,10]])})))).apply(this,arguments)}function Hs(e){var t=Buffer.from(e);return new Qs(t.readUIntBE(0,8),t.readUIntBE(8,8),t.readUIntBE(16,8),t.readUIntBE(24,8))}function $s(t){return e.decodeAddress(t).publicKey}function Zs(e){var t=Xs(e),n=new Uint8Array(vs.length+t.length);return n.set(vs,0),n.set(t,vs.length),n}function eo(e){var t=e-1;return[Math.floor(t/xs),t%xs]}function to(t,n){var r=e.decodeAddress(t).publicKey,a=Xs(n),s=new Uint8Array(r.length+a.length);return s.set(r,0),s.set(a,r.length),s}function no(e,t,n){return ro.apply(this,arguments)}function ro(){return(ro=i(s().mark((function e(t,n,r){var a,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=so(r),e.next=3,Ps(t,n,a);case 3:if(o=e.sent){e.next=6;break}return e.abrupt("return",null);case 6:return e.abrupt("return",ao(o));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function ao(t){return new Js(Number(e.bytesToBigInt(t.slice(t.length-16,t.length))))}function so(e){return Rs(ws,Xs(e))}function oo(e,t,n,r){return io.apply(this,arguments)}function io(){return(io=i(s().mark((function e(t,n,r,a){var o,i,u,c,p;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=0,r&&(o=Math.ceil(r/xs)),i=[],u=0;case 4:if(!(u4?d[4]:void 0,i=0,(a=d.length>3&&void 0!==d[3]?d[3]:null)&&(i=Math.ceil(a/xs)),u=[],c=0;case 6:if(!(c=e[r].timestamp))break;n=r}return n}function fo(e){for(var t,n=As,r=[],a=0;ai.freeTotalPowerSpaceCount&&(b+=ks),c||(b+=bs);var k=[e.makeAssetTransferTxnWithSuggestedParamsFromObject({amount:a,assetIndex:G[s],from:o,suggestedParams:u,to:e.getApplicationAddress(l)}),e.makeApplicationNoOpTxnFromObject({appIndex:l,from:o,suggestedParams:u,appArgs:[ye("create_lock"),Xs(r)],boxes:d.slice(0,8),note:p}),wo({sender:o,suggestedParams:u,index:l,boxes:d.slice(8)})];if(b){var _=e.makePaymentTxnWithSuggestedParamsFromObject({amount:b,from:o,suggestedParams:u,to:e.getApplicationAddress(l)});k.unshift(_)}return e.assignGroupID(k)}function bo(t){var n=t.accountState,r=t.lockedAmount,a=t.network,s=t.sender,o=t.vaultAppGlobalState,i=t.suggestedParams,u=t.appCallNote;if(ro.freeTotalPowerSpaceCount&&(v+=ks),!n.freeAccountPowerSpaceCount){var w=to(s,n.lastAccountPowerBoxIndex+1);h.push({appIndex:is[a],name:w}),v+=Ts}var y=[e.makeAssetTransferTxnWithSuggestedParamsFromObject({assetIndex:G[a],from:s,to:e.getApplicationAddress(is[a]),amount:r,suggestedParams:i}),e.makeApplicationNoOpTxnFromObject({appIndex:is[a],from:s,suggestedParams:i,appArgs:[ye("increase_lock_amount")],boxes:h,note:u}),wo({sender:s,suggestedParams:i,index:is[a]})];if(v){var b=e.makePaymentTxnWithSuggestedParamsFromObject({from:s,suggestedParams:i,to:e.getApplicationAddress(is[a]),amount:v});y.unshift(b)}return e.assignGroupID(y)}function To(t){var n=t.accountState,r=t.network,a=t.newLockEndTime,s=t.slopeChangeAtNewLockEndTime,o=t.sender,i=t.vaultAppGlobalState,u=t.suggestedParams,c=t.appCallNote;if(a%fs)throw new Error("Invalid lock end time");if(a<=n.lockEndTime)throw new Error("New lock end time must be greater than current lock end time");var p=$s(o),l=to(o,n.lastAccountPowerBoxIndex),d=Zs(i.lastTotalPowerBoxIndex),f=Zs(i.lastTotalPowerBoxIndex+1),m=so(n.lockEndTime),h=so(a),g=[{appIndex:is[r],name:p},{appIndex:is[r],name:l},{appIndex:is[r],name:d},{appIndex:is[r],name:f},{appIndex:is[r],name:m},{appIndex:is[r],name:h}];if(!n.freeAccountPowerSpaceCount){var A=to(o,n.lastAccountPowerBoxIndex+1);g.push({appIndex:is[r],name:A})}var x,I=Es(i.lastTotalPowerTimestamp,Math.floor(Date.now()/1e3)),v=I.length,w=T(I);try{for(w.s();!(x=w.n()).done;){var y=x.value;if(y%fs==0){var b=so(y);g.push({appIndex:is[r],name:b})}}}catch(e){w.e(e)}finally{w.f()}var k=0;s||(k+=bs),n.freeAccountPowerSpaceCount||(k+=Ts),v>i.freeTotalPowerSpaceCount&&(k+=ks);var _=[e.makeApplicationNoOpTxnFromObject({appIndex:is[r],from:o,suggestedParams:u,appArgs:[ye("extend_lock_end_time"),Xs(a)],boxes:g.slice(0,8),note:c}),wo({sender:o,suggestedParams:u,index:is[r],boxes:g.slice(8)})];if(k){var E=e.makePaymentTxnWithSuggestedParamsFromObject({from:o,suggestedParams:u,to:e.getApplicationAddress(is[r]),amount:k});_.unshift(E)}return e.assignGroupID(_)}function ko(t){var n=t.accountState,r=t.network,a=t.sender,s=t.suggestedParams,o=t.appCallNote,i=$s(a),u=to(a,n.lastAccountPowerBoxIndex),c=to(a,n.lastAccountPowerBoxIndex+1),p=[{appIndex:is[r],name:i},{appIndex:is[r],name:u},{appIndex:is[r],name:c}],l=e.makeApplicationNoOpTxnFromObject({appIndex:is[r],from:a,suggestedParams:s,appArgs:[ye("withdraw")],foreignAssets:[G[r]],boxes:p,note:o});l.fee*=2;var d=[l];if(!n.freeAccountPowerSpaceCount){var f=e.makePaymentTxnWithSuggestedParamsFromObject({from:a,suggestedParams:s,to:e.getApplicationAddress(is[r]),amount:Ts});d.unshift(f)}return e.assignGroupID(d)}var _o=8,Eo=ye("p"),Po=ye("a"),So=ye("v"),Do=28500,Oo=12500,No=ye("p"),Lo=ye("a"),Bo=24,Co=111300,Fo=ls+ds*(41+Bo),Ro=function(e){return e[e.Against=0]="Against",e[e.For=1]="For",e[e.Abstain=2]="Abstain",e}(Ro||{}),Mo=new Uint8Array(34),Uo="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ",jo=function(){function e(t,n,r,a,s,o,i,c,p,l,d,f,m,h,g,A,x){u(this,e),this.index=t,this.creationTimestamp=n,this.votingStartTimestamp=r,this.votingEndTimestamp=a,this.snapshotTotalVotingPower=s,this.voteCount=o,this.quorumNumerator=i,this.againstVotingPower=c,this.forVotingPower=p,this.abstainVotingPower=l,this.isApproved=d,this.isCancelled=f,this.isExecuted=m,this.isQuorumReached=h,this.proposerAddress=g,this.executionHash=A,this.executorAddress=x}return p(e,[{key:"snapshotTimestamp",get:function(){return this.creationTimestamp}}]),e}(),Vo=p((function e(t,n,r,a,s,o,i,c,p,l){u(this,e),this.vaultAppId=t,this.proposalIndexCounter=n,this.votingDelay=r,this.votingDuration=a,this.proposalThreshold=s,this.proposalThresholdNumerator=o,this.quorumThreshold=i,this.approvalRequirement=c,this.manager=p,this.proposalManager=l}));function Xo(e){return Rs(No,ye(e))}function Go(t){var n=Buffer.from(t);return new jo(n.readUIntBE(0,8),n.readUIntBE(8,8),n.readUIntBE(16,8),n.readUIntBE(24,8),n.readUIntBE(32,8),n.readUIntBE(40,8),n.readUIntBE(48,8),n.readUIntBE(56,8),n.readUIntBE(64,8),n.readUIntBE(72,8),Boolean(n.readUIntBE(80,1)),Boolean(n.readUIntBE(81,1)),Boolean(n.readUIntBE(82,1)),Boolean(n.readUIntBE(83,1)),e.encodeAddress(n.subarray(84,116)),t.slice(116,150).toString(),e.encodeAddress(n.subarray(150,182)))}function qo(){return(qo=i(s().mark((function e(t,n,r){var a,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=Xo(r),e.next=3,Ps(t,n,a);case 3:if(o=e.sent){e.next=6;break}return e.abrupt("return",null);case 6:return e.abrupt("return",Go(o));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}var Qo=p((function e(t,n,r,a,s,o,i){u(this,e),this.index=t,this.creationTimestamp=n,this.votingStartTimestamp=r,this.votingEndTimestamp=a,this.votingPower=s,this.voteCount=o,this.isCancelled=i}));function Wo(t,n){return Rs(Po,e.decodeAddress(t).publicKey,Xs(n))}function zo(e){return new Qo(qs(e.slice(0,8)),qs(e.slice(8,16)),qs(e.slice(16,24)),qs(e.slice(24,32)),qs(e.slice(32,40)),qs(e.slice(40,48)),Boolean(qs(e.slice(48,49))))}function Jo(){return(Jo=i(s().mark((function e(t,n,r){var a,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=Xo(r),e.next=3,Ps(t,n,a);case 3:if(o=e.sent){e.next=6;break}return e.abrupt("return",null);case 6:return e.abrupt("return",zo(o));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function Yo(t){var n=t.stakingVotingAppId,r=t.vaultAppId,a=t.sender,s=t.proposalId,o=t.proposal,i=t.votes,u=t.assetIds,c=t.accountPowerIndex,p=t.appBoxNames,l=t.suggestedParams,d=t.appCallNote,f=void 0===d?null:d;if(i.length!==u.length)throw new Error("The number of votes must be equal to the number of asset ids");if(u.length>_o)throw new Error("You cannot cast vote for more than ".concat(_o," different pools"));if(100!==i.reduce((function(e,t){return e+t}),0))throw new Error("The sum of the votes must equal 100%");var m,h=Rs.apply(void 0,w(i.map((function(e){return Xs(e)})))),g=Rs.apply(void 0,w(u.map((function(e){return Xs(e)})))),A=function(e){return Rs(Eo,ye(e))}(s),x=Wo(a,Math.floor(o.index/8192)),I=!p.some((function(e){return Gs(e,x)})),v=$s(a),y=Math.floor(c/xs),b=to(a,y),k=to(a,y+1),_=0,E=[],P=T(u);try{var S=function(){var e=m.value,t=function(e,t){return Rs(So,Xs(e),Xs(t))}(o.index,e);E.push({appIndex:n,name:t}),p.some((function(e){return Gs(e,t)}))||(_+=1)};for(P.s();!(m=P.n()).done;)S()}catch(e){P.e(e)}finally{P.f()}var D=[{appIndex:n,name:A},{appIndex:n,name:x}].concat(E,[{appIndex:r,name:v},{appIndex:r,name:b},{appIndex:r,name:k}]),O=[e.makeApplicationNoOpTxnFromObject({from:a,suggestedParams:l,appIndex:n,appArgs:[ye("cast_vote"),ye(s),h,g,Xs(c)],foreignApps:[r],boxes:D.slice(0,7),note:f?ye(f):void 0})];O[0].fee*=2,D.length>=7&&O.push(wo({sender:a,suggestedParams:l,index:r,foreignApps:[n],boxes:D.slice(7,14)})),D.length>=14&&O.push(wo({sender:a,suggestedParams:l,index:r,foreignApps:[n],boxes:D.slice(14)}));var N=Number(I)*Do+_*Oo;return N&&(O=[e.makePaymentTxnWithSuggestedParamsFromObject({from:a,suggestedParams:l,to:e.getApplicationAddress(n),amount:N})].concat(w(O))),e.assignGroupID(O)}var Ko=ye("rp"),Ho=1012,$o=ye("c"),Zo=42,ei=ls+ds*(41+Ho),ti=p((function e(t,n,r,a,s,o,i){u(this,e),this.tinyAssetId=t,this.vaultAppId=n,this.rewardHistoryCount=r,this.firstPeriodTimestamp=a,this.rewardPeriodCount=s,this.manager=o,this.rewardsManager=i})),ni=p((function e(t){u(this,e),this.value=t}));function ri(t,n){var r=e.decodeAddress(t).publicKey,a=Xs(n),s=new Uint8Array($o.length+r.length+a.length);return s.set($o,0),s.set(r,$o.length),s.set(a,$o.length+r.length),s}function ai(e,t,n,r){return si.apply(this,arguments)}function si(){return(si=i(s().mark((function e(t,n,r,a){var o,i;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return o=ri(r,a),e.next=3,Ps(t,n,o);case 3:if(i=e.sent){e.next=6;break}return e.abrupt("return",null);case 6:return e.abrupt("return",new ni(i));case 7:case"end":return e.stop()}}),e)})))).apply(this,arguments)}function oi(t){for(var n=t.rewardsAppId,r=t.vaultAppId,a=t.tinyAssetId,s=t.sender,o=t.periodIndexStart,i=t.periodCount,u=t.accountPowerIndexes,c=t.suggestedParams,p=t.createRewardClaimSheet,l=t.appCallNote,d=[],f=[],m=[],h=[],g=function(){var e,t,r=Math.floor(A/Zo),a=(e=Xs(r),(t=new Uint8Array(Ko.length+e.length)).set(Ko,0),t.set(e,Ko.length),t);f.find((function(e){return e.name.toString()===a.toString()}))||f.push({appIndex:n,name:a});var o=Math.floor(A/(8*Ho)),i=ri(s,o);m.find((function(e){return e.name.toString()===i.toString()}))||m.push({appIndex:n,name:i})},A=o;A=11)throw new Error("Boxes' length cannot be larger than 10");var y=d.slice(0,6),b=[e.makeApplicationNoOpTxnFromObject({from:s,suggestedParams:c,appIndex:n,appArgs:[ye("claim_rewards"),Xs(o),Xs(i),Rs.apply(void 0,w(u.map((function(e){return Xs(e)}))))],foreignApps:[r],foreignAssets:[a],boxes:y,note:l?ye(l):void 0})];b[0].fee=b[0].fee*(i+2);var k=0,_=92+865*i,E=700+700*i;if(_>E&&(k=Math.floor((_-E)/666)+1),k||d.length>6){var P=d.slice(6),S=wo({sender:s,suggestedParams:c,extraAppArgs:[Xs(Math.max(k-1,0))],index:n,foreignApps:[r],boxes:P});S.fee*=Math.max(k,1),b.unshift(S)}if(p){var D=e.makePaymentTxnWithSuggestedParamsFromObject({from:s,to:e.getApplicationAddress(n),amount:ei,suggestedParams:c});b.unshift(D)}return e.assignGroupID(b)}function ii(t){var n=t.proposalId,r=t.proposalVotingAppId,a=t.sender,s=t.vaultAppId,o=t.vaultAppGlobalState,i=t.executionHash,u=t.executor,c=t.suggestedParams,p=t.appCallNote,l=Xo(n),d=$s(a),f=Zs(o.lastTotalPowerBoxIndex),m=[e.makePaymentTxnWithSuggestedParamsFromObject({from:a,to:e.getApplicationAddress(r),amount:Co,suggestedParams:c}),e.makeApplicationNoOpTxnFromObject({from:a,suggestedParams:c,appIndex:r,appArgs:[ye("create_proposal"),ye(n),i?ye(i):Mo,null!=u?u:e.decodeAddress(Uo).publicKey],foreignApps:[s],boxes:[{appIndex:r,name:l},{appIndex:s,name:d},{appIndex:s,name:f}],note:p?ye(p):void 0})];return m[1].fee*=3,e.assignGroupID(m)}function ui(t){var n=t.accountPowerIndex,r=t.createAttendanceSheetBox,a=t.proposal,s=t.proposalId,o=t.proposalVotingAppId,i=t.sender,u=t.suggestedParams,c=t.vaultAppId,p=t.vote,l=t.appCallNote;if(![Ro.Abstain,Ro.Against,Ro.For].includes(p))throw new Error("Invalid vote");var d,f,m=Math.floor(n/xs),h=Math.floor(a.index/(8*Bo)),g=[{appIndex:o,name:Xo(s)},{appIndex:o,name:(d=i,f=h,Rs(Lo,e.decodeAddress(d).publicKey,Xs(f)))},{appIndex:c,name:$s(i)},{appIndex:c,name:to(i,m)},{appIndex:c,name:to(i,m+1)}],A=[e.makeApplicationNoOpTxnFromObject({from:i,suggestedParams:u,appIndex:o,appArgs:[ye("cast_vote"),ye(s),Xs(p),Xs(n)],foreignApps:[c],boxes:g,note:l?ye(l):void 0})];if(A[0].fee*=2,r){var x=e.makePaymentTxnWithSuggestedParamsFromObject({from:i,suggestedParams:u,to:e.getApplicationAddress(o),amount:Fo});A.unshift(x)}return e.assignGroupID(A)}var ci=function(){function t(e,n,r){u(this,t),this.algodClient=e,this.userAddress=n,this.network=r}var n,r,a,o,c,l,d,f,m,h,g,A,x,I,v,y;return p(t,[{key:"getTinyPower",value:(y=i(s().mark((function e(){var t,n,r,a,o,i,u,c,p=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return t=p.length>0&&void 0!==p[0]?p[0]:Math.floor(Date.now()/1e3),n=p.length>1?p[1]:void 0,e.next=4,this.fetchAccountState();case 4:if(r=e.sent){e.next=7;break}return e.abrupt("return",0);case 7:return e.next=9,co(this.algodClient,this.userAddress,is[this.network],r.powerCount,n);case 9:if(a=e.sent,null!==(o=lo(a,t))){e.next=13;break}return e.abrupt("return",0);case 13:return i=a[o],u=t-i.timestamp,c=Math.max(i.bias-Ns(i.slope,u),0),e.abrupt("return",c);case 17:case"end":return e.stop()}}),e,this)}))),function(){return y.apply(this,arguments)})},{key:"getTotalTinyPower",value:(v=i(s().mark((function e(){var t,n,r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return t=w.length>0&&void 0!==w[0]?w[0]:Math.floor(Date.now()/1e3),n=w.length>1?w[1]:void 0,e.next=4,this.fetchVaultAppGlobalState();case 4:if(r=e.sent){e.next=7;break}return e.abrupt("return",0);case 7:return e.next=9,oo(this.algodClient,is[this.network],r.totalPowerCount,n);case 9:if(a=e.sent,o=lo(a,t)){e.next=13;break}return e.abrupt("return",0);case 13:i=a[o],u=Math.floor(i.timestamp/fs),c=Math.floor(t/fs)-u,p=Array.from({length:c},(function(e,t){return(u+t)*fs})),l=p.map((function(e,t){return[0===t?i.timestamp:p[t-1],e]})),d=i.slope,f=i.bias,m=T(l),e.prev=20,m.s();case 22:if((h=m.n()).done){e.next=35;break}return g=h.value,A=g[1]-g[0],x=Ns(d,A),f=Math.max(f-x,0),e.next=29,no(this.algodClient,is[this.network],g[1]);case 29:I=e.sent,v=(null==I?void 0:I.slopeDelta)||0,d=Math.max(d-v,0),0!==f&&0!==d||(f=0,d=0);case 33:e.next=22;break;case 35:e.next=40;break;case 37:e.prev=37,e.t0=e.catch(20),m.e(e.t0);case 40:return e.prev=40,m.f(),e.finish(40);case 43:return e.abrupt("return",f);case 44:case"end":return e.stop()}}),e,this,[[20,37,40,43]])}))),function(){return v.apply(this,arguments)})},{key:"getCumulativeTinyPower",value:(I=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l=arguments;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=l.length>1&&void 0!==l[1]?l[1]:Math.floor(Date.now()/1e3),e.next=3,this.fetchAccountState();case 3:if(r=e.sent){e.next=6;break}return e.abrupt("return",0);case 6:return e.next=8,co(this.algodClient,this.userAddress,is[this.network],r.powerCount,t);case 8:if(a=e.sent,null!==(o=lo(a,n))){e.next=12;break}return e.abrupt("return",0);case 12:return i=a[o],u=n-i.timestamp,c=Ls(i.bias,i.slope,u),p=i.cumulativePower-c,e.abrupt("return",p);case 17:case"end":return e.stop()}}),e,this)}))),function(e){return I.apply(this,arguments)})},{key:"fetchVaultAppGlobalState",value:(x=i(s().mark((function e(){var t;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,Bs(this.algodClient,is[this.network]);case 3:return t=e.sent,e.abrupt("return",new Ys(t.tiny_asset_id,t.total_locked_amount,t.total_power_count,t.last_total_power_timestamp));case 7:return e.prev=7,e.t0=e.catch(0),console.error(e.t0),e.abrupt("return",null);case 11:case"end":return e.stop()}}),e,this,[[0,7]])}))),function(){return x.apply(this,arguments)})},{key:"generateCreateLockTransactions",value:(A=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.lockedAmount,r=t.lockEndTime,a=t.userAddress,o=t.suggestedParams,i=a||this.userAddress,e.next=4,this.fetchAccountState();case 4:return u=e.sent,e.next=7,this.fetchVaultAppGlobalState();case 7:if(c=e.sent,p=o,c){e.next=11;break}throw new Error("There was an error while fetching vault app global state");case 11:if(p){e.next=15;break}return e.next=14,this.algodClient.getTransactionParams().do();case 14:p=e.sent;case 15:return e.next=17,no(this.algodClient,is[this.network],r);case 17:return l=e.sent,e.abrupt("return",yo({lockedAmount:n,lockEndTime:r,vaultAppGlobalState:c,slopeChangeAtLockEndTime:l,sender:i,network:this.network,accountState:u,suggestedParams:p}));case 19:case"end":return e.stop()}}),e,this)}))),function(e){return A.apply(this,arguments)})},{key:"generateIncreaseLockAmountTransactions",value:(g=i(s().mark((function e(t){var n,r,a,o,i,u,c;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.lockedAmount,r=t.userAddress,a=t.suggestedParams,o=r||this.userAddress,e.next=4,this.fetchAccountState();case 4:return i=e.sent,e.next=7,this.fetchVaultAppGlobalState();case 7:if(u=e.sent,c=a,u){e.next=11;break}throw new Error("There was an error while fetching vault app global state");case 11:if(i){e.next=13;break}throw new Error("There was an error while fetcing the account state");case 13:if(c){e.next=17;break}return e.next=16,this.algodClient.getTransactionParams().do();case 16:c=e.sent;case 17:return e.abrupt("return",bo({accountState:i,lockedAmount:n,network:this.network,sender:o,vaultAppGlobalState:u,suggestedParams:c}));case 18:case"end":return e.stop()}}),e,this)}))),function(e){return g.apply(this,arguments)})},{key:"generateExtendLockTimeTransactions",value:(h=i(s().mark((function e(t){var n,r,a,o,i,u,c,p;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.newLockEndTime,r=t.userAddress,a=t.suggestedParams,o=r||this.userAddress,e.next=4,this.fetchAccountState();case 4:return i=e.sent,e.next=7,this.fetchVaultAppGlobalState();case 7:if(u=e.sent,c=a,u){e.next=11;break}throw new Error("There was an error while fetching vault app global state");case 11:if(i){e.next=13;break}throw new Error("There was an error while fetcing the account state");case 13:if(c){e.next=17;break}return e.next=16,this.algodClient.getTransactionParams().do();case 16:c=e.sent;case 17:return e.next=19,no(this.algodClient,is[this.network],n);case 19:return p=e.sent,e.abrupt("return",To({accountState:i,network:this.network,newLockEndTime:n,sender:o,vaultAppGlobalState:u,suggestedParams:c,slopeChangeAtNewLockEndTime:null==p?void 0:p.slopeDelta}));case 21:case"end":return e.stop()}}),e,this)}))),function(e){return h.apply(this,arguments)})},{key:"generateIncreaseLockAmountAndExtendLockEndTimeTransactions",value:(m=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.lockAmount,r=t.lockEndTime,a=t.userAddress,o=t.suggestedParams,i=a||this.userAddress,e.next=4,this.fetchAccountState();case 4:return u=e.sent,e.next=7,this.fetchVaultAppGlobalState();case 7:if(c=e.sent,p=[],l=[],d=o,c){e.next=13;break}throw new Error("There was an error while fetching vault app global state");case 13:if(u){e.next=15;break}throw new Error("There was an error while fetcing the account state");case 15:if(d){e.next=19;break}return e.next=18,this.algodClient.getTransactionParams().do();case 18:d=e.sent;case 19:return p=bo({accountState:u,lockedAmount:n,network:this.network,sender:i,vaultAppGlobalState:c,suggestedParams:d}),u.powerCount+=1,c.totalPowerCount+=1,e.next=24,no(this.algodClient,is[this.network],r);case 24:return f=e.sent,l=To({accountState:u,network:this.network,newLockEndTime:r,sender:i,vaultAppGlobalState:c,suggestedParams:d,slopeChangeAtNewLockEndTime:null==f?void 0:f.slopeDelta}),m=[].concat(w(p),w(l)),e.abrupt("return",Boolean(p.length)&&Boolean(l.length)?Us(p,l):m);case 28:case"end":return e.stop()}}),e,this)}))),function(e){return m.apply(this,arguments)})},{key:"generateWithdrawTransactions",value:(f=i(s().mark((function e(t,n,r){var a,o,i,u,c;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a=t||this.userAddress,e.next=3,this.fetchAccountState();case 3:if(o=e.sent,i=r,o){e.next=7;break}throw new Error("There was an error while fetcing the account state");case 7:if(i){e.next=11;break}return e.next=10,this.algodClient.getTransactionParams().do();case 10:i=e.sent;case 11:if(u=ko({accountState:o,network:this.network,sender:a,suggestedParams:i,client:this.algodClient}),!n){e.next=17;break}return e.next=15,Y({client:this.algodClient,initiatorAddr:a,assetID:G[this.network]});case 15:c=e.sent,u=Us([c[0].txn],u);case 17:return e.abrupt("return",u);case 18:case"end":return e.stop()}}),e,this)}))),function(e,t,n){return f.apply(this,arguments)})},{key:"fetchAccountState",value:function(){return function(e,t,n){return Ks.apply(this,arguments)}(this.algodClient,is[this.network],this.userAddress)}},{key:"fetchStakingDistributionProposal",value:function(e){return function(e,t,n){return Jo.apply(this,arguments)}(this.algodClient,us[this.network],e)}},{key:"generateCastVoteForStakingDistributionProposalTransactions",value:(d=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.proposalId,r=t.votes,a=t.assetIds,o=t.userAddress,i=t.suggestedParams,u=null!=o?o:this.userAddress,c=i,e.next=5,this.fetchStakingDistributionProposal(n);case 5:if(p=e.sent){e.next=8;break}throw new Error("There was an error while fetching staking distribution proposal");case 8:if(c){e.next=12;break}return e.next=11,this.algodClient.getTransactionParams().do();case 11:c=e.sent;case 12:return e.next=14,this.fetchAccountState();case 14:return l=e.sent,e.next=17,js(this.algodClient,us[this.network]);case 17:return d=e.sent,e.next=20,co(this.algodClient,u,is[this.network],null==l?void 0:l.powerCount);case 20:if(f=e.sent,null!==(m=lo(f,p.creationTimestamp))){e.next=24;break}throw new Error("It is required to have an account power at the staking distribution proposal creation timestamp");case 24:return e.abrupt("return",Yo({stakingVotingAppId:us[this.network],vaultAppId:is[this.network],sender:u,proposalId:n,proposal:p,votes:r,assetIds:a,accountPowerIndex:m,appBoxNames:d,suggestedParams:c,appCallNote:null}));case 25:case"end":return e.stop()}}),e,this)}))),function(e){return d.apply(this,arguments)})},{key:"fetchRewardsAppGlobalState",value:(l=i(s().mark((function t(){var n;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,Bs(this.algodClient,cs[this.network]);case 3:return n=t.sent,t.abrupt("return",new ti(n.tiny_asset_id,n.vault_app_id,n.reward_history_count,n.first_period_timestamp,n.reward_period_count,e.encodeAddress(n.manager),e.encodeAddress(n.rewards_manager)));case 7:return t.prev=7,t.t0=t.catch(0),console.error(t.t0),t.abrupt("return",null);case 11:case"end":return t.stop()}}),t,this,[[0,7]])}))),function(){return l.apply(this,arguments)})},{key:"generateClaimRewardTransactions",value:(c=i(s().mark((function e(t){var n,r,a,o,i,u,c,p,l,d,f,m,h,g,A,x,I,v,w,y,b,T;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.periodIndexStart,r=t.periodCount,a=t.userAddress,o=t.suggestedParams,i=t.shouldOptIntoTINY,u=null!=a?a:this.userAddress,c=o){e.next=7;break}return e.next=6,this.algodClient.getTransactionParams().do();case 6:c=e.sent;case 7:return e.next=9,this.fetchAccountState();case 9:return p=e.sent,e.next=12,this.fetchRewardsAppGlobalState();case 12:if(l=e.sent){e.next=15;break}throw new Error("There was an error while fetching rewards app global state");case 15:if(!(n+r>l.rewardPeriodCount)){e.next=17;break}throw new Error("The reward period index to be claimed cannot be larger than the latest reward period index");case 17:return e.next=19,co(this.algodClient,u,is[this.network],null==p?void 0:p.powerCount);case 19:for(d=e.sent,f=l.firstPeriodTimestamp+n*os,m=l.firstPeriodTimestamp+(n+r)*os,h=[],g=f;g=Math.floor(Date.now()/1e3)||c.votingEndTimestamp<=Math.floor(Date.now()/1e3))){e.next=23;break}throw new Error("Voting period is not active");case 23:return e.next=25,co(this.algodClient,i,is[this.network],p.powerCount);case 25:if(l=e.sent,null!==(d=lo(l,c.creationTimestamp))){e.next=29;break}throw new Error("Account power index not found");case 29:return f=Math.floor(c.index/(8*Bo)),m=Wo(i,f),e.next=33,Ds(this.algodClient,ps[this.network],m);case 33:return h=!e.sent,e.abrupt("return",ui({proposalVotingAppId:ps[this.network],vaultAppId:is[this.network],sender:i,proposalId:n,proposal:c,vote:a,accountPowerIndex:d,createAttendanceSheetBox:h,suggestedParams:u}));case 35:case"end":return e.stop()}}),e,this)}))),function(e){return a.apply(this,arguments)})},{key:"fetchProposalVotingAppGlobalState",value:(r=i(s().mark((function e(){var t;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,Bs(this.algodClient,ps[this.network]);case 2:return t=e.sent,e.abrupt("return",new Vo(t.vault_app_id,t.proposal_index_counter,t.voting_delay,t.voting_duration,t.proposal_threshold,t.proposal_threshold_numerator,t.quorum_threshold,t.approval_requirement,t.manager,t.proposal_manager));case 4:case"end":return e.stop()}}),e,this)}))),function(){return r.apply(this,arguments)})},{key:"getRequiredTinyPowerToCreateProposal",value:(n=i(s().mark((function e(){var t,n,r;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,this.fetchProposalVotingAppGlobalState();case 2:if(t=e.sent,n=t.proposalThreshold,!t.proposalThresholdNumerator){e.next=9;break}return e.next=7,this.getTotalTinyPower();case 7:r=e.sent,n=Math.max(n,Math.floor(r*t.proposalThresholdNumerator/100)+1);case 9:return e.abrupt("return",n);case 10:case"end":return e.stop()}}),e,this)}))),function(){return n.apply(this,arguments)})}]),t}();exports.ALGO_ASSET=V,exports.ALGO_ASSET_ID=j,exports.ASSET_OPT_IN_PROCESS_TXN_COUNT=1,exports.AccountState=Qs,exports.AddLiquidity=er,exports.BASE_MINIMUM_BALANCE=S,exports.Bootstrap=_n,exports.CONTRACT_VERSION=U,exports.LendingPool=la,exports.MINIMUM_ADD_LIQUIDITY_AMOUNT=F,exports.MINIMUM_BALANCE_REQUIRED_PER_APP=O,exports.MINIMUM_BALANCE_REQUIRED_PER_ASSET=D,exports.MINIMUM_BALANCE_REQUIRED_PER_BYTE_SCHEMA=B,exports.MINIMUM_BALANCE_REQUIRED_PER_INT_SCHEMA_VALUE=C,exports.OPT_IN_VALIDATOR_APP_PROCESS_TXN_COUNT=1,exports.OPT_OUT_VALIDATOR_APP_PROCESS_TXN_COUNT=1,exports.POOL_TOKEN_UNIT_NAME=X,exports.PoolStatus=Nt,exports.ProposalVote=Ro,exports.REDEEM_PROCESS_TXN_COUNT=3,exports.RemoveLiquidity=Pr,exports.Swap=Wr,exports.SwapQuoteError=E,exports.SwapQuoteErrorType=_,exports.SwapQuoteType=tt,exports.SwapType=Ne,exports.TINY_ASSET_ID=G,exports.TinymanGovernanceClient=ci,exports.V1_1AddLiquidityTxnIndices=En,exports.V1_1_ADD_LIQUIDITY_PROCESS_TXN_COUNT=5,exports.V1_1_REMOVE_LIQUIDITY_TXN_COUNT=nr,exports.V2AddLiquidityTxnIndices=Dn,exports.V2AddLiquidityType=Sn,exports.V2_REMOVE_LIQUIDITY_APP_CALL_INNER_TXN_COUNT=rr,exports.applySlippageToAmount=de,exports.calculateAccountMinimumRequiredBalance=_t,exports.calculatePriceImpact=ut,exports.calculateSwapRate=it,exports.calculateTinyPower=function(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Math.floor(Date.now()/1e3),a=(n=e,Math.floor(n*gs/ms)),s=t-r;return s<0?0:Ns(a,s)},exports.combineAndRegroupSignerTxns=function(){for(var t=arguments.length,n=new Array(t),r=0;r=e.minimum_required_balance},exports.intToBytes=Xs,exports.isAccountOptedIntoApp=function(e){var t=e.appID;return e.accountAppsLocalState.some((function(e){return e.id===t}))},exports.isSwapAssetInAmountLow=st,exports.isSwapQuoteErrorCausedByAmount=mt,exports.poolUtils=Kt,exports.prepareCommitTransactions=function(e){return fa.apply(this,arguments)},exports.redeemAllExcessAsset=function(e){return Kr.apply(this,arguments)},exports.redeemExcessAsset=function(e){return zr.apply(this,arguments)},exports.sendAndWaitRawTransaction=Ae,exports.sumUpTxnFees=Ie,exports.tinymanContract_v1_1=It,exports.tinymanContract_v2=yt,exports.tinymanJSSDKConfig=Te; diff --git a/dist/util/asset/assetConstants.d.ts b/dist/util/asset/assetConstants.d.ts index 40710139..27374c6c 100644 --- a/dist/util/asset/assetConstants.d.ts +++ b/dist/util/asset/assetConstants.d.ts @@ -1,3 +1,4 @@ +import { SupportedNetwork } from "../commonTypes"; import { TinymanAnalyticsApiAsset } from "./assetModels"; export declare const ALGO_ASSET_ID = 0; export declare const ALGO_ASSET: TinymanAnalyticsApiAsset; @@ -6,3 +7,4 @@ export declare const POOL_TOKEN_UNIT_NAME: { V1_1: string; V2: string; }; +export declare const TINY_ASSET_ID: Record; diff --git a/package-lock.json b/package-lock.json index a03848db..684d61f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,18 @@ { "name": "@tinymanorg/tinyman-js-sdk", - "version": "3.1.2", + "version": "4.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@tinymanorg/tinyman-js-sdk", - "version": "3.1.2", + "version": "4.0.0", "license": "MIT", "dependencies": { "algosdk": "^2.1.0", - "base64-js": "^1.5.1" + "base64-js": "^1.5.1", + "multiformats": "^13.2.1", + "uuid": "^10.0.0" }, "devDependencies": { "@babel/preset-env": "^7.20.2", @@ -24,6 +26,7 @@ "@rollup/plugin-terser": "0.4.0", "@types/jest": "^29.5.0", "@types/node": "^18.15.5", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.36.0", @@ -3044,6 +3047,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.23", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz", @@ -8441,6 +8450,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/multiformats": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.2.1.tgz", + "integrity": "sha512-83SyOLC30MyJtUt92LBeOmiEC4MQX7Xm25kBW70k92e6Ec+E+z1UfgCOuKABQ/30I/kgGS9A+rguJRSXYNZ86Q==" + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -10446,6 +10460,18 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -12924,6 +12950,12 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true + }, "@types/yargs": { "version": "17.0.23", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.23.tgz", @@ -16845,6 +16877,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "multiformats": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.2.1.tgz", + "integrity": "sha512-83SyOLC30MyJtUt92LBeOmiEC4MQX7Xm25kBW70k92e6Ec+E+z1UfgCOuKABQ/30I/kgGS9A+rguJRSXYNZ86Q==" + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -18308,6 +18345,11 @@ "punycode": "^2.1.0" } }, + "uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", diff --git a/package.json b/package.json index abddf25b..b3c9e4bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tinymanorg/tinyman-js-sdk", - "version": "3.1.2", + "version": "4.0.0", "description": "Tinyman JS SDK", "author": "Tinyman Core Team", "license": "MIT", @@ -43,6 +43,7 @@ "@rollup/plugin-commonjs": "^24.0.1", "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.0.1", + "@rollup/plugin-terser": "0.4.0", "@types/jest": "^29.5.0", "@types/node": "^18.15.5", "@typescript-eslint/eslint-plugin": "^5.56.0", @@ -58,12 +59,14 @@ "prettier": "^2.8.6", "rollup": "^3.20.0", "rollup-plugin-eslint": "^7.0.0", - "@rollup/plugin-terser": "0.4.0", - "typescript": "^5.0.2" + "typescript": "^5.0.2", + "@types/uuid": "^10.0.0" }, "dependencies": { "algosdk": "^2.1.0", - "base64-js": "^1.5.1" + "base64-js": "^1.5.1", + "multiformats": "^13.2.1", + "uuid": "^10.0.0" }, "lint-staged": { "src/**/*.{ts,md}": "prettier --write", diff --git a/src/governance/constants.ts b/src/governance/constants.ts new file mode 100644 index 00000000..e99bf8c1 --- /dev/null +++ b/src/governance/constants.ts @@ -0,0 +1,49 @@ +import {SupportedNetwork} from "../util/commonTypes"; + +const HOUR_IN_S = 60 * 60; +const DAY_IN_S = 24 * HOUR_IN_S; +const WEEK_IN_S = 7 * DAY_IN_S; + +const VAULT_APP_ID: Record = { + testnet: 480164661, + mainnet: 2200606875 +}; + +const STAKING_VOTING_APP_ID: Record = { + testnet: 360907790, + mainnet: 2200609638 +}; + +const REWARDS_APP_ID: Record = { + testnet: 336189106, + mainnet: 2200608153 +}; + +const PROPOSAL_VOTING_APP_ID: Record = { + testnet: 383416252, + mainnet: 2200608887 +}; + +const BOX_FLAT_MIN_BALANCE = 2_500; +const BOX_BYTE_MIN_BALANCE = 400; + +const HOUR = 60 * 60; +const DAY = 24 * HOUR; +const WEEK = 7 * DAY; + +export {HOUR, DAY, WEEK}; + +const TWO_TO_THE_64 = 2 ** 64; + +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, + PROPOSAL_VOTING_APP_ID +}; diff --git a/src/governance/index.ts b/src/governance/index.ts new file mode 100644 index 00000000..5ee82ff1 --- /dev/null +++ b/src/governance/index.ts @@ -0,0 +1,873 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import {decodeAddress, encodeAddress, SuggestedParams, Transaction} from "algosdk"; + +import { + getAccountPowers, + getAccountState, + getAllTotalPowers, + getPowerIndexAt, + getSlopeChange, + VaultAppGlobalState +} from "./vault/storage"; +import { + prepareCreateLockTransactions, + prepareExtendLockEndTimeTransactions, + prepareIncreaseLockAmountTransactions, + prepareWithdrawTransactions +} from "./vault/transactions"; +import { + PROPOSAL_VOTING_APP_ID, + REWARDS_APP_ID, + STAKING_VOTING_APP_ID, + VAULT_APP_ID, + WEEK, + WEEK_IN_S +} from "./constants"; +import { + doesBoxExist, + combineAndRegroupTxns, + getAllBoxNames, + getBias, + getCumulativePowerDelta, + getGlobalState +} from "./utils"; +import { + getStakingAttendanceSheetBoxName, + getStakingDistributionProposal +} from "./staking-voting/storage"; +import {prepareCastVoteForStakingDistributionProposalTransactions} from "./staking-voting/transactions"; +import {getRewardClaimSheet, RewardsAppGlobalState} from "./rewards/storage"; +import {REWARD_CLAIM_SHEET_BOX_SIZE} from "./rewards/constants"; +import {prepareClaimRewardsTransactions} from "./rewards/transactions"; +import {getProposal, ProposalVotingAppGlobalState} from "./proposal-voting/storage"; +import { + prepareCastVoteTransactions, + prepareCreateProposalTransactions +} from "./proposal-voting/transactions"; +import { + ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE, + EXECUTION_HASH_SIZE, + ProposalVote +} from "./proposal-voting/constants"; +import {GetRawBoxValueCacheProps} from "./types"; +import {SupportedNetwork} from "../util/commonTypes"; +import {generateOptIntoAssetTxns} from "../util/asset/assetUtils"; +import {TINYMAN_ANALYTICS_API_BASE_URLS} from "../util/constant"; +import {TINY_ASSET_ID} from "../util/asset/assetConstants"; + +class TinymanGovernanceClient { + private algodClient: AlgodClient; + private userAddress: string; + private network: SupportedNetwork; + + constructor(algodClient: AlgodClient, userAddress: string, network: SupportedNetwork) { + this.algodClient = algodClient; + this.userAddress = userAddress; + this.network = network; + } + + async getTinyPower( + timeStamp: number = Math.floor(Date.now() / 1000), + cacheProps?: GetRawBoxValueCacheProps + ) { + const accountState = await this.fetchAccountState(); + + if (!accountState) { + return 0; + } + + const accountPowers = await getAccountPowers( + this.algodClient, + this.userAddress, + VAULT_APP_ID[this.network], + accountState.powerCount, + cacheProps + ); + + const accountPowerIndex = getPowerIndexAt(accountPowers, timeStamp); + + if (accountPowerIndex === null) { + return 0; + } + + const accountPower = accountPowers[accountPowerIndex]; + const timeDelta = timeStamp - accountPower.timestamp; + const tinyPower = Math.max( + accountPower.bias - getBias(accountPower.slope, timeDelta), + 0 + ); + + return tinyPower; + } + + async getTotalTinyPower( + timeStamp: number = Math.floor(Date.now() / 1000), + cacheProps?: GetRawBoxValueCacheProps + ) { + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + + if (!vaultAppGlobalState) { + return 0; + } + + const totalPowers = await getAllTotalPowers( + this.algodClient, + VAULT_APP_ID[this.network], + vaultAppGlobalState.totalPowerCount, + cacheProps + ); + + const totalPowerIndex = getPowerIndexAt(totalPowers, timeStamp); + + if (!totalPowerIndex) { + return 0; + } + + const totalPower = totalPowers[totalPowerIndex]; + const totalPowerWeekIndex = Math.floor(totalPower.timestamp / WEEK); + + const newWeekCount = Math.floor(timeStamp / WEEK) - totalPowerWeekIndex; + + const weekTimestamps = Array.from( + {length: newWeekCount}, + (_, index) => (totalPowerWeekIndex + index) * WEEK + ); + + const timeRanges = weekTimestamps.map((weekTimestamp, index) => { + const start = index === 0 ? totalPower.timestamp : weekTimestamps[index - 1]; + const end = weekTimestamp; + + return [start, end]; + }); + + let {slope, bias: tinyPower} = totalPower; + + for (const timeRange of timeRanges) { + const timeDelta = timeRange[1] - timeRange[0]; + const biasDelta = getBias(slope, timeDelta); + + tinyPower = Math.max(tinyPower - biasDelta, 0); + + const slopeChange = await getSlopeChange( + this.algodClient, + VAULT_APP_ID[this.network], + timeRange[1] + ); + + const slopeDelta = slopeChange?.slopeDelta || 0; + + slope = Math.max(slope - slopeDelta, 0); + + if (tinyPower === 0 || slope === 0) { + tinyPower = 0; + slope = 0; + } + } + + return tinyPower; + } + + async getCumulativeTinyPower( + cacheProps?: GetRawBoxValueCacheProps, + timeStamp: number = Math.floor(Date.now() / 1000) + ) { + const accountState = await this.fetchAccountState(); + + if (!accountState) { + return 0; + } + + const accountPowers = await getAccountPowers( + this.algodClient, + this.userAddress, + VAULT_APP_ID[this.network], + accountState.powerCount, + cacheProps + ); + const accountPowerIndex = getPowerIndexAt(accountPowers, timeStamp); + + if (accountPowerIndex === null) { + return 0; + } + + const accountPower = accountPowers[accountPowerIndex]; + const timeDelta = timeStamp - accountPower.timestamp; + const cumulativePowerDelta = getCumulativePowerDelta( + accountPower.bias, + accountPower.slope, + timeDelta + ); + const cumulativeTinyPower = accountPower.cumulativePower - cumulativePowerDelta; + + return cumulativeTinyPower; + } + + async fetchVaultAppGlobalState() { + try { + const data = await getGlobalState(this.algodClient, VAULT_APP_ID[this.network]); + + return new VaultAppGlobalState( + data.tiny_asset_id, + data.total_locked_amount, + data.total_power_count, + data.last_total_power_timestamp + ); + } catch (error: any) { + console.error(error); + + return null; + } + } + + async generateCreateLockTransactions({ + lockedAmount, + lockEndTime, + userAddress, + suggestedParams + }: { + lockedAmount: number; + lockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const sender = userAddress || this.userAddress; + const accountState = await this.fetchAccountState(); + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + let sp = suggestedParams; + + if (!vaultAppGlobalState) { + throw new Error("There was an error while fetching vault app global state"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + const slopeChangeAtLockEndTime = await getSlopeChange( + this.algodClient, + VAULT_APP_ID[this.network], + lockEndTime + ); + + return prepareCreateLockTransactions({ + lockedAmount, + lockEndTime, + vaultAppGlobalState, + slopeChangeAtLockEndTime, + sender, + network: this.network, + accountState, + suggestedParams: sp + }); + } + + async generateIncreaseLockAmountTransactions({ + lockedAmount, + userAddress, + suggestedParams + }: { + lockedAmount: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const sender = userAddress || this.userAddress; + const accountState = await this.fetchAccountState(); + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + let sp = suggestedParams; + + if (!vaultAppGlobalState) { + throw new Error("There was an error while fetching vault app global state"); + } + + if (!accountState) { + throw new Error("There was an error while fetcing the account state"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + return prepareIncreaseLockAmountTransactions({ + accountState, + lockedAmount, + network: this.network, + sender, + vaultAppGlobalState, + suggestedParams: sp + }); + } + + async generateExtendLockTimeTransactions({ + newLockEndTime, + userAddress, + suggestedParams + }: { + newLockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const sender = userAddress || this.userAddress; + const accountState = await this.fetchAccountState(); + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + let sp = suggestedParams; + + if (!vaultAppGlobalState) { + throw new Error("There was an error while fetching vault app global state"); + } + + if (!accountState) { + throw new Error("There was an error while fetcing the account state"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + const slopeChangeAtNewLockEndTime = await getSlopeChange( + this.algodClient, + VAULT_APP_ID[this.network], + newLockEndTime + ); + + return prepareExtendLockEndTimeTransactions({ + accountState, + network: this.network, + newLockEndTime, + sender, + vaultAppGlobalState, + suggestedParams: sp, + slopeChangeAtNewLockEndTime: slopeChangeAtNewLockEndTime?.slopeDelta + }); + } + + async generateIncreaseLockAmountAndExtendLockEndTimeTransactions({ + lockAmount, + lockEndTime, + userAddress, + suggestedParams + }: { + lockAmount: number; + lockEndTime: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const sender = userAddress || this.userAddress; + const accountState = await this.fetchAccountState(); + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + + let increaseLockAmountTxnGroup: Transaction[] = []; + let extendLockEndTimeTxnGroup: Transaction[] = []; + + let sp = suggestedParams; + + if (!vaultAppGlobalState) { + throw new Error("There was an error while fetching vault app global state"); + } + + if (!accountState) { + throw new Error("There was an error while fetcing the account state"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + increaseLockAmountTxnGroup = prepareIncreaseLockAmountTransactions({ + accountState, + lockedAmount: lockAmount, + network: this.network, + sender, + vaultAppGlobalState, + suggestedParams: sp + }); + + accountState.powerCount += 1; + vaultAppGlobalState.totalPowerCount += 1; + + const slopeChangeAtNewLockEndTime = await getSlopeChange( + this.algodClient, + VAULT_APP_ID[this.network], + lockEndTime + ); + + extendLockEndTimeTxnGroup = prepareExtendLockEndTimeTransactions({ + accountState, + network: this.network, + newLockEndTime: lockEndTime, + sender, + vaultAppGlobalState, + suggestedParams: sp, + slopeChangeAtNewLockEndTime: slopeChangeAtNewLockEndTime?.slopeDelta + }); + + const txnGroup = [...increaseLockAmountTxnGroup, ...extendLockEndTimeTxnGroup]; + + return Boolean(increaseLockAmountTxnGroup.length) && + Boolean(extendLockEndTimeTxnGroup.length) + ? combineAndRegroupTxns(increaseLockAmountTxnGroup, extendLockEndTimeTxnGroup) + : txnGroup; + } + + async generateWithdrawTransactions( + userAddress?: string, + shouldOptIntoTINY?: boolean, + suggestedParams?: SuggestedParams + ) { + const sender = userAddress || this.userAddress; + const accountState = await this.fetchAccountState(); + let sp = suggestedParams; + + if (!accountState) { + throw new Error("There was an error while fetcing the account state"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + let withdrawTxns = prepareWithdrawTransactions({ + accountState, + network: this.network, + sender, + suggestedParams: sp, + client: this.algodClient + }); + + if (shouldOptIntoTINY) { + const optIntoTINYAssetTxn = await generateOptIntoAssetTxns({ + client: this.algodClient, + initiatorAddr: sender, + assetID: TINY_ASSET_ID[this.network] + }); + + withdrawTxns = combineAndRegroupTxns([optIntoTINYAssetTxn[0].txn], withdrawTxns); + } + + return withdrawTxns; + } + + fetchAccountState() { + return getAccountState( + this.algodClient, + VAULT_APP_ID[this.network], + this.userAddress + ); + } + + fetchStakingDistributionProposal(proposalId: string) { + return getStakingDistributionProposal( + this.algodClient, + STAKING_VOTING_APP_ID[this.network], + proposalId + ); + } + + async generateCastVoteForStakingDistributionProposalTransactions({ + proposalId, + votes, + assetIds, + userAddress, + suggestedParams + }: { + proposalId: string; + votes: number[]; + assetIds: number[]; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const selectedUserAddress = userAddress ?? this.userAddress; + let sp = suggestedParams; + const stakingDistributionProposal = await this.fetchStakingDistributionProposal( + proposalId + ); + + if (!stakingDistributionProposal) { + throw new Error("There was an error while fetching staking distribution proposal"); + } + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + const accountState = await this.fetchAccountState(); + + const appBoxNames = await getAllBoxNames( + this.algodClient, + STAKING_VOTING_APP_ID[this.network] + ); + const accountPowers = await getAccountPowers( + this.algodClient, + selectedUserAddress, + VAULT_APP_ID[this.network], + accountState?.powerCount + ); + const accountPowerIndex = getPowerIndexAt( + accountPowers, + stakingDistributionProposal.creationTimestamp + ); + + if (accountPowerIndex === null) { + throw new Error( + "It is required to have an account power at the staking distribution proposal creation timestamp" + ); + } + + return prepareCastVoteForStakingDistributionProposalTransactions({ + stakingVotingAppId: STAKING_VOTING_APP_ID[this.network], + vaultAppId: VAULT_APP_ID[this.network], + sender: selectedUserAddress, + proposalId, + proposal: stakingDistributionProposal, + votes, + assetIds, + accountPowerIndex, + appBoxNames, + suggestedParams: sp, + appCallNote: null + }); + } + + async fetchRewardsAppGlobalState() { + try { + const data = await getGlobalState(this.algodClient, REWARDS_APP_ID[this.network]); + + return new RewardsAppGlobalState( + data.tiny_asset_id, + data.vault_app_id, + data.reward_history_count, + data.first_period_timestamp, + data.reward_period_count, + encodeAddress(data.manager), + encodeAddress(data.rewards_manager) + ); + } catch (error: any) { + console.error(error); + + return null; + } + } + + async generateClaimRewardTransactions({ + periodIndexStart, + periodCount, + userAddress, + suggestedParams, + shouldOptIntoTINY + }: { + periodIndexStart: number; + periodCount: number; + userAddress?: string; + suggestedParams?: SuggestedParams; + shouldOptIntoTINY?: boolean; + }) { + const selectedUserAddress = userAddress ?? this.userAddress; + let sp = suggestedParams; + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + const accountState = await this.fetchAccountState(); + const rewardsAppGlobalState = await this.fetchRewardsAppGlobalState(); + + if (!rewardsAppGlobalState) { + throw new Error("There was an error while fetching rewards app global state"); + } + + if (periodIndexStart + periodCount > rewardsAppGlobalState.rewardPeriodCount) { + throw new Error( + "The reward period index to be claimed cannot be larger than the latest reward period index" + ); + } + + const accountPowers = await getAccountPowers( + this.algodClient, + selectedUserAddress, + VAULT_APP_ID[this.network], + accountState?.powerCount + ); + + const claimPeriodStartTimestamp = + rewardsAppGlobalState.firstPeriodTimestamp + periodIndexStart * WEEK_IN_S; + const claimPeriodEndTimestamp = + rewardsAppGlobalState.firstPeriodTimestamp + + (periodIndexStart + periodCount) * WEEK_IN_S; + + const accountPowerIndexes: number[] = []; + + for ( + let timestamp = claimPeriodStartTimestamp; + timestamp < claimPeriodEndTimestamp + 1; + timestamp = timestamp + WEEK_IN_S + ) { + accountPowerIndexes.push(getPowerIndexAt(accountPowers, timestamp) ?? 0); + } + + let createRewardClaimSheet = false; + const accountRewardClaimSheetBoxIndexes = new Set(); + + accountRewardClaimSheetBoxIndexes.add( + Math.floor(periodIndexStart / (REWARD_CLAIM_SHEET_BOX_SIZE * 8)) + ); + accountRewardClaimSheetBoxIndexes.add( + Math.floor((periodIndexStart + periodCount) / (REWARD_CLAIM_SHEET_BOX_SIZE * 8)) + ); + + for (const index of Array.from(accountRewardClaimSheetBoxIndexes)) { + const rewardClaimSheet = await getRewardClaimSheet( + this.algodClient, + REWARDS_APP_ID[this.network], + this.userAddress, + index + ); + + if (!rewardClaimSheet) { + createRewardClaimSheet = true; + break; + } + } + + let claimRewardsTxns = prepareClaimRewardsTransactions({ + rewardsAppId: REWARDS_APP_ID[this.network], + vaultAppId: VAULT_APP_ID[this.network], + tinyAssetId: TINY_ASSET_ID[this.network], + sender: this.userAddress, + periodIndexStart, + periodCount, + accountPowerIndexes, + createRewardClaimSheet, + suggestedParams: sp + }); + + if (shouldOptIntoTINY) { + const optIntoTINYAssetTxns = await generateOptIntoAssetTxns({ + client: this.algodClient, + initiatorAddr: selectedUserAddress, + assetID: TINY_ASSET_ID[this.network] + }); + + claimRewardsTxns = combineAndRegroupTxns( + [optIntoTINYAssetTxns[0].txn], + claimRewardsTxns + ); + } + + return claimRewardsTxns; + } + + fetchProposal(proposalId: string) { + return getProposal( + this.algodClient, + PROPOSAL_VOTING_APP_ID[this.network], + proposalId + ); + } + + // TODO: update metadata type + uploadProposalMetadata(proposalId: string, metadata: any) { + const payload = { + proposal_id: proposalId, + metadata + }; + const promise = fetch( + `${TINYMAN_ANALYTICS_API_BASE_URLS[this.network].v1}/governance/proposals/`, + { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(payload) + } + ); + + return promise + .catch(() => { + return Promise.reject(new Error("Network error. Try again later.")); + }) + .then((response) => { + if (response.ok) { + return Promise.resolve(response); + } + + return Promise.reject(response); + }) + .catch(async (errorResponse) => { + let finalError = errorResponse; + + // If the error is not an API error, it may not have a body that supports json conversion + if (typeof errorResponse.json === "function") { + const errorResponseJSON = await errorResponse.json(); + + finalError = errorResponseJSON; + } + + return Promise.reject(finalError); + }); + } + + async generateCreateProposalTransactions({ + proposalId, + userAddress, + suggestedParams, + executionHash, + executor + }: { + proposalId: string; + userAddress?: string; + suggestedParams?: SuggestedParams; + executionHash?: string; + executor?: string; + }) { + if (executionHash && executionHash.length !== EXECUTION_HASH_SIZE) { + throw new Error("Invalid execution hash"); + } + + const vaultAppGlobalState = await this.fetchVaultAppGlobalState(); + + if (!vaultAppGlobalState) { + throw new Error("There was an error while fetching vault app global state"); + } + + const sender = userAddress ?? this.userAddress; + let sp = suggestedParams; + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + return prepareCreateProposalTransactions({ + proposalId, + proposalVotingAppId: PROPOSAL_VOTING_APP_ID[this.network], + sender, + suggestedParams: sp, + vaultAppGlobalState, + vaultAppId: VAULT_APP_ID[this.network], + executionHash, + executor: executor + ? decodeAddress(executor).publicKey + : new Uint8Array((await this.fetchProposalVotingAppGlobalState()).proposalManager) + }); + } + + async generateCastVoteTransactions({ + proposalId, + suggestedParams, + vote, + userAddress + }: { + proposalId: string; + vote: ProposalVote; + userAddress?: string; + suggestedParams?: SuggestedParams; + }) { + const sender = userAddress ?? this.userAddress; + let sp = suggestedParams; + + if (!sp) { + sp = await this.algodClient.getTransactionParams().do(); + } + + const proposal = await this.fetchProposal(proposalId); + const accountState = await this.fetchAccountState(); + + if (!proposal) { + throw new Error("Proposal not found"); + } + + if (!accountState) { + throw new Error("Account state not found"); + } + + if (!proposal.isApproved) { + throw new Error("Proposal not approved"); + } + + if (!proposal.votingStartTimestamp) { + throw new Error("Voting start timestamp is not valid"); + } + + if ( + proposal.votingStartTimestamp >= Math.floor(Date.now() / 1000) || + proposal.votingEndTimestamp <= Math.floor(Date.now() / 1000) + ) { + throw new Error("Voting period is not active"); + } + + const accountPowers = await getAccountPowers( + this.algodClient, + sender, + VAULT_APP_ID[this.network], + accountState.powerCount + ); + const accountPowerIndex = getPowerIndexAt(accountPowers, proposal.creationTimestamp); + + if (accountPowerIndex === null) { + throw new Error("Account power index not found"); + } + + const accountAttendanceSheetBoxIndex = Math.floor( + proposal.index / (ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE * 8) + ); + const accountAttendanceSheetBoxName = getStakingAttendanceSheetBoxName( + sender, + accountAttendanceSheetBoxIndex + ); + const createAttendanceSheetBox = !(await doesBoxExist( + this.algodClient, + PROPOSAL_VOTING_APP_ID[this.network], + accountAttendanceSheetBoxName + )); + + return prepareCastVoteTransactions({ + proposalVotingAppId: PROPOSAL_VOTING_APP_ID[this.network], + vaultAppId: VAULT_APP_ID[this.network], + sender, + proposalId, + proposal, + vote, + accountPowerIndex, + createAttendanceSheetBox, + suggestedParams: sp + }); + } + + async fetchProposalVotingAppGlobalState(): Promise { + const data = await getGlobalState( + this.algodClient, + PROPOSAL_VOTING_APP_ID[this.network] + ); + + return new ProposalVotingAppGlobalState( + data.vault_app_id, + data.proposal_index_counter, + data.voting_delay, + data.voting_duration, + data.proposal_threshold, + data.proposal_threshold_numerator, + data.quorum_threshold, + data.approval_requirement, + data.manager, + data.proposal_manager + ); + } + + async getRequiredTinyPowerToCreateProposal() { + const votingAppGlobalState = await this.fetchProposalVotingAppGlobalState(); + let requiredTinyPower = votingAppGlobalState.proposalThreshold; + + if (votingAppGlobalState.proposalThresholdNumerator) { + const totalTinyPower = await this.getTotalTinyPower(); + + requiredTinyPower = Math.max( + requiredTinyPower, + Math.floor( + (totalTinyPower * votingAppGlobalState.proposalThresholdNumerator) / 100 + ) + 1 + ); + } + + return requiredTinyPower; + } +} + +export {TinymanGovernanceClient}; diff --git a/src/governance/proposal-voting/constants.ts b/src/governance/proposal-voting/constants.ts new file mode 100644 index 00000000..5a404c7b --- /dev/null +++ b/src/governance/proposal-voting/constants.ts @@ -0,0 +1,40 @@ +import {encodeString} from "../../util/util"; +import {BOX_FLAT_MIN_BALANCE, BOX_BYTE_MIN_BALANCE} from "../constants"; + +const PROPOSAL_BOX_PREFIX = encodeString("p"); +const ATTENDANCE_SHEET_BOX_PREFIX = encodeString("a"); + +const ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; +const PROPOSAL_BOX_SIZE = 116 + 64 + 32; + +const PROPOSAL_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (60 + PROPOSAL_BOX_SIZE); +const ATTENDANCE_SHEET_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (41 + ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE); + +enum ProposalVote { + Against = 0, + For = 1, + Abstain = 2 +} +const EXECUTION_HASH_SIZE = 34; + +const CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT = new Uint8Array( + EXECUTION_HASH_SIZE +); + +const EXECUTOR_FALLBACK_ADDRESS = + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"; + +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, + EXECUTOR_FALLBACK_ADDRESS +}; diff --git a/src/governance/proposal-voting/storage.ts b/src/governance/proposal-voting/storage.ts new file mode 100644 index 00000000..2da6fb91 --- /dev/null +++ b/src/governance/proposal-voting/storage.ts @@ -0,0 +1,159 @@ +import {decodeAddress, encodeAddress} from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; + +import {intToBytes} from "../util/utils"; +import {concatUint8Arrays, getRawBoxValue} from "../utils"; +import {ATTENDANCE_SHEET_BOX_PREFIX, PROPOSAL_BOX_PREFIX} from "./constants"; +import {encodeString} from "../../util/util"; + +export class Proposal { + 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; + + // eslint-disable-next-line max-params + 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 + ) { + this.index = index; + this.creationTimestamp = creationTimestamp; + this.votingStartTimestamp = votingStartTimestamp; + this.votingEndTimestamp = votingEndTimestamp; + this.snapshotTotalVotingPower = snapshotTotalVotingPower; + this.voteCount = voteCount; + this.quorumNumerator = quorumNumerator; + this.againstVotingPower = againstVotingPower; + this.forVotingPower = forVotingPower; + this.abstainVotingPower = abstainVotingPower; + this.isApproved = isApproved; + this.isCancelled = isCancelled; + this.isExecuted = isExecuted; + this.isQuorumReached = isQuorumReached; + this.proposerAddress = proposerAddress; + this.executionHash = executionHash; + this.executorAddress = executorAddress; + } + + get snapshotTimestamp(): number { + return this.creationTimestamp; + } +} + +export class ProposalVotingAppGlobalState { + vaultAppId: number; + proposalIndexCounter: number; + votingDelay: number; + votingDuration: number; + proposalThreshold: number; + proposalThresholdNumerator: number; + quorumThreshold: number; + approvalRequirement: number; + manager: string; + proposalManager: Uint8Array; + + // eslint-disable-next-line max-params + constructor( + vaultAppId: number, + proposalIndexCounter: number, + votingDelay: number, + votingDuration: number, + proposalThreshold: number, + proposalThresholdNumerator: number, + quorumThreshold: number, + approvalRequirement: number, + manager: string, + proposalManager: Uint8Array + ) { + this.vaultAppId = vaultAppId; + this.proposalIndexCounter = proposalIndexCounter; + this.votingDelay = votingDelay; + this.votingDuration = votingDuration; + this.proposalThreshold = proposalThreshold; + this.proposalThresholdNumerator = proposalThresholdNumerator; + this.quorumThreshold = quorumThreshold; + this.approvalRequirement = approvalRequirement; + this.manager = manager; + this.proposalManager = proposalManager; + } +} + +export function getProposalBoxName(proposalId: string) { + return concatUint8Arrays(PROPOSAL_BOX_PREFIX, encodeString(proposalId)); +} + +export function getAttendanceSheetBoxName(address: string, boxIndex: number) { + return concatUint8Arrays( + ATTENDANCE_SHEET_BOX_PREFIX, + decodeAddress(address).publicKey, + intToBytes(boxIndex) + ); +} + +function parseBoxProposal(rawBox: Uint8Array) { + const buffer = Buffer.from(rawBox); + + return new Proposal( + buffer.readUIntBE(0, 8), + buffer.readUIntBE(8, 8), + buffer.readUIntBE(16, 8), + buffer.readUIntBE(24, 8), + buffer.readUIntBE(32, 8), + buffer.readUIntBE(40, 8), + buffer.readUIntBE(48, 8), + buffer.readUIntBE(56, 8), + buffer.readUIntBE(64, 8), + buffer.readUIntBE(72, 8), + Boolean(buffer.readUIntBE(80, 1)), + Boolean(buffer.readUIntBE(81, 1)), + Boolean(buffer.readUIntBE(82, 1)), + Boolean(buffer.readUIntBE(83, 1)), + encodeAddress(buffer.subarray(84, 116)), + rawBox.slice(116, 150).toString(), + encodeAddress(buffer.subarray(150, 182)) + ); +} + +export async function getProposal( + client: AlgodClient, + appId: number, + proposalId: string +) { + const boxName = getProposalBoxName(proposalId); + const rawBox = await getRawBoxValue(client, appId, boxName); + + if (!rawBox) { + return null; + } + + return parseBoxProposal(rawBox); +} diff --git a/src/governance/proposal-voting/transactions.ts b/src/governance/proposal-voting/transactions.ts new file mode 100644 index 00000000..58414cfc --- /dev/null +++ b/src/governance/proposal-voting/transactions.ts @@ -0,0 +1,189 @@ +import algosdk, {decodeAddress, getApplicationAddress, SuggestedParams} from "algosdk"; + +import {intToBytes} from "../util/utils"; +import {ACCOUNT_POWER_BOX_ARRAY_LEN} from "../vault/constants"; +import { + getAccountPowerBoxName, + getAccountStateBoxName, + getTotalPowerBoxName, + VaultAppGlobalState +} from "../vault/storage"; +import { + ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE, + ATTENDANCE_SHEET_BOX_COST, + CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT, + EXECUTOR_FALLBACK_ADDRESS, + ProposalVote, + PROPOSAL_BOX_COST +} from "./constants"; +import {getAttendanceSheetBoxName, getProposalBoxName, Proposal} from "./storage"; +import {GenerateProposalMetadataPayload} from "./types"; +import {encodeString} from "../../util/util"; + +export function generateProposalMetadata({ + category, + description, + discussionUrl, + pollUrl, + title +}: GenerateProposalMetadataPayload) { + return { + category: category.trim(), + description: description.trim(), + discussion_url: discussionUrl.trim(), + poll_url: pollUrl.trim(), + title: title.trim() + }; +} + +export function prepareCreateProposalTransactions({ + proposalId, + proposalVotingAppId, + sender, + vaultAppId, + vaultAppGlobalState, + executionHash, + executor, + suggestedParams, + appCallNote +}: { + proposalVotingAppId: number; + sender: string; + proposalId: string; + vaultAppId: number; + vaultAppGlobalState: VaultAppGlobalState; + executionHash?: string; + executor?: Uint8Array; + suggestedParams: SuggestedParams; + appCallNote?: string; +}) { + const proposalBoxName = getProposalBoxName(proposalId); + const accountStateBoxName = getAccountStateBoxName(sender); + const lastTotalPowerBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + ); + + const txns: algosdk.Transaction[] = [ + algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + to: getApplicationAddress(proposalVotingAppId), + amount: PROPOSAL_BOX_COST, + suggestedParams + }), + algosdk.makeApplicationNoOpTxnFromObject({ + from: sender, + suggestedParams, + appIndex: proposalVotingAppId, + appArgs: [ + encodeString("create_proposal"), + encodeString(proposalId), + executionHash + ? encodeString(executionHash) + : CREATE_PROPOSAL_DEFAULT_EXECUTION_HASH_ARGUMENT, + executor ?? decodeAddress(EXECUTOR_FALLBACK_ADDRESS).publicKey + ], + foreignApps: [vaultAppId], + boxes: [ + {appIndex: proposalVotingAppId, name: proposalBoxName}, + {appIndex: vaultAppId, name: accountStateBoxName}, + {appIndex: vaultAppId, name: lastTotalPowerBoxName} + ], + note: appCallNote ? encodeString(appCallNote) : undefined + }) + ]; + + // 2 inner txns + txns[1].fee *= 3; + + return algosdk.assignGroupID(txns); +} + +export function prepareCastVoteTransactions({ + accountPowerIndex, + createAttendanceSheetBox, + proposal, + proposalId, + proposalVotingAppId, + sender, + suggestedParams, + vaultAppId, + vote, + appCallNote +}: { + proposalVotingAppId: number; + vaultAppId: number; + sender: string; + proposalId: string; + proposal: Proposal; + vote: ProposalVote; + accountPowerIndex: number; + createAttendanceSheetBox: boolean; + suggestedParams: SuggestedParams; + appCallNote?: string; +}) { + if (![ProposalVote.Abstain, ProposalVote.Against, ProposalVote.For].includes(vote)) { + throw new Error("Invalid vote"); + } + + const accountPowerBoxIndex = Math.floor( + accountPowerIndex / ACCOUNT_POWER_BOX_ARRAY_LEN + ); + const accountAttendanceBoxIndex = Math.floor( + proposal.index / (ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE * 8) + ); + const boxes: algosdk.BoxReference[] = [ + { + appIndex: proposalVotingAppId, + name: getProposalBoxName(proposalId) + }, + { + appIndex: proposalVotingAppId, + name: getAttendanceSheetBoxName(sender, accountAttendanceBoxIndex) + }, + { + appIndex: vaultAppId, + name: getAccountStateBoxName(sender) + }, + { + appIndex: vaultAppId, + name: getAccountPowerBoxName(sender, accountPowerBoxIndex) + }, + { + appIndex: vaultAppId, + name: getAccountPowerBoxName(sender, accountPowerBoxIndex + 1) + } + ]; + + const txns: algosdk.Transaction[] = [ + algosdk.makeApplicationNoOpTxnFromObject({ + from: sender, + suggestedParams, + appIndex: proposalVotingAppId, + appArgs: [ + encodeString("cast_vote"), + encodeString(proposalId), + intToBytes(vote), + intToBytes(accountPowerIndex) + ], + foreignApps: [vaultAppId], + boxes, + note: appCallNote ? encodeString(appCallNote) : undefined + }) + ]; + + // 1 inner txn + txns[0].fee *= 2; + + if (createAttendanceSheetBox) { + const minimumBalancePaymentTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + suggestedParams, + to: getApplicationAddress(proposalVotingAppId), + amount: ATTENDANCE_SHEET_BOX_COST + }); + + txns.unshift(minimumBalancePaymentTxn); + } + + return algosdk.assignGroupID(txns); +} diff --git a/src/governance/proposal-voting/types.ts b/src/governance/proposal-voting/types.ts new file mode 100644 index 00000000..7694761a --- /dev/null +++ b/src/governance/proposal-voting/types.ts @@ -0,0 +1,9 @@ +interface GenerateProposalMetadataPayload { + title: string; + description: string; + category: string; + discussionUrl: string; + pollUrl: string; +} + +export type {GenerateProposalMetadataPayload}; diff --git a/src/governance/rewards/constants.ts b/src/governance/rewards/constants.ts new file mode 100644 index 00000000..e2076e67 --- /dev/null +++ b/src/governance/rewards/constants.ts @@ -0,0 +1,24 @@ +import {encodeString} from "../../util/util"; +import {BOX_BYTE_MIN_BALANCE, BOX_FLAT_MIN_BALANCE} from "../constants"; + +const REWARD_PERIOD_BOX_PREFIX = encodeString("rp"); +const REWARD_CLAIM_SHEET_BOX_SIZE = 1012; +const REWARD_CLAIM_SHEET_BOX_PREFIX = encodeString("c"); + +const REWARD_PERIOD_SIZE = 24; +const REWARD_PERIOD_BOX_SIZE = 1008; +const REWARD_PERIOD_BOX_ARRAY_LEN = 42; + +const REWARD_CLAIM_SHEET_BOX_COST = + // eslint-disable-next-line no-magic-numbers + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (41 + REWARD_CLAIM_SHEET_BOX_SIZE); + +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 +}; diff --git a/src/governance/rewards/storage.ts b/src/governance/rewards/storage.ts new file mode 100644 index 00000000..db377c91 --- /dev/null +++ b/src/governance/rewards/storage.ts @@ -0,0 +1,104 @@ +import {decodeAddress} from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; + +import {intToBytes} from "../util/utils"; +import {REWARD_CLAIM_SHEET_BOX_PREFIX, REWARD_PERIOD_BOX_PREFIX} from "./constants"; +import {getRawBoxValue} from "../utils"; + +class RewardsAppGlobalState { + tinyAssetId: number; + vaultAppId: number; + rewardHistoryCount: number; + firstPeriodTimestamp: number; + rewardPeriodCount: number; + manager: string; + rewardsManager: string; + + // eslint-disable-next-line max-params + constructor( + tinyAssetId: number, + vaultAppId: number, + rewardHistoryCount: number, + firstPeriodTimestamp: number, + rewardPeriodCount: number, + manager: string, + rewardsManager: string + ) { + this.tinyAssetId = tinyAssetId; + this.vaultAppId = vaultAppId; + this.rewardHistoryCount = rewardHistoryCount; + this.firstPeriodTimestamp = firstPeriodTimestamp; + this.rewardPeriodCount = rewardPeriodCount; + this.manager = manager; + this.rewardsManager = rewardsManager; + } +} + +class RewardClaimSheet { + value: Uint8Array; + + constructor(value: Uint8Array) { + this.value = value; + } +} + +function getRewardPeriodBoxName(boxIndex: number): Uint8Array { + const boxIndexBytes = intToBytes(boxIndex); + const combinedArray = new Uint8Array( + REWARD_PERIOD_BOX_PREFIX.length + boxIndexBytes.length + ); + + combinedArray.set(REWARD_PERIOD_BOX_PREFIX, 0); + combinedArray.set(boxIndexBytes, REWARD_PERIOD_BOX_PREFIX.length); + + return combinedArray; +} + +function getAccountRewardClaimSheetBoxName( + address: string, + boxIndex: number +): Uint8Array { + const decodedAddress = decodeAddress(address).publicKey; + const boxIndexBytes = intToBytes(boxIndex); + + const combinedArray = new Uint8Array( + REWARD_CLAIM_SHEET_BOX_PREFIX.length + decodedAddress.length + boxIndexBytes.length + ); + + combinedArray.set(REWARD_CLAIM_SHEET_BOX_PREFIX, 0); + combinedArray.set(decodedAddress, REWARD_CLAIM_SHEET_BOX_PREFIX.length); + combinedArray.set( + boxIndexBytes, + REWARD_CLAIM_SHEET_BOX_PREFIX.length + decodedAddress.length + ); + + return combinedArray; +} + +async function getRewardClaimSheet( + algod: AlgodClient, + appId: number, + address: string, + accountRewardClaimSheetBoxIndex: number +) { + const boxName = getAccountRewardClaimSheetBoxName( + address, + accountRewardClaimSheetBoxIndex + ); + + const rawBox = await getRawBoxValue(algod, appId, boxName); + + if (!rawBox) { + return null; + } + + return new RewardClaimSheet(rawBox); +} + +export { + RewardClaimSheet, + RewardsAppGlobalState, + getRewardPeriodBoxName, + getAccountRewardClaimSheetBoxName, + getRewardClaimSheet +}; diff --git a/src/governance/rewards/transactions.ts b/src/governance/rewards/transactions.ts new file mode 100644 index 00000000..e2ac7d13 --- /dev/null +++ b/src/governance/rewards/transactions.ts @@ -0,0 +1,170 @@ +import algosdk, {SuggestedParams, Transaction, getApplicationAddress} from "algosdk"; + +import {getAccountPowerBoxName, getAccountStateBoxName} from "../vault/storage"; +import { + REWARD_CLAIM_SHEET_BOX_COST, + REWARD_CLAIM_SHEET_BOX_SIZE, + REWARD_PERIOD_BOX_ARRAY_LEN +} from "./constants"; +import {getAccountRewardClaimSheetBoxName, getRewardPeriodBoxName} from "./storage"; +import {ACCOUNT_POWER_BOX_ARRAY_LEN} from "../vault/constants"; +import {intToBytes} from "../util/utils"; +import {prepareBudgetIncreaseTxn} from "../transactions"; +import {concatUint8Arrays} from "../utils"; +import {encodeString} from "../../util/util"; + +function prepareClaimRewardsTransactions({ + rewardsAppId, + vaultAppId, + tinyAssetId, + sender, + periodIndexStart, + periodCount, + accountPowerIndexes, + suggestedParams, + createRewardClaimSheet, + appCallNote +}: { + rewardsAppId: number; + vaultAppId: number; + tinyAssetId: number; + sender: string; + periodIndexStart: number; + periodCount: number; + accountPowerIndexes: number[]; + suggestedParams: SuggestedParams; + createRewardClaimSheet: boolean; + appCallNote?: string; +}): Transaction[] { + let boxes: algosdk.BoxReference[] = []; + const rewardPeriodBoxes: algosdk.BoxReference[] = []; + const accountRewardClaimSheetBoxes: algosdk.BoxReference[] = []; + const accountPowerBoxes: algosdk.BoxReference[] = []; + + for ( + let periodIndex = periodIndexStart; + periodIndex < periodIndexStart + periodCount; + periodIndex++ + ) { + const rewardPeriodBoxIndex = Math.floor(periodIndex / REWARD_PERIOD_BOX_ARRAY_LEN); + const rewardPeriodBoxName = getRewardPeriodBoxName(rewardPeriodBoxIndex); + + if ( + !rewardPeriodBoxes.find( + (box) => box.name.toString() === rewardPeriodBoxName.toString() + ) + ) { + rewardPeriodBoxes.push({appIndex: rewardsAppId, name: rewardPeriodBoxName}); + } + + const accountRewardClaimSheetBoxIndex = Math.floor( + periodIndex / (REWARD_CLAIM_SHEET_BOX_SIZE * 8) + ); + const accountRewardClaimSheetBoxName = getAccountRewardClaimSheetBoxName( + sender, + accountRewardClaimSheetBoxIndex + ); + + if ( + !accountRewardClaimSheetBoxes.find( + (box) => box.name.toString() === accountRewardClaimSheetBoxName.toString() + ) + ) { + accountRewardClaimSheetBoxes.push({ + appIndex: rewardsAppId, + name: accountRewardClaimSheetBoxName + }); + } + } + + for (const accountPowerIndex of accountPowerIndexes) { + const accountPowerBoxIndex = Math.floor( + accountPowerIndex / ACCOUNT_POWER_BOX_ARRAY_LEN + ); + let boxName = getAccountPowerBoxName(sender, accountPowerBoxIndex); + let accountPowerBox = {appIndex: vaultAppId, name: boxName}; + + if (!accountPowerBoxes.find((box) => box.name.toString() === boxName.toString())) { + accountPowerBoxes.push(accountPowerBox); + } + + boxName = getAccountPowerBoxName(sender, accountPowerBoxIndex + 1); + accountPowerBox = {appIndex: vaultAppId, name: boxName}; + + if (!accountPowerBoxes.find((box) => box.name.toString() === boxName.toString())) { + accountPowerBoxes.push(accountPowerBox); + } + } + + boxes = [ + {appIndex: vaultAppId, name: getAccountStateBoxName(sender)}, + ...accountRewardClaimSheetBoxes, + ...rewardPeriodBoxes, + ...accountPowerBoxes + ]; + + if (boxes.length >= 11) { + throw new Error("Boxes' length cannot be larger than 10"); + } + + const txnsBoxes = boxes.slice(0, 6); + const txns = [ + algosdk.makeApplicationNoOpTxnFromObject({ + from: sender, + suggestedParams, + appIndex: rewardsAppId, + appArgs: [ + encodeString("claim_rewards"), + intToBytes(periodIndexStart), + intToBytes(periodCount), + concatUint8Arrays(...accountPowerIndexes.map((number) => intToBytes(number))) + ], + foreignApps: [vaultAppId], + foreignAssets: [tinyAssetId], + boxes: txnsBoxes, + note: appCallNote ? encodeString(appCallNote) : undefined + }) + ]; + + txns[0].fee = txns[0].fee * (periodCount + 2); + + // TODO: Update budget costs according to final code. (backend note) + let increaseBudgetTxnCount = 0; + const requiredOpcodeBudget = 92 + 865 * periodCount; + const opcodeBudget = 700 + 700 * periodCount; + + if (requiredOpcodeBudget > opcodeBudget) { + increaseBudgetTxnCount = Math.floor((requiredOpcodeBudget - opcodeBudget) / 666) + 1; + } + + if (increaseBudgetTxnCount || boxes.length > 6) { + const budgetIncreaseBoxes = boxes.slice(6); + const budgetIncreaseTxn = prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + extraAppArgs: [intToBytes(Math.max(increaseBudgetTxnCount - 1, 0))], + index: rewardsAppId, + foreignApps: [vaultAppId], + boxes: budgetIncreaseBoxes + }); + + budgetIncreaseTxn.fee *= Math.max(increaseBudgetTxnCount, 1); + + txns.unshift(budgetIncreaseTxn); + } + + if (createRewardClaimSheet) { + const minimumBalancePayment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + to: getApplicationAddress(rewardsAppId), + amount: REWARD_CLAIM_SHEET_BOX_COST, + suggestedParams + }); + + txns.unshift(minimumBalancePayment); + } + + return algosdk.assignGroupID(txns); +} + +export {prepareClaimRewardsTransactions}; diff --git a/src/governance/staking-voting/constants.ts b/src/governance/staking-voting/constants.ts new file mode 100644 index 00000000..a251d1d9 --- /dev/null +++ b/src/governance/staking-voting/constants.ts @@ -0,0 +1,27 @@ +import {encodeString} from "../../util/util"; +import {BOX_BYTE_MIN_BALANCE, BOX_FLAT_MIN_BALANCE} from "../constants"; + +const STAKING_VOTE_MAX_OPTION_COUNT = 8; + +// Box +const PROPOSAL_BOX_PREFIX = encodeString("p"); +const STAKING_ATTENDANCE_BOX_PREFIX = encodeString("a"); +const STAKING_VOTE_BOX_PREFIX = encodeString("v"); + +const STAKING_ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE = 24; +const STAKING_VOTE_BOX_SIZE = 8; + +const STAKING_ATTENDANCE_BOX_COST = + BOX_FLAT_MIN_BALANCE + + BOX_BYTE_MIN_BALANCE * (41 + STAKING_ACCOUNT_ATTENDANCE_SHEET_BOX_SIZE); +const STAKING_VOTE_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (17 + STAKING_VOTE_BOX_SIZE); + +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 +}; diff --git a/src/governance/staking-voting/storage.ts b/src/governance/staking-voting/storage.ts new file mode 100644 index 00000000..3786025b --- /dev/null +++ b/src/governance/staking-voting/storage.ts @@ -0,0 +1,100 @@ +import {decodeAddress} from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; + +import {concatUint8Arrays, getRawBoxValue} from "../utils"; +import { + PROPOSAL_BOX_PREFIX, + STAKING_ATTENDANCE_BOX_PREFIX, + STAKING_VOTE_BOX_PREFIX +} from "./constants"; +import {bytesToInt, intToBytes} from "../util/utils"; +import {getProposalBoxName} from "../proposal-voting/storage"; +import {encodeString} from "../../util/util"; + +class StakingDistributionProposal { + index: number; + creationTimestamp: number; + votingStartTimestamp: number; + votingEndTimestamp: number; + votingPower: number; + voteCount: number; + isCancelled: boolean; + + // eslint-disable-next-line max-params + constructor( + index: number, + creationTimestamp: number, + votingStartTimestamp: number, + votingEndTimestamp: number, + votingPower: number, + voteCount: number, + isCancelled: boolean + ) { + this.index = index; + this.creationTimestamp = creationTimestamp; + this.votingStartTimestamp = votingStartTimestamp; + this.votingEndTimestamp = votingEndTimestamp; + this.votingPower = votingPower; + this.voteCount = voteCount; + this.isCancelled = isCancelled; + } +} + +function getStakingDistributionProposalBoxName(proposalId: string): Uint8Array { + return concatUint8Arrays(PROPOSAL_BOX_PREFIX, encodeString(proposalId)); +} + +function getStakingAttendanceSheetBoxName(sender: string, boxIndex: number) { + return concatUint8Arrays( + STAKING_ATTENDANCE_BOX_PREFIX, + decodeAddress(sender).publicKey, + intToBytes(boxIndex) + ); +} + +function getStakingVoteBoxName(proposalIndex: number, assetId: number): Uint8Array { + return concatUint8Arrays( + STAKING_VOTE_BOX_PREFIX, + intToBytes(proposalIndex), + intToBytes(assetId) + ); +} + +function parseBoxStakingDistributionProposal( + rawBox: Uint8Array +): StakingDistributionProposal { + const proposal = new StakingDistributionProposal( + bytesToInt(rawBox.slice(0, 8)), + bytesToInt(rawBox.slice(8, 16)), + bytesToInt(rawBox.slice(16, 24)), + bytesToInt(rawBox.slice(24, 32)), + bytesToInt(rawBox.slice(32, 40)), + bytesToInt(rawBox.slice(40, 48)), + Boolean(bytesToInt(rawBox.slice(48, 49))) + ); + + return proposal; +} + +async function getStakingDistributionProposal( + algod: AlgodClient, + appId: number, + proposalId: string +) { + const boxName = getProposalBoxName(proposalId); + const rawBox = await getRawBoxValue(algod, appId, boxName); + + if (!rawBox) { + return null; + } + + return parseBoxStakingDistributionProposal(rawBox); +} + +export { + StakingDistributionProposal, + getStakingDistributionProposalBoxName, + getStakingAttendanceSheetBoxName, + getStakingVoteBoxName, + getStakingDistributionProposal +}; diff --git a/src/governance/staking-voting/transactions.ts b/src/governance/staking-voting/transactions.ts new file mode 100644 index 00000000..cdcf189b --- /dev/null +++ b/src/governance/staking-voting/transactions.ts @@ -0,0 +1,177 @@ +import { + BoxReference, + SuggestedParams, + assignGroupID, + getApplicationAddress, + makeApplicationNoOpTxnFromObject, + makePaymentTxnWithSuggestedParamsFromObject +} from "algosdk"; + +import { + StakingDistributionProposal, + getStakingAttendanceSheetBoxName, + getStakingDistributionProposalBoxName, + getStakingVoteBoxName +} from "./storage"; +import { + STAKING_VOTE_MAX_OPTION_COUNT, + STAKING_ATTENDANCE_BOX_COST, + STAKING_VOTE_BOX_COST +} from "./constants"; +import {concatUint8Arrays} from "../utils"; +import {areBuffersEqual, intToBytes, sum} from "../util/utils"; +import {getAccountPowerBoxName, getAccountStateBoxName} from "../vault/storage"; +import {ACCOUNT_POWER_BOX_ARRAY_LEN} from "../vault/constants"; +import {prepareBudgetIncreaseTxn} from "../transactions"; +import {encodeString} from "../../util/util"; + +function prepareCastVoteForStakingDistributionProposalTransactions({ + stakingVotingAppId, + vaultAppId, + sender, + proposalId, + proposal, + votes, + assetIds, + accountPowerIndex, + appBoxNames, + suggestedParams, + appCallNote = null +}: { + stakingVotingAppId: number; + vaultAppId: number; + sender: string; + proposalId: string; + proposal: StakingDistributionProposal; + votes: number[]; + assetIds: number[]; + accountPowerIndex: number; + appBoxNames: Uint8Array[]; + suggestedParams: SuggestedParams; + appCallNote: string | null; +}) { + if (votes.length !== assetIds.length) { + throw new Error("The number of votes must be equal to the number of asset ids"); + } + + if (assetIds.length > STAKING_VOTE_MAX_OPTION_COUNT) { + throw new Error( + `You cannot cast vote for more than ${STAKING_VOTE_MAX_OPTION_COUNT} different pools` + ); + } + + if (sum(votes) !== 100) { + throw new Error("The sum of the votes must equal 100%"); + } + + const argVotes = concatUint8Arrays(...votes.map((vote) => intToBytes(vote))); + const argAssetIds = concatUint8Arrays( + ...assetIds.map((assetId) => intToBytes(assetId)) + ); + + const proposalBoxName = getStakingDistributionProposalBoxName(proposalId); + + const accountAttendanceSheetBoxIndex = Math.floor(proposal.index / (1024 * 8)); + const accountAttendanceSheetBoxName = getStakingAttendanceSheetBoxName( + sender, + accountAttendanceSheetBoxIndex + ); + const createAttendanceSheetBox = !appBoxNames.some((appBoxName) => + areBuffersEqual(appBoxName, accountAttendanceSheetBoxName) + ); + + const accountStateBoxName = getAccountStateBoxName(sender); + const accountPowerBoxIndex = Math.floor( + accountPowerIndex / ACCOUNT_POWER_BOX_ARRAY_LEN + ); + const accountPowerBoxName = getAccountPowerBoxName(sender, accountPowerBoxIndex); + const nextAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountPowerBoxIndex + 1 + ); + + let newAssetCount = 0; + const voteBoxes: BoxReference[] = []; + + for (const assetId of assetIds) { + const voteBoxName = getStakingVoteBoxName(proposal.index, assetId); + + voteBoxes.push({appIndex: stakingVotingAppId, name: voteBoxName}); + if (!appBoxNames.some((appBoxName) => areBuffersEqual(appBoxName, voteBoxName))) { + newAssetCount += 1; + } + } + + const boxes: BoxReference[] = [ + {appIndex: stakingVotingAppId, name: proposalBoxName}, + {appIndex: stakingVotingAppId, name: accountAttendanceSheetBoxName}, + ...voteBoxes, + {appIndex: vaultAppId, name: accountStateBoxName}, + {appIndex: vaultAppId, name: accountPowerBoxName}, + {appIndex: vaultAppId, name: nextAccountPowerBoxName} + ]; + + let txns = [ + makeApplicationNoOpTxnFromObject({ + from: sender, + suggestedParams, + appIndex: stakingVotingAppId, + appArgs: [ + encodeString("cast_vote"), + encodeString(proposalId), + argVotes, + argAssetIds, + intToBytes(accountPowerIndex) + ], + foreignApps: [vaultAppId], + boxes: boxes.slice(0, 7), + note: appCallNote ? encodeString(appCallNote) : undefined + }) + ]; + + txns[0].fee *= 2; + + if (boxes.length >= 7) { + txns.push( + prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + index: vaultAppId, + foreignApps: [stakingVotingAppId], + boxes: boxes.slice(7, 14) + }) + ); + } + + if (boxes.length >= 14) { + txns.push( + prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + index: vaultAppId, + foreignApps: [stakingVotingAppId], + boxes: boxes.slice(14) + }) + ); + } + + const paymentAmount = + Number(createAttendanceSheetBox) * STAKING_ATTENDANCE_BOX_COST + + newAssetCount * STAKING_VOTE_BOX_COST; + + if (paymentAmount) { + txns = [ + makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + suggestedParams, + to: getApplicationAddress(stakingVotingAppId), + amount: paymentAmount + }), + ...txns + ]; + } + + return assignGroupID(txns); +} + +export {prepareCastVoteForStakingDistributionProposalTransactions}; diff --git a/src/governance/transactions.ts b/src/governance/transactions.ts new file mode 100644 index 00000000..1ee4af5b --- /dev/null +++ b/src/governance/transactions.ts @@ -0,0 +1,41 @@ +import algosdk, {SuggestedParams} from "algosdk"; +import {v4} from "uuid"; + +import {encodeString} from "../util/util"; + +function prepareBudgetIncreaseTxn({ + sender, + index, + suggestedParams, + boxes = [], + extraAppArgs = [], + foreignApps = [] +}: { + sender: string; + index: number; + suggestedParams: SuggestedParams; + extraAppArgs?: Uint8Array[]; + foreignApps?: number[]; + boxes?: algosdk.BoxReference[]; +}) { + const emptyBoxesCount = Math.max(0, 8 - foreignApps.length - boxes.length); + const emptyBoxes = Array(emptyBoxesCount).fill({ + appIndex: 0, + name: encodeString("") + }); + + const increaseBudgetTxnsBoxes = [...boxes, ...emptyBoxes]; + + return algosdk.makeApplicationNoOpTxnFromObject({ + from: sender, + suggestedParams, + appIndex: index, + appArgs: [encodeString("increase_budget"), ...extraAppArgs], + foreignApps, + boxes: increaseBudgetTxnsBoxes, + // Make transactions unique to avoid "transaction already in ledger" error + note: encodeString(v4()) + }); +} + +export {prepareBudgetIncreaseTxn}; diff --git a/src/governance/types.ts b/src/governance/types.ts new file mode 100644 index 00000000..ff649373 --- /dev/null +++ b/src/governance/types.ts @@ -0,0 +1,8 @@ +export interface RawBoxCacheValue { + [key: string]: Uint8Array; +} + +export interface GetRawBoxValueCacheProps { + onCacheUpdate: (cacheData: RawBoxCacheValue) => void; + cacheData: RawBoxCacheValue | null; +} diff --git a/src/governance/util/utils.ts b/src/governance/util/utils.ts new file mode 100644 index 00000000..27a7560c --- /dev/null +++ b/src/governance/util/utils.ts @@ -0,0 +1,35 @@ +/* eslint-disable no-bitwise */ +export function intToBytes(num: number, length = 8): Uint8Array { + const byteArray = new Uint8Array(length); + let newNum = num; + + for (let i = length - 1; i >= 0; i--) { + byteArray[i] = newNum & 0xff; + newNum >>= 8; + } + + return byteArray; +} + +export function areBuffersEqual(buf1: Uint8Array, buf2: Uint8Array) { + return Buffer.compare(buf1, buf2) === 0; +} + +export function bytesToInt(buffer: Uint8Array): number { + let num = 0; + + for (let i = 0; i < buffer.byteLength; i++) { + const byte = buffer[i]; + + num *= 0x100; + num += byte; + } + + return num; +} + +export function sum(values: number[]): number { + return values.reduce((total, value) => total + value, 0); +} + +/* eslint-enable no-bitwise */ diff --git a/src/governance/utils.ts b/src/governance/utils.ts new file mode 100644 index 00000000..7fb33ed6 --- /dev/null +++ b/src/governance/utils.ts @@ -0,0 +1,204 @@ +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; +import {CID} from "multiformats"; +/* eslint-disable import/no-unresolved */ +import {sha256} from "multiformats/hashes/sha2"; +import {code} from "multiformats/codecs/raw"; +import {base32} from "multiformats/bases/base32"; +/* eslint-enable import/no-unresolved */ +import { + Transaction, + assignGroupID, + decodeUnsignedTransaction, + encodeUnsignedTransaction +} from "algosdk"; + +import {TWO_TO_THE_64} from "./vault/constants"; +import {getSlope} from "./vault/utils"; +import {GetRawBoxValueCacheProps} from "./types"; + +async function getRawBoxValue( + algod: AlgodClient, + appId: number, + boxName: Uint8Array, + cacheProps?: GetRawBoxValueCacheProps +) { + try { + const boxNameString = Buffer.from(boxName).toString("base64"); + + if (cacheProps?.cacheData && cacheProps.cacheData[boxNameString]) { + return Uint8Array.from(Object.values(cacheProps.cacheData[boxNameString])); + } + + const {value} = await algod.getApplicationBoxByName(appId, boxName).do(); + + if (cacheProps?.onCacheUpdate) { + const newCacheData = {...cacheProps.cacheData, [boxNameString]: value}; + + cacheProps.onCacheUpdate(newCacheData); + } + + return value; + } catch (error: any) { + if ( + error.message === "Network request error. Received status 404 (): box not found" + ) { + return null; + } + + throw error; + } +} + +async function doesBoxExist( + algod: AlgodClient, + appId: number, + boxName: Uint8Array +): Promise { + try { + const value = await getRawBoxValue(algod, appId, boxName); + + return Boolean(value); + } catch (error: any) { + return false; + } +} + +function getBias(slope: number, timeDelta: number) { + if (timeDelta < 0) { + throw new Error("Time delta must be greater than or equal to 0"); + } + + return Math.floor((slope * timeDelta) / TWO_TO_THE_64); +} + +/** + * Calculates the tiny power at a given timestamp + * @param lockAmount - amount of tokens locked + * @param lockEndTime - timestamp of the end of the lock, in seconds + * @param timeStamp - timestamp of the time to calculate the tiny power for, in seconds + * @returns tiny power at the given timestamp + */ +function calculateTinyPower( + lockAmount: number, + lockEndTime: number, + timeStamp: number = Math.floor(Date.now() / 1000) +) { + const slope = getSlope(lockAmount); + const timeDelta = lockEndTime - timeStamp; + + return timeDelta < 0 ? 0 : getBias(slope, timeDelta); +} + +function getCumulativePowerDelta(bias: number, slope: number, timeDelta: number) { + let biasDelta = getBias(slope, timeDelta); + + if (biasDelta > bias) { + if (slope) { + biasDelta = (bias * bias * TWO_TO_THE_64) / (slope * 2); + } else { + biasDelta = 0; + } + } else { + const newBias = bias - biasDelta; + + biasDelta = ((bias + newBias) * timeDelta) / 2; + } + + return biasDelta; +} + +async function getGlobalState(algod: AlgodClient, appId: number) { + const applicationInfo = await algod.getApplicationByID(appId).do(); + + return parseGlobalStateFromApplicationInfo(applicationInfo); +} + +function parseGlobalStateFromApplicationInfo(applicationInfo: Record) { + const rawGlobalState = applicationInfo.params["global-state"]; + + const globalState: Record = {}; + + for (const pair of rawGlobalState) { + const key = Buffer.from(pair.key, "base64").toString(); + + let value; + + if (pair.value.type === 1) { + value = Buffer.from(pair.value.bytes || "", "base64"); + } else { + value = pair.value.uint || 0; + } + + globalState[key] = value; + } + + return globalState; +} + +// Move this function to global 'utils' folder +function concatUint8Arrays(...arrays: Uint8Array[]): Uint8Array { + const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0); + const result = new Uint8Array(totalLength); + let offset = 0; + + for (const arr of arrays) { + result.set(arr, offset); + offset += arr.length; + } + return result; +} + +function serializeMetadata(metadata: Record) { + return JSON.stringify(metadata, Object.keys(metadata).sort(), 0); +} + +async function generateCidFromSerializedMetadata(serializedMetadata: string) { + const bytes = new TextEncoder().encode(serializedMetadata); + const digest = await sha256.digest(bytes); + const cid = CID.createV1(code, digest); + + return cid.toString(base32); +} + +function generateCidFromProposalMetadata(metadata: Record) { + return generateCidFromSerializedMetadata(serializeMetadata(metadata)); +} +function combineAndRegroupTxns(...txns: Transaction[][]): Transaction[] { + const flattenedOldTxns = txns.flat(); + + // Remove the group data from the transactions + const degroupedTxns = flattenedOldTxns.map((txn) => { + txn.group = undefined; + + /** + * We do first encode and then decode, to make sure it's still an instance of Transaction + * Otherwise, algosdk will try to create a new instance of Transaction, + * and that will cause an error ("malformed address") + */ + return decodeUnsignedTransaction(encodeUnsignedTransaction(txn)); + }); + + // Assign a new group ID to the combined transactions + const newTxnGroup = assignGroupID(degroupedTxns); + + return newTxnGroup; +} + +async function getAllBoxNames(algod: AlgodClient, appId: number) { + const response = await algod.getApplicationBoxes(appId).do(); + + return response.boxes.map((box) => box.name); +} + +export { + getRawBoxValue, + getCumulativePowerDelta, + getBias, + getGlobalState, + concatUint8Arrays, + doesBoxExist, + getAllBoxNames, + generateCidFromProposalMetadata, + combineAndRegroupTxns, + calculateTinyPower +}; diff --git a/src/governance/vault/constants.ts b/src/governance/vault/constants.ts new file mode 100644 index 00000000..2ee90b4e --- /dev/null +++ b/src/governance/vault/constants.ts @@ -0,0 +1,52 @@ +import {encodeString} from "../../util/util"; +import {BOX_FLAT_MIN_BALANCE, BOX_BYTE_MIN_BALANCE} from "../constants"; + +const MAX_LOCK_TIME = 126_144_000; +const MIN_LOCK_AMOUNT = 10_000_000; +const MIN_LOCK_AMOUNT_INCREMENT = 10_000_000; +const TWO_TO_THE_64 = 2 ** 64; + +const ACCOUNT_STATE_BOX_SIZE = 32; +const SLOPE_CHANGE_BOX_SIZE = 16; + +const ACCOUNT_POWER_SIZE = 48; +const ACCOUNT_POWER_BOX_SIZE = 1008; +const ACCOUNT_POWER_BOX_ARRAY_LEN = 21; + +const TOTAL_POWER_SIZE = 48; +const TOTAL_POWER_BOX_SIZE = 1008; +const TOTAL_POWER_BOX_ARRAY_LEN = 21; + +// Boxes +const TOTAL_POWERS = encodeString("tp"); +const SLOPE_CHANGES = encodeString("sc"); + +const ACCOUNT_STATE_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (32 + ACCOUNT_STATE_BOX_SIZE); +const SLOPE_CHANGE_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (10 + SLOPE_CHANGE_BOX_SIZE); +const ACCOUNT_POWER_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (40 + ACCOUNT_POWER_BOX_SIZE); +const TOTAL_POWER_BOX_COST = + BOX_FLAT_MIN_BALANCE + BOX_BYTE_MIN_BALANCE * (10 + TOTAL_POWER_BOX_SIZE); + +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 +}; diff --git a/src/governance/vault/storage.ts b/src/governance/vault/storage.ts new file mode 100644 index 00000000..d2519762 --- /dev/null +++ b/src/governance/vault/storage.ts @@ -0,0 +1,369 @@ +import {bytesToBigInt, decodeAddress} from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; + +import {concatUint8Arrays, getCumulativePowerDelta, getRawBoxValue} from "../utils"; +import { + ACCOUNT_POWER_BOX_ARRAY_LEN, + ACCOUNT_POWER_SIZE, + SLOPE_CHANGES, + TOTAL_POWERS, + TOTAL_POWER_SIZE +} from "./constants"; +import {intToBytes} from "../util/utils"; +import {GetRawBoxValueCacheProps} from "../types"; + +class AccountState { + lockedAmount: number; + lockEndTime: number; + powerCount: number; + deletedPowerCount: number; + + constructor( + lockedAmount: number, + lockEndTime: number, + powerCount: number, + deletedPowerCount: number + ) { + this.lockedAmount = lockedAmount; + this.lockEndTime = lockEndTime; + this.powerCount = powerCount; + this.deletedPowerCount = deletedPowerCount; + } + + get freeAccountPowerSpaceCount() { + const remainder = this.powerCount % ACCOUNT_POWER_BOX_ARRAY_LEN; + + if (remainder > 0) { + return ACCOUNT_POWER_BOX_ARRAY_LEN - remainder; + } + + return 0; + } + + get lastAccountPowerBoxIndex() { + return getLastAccountPowerBoxIndexes(this.powerCount)[0]; + } + + get lastAccountPowerArrayIndex() { + return getLastAccountPowerBoxIndexes(this.powerCount)[1]; + } +} + +class AccountPower { + bias: number; + timestamp: number; + slope: number; + cumulativePower: number; + + constructor(bias: number, timestamp: number, slope: number, cumulativePower: number) { + this.bias = bias; + this.timestamp = timestamp; + this.slope = slope; + this.cumulativePower = cumulativePower; + } + + get lockEndTimestamp() { + const lockDuration = (this.bias * 2 ** 64) / this.slope; + + return this.timestamp + lockDuration; + } + + cumulativePowerAt(timestamp: number) { + const timeDelta = timestamp - this.timestamp; + + if (timeDelta < 0) { + throw new Error("Time delta must be greater than or equal to 0"); + } + + return ( + this.cumulativePower + getCumulativePowerDelta(this.bias, this.slope, timeDelta) + ); + } +} + +class TotalPower { + bias: number; + timestamp: number; + slope: number; + cumulativePower: number; + + constructor(bias: number, timestamp: number, slope: number, cumulativePower: number) { + this.bias = bias; + this.timestamp = timestamp; + this.slope = slope; + this.cumulativePower = cumulativePower; + } +} + +class SlopeChange { + slopeDelta?: number; + + constructor(slopeDelta?: number) { + this.slopeDelta = slopeDelta; + } +} + +class VaultAppGlobalState { + // eslint-disable-next-line no-useless-constructor + constructor( + public tinyAssetId: number, + public totalLockedAmount: number, + public totalPowerCount: number, + public lastTotalPowerTimestamp: number + ) {} + + get freeTotalPowerSpaceCount() { + const remainder = this.totalPowerCount % ACCOUNT_POWER_BOX_ARRAY_LEN; + + return remainder > 0 ? ACCOUNT_POWER_BOX_ARRAY_LEN - remainder : 0; + } + + get lastTotalPowerBoxIndex() { + return getLastAccountPowerBoxIndexes(this.totalPowerCount)[0]; + } + + get lastTotalPowerArrayIndex() { + return getLastAccountPowerBoxIndexes(this.totalPowerCount)[1]; + } +} + +async function getAccountState(algodClient: AlgodClient, appId: number, address: string) { + const boxName = getAccountStateBoxName(address); + + try { + const rawBox = await getRawBoxValue(algodClient, appId, boxName); + + if (rawBox) { + return parseBoxAccountState(rawBox); + } + + return null; + } catch (error) { + console.log(error); + return null; + } +} + +function parseBoxAccountState(rawBox: Uint8Array): AccountState { + const buffer = Buffer.from(rawBox); + + return new AccountState( + buffer.readUIntBE(0, 8), + buffer.readUIntBE(8, 8), + buffer.readUIntBE(16, 8), + buffer.readUIntBE(24, 8) + ); +} + +function getAccountStateBoxName(address: string): Uint8Array { + return decodeAddress(address).publicKey; +} + +function getTotalPowerBoxName(boxIndex: number): Uint8Array { + const boxIndexBytes = intToBytes(boxIndex); + const combinedArray = new Uint8Array(TOTAL_POWERS.length + boxIndexBytes.length); + + combinedArray.set(TOTAL_POWERS, 0); + combinedArray.set(boxIndexBytes, TOTAL_POWERS.length); + + return combinedArray; +} + +function getLastAccountPowerBoxIndexes(powerCount: number): [number, number] { + const lastIndex = powerCount - 1; + const boxIndex = Math.floor(lastIndex / ACCOUNT_POWER_BOX_ARRAY_LEN); + const arrayIndex = lastIndex % ACCOUNT_POWER_BOX_ARRAY_LEN; + + return [boxIndex, arrayIndex]; +} + +function getAccountPowerBoxName(address: string, boxIndex: number) { + const decodedAddress = decodeAddress(address).publicKey; + const boxIndexBytes = intToBytes(boxIndex); + + const combinedArray = new Uint8Array(decodedAddress.length + boxIndexBytes.length); + + combinedArray.set(decodedAddress, 0); + combinedArray.set(boxIndexBytes, decodedAddress.length); + + return combinedArray; +} + +async function getSlopeChange(algod: AlgodClient, appId: number, timeStamp: number) { + const boxName = getSlopeChangeBoxName(timeStamp); + + const rawBox = await getRawBoxValue(algod, appId, boxName); + + if (!rawBox) { + return null; + } + + return parseBoxSlopeChange(rawBox); +} + +function parseBoxSlopeChange(rawBox: Uint8Array) { + return new SlopeChange( + Number(bytesToBigInt(rawBox.slice(rawBox.length - 16, rawBox.length))) + ); +} + +function getSlopeChangeBoxName(timestamp: number) { + return concatUint8Arrays(SLOPE_CHANGES, intToBytes(timestamp)); +} + +async function getAllTotalPowers( + algodClient: AlgodClient, + appId: number, + totalPowerCount: number, + cacheProps?: GetRawBoxValueCacheProps +): Promise { + let boxCount = 0; + + if (totalPowerCount) { + boxCount = Math.ceil(totalPowerCount / ACCOUNT_POWER_BOX_ARRAY_LEN); + } + + const totalPowers: TotalPower[] = []; + + for (let boxIndex = 0; boxIndex < boxCount; boxIndex++) { + const boxName = getTotalPowerBoxName(boxIndex); + const rawBox = await getRawBoxValue(algodClient, appId, boxName, cacheProps); + + if (rawBox) { + totalPowers.push(...parseBoxTotalPower(rawBox)); + } + } + + return totalPowers; +} + +function parseBoxTotalPower(rawBox: Uint8Array) { + const boxSize = TOTAL_POWER_SIZE; + + const rows: Uint8Array[] = []; + + let rawBoxSubArray: Uint8Array; + + for (let i = 0; i < rawBox.length; i += boxSize) { + rawBoxSubArray = rawBox.slice(i, i + boxSize); + + rows.push(rawBoxSubArray); + } + + const powers: TotalPower[] = []; + + for (const row of rows) { + if (row.every((byte) => byte === 0x00)) { + break; + } + + const buffer = Buffer.from(row); + + powers.push( + new TotalPower( + buffer.readUIntBE(0, 8), + buffer.readUIntBE(8, 8), + buffer.readUIntBE(16, 16), + buffer.readUIntBE(32, 16) + ) + ); + } + + return powers; +} + +async function getAccountPowers( + algodClient: AlgodClient, + address: string, + appId: number, + powerCount: number | null = null, + cacheProps?: GetRawBoxValueCacheProps +) { + let boxCount = 0; + + if (powerCount) { + boxCount = Math.ceil(powerCount / ACCOUNT_POWER_BOX_ARRAY_LEN); + } + + const accountPowers: AccountPower[] = []; + + for (let boxIndex = 0; boxIndex < boxCount; boxIndex++) { + const boxName = getAccountPowerBoxName(address, boxIndex); + const rawBox = await getRawBoxValue(algodClient, appId, boxName, cacheProps); + + if (rawBox) { + accountPowers.push(...parseBoxAccountPower(rawBox)); + } + } + + return accountPowers; +} + +function getPowerIndexAt(powers: AccountPower[] | TotalPower[], timestamp: number) { + let powerIndex: number | null = null; + + for (let index = 0; index < powers.length; index++) { + const power = powers[index]; + + if (timestamp >= power.timestamp) { + powerIndex = index; + } else { + break; + } + } + + return powerIndex; +} + +function parseBoxAccountPower(rawBox: Uint8Array) { + const boxSize = ACCOUNT_POWER_SIZE; + + const rows: Uint8Array[] = []; + + let rawBoxSubArray: Uint8Array; + + for (let i = 0; i < rawBox.length; i += boxSize) { + rawBoxSubArray = rawBox.slice(i, i + boxSize); + + rows.push(rawBoxSubArray); + } + + const powers: AccountPower[] = []; + + for (const row of rows) { + if (row.every((byte) => byte === 0x00)) { + break; + } + + const buffer = Buffer.from(row); + + powers.push( + new AccountPower( + buffer.readUIntBE(0, 8), + buffer.readUIntBE(8, 8), + buffer.readUIntBE(16, 16), + buffer.readUIntBE(32, 16) + ) + ); + } + + return powers; +} + +export { + AccountState, + AccountPower, + TotalPower, + VaultAppGlobalState, + SlopeChange, + getAccountState, + getAccountPowers, + getAccountPowerBoxName, + getAccountStateBoxName, + getLastAccountPowerBoxIndexes, + getPowerIndexAt, + getTotalPowerBoxName, + getSlopeChangeBoxName, + getSlopeChange, + getAllTotalPowers +}; diff --git a/src/governance/vault/transactions.ts b/src/governance/vault/transactions.ts new file mode 100644 index 00000000..dda0b4be --- /dev/null +++ b/src/governance/vault/transactions.ts @@ -0,0 +1,479 @@ +import algosdk, {SuggestedParams} from "algosdk"; +import AlgodClient from "algosdk/dist/types/client/v2/algod/algod"; + +import {VAULT_APP_ID, WEEK} from "../constants"; +import { + ACCOUNT_POWER_BOX_COST, + ACCOUNT_STATE_BOX_COST, + MIN_LOCK_AMOUNT, + SLOPE_CHANGE_BOX_COST, + TOTAL_POWER_BOX_COST +} from "./constants"; +import { + AccountState, + SlopeChange, + VaultAppGlobalState, + getAccountPowerBoxName, + getAccountStateBoxName, + getSlopeChangeBoxName, + getTotalPowerBoxName +} from "./storage"; +import {prepareBudgetIncreaseTxn} from "../transactions"; +import {getNewTotalPowerTimestamps} from "./utils"; +import {intToBytes} from "../util/utils"; +import {SupportedNetwork} from "../../util/commonTypes"; +import {encodeString} from "../../util/util"; +import {TINY_ASSET_ID} from "../../util/asset/assetConstants"; + +function prepareCreateLockTransactions({ + accountState, + lockEndTime, + lockedAmount, + network, + sender, + vaultAppGlobalState, + suggestedParams, + slopeChangeAtLockEndTime, + appCallNote +}: { + network: SupportedNetwork; + sender: string; + lockedAmount: number; + lockEndTime: number; + vaultAppGlobalState: VaultAppGlobalState; + suggestedParams: SuggestedParams; + accountState?: AccountState | null; + slopeChangeAtLockEndTime?: SlopeChange | null; + appCallNote?: Uint8Array; +}) { + if (lockedAmount < MIN_LOCK_AMOUNT) { + throw new Error("Insufficient lock amount"); + } + + if (lockEndTime % WEEK !== 0) { + throw new Error("Invalid lock end time"); + } + + const vaultAppId = VAULT_APP_ID[network]; + + // Boxes + const accountStateBoxName = getAccountStateBoxName(sender); + const lastTotalPowerBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + ); + const nextTotalPowerBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + 1 + ); + const boxes: algosdk.BoxReference[] = [ + {appIndex: vaultAppId, name: accountStateBoxName}, + {appIndex: vaultAppId, name: lastTotalPowerBoxName}, + // Always pass the next total power box ref, other transactions may increase the total power count. + {appIndex: vaultAppId, name: nextTotalPowerBoxName} + ]; + + if (accountState) { + const lastAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + ); + + boxes.push({appIndex: vaultAppId, name: lastAccountPowerBoxName}); + + if (!accountState.freeAccountPowerSpaceCount) { + const nextAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + 1 + ); + + boxes.push({appIndex: vaultAppId, name: nextAccountPowerBoxName}); + } + } else { + const accountPowerBoxName = getAccountPowerBoxName(sender, 0); + + boxes.push({appIndex: vaultAppId, name: accountPowerBoxName}); + } + + // slope change will be updated or created for lock end time + const slopeChangeBoxName = getSlopeChangeBoxName(lockEndTime); + + boxes.push({appIndex: vaultAppId, name: slopeChangeBoxName}); + + // contract will create weekly checkpoints automatically + const newTotalPowerTimestamps = getNewTotalPowerTimestamps( + vaultAppGlobalState.lastTotalPowerTimestamp, + Date.now() / 1000 + ); + const newTotalPowerCount = newTotalPowerTimestamps.length; + + for (const timestamp of newTotalPowerTimestamps) { + if (timestamp % WEEK === 0) { + const newTimestampSlopeChangeBoxName = getSlopeChangeBoxName(timestamp); + + boxes.push({appIndex: vaultAppId, name: newTimestampSlopeChangeBoxName}); + } + } + + // Min Balance + let minBalanceIncrease = 0; + + if (!accountState) { + minBalanceIncrease += ACCOUNT_STATE_BOX_COST; + minBalanceIncrease += ACCOUNT_POWER_BOX_COST; + } else if (!accountState.freeAccountPowerSpaceCount) { + minBalanceIncrease += ACCOUNT_POWER_BOX_COST; + } + + if (newTotalPowerCount > vaultAppGlobalState.freeTotalPowerSpaceCount) { + minBalanceIncrease += TOTAL_POWER_BOX_COST; + } + + if (!slopeChangeAtLockEndTime) { + minBalanceIncrease += SLOPE_CHANGE_BOX_COST; + } + + const txns = [ + algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({ + amount: lockedAmount, + assetIndex: TINY_ASSET_ID[network], + from: sender, + suggestedParams, + to: algosdk.getApplicationAddress(vaultAppId) + }), + algosdk.makeApplicationNoOpTxnFromObject({ + appIndex: vaultAppId, + from: sender, + suggestedParams, + appArgs: [encodeString("create_lock"), intToBytes(lockEndTime)], + boxes: boxes.slice(0, 8), + note: appCallNote + }), + prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + index: vaultAppId, + boxes: boxes.slice(8) + }) + ]; + + if (minBalanceIncrease) { + const minimumBalancePayment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + amount: minBalanceIncrease, + from: sender, + suggestedParams, + to: algosdk.getApplicationAddress(vaultAppId) + }); + + txns.unshift(minimumBalancePayment); + } + + const txnGroup = algosdk.assignGroupID(txns); + + return txnGroup; +} + +function prepareIncreaseLockAmountTransactions({ + accountState, + lockedAmount, + network, + sender, + vaultAppGlobalState, + suggestedParams, + appCallNote +}: { + network: SupportedNetwork; + sender: string; + lockedAmount: number; + vaultAppGlobalState: VaultAppGlobalState; + accountState: AccountState; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}) { + if (lockedAmount < MIN_LOCK_AMOUNT) { + throw new Error("Insufficient lock amount"); + } + + // Boxes + const accountStateBoxName = getAccountStateBoxName(sender); + const accountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + ); + const totalPowersBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + ); + const nextTotalPowersBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + 1 + ); + let slopeChangeBoxName = getSlopeChangeBoxName(accountState.lockEndTime); + + const boxes: algosdk.BoxReference[] = [ + {appIndex: VAULT_APP_ID[network], name: accountStateBoxName}, + {appIndex: VAULT_APP_ID[network], name: accountPowerBoxName}, + {appIndex: VAULT_APP_ID[network], name: totalPowersBoxName}, + {appIndex: VAULT_APP_ID[network], name: nextTotalPowersBoxName}, + {appIndex: VAULT_APP_ID[network], name: slopeChangeBoxName} + ]; + + // contract will create weekly checkpoints automatically + const newTotalPowerTimestamps = getNewTotalPowerTimestamps( + vaultAppGlobalState.lastTotalPowerTimestamp, + Date.now() / 1000 + ); + const newTotalPowerCount = newTotalPowerTimestamps.length; + + for (const timestamp of newTotalPowerTimestamps) { + if (timestamp % WEEK === 0) { + slopeChangeBoxName = getSlopeChangeBoxName(timestamp); + + boxes.push({appIndex: VAULT_APP_ID[network], name: slopeChangeBoxName}); + } + } + + // Min Balance + let minBalanceIncrease = 0; + + if (newTotalPowerCount > vaultAppGlobalState.freeTotalPowerSpaceCount) { + minBalanceIncrease += TOTAL_POWER_BOX_COST; + } + + if (!accountState.freeAccountPowerSpaceCount) { + const newAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + 1 + ); + + boxes.push({appIndex: VAULT_APP_ID[network], name: newAccountPowerBoxName}); + minBalanceIncrease += ACCOUNT_POWER_BOX_COST; + } + + const txns = [ + algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({ + assetIndex: TINY_ASSET_ID[network], + from: sender, + to: algosdk.getApplicationAddress(VAULT_APP_ID[network]), + amount: lockedAmount, + suggestedParams + }), + algosdk.makeApplicationNoOpTxnFromObject({ + appIndex: VAULT_APP_ID[network], + from: sender, + suggestedParams, + appArgs: [encodeString("increase_lock_amount")], + boxes, + note: appCallNote + }), + prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + index: VAULT_APP_ID[network] + }) + ]; + + if (minBalanceIncrease) { + const minimumBalancePayment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + suggestedParams, + to: algosdk.getApplicationAddress(VAULT_APP_ID[network]), + amount: minBalanceIncrease + }); + + txns.unshift(minimumBalancePayment); + } + + const txnGroup = algosdk.assignGroupID(txns); + + return txnGroup; +} + +function prepareExtendLockEndTimeTransactions({ + accountState, + network, + newLockEndTime, + slopeChangeAtNewLockEndTime, + sender, + vaultAppGlobalState, + suggestedParams, + appCallNote +}: { + network: SupportedNetwork; + sender: string; + newLockEndTime: number; + vaultAppGlobalState: VaultAppGlobalState; + accountState: AccountState; + slopeChangeAtNewLockEndTime?: number; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}) { + if (newLockEndTime % WEEK) { + throw new Error("Invalid lock end time"); + } + + if (newLockEndTime <= accountState.lockEndTime) { + throw new Error("New lock end time must be greater than current lock end time"); + } + + // Boxes + const accountStateBoxName = getAccountStateBoxName(sender); + const accountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + ); + const totalPowersBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + ); + const nextTotalPowersBoxName = getTotalPowerBoxName( + vaultAppGlobalState.lastTotalPowerBoxIndex + 1 + ); + const currentAccountSlopeChangeBoxName = getSlopeChangeBoxName( + accountState.lockEndTime + ); + const newAccountSlopeChangeBoxName = getSlopeChangeBoxName(newLockEndTime); + + const boxes: algosdk.BoxReference[] = [ + {appIndex: VAULT_APP_ID[network], name: accountStateBoxName}, + {appIndex: VAULT_APP_ID[network], name: accountPowerBoxName}, + {appIndex: VAULT_APP_ID[network], name: totalPowersBoxName}, + {appIndex: VAULT_APP_ID[network], name: nextTotalPowersBoxName}, + {appIndex: VAULT_APP_ID[network], name: currentAccountSlopeChangeBoxName}, + {appIndex: VAULT_APP_ID[network], name: newAccountSlopeChangeBoxName} + ]; + + if (!accountState.freeAccountPowerSpaceCount) { + const newAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + 1 + ); + + boxes.push({appIndex: VAULT_APP_ID[network], name: newAccountPowerBoxName}); + } + + // contract will create weekly checkpoints automatically + const newTotalPowerTimestamps = getNewTotalPowerTimestamps( + vaultAppGlobalState.lastTotalPowerTimestamp, + Math.floor(Date.now() / 1000) + ); + const newTotalPowerCount = newTotalPowerTimestamps.length; + + for (const timestamp of newTotalPowerTimestamps) { + if (timestamp % WEEK === 0) { + const slopeChangeBoxName = getSlopeChangeBoxName(timestamp); + + boxes.push({appIndex: VAULT_APP_ID[network], name: slopeChangeBoxName}); + } + } + + // Min Balance + let minBalanceIncrease = 0; + + if (!slopeChangeAtNewLockEndTime) { + minBalanceIncrease += SLOPE_CHANGE_BOX_COST; + } + + if (!accountState.freeAccountPowerSpaceCount) { + minBalanceIncrease += ACCOUNT_POWER_BOX_COST; + } + + if (newTotalPowerCount > vaultAppGlobalState.freeTotalPowerSpaceCount) { + minBalanceIncrease += TOTAL_POWER_BOX_COST; + } + + const txns = [ + algosdk.makeApplicationNoOpTxnFromObject({ + appIndex: VAULT_APP_ID[network], + from: sender, + suggestedParams, + appArgs: [encodeString("extend_lock_end_time"), intToBytes(newLockEndTime)], + boxes: boxes.slice(0, 8), + note: appCallNote + }), + prepareBudgetIncreaseTxn({ + sender, + suggestedParams, + index: VAULT_APP_ID[network], + boxes: boxes.slice(8) + }) + ]; + + if (minBalanceIncrease) { + const minimumBalancePayment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + suggestedParams, + to: algosdk.getApplicationAddress(VAULT_APP_ID[network]), + amount: minBalanceIncrease + }); + + txns.unshift(minimumBalancePayment); + } + + const txnGroup = algosdk.assignGroupID(txns); + + return txnGroup; +} + +function prepareWithdrawTransactions({ + accountState, + network, + sender, + suggestedParams, + appCallNote +}: { + network: SupportedNetwork; + client: AlgodClient; + sender: string; + accountState: AccountState; + suggestedParams: SuggestedParams; + appCallNote?: Uint8Array; +}) { + // Boxes + const accountStateBoxName = getAccountStateBoxName(sender); + const accountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + ); + const nextAccountPowerBoxName = getAccountPowerBoxName( + sender, + accountState.lastAccountPowerBoxIndex + 1 + ); + const boxes: algosdk.BoxReference[] = [ + {appIndex: VAULT_APP_ID[network], name: accountStateBoxName}, + {appIndex: VAULT_APP_ID[network], name: accountPowerBoxName}, + {appIndex: VAULT_APP_ID[network], name: nextAccountPowerBoxName} + ]; + + const withdrawTxn = algosdk.makeApplicationNoOpTxnFromObject({ + appIndex: VAULT_APP_ID[network], + from: sender, + suggestedParams, + appArgs: [encodeString("withdraw")], + foreignAssets: [TINY_ASSET_ID[network]], + boxes, + note: appCallNote + }); + + withdrawTxn.fee *= 2; + + const txns = [withdrawTxn]; + + // Min Balance + if (!accountState.freeAccountPowerSpaceCount) { + const minBalancePaymentTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: sender, + suggestedParams, + to: algosdk.getApplicationAddress(VAULT_APP_ID[network]), + amount: ACCOUNT_POWER_BOX_COST + }); + + txns.unshift(minBalancePaymentTxn); + } + + const txnGroup = algosdk.assignGroupID(txns); + + return txnGroup; +} + +export { + prepareCreateLockTransactions, + prepareIncreaseLockAmountTransactions, + prepareExtendLockEndTimeTransactions, + prepareWithdrawTransactions +}; diff --git a/src/governance/vault/utils.ts b/src/governance/vault/utils.ts new file mode 100644 index 00000000..1992158d --- /dev/null +++ b/src/governance/vault/utils.ts @@ -0,0 +1,32 @@ +import {WEEK} from "../constants"; +import {MAX_LOCK_TIME, TWO_TO_THE_64} from "./constants"; + +function getStartTimestampOfWeek(value: number) { + return Math.floor(value / WEEK) * WEEK; +} + +function getNewTotalPowerTimestamps(oldTimeStamp: number, newTimeStamp: number) { + if (oldTimeStamp > newTimeStamp) { + throw new Error("Old timestamp must be less than or equal to new timestamp"); + } + + const timestamps: number[] = []; + + let weekTimeStamp = getStartTimestampOfWeek(oldTimeStamp) + WEEK; + + while (weekTimeStamp < newTimeStamp) { + timestamps.push(weekTimeStamp); + + weekTimeStamp += WEEK; + } + + timestamps.push(newTimeStamp); + + return timestamps; +} + +function getSlope(lockedAmount: number) { + return Math.floor((lockedAmount * TWO_TO_THE_64) / MAX_LOCK_TIME); +} + +export {getNewTotalPowerTimestamps, getStartTimestampOfWeek, getSlope}; diff --git a/src/index.ts b/src/index.ts index 559a8534..ccac64bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -40,7 +40,8 @@ export type { export { ALGO_ASSET, ALGO_ASSET_ID, - POOL_TOKEN_UNIT_NAME + POOL_TOKEN_UNIT_NAME, + TINY_ASSET_ID } from "./util/asset/assetConstants"; export { @@ -139,3 +140,20 @@ export type {FolksLendingPool} from "./folks-lending-pools/types"; export {prepareCommitTransactions, getStakingAppID} from "./stake"; export {tinymanJSSDKConfig} from "./config"; export {combineAndRegroupSignerTxns} from "./util/transaction/transactionUtils"; + +export {TinymanGovernanceClient} from "./governance"; +export type {GetRawBoxValueCacheProps, RawBoxCacheValue} from "./governance/types"; + +export {AccountState} from "./governance/vault/storage"; +export {getStartTimestampOfWeek} from "./governance/vault/utils"; +export {ProposalVote} from "./governance/proposal-voting/constants"; +export {generateProposalMetadata} from "./governance/proposal-voting/transactions"; +export type {GenerateProposalMetadataPayload} from "./governance/proposal-voting/types"; +export {intToBytes} from "./governance/util/utils"; + +export { + generateCidFromProposalMetadata, + calculateTinyPower, + combineAndRegroupTxns, + concatUint8Arrays +} from "./governance/utils"; diff --git a/src/util/asset/assetConstants.ts b/src/util/asset/assetConstants.ts index 2e6b1d0e..30c84d87 100644 --- a/src/util/asset/assetConstants.ts +++ b/src/util/asset/assetConstants.ts @@ -1,3 +1,4 @@ +import {SupportedNetwork} from "../commonTypes"; import {TinymanAnalyticsApiAsset} from "./assetModels"; export const ALGO_ASSET_ID = 0; @@ -18,3 +19,8 @@ export const POOL_TOKEN_UNIT_NAME = { V1_1: "TMPOOL11", V2: "TMPOOL2" }; + +export const TINY_ASSET_ID: Record = { + testnet: 258703304, + mainnet: 2200000000 +};