Skip to content

Commit 1a4d2ba

Browse files
committed
feat(sui): add XMN staking support
Add XMN (xMoney) token staking support on SUI blockchain: - Register tsui:xmn testnet entry in statics with SUI_TOKEN_FEATURES_STAKING - Upgrade sui:xmn mainnet entry from SUI_TOKEN_FEATURES to SUI_TOKEN_FEATURES_STAKING - Add XmnStake/XmnRequestUnstake/XmnUnbond/XmnClaimRewards transaction types to iface.ts - Add xmnConfig.ts with mainnet/testnet StakingFactory contract addresses - Add XmnStakingBuilder, XmnUnstakeBuilder, XmnClaimRewardsBuilder - Wire all builders in TransactionBuilderFactory.from() and getters - Add XMN method name detection in utils.ts getSuiTransactionType() - Fix utils.ts getTransactionType() to handle new XMN SuiTransactionTypes XMN uses an app-level StakingFactory contract (no validators). All staking functions have void returns and transfer objects internally — no transferObjects calls needed. Type args for all calls: <XMN, XMN, BRIDGE_TOKEN>.
1 parent 2a1d677 commit 1a4d2ba

10 files changed

Lines changed: 751 additions & 2 deletions

File tree

modules/sdk-coin-sui/src/lib/iface.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ export enum SuiTransactionType {
2222
WalrusStakeWithPool = 'WalrusStakeWithPool',
2323
WalrusRequestWithdrawStake = 'WalrusRequestWithdrawStake',
2424
WalrusWithdrawStake = 'WalrusWithdrawStake',
25+
XmnStake = 'XmnStake',
26+
XmnRequestUnstake = 'XmnRequestUnstake',
27+
XmnUnbond = 'XmnUnbond',
28+
XmnClaimRewards = 'XmnClaimRewards',
2529
}
2630

2731
export interface TransactionExplanation extends BaseTransactionExplanation {
@@ -35,7 +39,10 @@ export type SuiProgrammableTransaction =
3539
| CustomProgrammableTransaction
3640
| TokenTransferProgrammableTransaction
3741
| WalrusStakingProgrammableTransaction
38-
| WalrusWithdrawStakeProgrammableTransaction;
42+
| WalrusWithdrawStakeProgrammableTransaction
43+
| XmnStakingProgrammableTransaction
44+
| XmnUnstakeProgrammableTransaction
45+
| XmnClaimRewardsProgrammableTransaction;
3946

4047
export interface TxData {
4148
id?: string;
@@ -97,6 +104,27 @@ export type WalrusWithdrawStakeProgrammableTransaction =
97104
transactions: TransactionType[];
98105
};
99106

107+
export type XmnStakingProgrammableTransaction =
108+
| ProgrammableTransaction
109+
| {
110+
inputs: CallArg[] | TransactionBlockInput[];
111+
transactions: TransactionType[];
112+
};
113+
114+
export type XmnUnstakeProgrammableTransaction =
115+
| ProgrammableTransaction
116+
| {
117+
inputs: CallArg[] | TransactionBlockInput[];
118+
transactions: TransactionType[];
119+
};
120+
121+
export type XmnClaimRewardsProgrammableTransaction =
122+
| ProgrammableTransaction
123+
| {
124+
inputs: CallArg[] | TransactionBlockInput[];
125+
transactions: TransactionType[];
126+
};
127+
100128
export interface SuiTransaction<T = SuiProgrammableTransaction> {
101129
id?: string;
102130
type: SuiTransactionType;
@@ -126,6 +154,30 @@ export interface RequestWalrusWithdrawStake {
126154
stakedWal: SuiObjectRef;
127155
}
128156

157+
export interface RequestXmnStake {
158+
/** Amount in base units (1 XMN = 1_000_000) */
159+
amount: number;
160+
/** XMN coin objects to spend */
161+
inputObjects: SuiObjectRef[];
162+
}
163+
164+
export interface RequestXmnRequestUnstake {
165+
/** OpenPosition object owned by the staker */
166+
openPosition: SuiObjectRef;
167+
/** Amount to unstake in base units; if omitted, the full position amount is used */
168+
amount?: number;
169+
}
170+
171+
export interface RequestXmnUnbond {
172+
/** UnbondingTicket object owned by the staker (created by request_unstake) */
173+
unbondingTicket: SuiObjectRef;
174+
}
175+
176+
export interface RequestXmnClaimRewards {
177+
/** OpenPosition object owned by the staker */
178+
openPosition: SuiObjectRef;
179+
}
180+
129181
/**
130182
* Method names for the transaction method. Names change based on the type of transaction e.g 'request_add_delegation_mul_coin' for the staking transaction
131183
*/
@@ -172,6 +224,22 @@ export enum MethodNames {
172224
* @see https://github.com/MystenLabs/walrus-docs/blob/9307e66df0ea3f6555cdef78d46aefa62737e216/contracts/walrus/sources/staking/staked_wal.move#L143
173225
*/
174226
WalrusSplitStakedWal = '::staked_wal::split',
227+
/**
228+
* XMN staking_factory::stake — stakes XMN tokens, mints OpenPosition (void return).
229+
*/
230+
XmnStake = '::staking_factory::stake',
231+
/**
232+
* XMN staking_factory::request_unstake — initiates unbonding, mints UnbondingTicket (void return).
233+
*/
234+
XmnRequestUnstake = '::staking_factory::request_unstake',
235+
/**
236+
* XMN staking_factory::unbond — redeems UnbondingTicket after cooldown, returns principal (void return).
237+
*/
238+
XmnUnbond = '::staking_factory::unbond',
239+
/**
240+
* XMN staking_factory::claim_and_transfer — claims accrued rewards to liquid balance (void return).
241+
*/
242+
XmnClaimRewards = '::staking_factory::claim_and_transfer',
175243
}
176244

177245
export interface SuiObjectInfo extends SuiObjectRef {

modules/sdk-coin-sui/src/lib/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,9 @@ export { WalrusStakingTransaction } from './walrusStakingTransaction';
1818
export { WalrusStakingBuilder } from './walrusStakingBuilder';
1919
export { WalrusWithdrawStakeTransaction } from './walrusWithdrawStakeTransaction';
2020
export { WalrusWithdrawStakeBuilder } from './walrusWithdrawStakeBuilder';
21+
export { XmnStakingBuilder } from './xmnStakingBuilder';
22+
export { XmnUnstakeBuilder } from './xmnUnstakeBuilder';
23+
export { XmnClaimRewardsBuilder } from './xmnClaimRewardsBuilder';
24+
export { XMN_MAINNET_CONFIG, XMN_TESTNET_CONFIG } from './resources/xmnConfig';
2125
export { TransactionBuilderFactory } from './transactionBuilderFactory';
2226
export { Interface, Utils };
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* XMN staking contract configuration for mainnet and testnet.
3+
*
4+
* XMN uses an app-level staking contract (StakingFactory) on the SUI blockchain.
5+
* There are no validators — all staked XMN goes into a single liquidity pool.
6+
*
7+
* Key insight: stake(), request_unstake(), unbond(), and claim_and_transfer() all
8+
* have void returns and transfer objects internally to ctx.sender(). Scripts must
9+
* NOT call tx.transferObjects() on their results.
10+
*
11+
* Type arguments for all StakingFactory calls: <XMN, XMN, BRIDGE_TOKEN>
12+
* The Db (boosted deposit) type is BRIDGE_TOKEN, not XMN.
13+
*/
14+
15+
export interface XmnSharedObject {
16+
objectId: string;
17+
initialSharedVersion: number;
18+
mutable: boolean;
19+
}
20+
21+
export interface XmnConfig {
22+
/** Active (upgraded) package ID — used for Move call targets */
23+
XMN_PKG_ID: string;
24+
/** Original package ID — used for type tag matching in on-chain object types */
25+
XMN_ORIGINAL_PKG_ID: string;
26+
/** StakingFactory shared object reference */
27+
XMN_STAKING_FACTORY: XmnSharedObject;
28+
/** XMN coin type tag (R and Dn type args) */
29+
XMN_COIN_TYPE: string;
30+
/** BRIDGE_TOKEN coin type tag (Db type arg — NOT XMN) */
31+
BRIDGE_TOKEN_COIN_TYPE: string;
32+
/** Module name in the staking contract */
33+
STAKING_MODULE: string;
34+
}
35+
36+
export const XMN_TESTNET_CONFIG: XmnConfig = {
37+
XMN_PKG_ID: '0x82e3f0021547fdbc88d25b09a99e175742e7fb45b3a457e4373817f768494454',
38+
XMN_ORIGINAL_PKG_ID: '0x49934c5c0866e0b62db2f43296994f28d09505f48005032d4285a5da53f35e2a',
39+
XMN_STAKING_FACTORY: {
40+
objectId: '0x016a243d61c0814da7e07bbc5f6963f73941839433da9a11e2bc8a251dbd83a0',
41+
initialSharedVersion: 685940293,
42+
mutable: true,
43+
},
44+
XMN_COIN_TYPE:
45+
'0x49934c5c0866e0b62db2f43296994f28d09505f48005032d4285a5da53f35e2a::xmn::XMN',
46+
BRIDGE_TOKEN_COIN_TYPE:
47+
'0x4d2ba7e9a819c306c94c744efdd89f52009b0ed892c97b4e49adf4c78923d801::bridge_token::BRIDGE_TOKEN',
48+
STAKING_MODULE: 'staking_factory',
49+
};
50+
51+
export const XMN_MAINNET_CONFIG: XmnConfig = {
52+
...XMN_TESTNET_CONFIG,
53+
XMN_PKG_ID: '0x37e54838496fc4d620032cfa9e1d2542f21874429b107f097c1dab2c8bad2de8',
54+
XMN_ORIGINAL_PKG_ID: '0x3cc209ca80fde4e68f9abbae4776abc57de7bb3da33bdb8cbf6a66740ff81bd8',
55+
XMN_STAKING_FACTORY: {
56+
objectId: '0x8f8a82182a12f08f579046f167303a1083fcdd3b2eb7f58c3eefe7835639d5f8',
57+
initialSharedVersion: 648114799,
58+
mutable: true,
59+
},
60+
XMN_COIN_TYPE:
61+
'0x3cc209ca80fde4e68f9abbae4776abc57de7bb3da33bdb8cbf6a66740ff81bd8::xmn::XMN',
62+
BRIDGE_TOKEN_COIN_TYPE:
63+
'0x8db9d9dc5cd5723ee55725869620073e28f88ddf3c360a512ebd73cb46f1903d::bridge_token::BRIDGE_TOKEN',
64+
};

modules/sdk-coin-sui/src/lib/transactionBuilderFactory.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import {
1414
TokenTransferProgrammableTransaction,
1515
WalrusStakingProgrammableTransaction,
1616
WalrusWithdrawStakeProgrammableTransaction,
17+
XmnStakingProgrammableTransaction,
18+
XmnUnstakeProgrammableTransaction,
19+
XmnClaimRewardsProgrammableTransaction,
1720
} from './iface';
1821
import { StakingTransaction } from './stakingTransaction';
1922
import { TransferTransaction } from './transferTransaction';
@@ -29,6 +32,9 @@ import { WalrusStakingBuilder } from './walrusStakingBuilder';
2932
import { WalrusStakingTransaction } from './walrusStakingTransaction';
3033
import { WalrusWithdrawStakeBuilder } from './walrusWithdrawStakeBuilder';
3134
import { WalrusWithdrawStakeTransaction } from './walrusWithdrawStakeTransaction';
35+
import { XmnStakingBuilder } from './xmnStakingBuilder';
36+
import { XmnUnstakeBuilder } from './xmnUnstakeBuilder';
37+
import { XmnClaimRewardsBuilder } from './xmnClaimRewardsBuilder';
3238

3339
export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
3440
constructor(_coinConfig: Readonly<CoinConfig>) {
@@ -70,6 +76,19 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
7076
const walrusRequestWithdrawStakeTransaction = new WalrusWithdrawStakeTransaction(this._coinConfig);
7177
walrusRequestWithdrawStakeTransaction.fromRawTransaction(raw);
7278
return this.getWalrusRequestWithdrawStakeBuilder(walrusRequestWithdrawStakeTransaction);
79+
case SuiTransactionType.XmnStake:
80+
const xmnStakeTx = new StakingTransaction(this._coinConfig);
81+
xmnStakeTx.fromRawTransaction(raw);
82+
return this.getXmnStakingBuilder(xmnStakeTx);
83+
case SuiTransactionType.XmnRequestUnstake:
84+
case SuiTransactionType.XmnUnbond:
85+
const xmnUnstakeTx = new UnstakingTransaction(this._coinConfig);
86+
xmnUnstakeTx.fromRawTransaction(raw);
87+
return this.getXmnUnstakeBuilder(xmnUnstakeTx);
88+
case SuiTransactionType.XmnClaimRewards:
89+
const xmnClaimTx = new StakingTransaction(this._coinConfig);
90+
xmnClaimTx.fromRawTransaction(raw);
91+
return this.getXmnClaimRewardsBuilder(xmnClaimTx);
7392
default:
7493
throw new InvalidTransactionError('Invalid transaction');
7594
}
@@ -115,6 +134,21 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
115134
return this.initializeBuilder(tx, new WalrusWithdrawStakeBuilder(this._coinConfig));
116135
}
117136

137+
/** @inheritdoc */
138+
getXmnStakingBuilder(tx?: Transaction<XmnStakingProgrammableTransaction>): XmnStakingBuilder {
139+
return this.initializeBuilder(tx, new XmnStakingBuilder(this._coinConfig));
140+
}
141+
142+
/** @inheritdoc */
143+
getXmnUnstakeBuilder(tx?: Transaction<XmnUnstakeProgrammableTransaction>): XmnUnstakeBuilder {
144+
return this.initializeBuilder(tx, new XmnUnstakeBuilder(this._coinConfig));
145+
}
146+
147+
/** @inheritdoc */
148+
getXmnClaimRewardsBuilder(tx?: Transaction<XmnClaimRewardsProgrammableTransaction>): XmnClaimRewardsBuilder {
149+
return this.initializeBuilder(tx, new XmnClaimRewardsBuilder(this._coinConfig));
150+
}
151+
118152
/** @inheritdoc */
119153
getWalletInitializationBuilder(): void {
120154
throw new Error('Method not implemented.');

modules/sdk-coin-sui/src/lib/utils.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,13 @@ export class Utils implements BaseUtils {
208208
return TransactionType.StakingWithdraw;
209209
case SuiTransactionType.CustomTx:
210210
return TransactionType.CustomTx;
211+
case SuiTransactionType.XmnStake:
212+
return TransactionType.StakingAdd;
213+
case SuiTransactionType.XmnRequestUnstake:
214+
case SuiTransactionType.XmnUnbond:
215+
return TransactionType.StakingDeactivate;
216+
case SuiTransactionType.XmnClaimRewards:
217+
return TransactionType.StakingClaim;
211218
}
212219
}
213220

@@ -250,6 +257,14 @@ export class Utils implements BaseUtils {
250257
return SuiTransactionType.WalrusRequestWithdrawStake;
251258
} else if (command.target.endsWith(MethodNames.WalrusWithdrawStake)) {
252259
return SuiTransactionType.WalrusWithdrawStake;
260+
} else if (command.target.endsWith(MethodNames.XmnStake)) {
261+
return SuiTransactionType.XmnStake;
262+
} else if (command.target.endsWith(MethodNames.XmnRequestUnstake)) {
263+
return SuiTransactionType.XmnRequestUnstake;
264+
} else if (command.target.endsWith(MethodNames.XmnUnbond)) {
265+
return SuiTransactionType.XmnUnbond;
266+
} else if (command.target.endsWith(MethodNames.XmnClaimRewards)) {
267+
return SuiTransactionType.XmnClaimRewards;
253268
} else {
254269
throw new InvalidTransactionError(`unsupported target method ${command.target}`);
255270
}

0 commit comments

Comments
 (0)