PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-dot/src/lib
Просмотр файла: stakingBuilder.ts
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import { DecodedSignedTx, DecodedSigningPayload, UnsignedTransaction } from '@substrate/txwrapper-core';
import { methods } from '@substrate/txwrapper-polkadot';
import BigNumber from 'bignumber.js';
import utils from './utils';
import { BaseAddress, DotAssetTypes, InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
import { MethodNames, StakeArgs, StakeArgsPayee, StakeArgsPayeeRaw, StakeMoreArgs } from './iface';
import { Transaction } from './transaction';
import { TransactionBuilder } from './transactionBuilder';
import { StakeTransactionSchema } from './txnSchema';
export class StakingBuilder extends TransactionBuilder {
protected _amount: string;
protected _controller: string;
protected _payee: StakeArgsPayee;
protected _addToStake: boolean;
constructor(_coinConfig: Readonly<CoinConfig>) {
super(_coinConfig);
}
/**
* Take the origin account as a stash and lock up value of its balance.
* Controller will be the account that controls it.
*
* @returns {UnsignedTransaction} an unsigned Dot transaction
*
* @see https://polkadot.js.org/docs/substrate/extrinsics/#staking
*/
protected buildTransaction(): UnsignedTransaction {
const baseTxInfo = this.createBaseTxInfo();
if (this._addToStake) {
return methods.staking.bondExtra(
{
maxAdditional: this._amount,
},
baseTxInfo.baseTxInfo,
baseTxInfo.options
);
} else {
return methods.staking.bond(
{
value: this._amount,
payee: this._payee,
},
baseTxInfo.baseTxInfo,
baseTxInfo.options
);
}
}
protected get transactionType(): TransactionType {
return TransactionType.StakingActivate;
}
/**
* The amount to stake.
*
* @param {string} amount
* @returns {StakeBuilder} This staking builder.
*
* @see https://wiki.polkadot.network/docs/learn-nominator#required-minimum-stake
*/
amount(amount: string): this {
this.validateValue(new BigNumber(amount));
this._amount = amount;
return this;
}
/**
* true if we should add to an existing stake, false otherwise.
*
* @param {boolean} addToStake
* @returns {StakeBuilder} This staking builder.
*/
addToStake(addToStake: boolean): this {
this._addToStake = addToStake;
return this;
}
/**
* The controller of the staked amount.
*
* @param {string} controller
* @returns {StakeBuilder} This staking builder.
*
* @see https://wiki.polkadot.network/docs/learn-staking#accounts
*/
owner(controller: BaseAddress): this {
this.validateAddress(controller);
this._controller = controller.address;
return this;
}
/**
* The rewards destination of the staked amount.
* Can be set to another accounts address.
*
* @param {string} payee
* @returns {StakeBuilder} This staking builder.
*
* @see https://wiki.polkadot.network/docs/learn-staking#4-rewards-mechanism
*/
payee(payee: StakeArgsPayee): this {
if (typeof payee !== 'string') {
this.validateAddress({ address: payee.Account });
this._payee = { Account: payee.Account };
} else {
this._payee = payee;
}
return this;
}
/** @inheritdoc */
validateDecodedTransaction(decodedTxn: DecodedSigningPayload | DecodedSignedTx): void {
if (decodedTxn.method?.name === MethodNames.Bond) {
const txMethod = decodedTxn.method.args as unknown as StakeArgs;
const value = txMethod.value;
const controller = this._sender;
const payee = txMethod.payee;
const validationResult = StakeTransactionSchema.validate({ value, controller, payee });
if (validationResult.error) {
throw new InvalidTransactionError(`Transaction validation failed: ${validationResult.error.message}`);
}
} else if (decodedTxn.method?.name === MethodNames.BondExtra) {
const txMethod = decodedTxn.method.args as unknown as StakeMoreArgs;
const value = txMethod.maxAdditional;
const validationResult = StakeTransactionSchema.validate({ value, addToStake: true });
if (validationResult.error) {
throw new InvalidTransactionError(`Transaction validation failed: ${validationResult.error.message}`);
}
}
}
/** @inheritdoc */
protected fromImplementation(rawTransaction: string): Transaction {
const tx = super.fromImplementation(rawTransaction);
if (this._method?.name === MethodNames.Bond) {
const txMethod = this._method.args as StakeArgs;
this.amount(txMethod.value);
this.owner({
address: utils.decodeDotAddress(this._sender, utils.getAddressFormat(this._coinConfig.name as DotAssetTypes)),
});
const payee = txMethod.payee as StakeArgsPayeeRaw;
if (payee.account) {
this.payee({
Account: utils.decodeDotAddress(
payee.account,
utils.getAddressFormat(this._coinConfig.name as DotAssetTypes)
),
});
} else {
const payeeType = utils.capitalizeFirstLetter(Object.keys(payee)[0]) as StakeArgsPayee;
this.payee(payeeType);
}
} else if (this._method?.name === MethodNames.BondExtra) {
const txMethod = this._method.args as StakeMoreArgs;
this.amount(txMethod.maxAdditional);
this.addToStake(true);
} else {
throw new InvalidTransactionError(`Invalid Transaction Type: ${this._method?.name}. Expected bond or bondExtra`);
}
return tx;
}
/** @inheritdoc */
validateTransaction(_: Transaction): void {
super.validateTransaction(_);
this.validateFields(this._amount, this._controller, this._payee, this._addToStake);
}
private validateFields(value: string, controller: string, payee: StakeArgsPayee, addToStake: boolean): void {
const validationResult = StakeTransactionSchema.validate({
value,
controller,
payee,
addToStake,
});
if (validationResult.error) {
throw new InvalidTransactionError(
`Stake Builder Transaction validation failed: ${validationResult.error.message}`
);
}
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!