Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 69 additions & 1 deletion modules/sdk-coin-sui/src/lib/iface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export enum SuiTransactionType {
WalrusStakeWithPool = 'WalrusStakeWithPool',
WalrusRequestWithdrawStake = 'WalrusRequestWithdrawStake',
WalrusWithdrawStake = 'WalrusWithdrawStake',
XmnStake = 'XmnStake',
XmnRequestUnstake = 'XmnRequestUnstake',
XmnUnbond = 'XmnUnbond',
XmnClaimRewards = 'XmnClaimRewards',
}

export interface TransactionExplanation extends BaseTransactionExplanation {
Expand All @@ -35,7 +39,10 @@ export type SuiProgrammableTransaction =
| CustomProgrammableTransaction
| TokenTransferProgrammableTransaction
| WalrusStakingProgrammableTransaction
| WalrusWithdrawStakeProgrammableTransaction;
| WalrusWithdrawStakeProgrammableTransaction
| XmnStakingProgrammableTransaction
| XmnUnstakeProgrammableTransaction
| XmnClaimRewardsProgrammableTransaction;

export interface TxData {
id?: string;
Expand Down Expand Up @@ -97,6 +104,27 @@ export type WalrusWithdrawStakeProgrammableTransaction =
transactions: TransactionType[];
};

export type XmnStakingProgrammableTransaction =
| ProgrammableTransaction
| {
inputs: CallArg[] | TransactionBlockInput[];
transactions: TransactionType[];
};

export type XmnUnstakeProgrammableTransaction =
| ProgrammableTransaction
| {
inputs: CallArg[] | TransactionBlockInput[];
transactions: TransactionType[];
};

export type XmnClaimRewardsProgrammableTransaction =
| ProgrammableTransaction
| {
inputs: CallArg[] | TransactionBlockInput[];
transactions: TransactionType[];
};

export interface SuiTransaction<T = SuiProgrammableTransaction> {
id?: string;
type: SuiTransactionType;
Expand Down Expand Up @@ -126,6 +154,30 @@ export interface RequestWalrusWithdrawStake {
stakedWal: SuiObjectRef;
}

export interface RequestXmnStake {
/** Amount in base units (1 XMN = 1_000_000) */
amount: number;
/** XMN coin objects to spend */
inputObjects: SuiObjectRef[];
}

export interface RequestXmnRequestUnstake {
/** OpenPosition object owned by the staker */
openPosition: SuiObjectRef;
/** Amount to unstake in base units; if omitted, the full position amount is used */
amount?: number;
}

export interface RequestXmnUnbond {
/** UnbondingTicket object owned by the staker (created by request_unstake) */
unbondingTicket: SuiObjectRef;
}

export interface RequestXmnClaimRewards {
/** OpenPosition object owned by the staker */
openPosition: SuiObjectRef;
}

/**
* 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
*/
Expand Down Expand Up @@ -172,6 +224,22 @@ export enum MethodNames {
* @see https://github.com/MystenLabs/walrus-docs/blob/9307e66df0ea3f6555cdef78d46aefa62737e216/contracts/walrus/sources/staking/staked_wal.move#L143
*/
WalrusSplitStakedWal = '::staked_wal::split',
/**
* XMN staking_factory::stake — stakes XMN tokens, mints OpenPosition (void return).
*/
XmnStake = '::staking_factory::stake',
/**
* XMN staking_factory::request_unstake — initiates unbonding, mints UnbondingTicket (void return).
*/
XmnRequestUnstake = '::staking_factory::request_unstake',
/**
* XMN staking_factory::unbond — redeems UnbondingTicket after cooldown, returns principal (void return).
*/
XmnUnbond = '::staking_factory::unbond',
/**
* XMN staking_factory::claim_and_transfer — claims accrued rewards to liquid balance (void return).
*/
XmnClaimRewards = '::staking_factory::claim_and_transfer',
}

export interface SuiObjectInfo extends SuiObjectRef {
Expand Down
4 changes: 4 additions & 0 deletions modules/sdk-coin-sui/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@ export { WalrusStakingTransaction } from './walrusStakingTransaction';
export { WalrusStakingBuilder } from './walrusStakingBuilder';
export { WalrusWithdrawStakeTransaction } from './walrusWithdrawStakeTransaction';
export { WalrusWithdrawStakeBuilder } from './walrusWithdrawStakeBuilder';
export { XmnStakingBuilder } from './xmnStakingBuilder';
export { XmnUnstakeBuilder } from './xmnUnstakeBuilder';
export { XmnClaimRewardsBuilder } from './xmnClaimRewardsBuilder';
export { XMN_MAINNET_CONFIG, XMN_TESTNET_CONFIG } from './resources/xmnConfig';
export { TransactionBuilderFactory } from './transactionBuilderFactory';
export { Interface, Utils };
62 changes: 62 additions & 0 deletions modules/sdk-coin-sui/src/lib/resources/xmnConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* XMN staking contract configuration for mainnet and testnet.
*
* XMN uses an app-level staking contract (StakingFactory) on the SUI blockchain.
* There are no validators — all staked XMN goes into a single liquidity pool.
*
* Key insight: stake(), request_unstake(), unbond(), and claim_and_transfer() all
* have void returns and transfer objects internally to ctx.sender(). Scripts must
* NOT call tx.transferObjects() on their results.
*
* Type arguments for all StakingFactory calls: <XMN, XMN, BRIDGE_TOKEN>
* The Db (boosted deposit) type is BRIDGE_TOKEN, not XMN.
*/

export interface XmnSharedObject {
objectId: string;
initialSharedVersion: number;
mutable: boolean;
}

export interface XmnConfig {
/** Active (upgraded) package ID — used for Move call targets */
XMN_PKG_ID: string;
/** Original package ID — used for type tag matching in on-chain object types */
XMN_ORIGINAL_PKG_ID: string;
/** StakingFactory shared object reference */
XMN_STAKING_FACTORY: XmnSharedObject;
/** XMN coin type tag (R and Dn type args) */
XMN_COIN_TYPE: string;
/** BRIDGE_TOKEN coin type tag (Db type arg — NOT XMN) */
BRIDGE_TOKEN_COIN_TYPE: string;
/** Module name in the staking contract */
STAKING_MODULE: string;
}

export const XMN_TESTNET_CONFIG: XmnConfig = {
XMN_PKG_ID: '0x82e3f0021547fdbc88d25b09a99e175742e7fb45b3a457e4373817f768494454',
XMN_ORIGINAL_PKG_ID: '0x49934c5c0866e0b62db2f43296994f28d09505f48005032d4285a5da53f35e2a',
XMN_STAKING_FACTORY: {
objectId: '0x016a243d61c0814da7e07bbc5f6963f73941839433da9a11e2bc8a251dbd83a0',
initialSharedVersion: 685940293,
mutable: true,
},
XMN_COIN_TYPE: '0x49934c5c0866e0b62db2f43296994f28d09505f48005032d4285a5da53f35e2a::xmn::XMN',
BRIDGE_TOKEN_COIN_TYPE:
'0x4d2ba7e9a819c306c94c744efdd89f52009b0ed892c97b4e49adf4c78923d801::bridge_token::BRIDGE_TOKEN',
STAKING_MODULE: 'staking_factory',
};

export const XMN_MAINNET_CONFIG: XmnConfig = {
...XMN_TESTNET_CONFIG,
XMN_PKG_ID: '0x37e54838496fc4d620032cfa9e1d2542f21874429b107f097c1dab2c8bad2de8',
XMN_ORIGINAL_PKG_ID: '0x3cc209ca80fde4e68f9abbae4776abc57de7bb3da33bdb8cbf6a66740ff81bd8',
XMN_STAKING_FACTORY: {
objectId: '0x8f8a82182a12f08f579046f167303a1083fcdd3b2eb7f58c3eefe7835639d5f8',
initialSharedVersion: 648114799,
mutable: true,
},
XMN_COIN_TYPE: '0x3cc209ca80fde4e68f9abbae4776abc57de7bb3da33bdb8cbf6a66740ff81bd8::xmn::XMN',
BRIDGE_TOKEN_COIN_TYPE:
'0x8db9d9dc5cd5723ee55725869620073e28f88ddf3c360a512ebd73cb46f1903d::bridge_token::BRIDGE_TOKEN',
};
34 changes: 34 additions & 0 deletions modules/sdk-coin-sui/src/lib/transactionBuilderFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import {
TokenTransferProgrammableTransaction,
WalrusStakingProgrammableTransaction,
WalrusWithdrawStakeProgrammableTransaction,
XmnStakingProgrammableTransaction,
XmnUnstakeProgrammableTransaction,
XmnClaimRewardsProgrammableTransaction,
} from './iface';
import { StakingTransaction } from './stakingTransaction';
import { TransferTransaction } from './transferTransaction';
Expand All @@ -29,6 +32,9 @@ import { WalrusStakingBuilder } from './walrusStakingBuilder';
import { WalrusStakingTransaction } from './walrusStakingTransaction';
import { WalrusWithdrawStakeBuilder } from './walrusWithdrawStakeBuilder';
import { WalrusWithdrawStakeTransaction } from './walrusWithdrawStakeTransaction';
import { XmnStakingBuilder } from './xmnStakingBuilder';
import { XmnUnstakeBuilder } from './xmnUnstakeBuilder';
import { XmnClaimRewardsBuilder } from './xmnClaimRewardsBuilder';

export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
constructor(_coinConfig: Readonly<CoinConfig>) {
Expand Down Expand Up @@ -70,6 +76,19 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
const walrusRequestWithdrawStakeTransaction = new WalrusWithdrawStakeTransaction(this._coinConfig);
walrusRequestWithdrawStakeTransaction.fromRawTransaction(raw);
return this.getWalrusRequestWithdrawStakeBuilder(walrusRequestWithdrawStakeTransaction);
case SuiTransactionType.XmnStake:
const xmnStakeTx = new StakingTransaction(this._coinConfig);
xmnStakeTx.fromRawTransaction(raw);
return this.getXmnStakingBuilder(xmnStakeTx);
case SuiTransactionType.XmnRequestUnstake:
case SuiTransactionType.XmnUnbond:
const xmnUnstakeTx = new UnstakingTransaction(this._coinConfig);
xmnUnstakeTx.fromRawTransaction(raw);
return this.getXmnUnstakeBuilder(xmnUnstakeTx);
case SuiTransactionType.XmnClaimRewards:
const xmnClaimTx = new StakingTransaction(this._coinConfig);
xmnClaimTx.fromRawTransaction(raw);
return this.getXmnClaimRewardsBuilder(xmnClaimTx);
default:
throw new InvalidTransactionError('Invalid transaction');
}
Expand Down Expand Up @@ -115,6 +134,21 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
return this.initializeBuilder(tx, new WalrusWithdrawStakeBuilder(this._coinConfig));
}

/** @inheritdoc */
getXmnStakingBuilder(tx?: Transaction<XmnStakingProgrammableTransaction>): XmnStakingBuilder {
return this.initializeBuilder(tx, new XmnStakingBuilder(this._coinConfig));
}

/** @inheritdoc */
getXmnUnstakeBuilder(tx?: Transaction<XmnUnstakeProgrammableTransaction>): XmnUnstakeBuilder {
return this.initializeBuilder(tx, new XmnUnstakeBuilder(this._coinConfig));
}

/** @inheritdoc */
getXmnClaimRewardsBuilder(tx?: Transaction<XmnClaimRewardsProgrammableTransaction>): XmnClaimRewardsBuilder {
return this.initializeBuilder(tx, new XmnClaimRewardsBuilder(this._coinConfig));
}

/** @inheritdoc */
getWalletInitializationBuilder(): void {
throw new Error('Method not implemented.');
Expand Down
15 changes: 15 additions & 0 deletions modules/sdk-coin-sui/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ export class Utils implements BaseUtils {
return TransactionType.StakingWithdraw;
case SuiTransactionType.CustomTx:
return TransactionType.CustomTx;
case SuiTransactionType.XmnStake:
return TransactionType.StakingAdd;
case SuiTransactionType.XmnRequestUnstake:
case SuiTransactionType.XmnUnbond:
return TransactionType.StakingDeactivate;
case SuiTransactionType.XmnClaimRewards:
return TransactionType.StakingClaim;
}
}

Expand Down Expand Up @@ -250,6 +257,14 @@ export class Utils implements BaseUtils {
return SuiTransactionType.WalrusRequestWithdrawStake;
} else if (command.target.endsWith(MethodNames.WalrusWithdrawStake)) {
return SuiTransactionType.WalrusWithdrawStake;
} else if (command.target.endsWith(MethodNames.XmnStake)) {
return SuiTransactionType.XmnStake;
} else if (command.target.endsWith(MethodNames.XmnRequestUnstake)) {
return SuiTransactionType.XmnRequestUnstake;
} else if (command.target.endsWith(MethodNames.XmnUnbond)) {
return SuiTransactionType.XmnUnbond;
} else if (command.target.endsWith(MethodNames.XmnClaimRewards)) {
return SuiTransactionType.XmnClaimRewards;
} else {
throw new InvalidTransactionError(`unsupported target method ${command.target}`);
}
Expand Down
Loading
Loading