You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
10 KiB
419 lines
10 KiB
import {
|
|
RPCMethod,
|
|
Messenger,
|
|
ResponseMiddleware,
|
|
WSProvider,
|
|
NewPendingTransactions,
|
|
NewHeaders,
|
|
LogSub,
|
|
Syncing,
|
|
} from '@harmony-js/network';
|
|
|
|
import {
|
|
assertObject,
|
|
AssertType,
|
|
// HarmonyCore,
|
|
DefaultBlockParams,
|
|
} from '@harmony-js/utils';
|
|
|
|
import { getAddress } from '@harmony-js/crypto';
|
|
|
|
import { Transaction } from '@harmony-js/transaction';
|
|
|
|
class Blockchain {
|
|
messenger: Messenger;
|
|
|
|
constructor(messenger: Messenger) {
|
|
this.messenger = messenger;
|
|
}
|
|
setMessenger(messenger: Messenger) {
|
|
this.messenger = messenger;
|
|
}
|
|
getRpcResult(result: any) {
|
|
if (result instanceof ResponseMiddleware) {
|
|
return result.getRaw;
|
|
} else {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
address: ['isValidAddress', AssertType.required],
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getBalance({
|
|
address,
|
|
blockNumber = DefaultBlockParams.latest,
|
|
shardID = 0,
|
|
}: {
|
|
address: string;
|
|
blockNumber?: string;
|
|
shardID?: number;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetBalance,
|
|
[getAddress(address).checksum, blockNumber],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async getBlockNumber() {
|
|
const result = await this.messenger.send(RPCMethod.BlockNumber, [], this.messenger.chainPrefix);
|
|
return this.getRpcResult(result);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
blockHash: ['isHash', AssertType.required],
|
|
returnObject: ['isBoolean', AssertType.optional],
|
|
})
|
|
async getBlockByHash({
|
|
blockHash,
|
|
returnObject = true,
|
|
}: {
|
|
blockHash: string;
|
|
returnObject?: boolean;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetBlockByHash,
|
|
[blockHash, returnObject],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
returnObject: ['isBoolean', AssertType.optional],
|
|
})
|
|
async getBlockByNumber({
|
|
blockNumber = DefaultBlockParams.latest,
|
|
returnObject = true,
|
|
}: {
|
|
blockNumber?: string;
|
|
returnObject?: boolean;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetBlockByNumber,
|
|
[blockNumber, returnObject],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
blockHash: ['isHash', AssertType.required],
|
|
})
|
|
async getBlockTransactionCountByHash({ blockHash }: { blockHash: string }) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetBlockTransactionCountByHash,
|
|
[blockHash],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
blockNumber: ['isBlockNumber', AssertType.required],
|
|
})
|
|
async getBlockTransactionCountByNumber({ blockNumber }: { blockNumber: string }) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetBlockTransactionCountByNumber,
|
|
[blockNumber],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
blockHash: ['isHash', AssertType.required],
|
|
index: ['isHex', AssertType.required],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getTransactionByBlockHashAndIndex({
|
|
blockHash,
|
|
index,
|
|
shardID = 0,
|
|
}: {
|
|
blockHash: string;
|
|
index: string;
|
|
shardID?: number;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetTransactionByBlockHashAndIndex,
|
|
[blockHash, index],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
index: ['isHex', AssertType.required],
|
|
})
|
|
async getTransactionByBlockNumberAndIndex({
|
|
blockNumber = DefaultBlockParams.latest,
|
|
index,
|
|
}: {
|
|
blockNumber?: string;
|
|
index: string;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetTransactionByBlockNumberAndIndex,
|
|
[blockNumber, index],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
txnHash: ['isHash', AssertType.required],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getTransactionByHash({ txnHash, shardID = 0 }: { txnHash: string; shardID?: number }) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetTransactionByHash,
|
|
[txnHash],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
txnHash: ['isString', AssertType.required],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getTransactionReceipt({ txnHash, shardID = 0 }: { txnHash: string; shardID?: number }) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetTransactionReceipt,
|
|
[txnHash],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
/**
|
|
*
|
|
*/
|
|
@assertObject({
|
|
address: ['isValidAddress', AssertType.required],
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
})
|
|
async getCode({
|
|
address,
|
|
blockNumber = DefaultBlockParams.latest,
|
|
}: {
|
|
address: string;
|
|
blockNumber?: string;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetCode,
|
|
[getAddress(address).checksum, blockNumber],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async net_peerCount() {
|
|
const result = await this.messenger.send(RPCMethod.PeerCount, [], 'net');
|
|
|
|
return this.getRpcResult(result);
|
|
}
|
|
async net_version() {
|
|
const result = await this.messenger.send(RPCMethod.NetVersion, [], 'net');
|
|
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async getProtocolVersion() {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.ProtocolVersion,
|
|
[],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
address: ['isValidAddress', AssertType.required],
|
|
position: ['isHex', AssertType.required],
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getStorageAt({
|
|
address,
|
|
position,
|
|
blockNumber = DefaultBlockParams.latest,
|
|
shardID = 0,
|
|
}: {
|
|
address: string;
|
|
position: string;
|
|
blockNumber?: string;
|
|
shardID?: number;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetStorageAt,
|
|
[getAddress(address).checksum, position, blockNumber],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
@assertObject({
|
|
address: ['isValidAddress', AssertType.required],
|
|
blockNumber: ['isBlockNumber', AssertType.optional],
|
|
shardID: ['isNumber', AssertType.optional],
|
|
})
|
|
async getTransactionCount({
|
|
address,
|
|
blockNumber = DefaultBlockParams.latest,
|
|
shardID = 0,
|
|
}: {
|
|
address: string;
|
|
blockNumber?: string;
|
|
shardID?: number;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetTransactionCount,
|
|
[getAddress(address).checksum, blockNumber],
|
|
this.messenger.chainPrefix,
|
|
shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async getShardingStructure() {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.GetShardingStructure,
|
|
[],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async sendTransaction(transaction: Transaction) {
|
|
if (!transaction.isSigned() || !transaction) {
|
|
throw new Error('transaction is not signed or not exist');
|
|
}
|
|
const result = await this.messenger.send(
|
|
RPCMethod.SendRawTransaction,
|
|
[transaction.getRawTransaction()],
|
|
this.messenger.chainPrefix,
|
|
typeof transaction.txParams.shardID === 'string'
|
|
? Number.parseInt(transaction.txParams.shardID, 10)
|
|
: transaction.txParams.shardID,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async sendRawTransaction(transaction: Transaction) {
|
|
if (!transaction.isSigned() || !transaction) {
|
|
throw new Error('transaction is not signed or not exist');
|
|
}
|
|
const [txn, result] = await transaction.sendTransaction();
|
|
if (txn.isPending) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
createObservedTransaction(transaction: Transaction) {
|
|
try {
|
|
transaction.sendTransaction().then((response) => {
|
|
const [txReturned, TranID] = response;
|
|
|
|
txReturned.confirm(TranID).then((txConfirmed) => {
|
|
transaction.emitter.resolve(txConfirmed);
|
|
});
|
|
});
|
|
return transaction.emitter;
|
|
} catch (err) {
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
@assertObject({
|
|
to: ['isValidAddress', AssertType.optional],
|
|
data: ['isHex', AssertType.optional],
|
|
})
|
|
async estimateGas({ to, data }: { to: string; data: string }) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.EstimateGas,
|
|
[{ to: getAddress(to).checksum, data }],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async gasPrice() {
|
|
const result = await this.messenger.send(RPCMethod.GasPrice, [], this.messenger.chainPrefix);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
async call({
|
|
payload,
|
|
blockNumber = DefaultBlockParams.latest,
|
|
}: {
|
|
payload: any;
|
|
blockNumber?: string;
|
|
}) {
|
|
const result = await this.messenger.send(
|
|
RPCMethod.Call,
|
|
[payload, blockNumber],
|
|
this.messenger.chainPrefix,
|
|
);
|
|
return this.getRpcResult(result);
|
|
}
|
|
|
|
newPendingTransactions(shardID: number = 0) {
|
|
if (this.messenger.provider instanceof WSProvider) {
|
|
return new NewPendingTransactions(this.messenger, shardID);
|
|
} else {
|
|
throw new Error('HttpProvider does not support this feature');
|
|
}
|
|
}
|
|
|
|
newBlockHeaders(shardID: number = 0) {
|
|
if (this.messenger.provider instanceof WSProvider) {
|
|
return new NewHeaders(this.messenger, shardID);
|
|
} else {
|
|
throw new Error('HttpProvider does not support this feature');
|
|
}
|
|
}
|
|
|
|
syncing(shardID: number = 0) {
|
|
if (this.messenger.provider instanceof WSProvider) {
|
|
return new Syncing(this.messenger, shardID);
|
|
} else {
|
|
throw new Error('HttpProvider does not support this feature');
|
|
}
|
|
}
|
|
|
|
logs(options: any, shardID: number = 0) {
|
|
if (this.messenger.provider instanceof WSProvider) {
|
|
return new LogSub(options, this.messenger, shardID);
|
|
} else {
|
|
throw new Error('HttpProvider does not support this feature');
|
|
}
|
|
}
|
|
}
|
|
|
|
export { Blockchain };
|
|
|