@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.
Files changed (146) hide show
  1. package/README.md +4 -0
  2. package/clmm/artifacts/BitmapWord.ral.json +125 -0
  3. package/clmm/artifacts/BitmapWordDeployer.ral.json +31 -0
  4. package/clmm/artifacts/CreateConfig.ral.json +37 -0
  5. package/clmm/artifacts/CreateLiquidPool.ral.json +55 -0
  6. package/clmm/artifacts/DexAccount.ral.json +110 -0
  7. package/clmm/artifacts/LiquidityAmountsTest.ral.json +161 -0
  8. package/clmm/artifacts/LiquidityManagmentTest.ral.json +384 -0
  9. package/clmm/artifacts/Pool.ral.json +1530 -0
  10. package/clmm/artifacts/PoolConfig.ral.json +31 -0
  11. package/clmm/artifacts/PoolFactory.ral.json +300 -0
  12. package/clmm/artifacts/PoolRouterDemo.ral.json +49 -0
  13. package/clmm/artifacts/PoolUser.ral.json +89 -0
  14. package/clmm/artifacts/Position.ral.json +183 -0
  15. package/clmm/artifacts/PositionManager.ral.json +416 -0
  16. package/clmm/artifacts/SwapWithoutAccount.ral.json +46 -0
  17. package/clmm/artifacts/TestToken.ral.json +68 -0
  18. package/clmm/artifacts/Tick.ral.json +161 -0
  19. package/clmm/artifacts/TickBitmapTest.ral.json +220 -0
  20. package/clmm/artifacts/constants.ral.json +81 -0
  21. package/clmm/artifacts/structs.ral.json +335 -0
  22. package/clmm/artifacts/ts/BitmapWord.ts +337 -0
  23. package/clmm/artifacts/ts/BitmapWordDeployer.ts +164 -0
  24. package/clmm/artifacts/ts/DexAccount.ts +330 -0
  25. package/clmm/artifacts/ts/LiquidityAmountsTest.ts +464 -0
  26. package/clmm/artifacts/ts/LiquidityManagmentTest.ts +859 -0
  27. package/clmm/artifacts/ts/Pool.ts +2535 -0
  28. package/clmm/artifacts/ts/PoolConfig.ts +179 -0
  29. package/clmm/artifacts/ts/PoolFactory.ts +640 -0
  30. package/clmm/artifacts/ts/PoolUser.ts +237 -0
  31. package/clmm/artifacts/ts/Position.ts +440 -0
  32. package/clmm/artifacts/ts/PositionManager.ts +929 -0
  33. package/clmm/artifacts/ts/TestToken.ts +277 -0
  34. package/clmm/artifacts/ts/Tick.ts +351 -0
  35. package/clmm/artifacts/ts/TickBitmapTest.ts +512 -0
  36. package/clmm/artifacts/ts/constants.ts +17 -0
  37. package/clmm/artifacts/ts/contracts.ts +26 -0
  38. package/clmm/artifacts/ts/deployments.ts +160 -0
  39. package/clmm/artifacts/ts/index.ts +20 -0
  40. package/clmm/artifacts/ts/scripts.ts +76 -0
  41. package/clmm/artifacts/ts/types.ts +105 -0
  42. package/clmm/deployments/.deployments.devnet.json +350 -0
  43. package/clmm/deployments/.deployments.testnet.json +350 -0
  44. package/cpmm/artifacts/dex/DexAccount.ral.json +110 -0
  45. package/cpmm/artifacts/dex/Router.ral.json +361 -0
  46. package/cpmm/artifacts/dex/TokenPair.ral.json +512 -0
  47. package/cpmm/artifacts/dex/TokenPairFactory.ral.json +297 -0
  48. package/cpmm/artifacts/examples/ExampleOracleSimple.ral.json +192 -0
  49. package/cpmm/artifacts/examples/FeeCollectorFactoryImpl.ral.json +185 -0
  50. package/cpmm/artifacts/examples/FeeCollectorPerTokenPairImpl.ral.json +216 -0
  51. package/cpmm/artifacts/examples/FullMathTest.ral.json +123 -0
  52. package/cpmm/artifacts/scripts/AddLiquidity.ral.json +46 -0
  53. package/cpmm/artifacts/scripts/Burn.ral.json +31 -0
  54. package/cpmm/artifacts/scripts/CollectFee.ral.json +25 -0
  55. package/cpmm/artifacts/scripts/CreatePair.ral.json +37 -0
  56. package/cpmm/artifacts/scripts/CreatePairAndAddLiquidity.ral.json +43 -0
  57. package/cpmm/artifacts/scripts/EnableFeeCollector.ral.json +28 -0
  58. package/cpmm/artifacts/scripts/Mint.ral.json +34 -0
  59. package/cpmm/artifacts/scripts/RemoveLiquidity.ral.json +43 -0
  60. package/cpmm/artifacts/scripts/SetFeeCollectorFactory.ral.json +28 -0
  61. package/cpmm/artifacts/scripts/Swap.ral.json +46 -0
  62. package/cpmm/artifacts/scripts/SwapMaxIn.ral.json +46 -0
  63. package/cpmm/artifacts/scripts/SwapMinOut.ral.json +46 -0
  64. package/cpmm/artifacts/test/GetToken.ral.json +31 -0
  65. package/cpmm/artifacts/test/MathTest.ral.json +49 -0
  66. package/cpmm/artifacts/test/TestToken.ral.json +87 -0
  67. package/cpmm/artifacts/ts/DexAccount.ts +329 -0
  68. package/cpmm/artifacts/ts/ExampleOracleSimple.ts +383 -0
  69. package/cpmm/artifacts/ts/FeeCollectorFactoryImpl.ts +227 -0
  70. package/cpmm/artifacts/ts/FeeCollectorPerTokenPairImpl.ts +327 -0
  71. package/cpmm/artifacts/ts/FullMathTest.ts +251 -0
  72. package/cpmm/artifacts/ts/MathTest.ts +183 -0
  73. package/cpmm/artifacts/ts/Router.ts +554 -0
  74. package/cpmm/artifacts/ts/TestToken.ts +312 -0
  75. package/cpmm/artifacts/ts/TokenPair.ts +947 -0
  76. package/cpmm/artifacts/ts/TokenPairFactory.ts +501 -0
  77. package/cpmm/artifacts/ts/contracts.ts +26 -0
  78. package/cpmm/artifacts/ts/deployments.ts +109 -0
  79. package/cpmm/artifacts/ts/index.ts +16 -0
  80. package/cpmm/artifacts/ts/scripts.ts +142 -0
  81. package/cpmm/deployments/.deployments.devnet.json +77 -0
  82. package/cpmm/deployments/.deployments.testnet.json +79 -0
  83. package/lib/index.d.mts +8800 -0
  84. package/lib/index.d.ts +8800 -0
  85. package/lib/index.js +21769 -0
  86. package/lib/index.js.map +1 -0
  87. package/lib/index.mjs +22118 -0
  88. package/lib/index.mjs.map +1 -0
  89. package/package.json +80 -0
  90. package/src/clmm/clmm.ts +607 -0
  91. package/src/clmm/constants.ts +7 -0
  92. package/src/clmm/index.ts +6 -0
  93. package/src/clmm/liquidity.ts +163 -0
  94. package/src/clmm/pool.ts +154 -0
  95. package/src/clmm/tick.ts +335 -0
  96. package/src/clmm/types.ts +155 -0
  97. package/src/common/constants.ts +1 -0
  98. package/src/common/error.ts +46 -0
  99. package/src/common/index.ts +7 -0
  100. package/src/common/logger.ts +82 -0
  101. package/src/common/math.ts +88 -0
  102. package/src/common/numeric.ts +64 -0
  103. package/src/common/types.ts +49 -0
  104. package/src/common/utils.ts +3 -0
  105. package/src/cpmm/constants.ts +2 -0
  106. package/src/cpmm/cpmm.ts +631 -0
  107. package/src/cpmm/index.ts +3 -0
  108. package/src/cpmm/types.ts +113 -0
  109. package/src/index.ts +25 -0
  110. package/src/moduleBase.ts +64 -0
  111. package/src/staking/index.ts +4 -0
  112. package/src/staking/settings.ts +38 -0
  113. package/src/staking/staking.ts +277 -0
  114. package/src/staking/types.ts +15 -0
  115. package/src/staking/utils.ts +25 -0
  116. package/src/token/index.ts +1 -0
  117. package/src/token/token.ts +163 -0
  118. package/src/zeta.ts +105 -0
  119. package/staking/artifacts/AlphStakeAndLock.ral.json +31 -0
  120. package/staking/artifacts/AlphUnstakeVault.ral.json +151 -0
  121. package/staking/artifacts/XAlphStakeVault.ral.json +559 -0
  122. package/staking/artifacts/XAlphToken.ral.json +404 -0
  123. package/staking/artifacts/XAlphUnlockAndStartUnstake.ral.json +31 -0
  124. package/staking/artifacts/examples/GovernanceDemo.ral.json +282 -0
  125. package/staking/artifacts/examples/RewardSharingVault.ral.json +253 -0
  126. package/staking/artifacts/structs.ral.json +47 -0
  127. package/staking/artifacts/ts/AlphUnstakeVault.ts +354 -0
  128. package/staking/artifacts/ts/FullMathTest.ts +175 -0
  129. package/staking/artifacts/ts/GovernanceDemo.ts +726 -0
  130. package/staking/artifacts/ts/RewardSharingVault.ts +559 -0
  131. package/staking/artifacts/ts/TestDynamicArrayByteVec32.ts +431 -0
  132. package/staking/artifacts/ts/TestDynamicSortedArrayForU256.ts +516 -0
  133. package/staking/artifacts/ts/TestMerkleProof.ts +343 -0
  134. package/staking/artifacts/ts/XAlphStakeVault.ts +1120 -0
  135. package/staking/artifacts/ts/XAlphToken.ts +835 -0
  136. package/staking/artifacts/ts/contracts.ts +26 -0
  137. package/staking/artifacts/ts/deployments.ts +109 -0
  138. package/staking/artifacts/ts/index.ts +15 -0
  139. package/staking/artifacts/ts/scripts.ts +35 -0
  140. package/staking/artifacts/ts/types.ts +19 -0
  141. package/staking/artifacts/utils/FullMathTest.ral.json +57 -0
  142. package/staking/artifacts/utils/TestDynamicArrayByteVec32.ral.json +165 -0
  143. package/staking/artifacts/utils/TestDynamicSortedArrayForU256.ral.json +189 -0
  144. package/staking/artifacts/utils/TestMerkleProof.ral.json +134 -0
  145. package/staking/deployments/.deployments.devnet.json +77 -0
  146. 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,4 @@
1
+ export * from './staking';
2
+ export * from './types';
3
+ export * from './utils';
4
+ export * from './settings';
@@ -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';