PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-xtz/src
Просмотр файла: xtz.ts
import {
BaseCoin,
BaseTransactionBuilder,
BitGoBase,
MethodNotImplementedError,
ParsedTransaction,
ParseTransactionOptions,
KeyPair as SdkCoreKeyPair,
SignedTransaction,
TransactionExplanation,
VerifyAddressOptions,
VerifyTransactionOptions,
MultisigType,
multisigTypes,
} from '@bitgo/sdk-core';
import { bip32 } from '@bitgo/secp256k1';
import { CoinFamily, coins, BaseCoin as StaticsBaseCoin } from '@bitgo/statics';
import BigNumber from 'bignumber.js';
import { Interface, KeyPair, TransactionBuilder, Utils } from './lib';
export class Xtz extends BaseCoin {
protected readonly _staticsCoin: Readonly<StaticsBaseCoin>;
constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
super(bitgo);
if (!staticsCoin) {
throw new Error('missing required constructor parameter staticsCoin');
}
this._staticsCoin = staticsCoin;
}
static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
return new Xtz(bitgo, staticsCoin);
}
getChain(): string {
return this._staticsCoin.name;
}
getFamily(): CoinFamily {
return this._staticsCoin.family;
}
getFullName(): string {
return this._staticsCoin.fullName;
}
getBaseFactor() {
return Math.pow(10, this._staticsCoin.decimalPlaces);
}
/** {@inheritDoc } **/
supportsMultisig(): boolean {
return true;
}
/** inherited doc */
getDefaultMultisigType(): MultisigType {
return multisigTypes.onchain;
}
/**
* Flag for sending value of 0
* @returns {boolean} True if okay to send 0 value, false otherwise
*/
valuelessTransferAllowed(): boolean {
return true;
}
/**
* Xtz supports transfers to consolidate balance from receive address to the wallet contract
*/
allowsAccountConsolidations(): boolean {
return true;
}
/**
* Checks if this is a valid base58 or hex address
* @param address
*/
isValidAddress(address: string): boolean {
if (!address) {
return false;
}
return Utils.isValidAddress(address);
}
/**
* Generate Tezos key pair - BitGo xpub format
*
* @param seed
* @returns {Object} object with generated xpub, xprv
*/
generateKeyPair(seed?: Buffer): SdkCoreKeyPair {
const keyPair = seed ? new KeyPair({ seed }) : new KeyPair();
const keys = keyPair.getExtendedKeys();
if (!keys.xprv) {
throw new Error('Missing xprv in key generation.');
}
return {
pub: keys.xpub,
prv: keys.xprv,
};
}
async parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
return {};
}
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
throw new MethodNotImplementedError();
}
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
const { txParams } = params;
if (Array.isArray(txParams.recipients) && txParams.recipients.length > 1) {
throw new Error(
`${this.getChain()} doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`
);
}
return true;
}
/**
* Derive a user key using the chain path of the address
* @param key
* @param path
* @returns {string} derived private key
*/
deriveKeyWithPath({ key, path }: { key: string; path: string }): string {
const keychain = bip32.fromBase58(key);
const derivedKeyNode = keychain.derivePath(path);
return derivedKeyNode.toBase58();
}
/**
* Assemble keychain and half-sign prebuilt transaction
*
* @param params
* @param params.txPrebuild {Object} prebuild object returned by platform
* @param params.prv {String} user prv
* @returns Bluebird<SignedTransaction>
*/
async signTransaction(params: Interface.XtzSignTransactionOptions): Promise<SignedTransaction> {
const txBuilder = new TransactionBuilder(coins.get(this.getChain()));
txBuilder.from(params.txPrebuild.txHex);
txBuilder.source(params.txPrebuild.source);
if (params.txPrebuild.dataToSign) {
txBuilder.overrideDataToSign({ dataToSign: params.txPrebuild.dataToSign });
}
// The path /0/0/0/0 is used by the wallet base address
// Derive the user key only if the transaction is sent from a receive address
let key;
const { chain, index } = params.txPrebuild.addressInfo;
if (chain === 0 && index === 0) {
key = params.prv;
} else {
const derivationPath = `0/0/${chain}/${index}`;
key = this.deriveKeyWithPath({ key: params.prv, path: derivationPath });
}
txBuilder.sign({ key });
const transaction = await txBuilder.build();
if (!transaction) {
throw new Error('Invalid messaged passed to signMessage');
}
const response = {
txHex: transaction.toBroadcastFormat(),
};
return transaction.signature.length >= 2 ? response : { halfSigned: response };
}
/**
* Sign message with private key
*
* @param key
* @param message
*/
async signMessage(key: SdkCoreKeyPair, message: string | Buffer): Promise<Buffer> {
const keyPair = new KeyPair({ prv: key.prv });
const messageHex =
message instanceof Buffer ? message.toString('hex') : Buffer.from(message as string, 'utf-8').toString('hex');
const signatureData = await Utils.sign(keyPair, messageHex);
return Buffer.from(signatureData.sig);
}
/**
* Builds a funds recovery transaction without BitGo.
* We need to do three queries during this:
* 1) Node query - how much money is in the account
* 2) Build transaction - build our transaction for the amount
* 3) Send signed build - send our signed build to a public node
* @param params
*/
async recover(params: any): Promise<any> {
throw new MethodNotImplementedError();
}
/**
* Explain a Tezos transaction from txHex
* @param params
*/
async explainTransaction(params: Interface.ExplainTransactionOptions): Promise<TransactionExplanation> {
const txHex = params.txHex || (params.halfSigned && params.halfSigned.txHex);
if (!txHex || !params.feeInfo) {
throw new Error('missing explain tx parameters');
}
const txBuilder = new TransactionBuilder(coins.get(this.getChain()));
// Newer coins can return BaseTransactionBuilderFactory instead of BaseTransactionBuilder
if (!(txBuilder instanceof BaseTransactionBuilder)) {
throw new Error('getBuilder() did not return an BaseTransactionBuilder object. Has it been updated?');
}
txBuilder.from(txHex);
const tx = await txBuilder.build();
const displayOrder = ['id', 'outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee'];
return {
displayOrder,
id: tx.id,
outputs: tx.outputs,
outputAmount: tx.outputs
.reduce((accumulator, output) => accumulator.plus(output.value), new BigNumber('0'))
.toFixed(0),
changeOutputs: [], // account based does not use change outputs
changeAmount: '0', // account base does not make change
fee: params.feeInfo,
} as any;
}
isValidPub(pub: string): boolean {
return Utils.isValidPublicKey(pub);
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!