PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-sui/src/lib
Просмотр файла: walrusWithdrawStakeBuilder.ts
import {
SuiTransaction,
RequestWalrusWithdrawStake,
WalrusWithdrawStakeProgrammableTransaction,
SuiTransactionType,
} from './iface';
import { BaseCoin as CoinConfig, NetworkType } from '@bitgo/statics';
import { TransactionBuilder } from './transactionBuilder';
import { WalrusWithdrawStakeTransaction } from './walrusWithdrawStakeTransaction';
import utils from './utils';
import { WALRUS_TESTNET_CONFIG, WALRUS_PROD_CONFIG } from './resources/walrusConfig';
import { BaseKey, BuildTransactionError, TransactionType } from '@bitgo/sdk-core';
import { TransferTransaction } from './transferTransaction';
import { Transaction } from './transaction';
import { normalizeSuiObjectId } from './mystenlab/types';
import {
Inputs,
MoveCallTransaction,
TransactionBlock as ProgrammingTransactionBlockBuilder,
} from './mystenlab/builder';
import assert from 'assert';
import { MAX_GAS_OBJECTS } from './constants';
export class WalrusWithdrawStakeBuilder extends TransactionBuilder<WalrusWithdrawStakeProgrammableTransaction> {
protected _withdrawStake: RequestWalrusWithdrawStake;
private walrusConfig: any;
constructor(_coinConfig: Readonly<CoinConfig>) {
super(_coinConfig);
this._transaction = new WalrusWithdrawStakeTransaction(_coinConfig);
// TODO improve mainnet vs. testnet configuration
this.walrusConfig = _coinConfig.network.type === NetworkType.MAINNET ? WALRUS_PROD_CONFIG : WALRUS_TESTNET_CONFIG;
}
/**
* Get staking transaction type
*
* @return {TransactionType}
* @protected
*/
protected get transactionType(): TransactionType {
return utils.getTransactionType(this.transaction.suiTransaction.type);
}
/** @inheritDoc */
validateTransaction(transaction: TransferTransaction): void {
if (!transaction.suiTransaction) {
return;
}
this.validateTransactionFields();
}
/** @inheritDoc */
sign(key: BaseKey) {
this.transaction.setSuiTransaction(this.buildSuiTransaction());
super.sign(key);
}
/**
* Create a new transaction for requesting coin withdrawal, ready to be signed and executed.
*
* @param request - the request object
*/
requestWithdrawStake(request: RequestWalrusWithdrawStake): this {
this.validateSuiObjectRef(request.stakedWal, 'stakedWal');
if (request.amount !== undefined) {
if (!utils.isValidAmount(request.amount)) {
throw new Error(`invalid amount: ${request.amount}`);
}
}
this._withdrawStake = request;
return this;
}
/** @inheritDoc */
protected fromImplementation(rawTransaction: string): Transaction<WalrusWithdrawStakeProgrammableTransaction> {
const tx = new WalrusWithdrawStakeTransaction(this._coinConfig);
this.validateRawTransaction(rawTransaction);
tx.fromRawTransaction(rawTransaction);
this.initBuilder(tx);
return this.transaction;
}
/** @inheritDoc */
protected async buildImplementation(): Promise<Transaction<WalrusWithdrawStakeProgrammableTransaction>> {
this.transaction.setSuiTransaction(this.buildSuiTransaction());
this.transaction.transactionType(this.transactionType);
if (this._signer) {
this.transaction.sign(this._signer);
}
this._signatures.forEach((signature) => {
this.transaction.addSignature(signature.publicKey, signature.signature);
});
this.transaction.loadInputsAndOutputs();
return this.transaction;
}
initBuilder(tx: Transaction<WalrusWithdrawStakeProgrammableTransaction>): void {
this._transaction = tx;
if (tx.signature && tx.signature.length > 0) {
this._signatures = [tx.suiSignature];
}
const txData = tx.toJson();
this.type(tx.suiTransaction.type);
this.sender(txData.sender);
this.gasData(txData.gasData);
const parsed = utils.getWalrusWithdrawStakeRequests(tx.suiTransaction.tx);
this.requestWithdrawStake({
stakedWal: {
...parsed.stakedWal,
objectId: normalizeSuiObjectId(parsed.stakedWal.objectId),
version: Number(parsed.stakedWal.version),
},
amount: parsed.amount === undefined ? undefined : Number(parsed.amount),
});
}
private validateTransactionFields(): void {
assert(this._type, new BuildTransactionError('type is required before building'));
assert(this._sender, new BuildTransactionError('sender is required before building'));
assert(this._withdrawStake.stakedWal, new BuildTransactionError('stakedWal object is required before building'));
assert(this._gasData, new BuildTransactionError('gasData is required before building'));
this.validateGasData(this._gasData);
}
protected buildSuiTransaction(): SuiTransaction<WalrusWithdrawStakeProgrammableTransaction> {
this.validateTransactionFields();
const ptb = new ProgrammingTransactionBlockBuilder();
switch (this._type) {
case SuiTransactionType.WalrusRequestWithdrawStake:
// For request_withdraw, we may need to split the staked WAL into two objects
if (this._withdrawStake.amount !== undefined) {
// This is a partial unstake. Split the StakedWAL
const splitStakedWal = ptb.moveCall({
target: `${this.walrusConfig.WALRUS_PKG_ID}::staked_wal::split`,
arguments: [
ptb.object(Inputs.ObjectRef(this._withdrawStake.stakedWal)),
ptb.pure(Number(this._withdrawStake.amount)),
],
} as unknown as MoveCallTransaction);
// Request to withdraw the split StakedWAL
ptb.moveCall({
target: `${this.walrusConfig.WALRUS_PKG_ID}::${this.walrusConfig.WALRUS_STAKING_MODULE_NAME}::request_withdraw_stake`,
arguments: [ptb.object(Inputs.SharedObjectRef(this.walrusConfig.WALRUS_STAKING_OBJECT)), splitStakedWal],
});
ptb.transferObjects([splitStakedWal], ptb.object(this._sender));
} else {
// This is a full unstake. No need to split, just withdraw the provided StakedWAL.
// Also, since there is no newly-created StakedWAL, no need to transferObjects.
ptb.moveCall({
target: `${this.walrusConfig.WALRUS_PKG_ID}::${this.walrusConfig.WALRUS_STAKING_MODULE_NAME}::request_withdraw_stake`,
arguments: [
ptb.object(Inputs.SharedObjectRef(this.walrusConfig.WALRUS_STAKING_OBJECT)),
ptb.object(Inputs.ObjectRef(this._withdrawStake.stakedWal)),
],
});
}
break;
case SuiTransactionType.WalrusWithdrawStake:
// For the actual withdraw, we are using the already split StakedWAL from above
// No need to split, just do the withdraw_stake move call
const unstakedWal = ptb.moveCall({
target: `${this.walrusConfig.WALRUS_PKG_ID}::${this.walrusConfig.WALRUS_STAKING_MODULE_NAME}::withdraw_stake`,
arguments: [
ptb.object(Inputs.SharedObjectRef(this.walrusConfig.WALRUS_STAKING_OBJECT)),
ptb.object(Inputs.ObjectRef(this._withdrawStake.stakedWal)),
],
});
ptb.transferObjects([unstakedWal], ptb.object(this._sender));
break;
default:
throw new BuildTransactionError(`Invalid transaction type: ${this._type}`);
}
const txData = ptb.blockData;
return {
type: this._type,
sender: this._sender,
tx: {
inputs: [...txData.inputs],
transactions: [...txData.transactions],
},
gasData: {
...this._gasData,
payment: this._gasData.payment.slice(0, MAX_GAS_OBJECTS - 1),
},
};
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!