@alephium/powfi-sdk 0.0.1-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/clmm/artifacts/BitmapWord.ral.json +125 -0
- package/clmm/artifacts/BitmapWordDeployer.ral.json +31 -0
- package/clmm/artifacts/CreateConfig.ral.json +37 -0
- package/clmm/artifacts/CreateLiquidPool.ral.json +55 -0
- package/clmm/artifacts/DexAccount.ral.json +110 -0
- package/clmm/artifacts/LiquidityAmountsTest.ral.json +161 -0
- package/clmm/artifacts/LiquidityManagmentTest.ral.json +384 -0
- package/clmm/artifacts/Pool.ral.json +1530 -0
- package/clmm/artifacts/PoolConfig.ral.json +31 -0
- package/clmm/artifacts/PoolFactory.ral.json +300 -0
- package/clmm/artifacts/PoolRouterDemo.ral.json +49 -0
- package/clmm/artifacts/PoolUser.ral.json +89 -0
- package/clmm/artifacts/Position.ral.json +183 -0
- package/clmm/artifacts/PositionManager.ral.json +416 -0
- package/clmm/artifacts/SwapWithoutAccount.ral.json +46 -0
- package/clmm/artifacts/TestToken.ral.json +68 -0
- package/clmm/artifacts/Tick.ral.json +161 -0
- package/clmm/artifacts/TickBitmapTest.ral.json +220 -0
- package/clmm/artifacts/constants.ral.json +81 -0
- package/clmm/artifacts/structs.ral.json +335 -0
- package/clmm/artifacts/ts/BitmapWord.ts +337 -0
- package/clmm/artifacts/ts/BitmapWordDeployer.ts +164 -0
- package/clmm/artifacts/ts/DexAccount.ts +330 -0
- package/clmm/artifacts/ts/LiquidityAmountsTest.ts +464 -0
- package/clmm/artifacts/ts/LiquidityManagmentTest.ts +859 -0
- package/clmm/artifacts/ts/Pool.ts +2535 -0
- package/clmm/artifacts/ts/PoolConfig.ts +179 -0
- package/clmm/artifacts/ts/PoolFactory.ts +640 -0
- package/clmm/artifacts/ts/PoolUser.ts +237 -0
- package/clmm/artifacts/ts/Position.ts +440 -0
- package/clmm/artifacts/ts/PositionManager.ts +929 -0
- package/clmm/artifacts/ts/TestToken.ts +277 -0
- package/clmm/artifacts/ts/Tick.ts +351 -0
- package/clmm/artifacts/ts/TickBitmapTest.ts +512 -0
- package/clmm/artifacts/ts/constants.ts +17 -0
- package/clmm/artifacts/ts/contracts.ts +26 -0
- package/clmm/artifacts/ts/deployments.ts +160 -0
- package/clmm/artifacts/ts/index.ts +20 -0
- package/clmm/artifacts/ts/scripts.ts +76 -0
- package/clmm/artifacts/ts/types.ts +105 -0
- package/clmm/deployments/.deployments.devnet.json +350 -0
- package/clmm/deployments/.deployments.testnet.json +350 -0
- package/cpmm/artifacts/dex/DexAccount.ral.json +110 -0
- package/cpmm/artifacts/dex/Router.ral.json +361 -0
- package/cpmm/artifacts/dex/TokenPair.ral.json +512 -0
- package/cpmm/artifacts/dex/TokenPairFactory.ral.json +297 -0
- package/cpmm/artifacts/examples/ExampleOracleSimple.ral.json +192 -0
- package/cpmm/artifacts/examples/FeeCollectorFactoryImpl.ral.json +185 -0
- package/cpmm/artifacts/examples/FeeCollectorPerTokenPairImpl.ral.json +216 -0
- package/cpmm/artifacts/examples/FullMathTest.ral.json +123 -0
- package/cpmm/artifacts/scripts/AddLiquidity.ral.json +46 -0
- package/cpmm/artifacts/scripts/Burn.ral.json +31 -0
- package/cpmm/artifacts/scripts/CollectFee.ral.json +25 -0
- package/cpmm/artifacts/scripts/CreatePair.ral.json +37 -0
- package/cpmm/artifacts/scripts/CreatePairAndAddLiquidity.ral.json +43 -0
- package/cpmm/artifacts/scripts/EnableFeeCollector.ral.json +28 -0
- package/cpmm/artifacts/scripts/Mint.ral.json +34 -0
- package/cpmm/artifacts/scripts/RemoveLiquidity.ral.json +43 -0
- package/cpmm/artifacts/scripts/SetFeeCollectorFactory.ral.json +28 -0
- package/cpmm/artifacts/scripts/Swap.ral.json +46 -0
- package/cpmm/artifacts/scripts/SwapMaxIn.ral.json +46 -0
- package/cpmm/artifacts/scripts/SwapMinOut.ral.json +46 -0
- package/cpmm/artifacts/test/GetToken.ral.json +31 -0
- package/cpmm/artifacts/test/MathTest.ral.json +49 -0
- package/cpmm/artifacts/test/TestToken.ral.json +87 -0
- package/cpmm/artifacts/ts/DexAccount.ts +329 -0
- package/cpmm/artifacts/ts/ExampleOracleSimple.ts +383 -0
- package/cpmm/artifacts/ts/FeeCollectorFactoryImpl.ts +227 -0
- package/cpmm/artifacts/ts/FeeCollectorPerTokenPairImpl.ts +327 -0
- package/cpmm/artifacts/ts/FullMathTest.ts +251 -0
- package/cpmm/artifacts/ts/MathTest.ts +183 -0
- package/cpmm/artifacts/ts/Router.ts +554 -0
- package/cpmm/artifacts/ts/TestToken.ts +312 -0
- package/cpmm/artifacts/ts/TokenPair.ts +947 -0
- package/cpmm/artifacts/ts/TokenPairFactory.ts +501 -0
- package/cpmm/artifacts/ts/contracts.ts +26 -0
- package/cpmm/artifacts/ts/deployments.ts +109 -0
- package/cpmm/artifacts/ts/index.ts +16 -0
- package/cpmm/artifacts/ts/scripts.ts +142 -0
- package/cpmm/deployments/.deployments.devnet.json +77 -0
- package/cpmm/deployments/.deployments.testnet.json +79 -0
- package/lib/index.d.mts +8800 -0
- package/lib/index.d.ts +8800 -0
- package/lib/index.js +21769 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +22118 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +80 -0
- package/src/clmm/clmm.ts +607 -0
- package/src/clmm/constants.ts +7 -0
- package/src/clmm/index.ts +6 -0
- package/src/clmm/liquidity.ts +163 -0
- package/src/clmm/pool.ts +154 -0
- package/src/clmm/tick.ts +335 -0
- package/src/clmm/types.ts +155 -0
- package/src/common/constants.ts +1 -0
- package/src/common/error.ts +46 -0
- package/src/common/index.ts +7 -0
- package/src/common/logger.ts +82 -0
- package/src/common/math.ts +88 -0
- package/src/common/numeric.ts +64 -0
- package/src/common/types.ts +49 -0
- package/src/common/utils.ts +3 -0
- package/src/cpmm/constants.ts +2 -0
- package/src/cpmm/cpmm.ts +631 -0
- package/src/cpmm/index.ts +3 -0
- package/src/cpmm/types.ts +113 -0
- package/src/index.ts +25 -0
- package/src/moduleBase.ts +64 -0
- package/src/staking/index.ts +4 -0
- package/src/staking/settings.ts +38 -0
- package/src/staking/staking.ts +277 -0
- package/src/staking/types.ts +15 -0
- package/src/staking/utils.ts +25 -0
- package/src/token/index.ts +1 -0
- package/src/token/token.ts +163 -0
- package/src/zeta.ts +105 -0
- package/staking/artifacts/AlphStakeAndLock.ral.json +31 -0
- package/staking/artifacts/AlphUnstakeVault.ral.json +151 -0
- package/staking/artifacts/XAlphStakeVault.ral.json +559 -0
- package/staking/artifacts/XAlphToken.ral.json +404 -0
- package/staking/artifacts/XAlphUnlockAndStartUnstake.ral.json +31 -0
- package/staking/artifacts/examples/GovernanceDemo.ral.json +282 -0
- package/staking/artifacts/examples/RewardSharingVault.ral.json +253 -0
- package/staking/artifacts/structs.ral.json +47 -0
- package/staking/artifacts/ts/AlphUnstakeVault.ts +354 -0
- package/staking/artifacts/ts/FullMathTest.ts +175 -0
- package/staking/artifacts/ts/GovernanceDemo.ts +726 -0
- package/staking/artifacts/ts/RewardSharingVault.ts +559 -0
- package/staking/artifacts/ts/TestDynamicArrayByteVec32.ts +431 -0
- package/staking/artifacts/ts/TestDynamicSortedArrayForU256.ts +516 -0
- package/staking/artifacts/ts/TestMerkleProof.ts +343 -0
- package/staking/artifacts/ts/XAlphStakeVault.ts +1120 -0
- package/staking/artifacts/ts/XAlphToken.ts +835 -0
- package/staking/artifacts/ts/contracts.ts +26 -0
- package/staking/artifacts/ts/deployments.ts +109 -0
- package/staking/artifacts/ts/index.ts +15 -0
- package/staking/artifacts/ts/scripts.ts +35 -0
- package/staking/artifacts/ts/types.ts +19 -0
- package/staking/artifacts/utils/FullMathTest.ral.json +57 -0
- package/staking/artifacts/utils/TestDynamicArrayByteVec32.ral.json +165 -0
- package/staking/artifacts/utils/TestDynamicSortedArrayForU256.ral.json +189 -0
- package/staking/artifacts/utils/TestMerkleProof.ral.json +134 -0
- package/staking/deployments/.deployments.devnet.json +77 -0
- package/staking/deployments/.deployments.testnet.json +78 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { TokenInfo } from '@alephium/token-list';
|
|
2
|
+
|
|
3
|
+
export interface CpmmConfig {
|
|
4
|
+
groupIndex: number;
|
|
5
|
+
factoryId: string;
|
|
6
|
+
routerId: string;
|
|
7
|
+
feeCollectorFactoryId?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface CpmmPoolContractState {
|
|
11
|
+
poolId: string;
|
|
12
|
+
reserve0: bigint;
|
|
13
|
+
reserve1: bigint;
|
|
14
|
+
token0Info: TokenInfo;
|
|
15
|
+
token1Info: TokenInfo;
|
|
16
|
+
totalSupply: bigint;
|
|
17
|
+
dexAccount: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SwapParams {
|
|
21
|
+
tokenIn: TokenInfo;
|
|
22
|
+
tokenOut: TokenInfo;
|
|
23
|
+
amountIn?: bigint;
|
|
24
|
+
amountOut?: bigint;
|
|
25
|
+
slippage: bigint; // bps
|
|
26
|
+
sender: string;
|
|
27
|
+
ttl?: number; // Time to live in minutes, default 60
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SwapDetails {
|
|
31
|
+
swapType: 'ExactIn' | 'ExactOut';
|
|
32
|
+
state: CpmmPoolContractState;
|
|
33
|
+
tokenInInfo: TokenInfo;
|
|
34
|
+
tokenOutInfo: TokenInfo;
|
|
35
|
+
tokenInAmount: bigint;
|
|
36
|
+
maximalTokenInAmount: bigint | undefined;
|
|
37
|
+
tokenOutAmount: bigint;
|
|
38
|
+
minimalTokenOutAmount: bigint | undefined;
|
|
39
|
+
priceImpact: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface AddLiquidityParams {
|
|
43
|
+
cpmmPoolState: CpmmPoolContractState;
|
|
44
|
+
tokenA: TokenInfo;
|
|
45
|
+
tokenB: TokenInfo;
|
|
46
|
+
amountA: bigint;
|
|
47
|
+
amountB: bigint;
|
|
48
|
+
slippage: bigint; // bps
|
|
49
|
+
sender: string;
|
|
50
|
+
ttl?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface AddLiquidityDetails {
|
|
54
|
+
state?: CpmmPoolContractState;
|
|
55
|
+
tokenAId: string;
|
|
56
|
+
tokenBId: string;
|
|
57
|
+
amountA: bigint;
|
|
58
|
+
amountB: bigint;
|
|
59
|
+
shareAmount: bigint;
|
|
60
|
+
sharePercentage: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface RemoveLiquidityParams {
|
|
64
|
+
state: CpmmPoolContractState;
|
|
65
|
+
liquidity: bigint;
|
|
66
|
+
totalLiquidityAmount?: bigint;
|
|
67
|
+
slippage: bigint; // bps
|
|
68
|
+
sender: string;
|
|
69
|
+
ttl?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface RemoveLiquidityDetails {
|
|
73
|
+
state: CpmmPoolContractState;
|
|
74
|
+
token0: TokenInfo;
|
|
75
|
+
amount0: bigint;
|
|
76
|
+
token1: TokenInfo;
|
|
77
|
+
amount1: bigint;
|
|
78
|
+
remainShareAmount: bigint;
|
|
79
|
+
remainSharePercentage: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ClaimableAmounts {
|
|
83
|
+
token0: TokenInfo;
|
|
84
|
+
amount0: bigint;
|
|
85
|
+
token1: TokenInfo;
|
|
86
|
+
amount1: bigint;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface CreatePoolParams {
|
|
90
|
+
tokenA: TokenInfo;
|
|
91
|
+
tokenB: TokenInfo;
|
|
92
|
+
sender: string;
|
|
93
|
+
tokenAAmount?: bigint;
|
|
94
|
+
tokenBAmount?: bigint;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface ComputeSwapParams {
|
|
98
|
+
state: CpmmPoolContractState;
|
|
99
|
+
tokenIn: TokenInfo;
|
|
100
|
+
tokenOut: TokenInfo;
|
|
101
|
+
amountIn?: bigint;
|
|
102
|
+
amountOut?: bigint;
|
|
103
|
+
slippage: bigint; // bps
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface ComputeLiquidityParams {
|
|
107
|
+
state?: CpmmPoolContractState;
|
|
108
|
+
tokenA: TokenInfo;
|
|
109
|
+
tokenB: TokenInfo;
|
|
110
|
+
amountA?: bigint;
|
|
111
|
+
amountB?: bigint;
|
|
112
|
+
inputType?: 'TokenA' | 'TokenB';
|
|
113
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export * from './zeta';
|
|
2
|
+
export * from './common';
|
|
3
|
+
export * from './cpmm';
|
|
4
|
+
export * from './clmm';
|
|
5
|
+
export * from './token';
|
|
6
|
+
export * from './staking';
|
|
7
|
+
|
|
8
|
+
export type { TokenPairTypes as CpmmTokenPairTypes } from 'cpmm/artifacts/ts/TokenPair';
|
|
9
|
+
export type { TokenPairFactoryTypes as CpmmTokenPairFactoryTypes } from 'cpmm/artifacts/ts/TokenPairFactory';
|
|
10
|
+
export type { PoolTypes as ClmmPoolTypes } from 'clmm/artifacts/ts/Pool';
|
|
11
|
+
export type { PoolFactoryTypes as ClmmPoolFactoryTypes } from 'clmm/artifacts/ts/PoolFactory';
|
|
12
|
+
export type { PositionManagerTypes as ClmmPositionManagerTypes } from 'clmm/artifacts/ts/PositionManager';
|
|
13
|
+
export type { XAlphTokenTypes } from 'staking/artifacts/ts/XAlphToken';
|
|
14
|
+
export type { XAlphStakeVaultTypes } from 'staking/artifacts/ts/XAlphStakeVault';
|
|
15
|
+
export type { RewardSharingVaultTypes } from 'staking/artifacts/ts/RewardSharingVault';
|
|
16
|
+
export type { GovernanceDemoTypes } from 'staking/artifacts/ts/GovernanceDemo';
|
|
17
|
+
|
|
18
|
+
export * as CpmmContracts from 'cpmm/artifacts/ts';
|
|
19
|
+
export * as ClmmContracts from 'clmm/artifacts/ts';
|
|
20
|
+
export * as CpmmScripts from 'cpmm/artifacts/ts/scripts';
|
|
21
|
+
export * as ClmmScripts from 'clmm/artifacts/ts/scripts';
|
|
22
|
+
export * as StakingContracts from 'staking/artifacts/ts';
|
|
23
|
+
export { loadDeployments as loadCpmmDeployments } from 'cpmm/artifacts/ts/deployments';
|
|
24
|
+
export { loadDeployments as loadClmmDeployments } from 'clmm/artifacts/ts/deployments';
|
|
25
|
+
export { loadDeployments as loadStakingDeployments } from 'staking/artifacts/ts/deployments';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Logger } from './common/logger';
|
|
2
|
+
import { createLogger } from './common/logger';
|
|
3
|
+
import type { Zeta } from './zeta';
|
|
4
|
+
|
|
5
|
+
export interface ModuleBaseProps {
|
|
6
|
+
scope: Zeta;
|
|
7
|
+
moduleName: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const joinMsg = (...args: unknown[]): string =>
|
|
11
|
+
args
|
|
12
|
+
.map((arg) => {
|
|
13
|
+
if (arg instanceof Error) {
|
|
14
|
+
const base = arg.message ?? arg.name;
|
|
15
|
+
return arg.stack ? `${base}\n${arg.stack}` : base;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.stringify(arg);
|
|
21
|
+
} catch {
|
|
22
|
+
return String(arg);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return String(arg);
|
|
27
|
+
})
|
|
28
|
+
.join(', ');
|
|
29
|
+
|
|
30
|
+
export default class ModuleBase {
|
|
31
|
+
public scope: Zeta;
|
|
32
|
+
private disabled = false;
|
|
33
|
+
protected logger: Logger;
|
|
34
|
+
|
|
35
|
+
constructor({ scope, moduleName }: ModuleBaseProps) {
|
|
36
|
+
this.scope = scope;
|
|
37
|
+
this.logger = createLogger(moduleName);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public logDebug(...args: unknown[]): void {
|
|
41
|
+
this.logger.debug(joinMsg(...args));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public logInfo(...args: unknown[]): void {
|
|
45
|
+
this.logger.info(joinMsg(...args));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public logWarning(...args: unknown[]): void {
|
|
49
|
+
this.logger.warning(joinMsg(...args));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public logError(...args: unknown[]): void {
|
|
53
|
+
this.logger.error(joinMsg(...args));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public logAndThrowError(...args: unknown[]): never {
|
|
57
|
+
const message = joinMsg(...args);
|
|
58
|
+
throw new Error(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public checkDisabled(): void {
|
|
62
|
+
if (this.disabled || !this.scope) this.logAndThrowError('module not working');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { NetworkId } from '@alephium/web3';
|
|
2
|
+
|
|
3
|
+
export type StakingSettings = {
|
|
4
|
+
unstakeDuration: bigint;
|
|
5
|
+
maxActiveUnstakeRequestsPerUser: bigint;
|
|
6
|
+
maxConnectedDapps: bigint;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const defaultSettings: StakingSettings = {
|
|
10
|
+
unstakeDuration: 30n * 24n * 60n * 60n * 1000n, // 30 days in milliseconds
|
|
11
|
+
maxActiveUnstakeRequestsPerUser: 16n,
|
|
12
|
+
maxConnectedDapps: 10n,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const networkOverrides: Partial<Record<NetworkId, Partial<StakingSettings>>> = {
|
|
16
|
+
devnet: {
|
|
17
|
+
unstakeDuration: 60n * 1000n, // 1 minute
|
|
18
|
+
maxConnectedDapps: 2n,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function buildSettings(networkId: NetworkId): StakingSettings {
|
|
23
|
+
const overrides = networkOverrides[networkId];
|
|
24
|
+
return {
|
|
25
|
+
...defaultSettings,
|
|
26
|
+
...(overrides ?? {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const stakingSettingsByNetwork: Record<NetworkId, StakingSettings> = {
|
|
31
|
+
mainnet: buildSettings('mainnet'),
|
|
32
|
+
testnet: buildSettings('testnet'),
|
|
33
|
+
devnet: buildSettings('devnet'),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function getStakingSettings(networkId: NetworkId): StakingSettings {
|
|
37
|
+
return stakingSettingsByNetwork[networkId];
|
|
38
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { ExecuteScriptResult, HexString } from '@alephium/web3';
|
|
2
|
+
import {
|
|
3
|
+
MINIMAL_CONTRACT_DEPOSIT,
|
|
4
|
+
addressFromContractId,
|
|
5
|
+
addressToBytes,
|
|
6
|
+
binToHex,
|
|
7
|
+
codec,
|
|
8
|
+
groupOfAddress,
|
|
9
|
+
isGrouplessAddressWithoutGroupIndex,
|
|
10
|
+
subContractId,
|
|
11
|
+
} from '@alephium/web3';
|
|
12
|
+
import type {
|
|
13
|
+
AlphUnstakeVaultInstance,
|
|
14
|
+
AlphUnstakeVaultTypes,
|
|
15
|
+
GovernanceDemoInstance,
|
|
16
|
+
RewardSharingVaultInstance,
|
|
17
|
+
XAlphStakeVaultInstance,
|
|
18
|
+
XAlphStakeVaultTypes,
|
|
19
|
+
XAlphTokenInstance,
|
|
20
|
+
XAlphTokenTypes,
|
|
21
|
+
} from 'staking/artifacts/ts';
|
|
22
|
+
import {
|
|
23
|
+
AlphStakeAndLock,
|
|
24
|
+
AlphUnstakeVault,
|
|
25
|
+
GovernanceDemo,
|
|
26
|
+
RewardSharingVault,
|
|
27
|
+
XAlphStakeVault,
|
|
28
|
+
XAlphToken,
|
|
29
|
+
XAlphUnlockAndStartUnstake,
|
|
30
|
+
} from 'staking/artifacts/ts';
|
|
31
|
+
import { loadDeployments } from 'staking/artifacts/ts/deployments';
|
|
32
|
+
import ModuleBase from '../moduleBase';
|
|
33
|
+
import type { Zeta } from '../zeta';
|
|
34
|
+
import type { StakeVaultUserInfo, StakingConfig } from './types';
|
|
35
|
+
import { decodeContractIdList, decodeU256List } from './utils';
|
|
36
|
+
import type { StakingSettings } from './settings';
|
|
37
|
+
import { getStakingSettings } from './settings';
|
|
38
|
+
|
|
39
|
+
export class StakingModule extends ModuleBase {
|
|
40
|
+
private config: StakingConfig;
|
|
41
|
+
private xAlphTokenContract: XAlphTokenInstance;
|
|
42
|
+
private stakeVaultContract: XAlphStakeVaultInstance;
|
|
43
|
+
|
|
44
|
+
constructor(scope: Zeta) {
|
|
45
|
+
super({ scope, moduleName: 'StakingModule' });
|
|
46
|
+
|
|
47
|
+
this.config = this.loadStakingConfig();
|
|
48
|
+
this.xAlphTokenContract = XAlphToken.at(addressFromContractId(this.config.xAlphTokenId));
|
|
49
|
+
this.stakeVaultContract = XAlphStakeVault.at(
|
|
50
|
+
addressFromContractId(this.config.xAlphStakeVaultId),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setConfig(config: StakingConfig): void {
|
|
55
|
+
this.config = config;
|
|
56
|
+
this.xAlphTokenContract = XAlphToken.at(addressFromContractId(config.xAlphTokenId));
|
|
57
|
+
this.stakeVaultContract = XAlphStakeVault.at(addressFromContractId(config.xAlphStakeVaultId));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getConfig(): StakingConfig {
|
|
61
|
+
return this.config;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getXAlphToken(): XAlphTokenInstance {
|
|
65
|
+
return this.xAlphTokenContract;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getStakeVault(): XAlphStakeVaultInstance {
|
|
69
|
+
return this.stakeVaultContract;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getRewardSharingVault(contractId: string): RewardSharingVaultInstance {
|
|
73
|
+
return RewardSharingVault.at(addressFromContractId(contractId));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getGovernanceContract(contractId: string): GovernanceDemoInstance {
|
|
77
|
+
return GovernanceDemo.at(addressFromContractId(contractId));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async getXAlphTokenState(): Promise<XAlphTokenTypes.State> {
|
|
81
|
+
return this.xAlphTokenContract.fetchState();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async getStakeVaultState(): Promise<XAlphStakeVaultTypes.State> {
|
|
85
|
+
return this.stakeVaultContract.fetchState();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async stakeAlph(amount: bigint): Promise<XAlphTokenTypes.SignExecuteMethodResult<'stake'>> {
|
|
89
|
+
this.ensurePositiveAmount(amount, 'Stake amount');
|
|
90
|
+
return this.xAlphTokenContract.transact.stake({
|
|
91
|
+
signer: this.scope.signer,
|
|
92
|
+
args: { amount },
|
|
93
|
+
attoAlphAmount: amount + MINIMAL_CONTRACT_DEPOSIT,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async startUnstake(
|
|
98
|
+
amount: bigint,
|
|
99
|
+
): Promise<XAlphTokenTypes.SignExecuteMethodResult<'startUnstake'>> {
|
|
100
|
+
this.ensurePositiveAmount(amount, 'Unstake amount');
|
|
101
|
+
return this.xAlphTokenContract.transact.startUnstake({
|
|
102
|
+
signer: this.scope.signer,
|
|
103
|
+
args: { amount },
|
|
104
|
+
tokens: [{ id: this.config.xAlphTokenId, amount }],
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async claimUnstaked(
|
|
109
|
+
vaultIndex: bigint,
|
|
110
|
+
amount: bigint,
|
|
111
|
+
): Promise<XAlphTokenTypes.SignExecuteMethodResult<'claimUnstaked'>> {
|
|
112
|
+
this.ensurePositiveAmount(amount, 'Claim amount');
|
|
113
|
+
return this.xAlphTokenContract.transact.claimUnstaked({
|
|
114
|
+
signer: this.scope.signer,
|
|
115
|
+
args: {
|
|
116
|
+
vaultIndex,
|
|
117
|
+
amount,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async stakeXAlph(amount: bigint): Promise<XAlphStakeVaultTypes.SignExecuteMethodResult<'stake'>> {
|
|
123
|
+
this.ensurePositiveAmount(amount, 'Stake amount');
|
|
124
|
+
return this.stakeVaultContract.transact.stake({
|
|
125
|
+
signer: this.scope.signer,
|
|
126
|
+
args: { amount },
|
|
127
|
+
tokens: [{ id: this.config.xAlphTokenId, amount }],
|
|
128
|
+
attoAlphAmount: MINIMAL_CONTRACT_DEPOSIT,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async unstakeXAlph(
|
|
133
|
+
amount: bigint,
|
|
134
|
+
): Promise<XAlphStakeVaultTypes.SignExecuteMethodResult<'unstake'>> {
|
|
135
|
+
this.ensurePositiveAmount(amount, 'Unstake amount');
|
|
136
|
+
return this.stakeVaultContract.transact.unstake({
|
|
137
|
+
signer: this.scope.signer,
|
|
138
|
+
args: { amount },
|
|
139
|
+
attoAlphAmount: MINIMAL_CONTRACT_DEPOSIT,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async stakeAndLockAlph(amount: bigint): Promise<ExecuteScriptResult> {
|
|
144
|
+
return AlphStakeAndLock.execute({
|
|
145
|
+
signer: this.scope.signer,
|
|
146
|
+
initialFields: {
|
|
147
|
+
xAlphToken: this.xAlphTokenContract.contractId,
|
|
148
|
+
xAlphStakeVault: this.stakeVaultContract.contractId,
|
|
149
|
+
amount,
|
|
150
|
+
},
|
|
151
|
+
attoAlphAmount: amount + MINIMAL_CONTRACT_DEPOSIT,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async unlockAndStartUnstake(amount: bigint): Promise<ExecuteScriptResult> {
|
|
156
|
+
return XAlphUnlockAndStartUnstake.execute({
|
|
157
|
+
signer: this.scope.signer,
|
|
158
|
+
initialFields: {
|
|
159
|
+
xAlphToken: this.xAlphTokenContract.contractId,
|
|
160
|
+
xAlphStakeVault: this.stakeVaultContract.contractId,
|
|
161
|
+
amount,
|
|
162
|
+
},
|
|
163
|
+
attoAlphAmount: MINIMAL_CONTRACT_DEPOSIT,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
getAlphUnstakeVault(userAddress: string, vaultIndex: bigint): AlphUnstakeVaultInstance {
|
|
168
|
+
const userHex = binToHex(addressToBytes(userAddress));
|
|
169
|
+
const indexHex = binToHex(codec.u256Codec.encode(vaultIndex));
|
|
170
|
+
const contractId = subContractId(
|
|
171
|
+
this.config.xAlphTokenId,
|
|
172
|
+
`${userHex}${indexHex}`,
|
|
173
|
+
groupOfAddress(this.config.xAlphTokenAddress),
|
|
174
|
+
);
|
|
175
|
+
return AlphUnstakeVault.at(addressFromContractId(contractId));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async getAlphUnstakeVaultState(
|
|
179
|
+
userAddress: string,
|
|
180
|
+
vaultIndex: bigint,
|
|
181
|
+
): Promise<AlphUnstakeVaultTypes.State> {
|
|
182
|
+
return this.getAlphUnstakeVault(userAddress, vaultIndex).fetchState();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async connectToDapp(
|
|
186
|
+
contractId: string,
|
|
187
|
+
merkleProof: HexString,
|
|
188
|
+
): Promise<XAlphStakeVaultTypes.SignExecuteMethodResult<'connectToDapp'>> {
|
|
189
|
+
return this.stakeVaultContract.transact.connectToDapp({
|
|
190
|
+
signer: this.scope.signer,
|
|
191
|
+
args: { contractId, merkleProof },
|
|
192
|
+
attoAlphAmount: MINIMAL_CONTRACT_DEPOSIT,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
async disconnectFromDapp(
|
|
197
|
+
contractId: string,
|
|
198
|
+
): Promise<XAlphStakeVaultTypes.SignExecuteMethodResult<'disconnectFromDapp'>> {
|
|
199
|
+
return this.stakeVaultContract.transact.disconnectFromDapp({
|
|
200
|
+
signer: this.scope.signer,
|
|
201
|
+
args: { contractId },
|
|
202
|
+
attoAlphAmount: MINIMAL_CONTRACT_DEPOSIT,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async getUserStakeVaultInfo(address: string): Promise<StakeVaultUserInfo> {
|
|
207
|
+
let stakerAddress = address;
|
|
208
|
+
if (isGrouplessAddressWithoutGroupIndex(address)) {
|
|
209
|
+
stakerAddress = `${address}:${this.stakeVaultContract.groupIndex}`;
|
|
210
|
+
}
|
|
211
|
+
const result = await this.stakeVaultContract.view.getUserStakingInfo({
|
|
212
|
+
args: { user: stakerAddress },
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
amount: result.returns.amount,
|
|
216
|
+
connectedDapps: decodeContractIdList(result.returns.connectedDapps),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async isUserStaking(address: string): Promise<boolean> {
|
|
221
|
+
const result = await this.stakeVaultContract.view.isStaking({ args: { user: address } });
|
|
222
|
+
return result.returns;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async getUserWeight(address: string): Promise<bigint> {
|
|
226
|
+
const result = await this.stakeVaultContract.view.getWeight({ args: { user: address } });
|
|
227
|
+
return result.returns;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async getActiveUnstakeVaultIndexes(address: string): Promise<bigint[]> {
|
|
231
|
+
const result = await this.xAlphTokenContract.view.getActiveUnstakeVaultIndexes({
|
|
232
|
+
args: { caller: address },
|
|
233
|
+
});
|
|
234
|
+
return decodeU256List(result.returns);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async getClaimableAmount(address: string, vaultIndex: bigint): Promise<bigint> {
|
|
238
|
+
const result = await this.xAlphTokenContract.view.getClaimableAmount({
|
|
239
|
+
args: { user: address, vaultIndex },
|
|
240
|
+
});
|
|
241
|
+
return result.returns;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
getSettings(): StakingSettings {
|
|
245
|
+
return getStakingSettings(this.scope.network.id);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private loadStakingConfig(): StakingConfig {
|
|
249
|
+
const networkId = this.scope.network.id;
|
|
250
|
+
try {
|
|
251
|
+
const deployments = loadDeployments(networkId);
|
|
252
|
+
const alphUnstakeVault = deployments.contracts.AlphUnstakeVault.contractInstance;
|
|
253
|
+
const xAlphToken = deployments.contracts.XAlphToken.contractInstance;
|
|
254
|
+
const stakeVault = deployments.contracts.XAlphStakeVault.contractInstance;
|
|
255
|
+
const rewardVault = deployments.contracts.RewardSharingVault.contractInstance;
|
|
256
|
+
const governance = deployments.contracts.GovernanceDemo.contractInstance;
|
|
257
|
+
return {
|
|
258
|
+
groupIndex: stakeVault.groupIndex,
|
|
259
|
+
alphUnstakeVaultTemplateId: alphUnstakeVault.contractId,
|
|
260
|
+
xAlphTokenId: xAlphToken.contractId,
|
|
261
|
+
xAlphTokenAddress: xAlphToken.address,
|
|
262
|
+
xAlphStakeVaultId: stakeVault.contractId,
|
|
263
|
+
xAlphStakeVaultAddress: stakeVault.address,
|
|
264
|
+
rewardSharingTemplateId: rewardVault.contractId,
|
|
265
|
+
governanceDemoTemplateId: governance.contractId,
|
|
266
|
+
};
|
|
267
|
+
} catch (error) {
|
|
268
|
+
this.logAndThrowError(`Failed to load staking deployments on ${networkId}`, error);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private ensurePositiveAmount(amount: bigint, label: string): void {
|
|
273
|
+
if (amount <= 0n) {
|
|
274
|
+
throw new Error(`${label} must be greater than zero`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface StakingConfig {
|
|
2
|
+
groupIndex: number;
|
|
3
|
+
alphUnstakeVaultTemplateId: string;
|
|
4
|
+
xAlphTokenId: string;
|
|
5
|
+
xAlphTokenAddress: string;
|
|
6
|
+
xAlphStakeVaultId: string;
|
|
7
|
+
xAlphStakeVaultAddress: string;
|
|
8
|
+
rewardSharingTemplateId?: string;
|
|
9
|
+
governanceDemoTemplateId?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface StakeVaultUserInfo {
|
|
13
|
+
amount: bigint;
|
|
14
|
+
connectedDapps: string[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const U256_HEX_CHARS = 64;
|
|
2
|
+
const CONTRACT_ID_HEX_CHARS = 64;
|
|
3
|
+
|
|
4
|
+
const chunkHexString = (hex: string, chunkLength: number): string[] => {
|
|
5
|
+
if (hex.length === 0) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
if (hex.length % chunkLength !== 0) {
|
|
9
|
+
throw new Error(`Packed data must be a multiple of ${chunkLength / 2} bytes`);
|
|
10
|
+
}
|
|
11
|
+
const chunks: string[] = [];
|
|
12
|
+
for (let offset = 0; offset < hex.length; offset += chunkLength) {
|
|
13
|
+
const chunk = hex.slice(offset, offset + chunkLength);
|
|
14
|
+
chunks.push(chunk);
|
|
15
|
+
}
|
|
16
|
+
return chunks;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const decodeU256List = (str: string): bigint[] => {
|
|
20
|
+
return chunkHexString(str, U256_HEX_CHARS).map((chunk) => BigInt(`0x${chunk}`));
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const decodeContractIdList = (str: string): string[] => {
|
|
24
|
+
return chunkHexString(str, CONTRACT_ID_HEX_CHARS);
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './token';
|