vue-tronlink
Version:
Vue support for the TronLink browser extension
515 lines (440 loc) • 16.7 kB
text/typescript
import {Address} from "./base/Address"
import {TokenTrc20} from "./TokenTrc20";
import {
TronLinkEventCaller,
TronLinkTabReply,
TronLinkToken,
TronLinkTunnelMessage, TronMapContract,
TronTRC20Token
} from "./base/types";
import {Vue} from "vue/types/vue";
import CoinDetail from "./CoinDetail";
import {txtUnit} from "../utils/bnx"
/**
* TronLink extension interaction functionality
*/
export default class TronLink {
tronWeb: any
tokens: TronLinkToken
contracts: TronMapContract
selected_function_reply: string
selected_function_human_operation: string
selected_function_caller: TronLinkEventCaller
debug: boolean = false
/**
* Initiates TronLink support object.
*
* @param {Object} tronWeb tronWeb entity object
* (details: https://github.com/tronprotocol/tron-web)
*/
constructor(tronWeb) {
this.tronWeb = tronWeb
this.tokens = {}
this.selected_function_human_operation = ""
if (window && !window.hasOwnProperty("__tronlinkbase_codex")) {
// @ts-ignore
window.__tronlinkbase_codex = this
}
}
public static Instance(): (TronLink | any | boolean) {
if (window && window.hasOwnProperty("__tronlinkbase_codex")) {
// @ts-ignore
const obj = window.__tronlinkbase_codex
if (obj instanceof TronLink) {
return (obj) as TronLink
} else {
return (obj) as TronLink
}
} else {
return false
}
}
setDebug(x: boolean): void {
this.debug = x
}
/**
* Checks if TronLink browser extension is installed
*/
isInstalled(): boolean {
return !!this.tronWeb
}
/**
* Checks if user is logged in to the TronLink plugin
*/
isLoggedIn(): boolean {
return this.tronWeb && this.tronWeb.ready
}
/**
* Checks if user is logged in to the TronLink plugin.
* Alias for isLoggedIn() method.
*/
isUnlocked(): boolean {
return this.isLoggedIn()
}
/**
* Returns logged in user Tron address
*/
getAccountAddress(): string {
return this.tronWeb.defaultAddress.base58
}
/**
* returns the address with 41e...
*/
getAccountAddressHex(): string {
return this.tronWeb.defaultAddress.hex
}
/**
* returns the address with 0x...
*/
getAccountAddress0x(): string {
return "0x" + this.getAccountAddressHex().substr(2)
}
NewContract(abi: any[] = [], address: boolean = false): any {
return new this.tronWeb.Contract(this.tronWeb, abi, address)
}
removeAllFunctionCalls(): void {
this.selected_function_human_operation = ""
}
/**
* Converts Tron address from one format to another.
*
* @param {String, Number} address Address to convert
* @param {String} fromFormat From format string
* @param {String} toFormat To format string
*/
convertAddress(address, fromFormat: string, toFormat: string): string {
if (fromFormat == toFormat) {
throw "From and To address formats are equal"
}
switch (toFormat) {
case "hex":
switch (fromFormat) {
case "base58":
case "tron":
case "trx":
return "0x" + this.tronWeb.address.toHex(address)
}
break
case "base58":
case "tron":
case "trx":
switch (fromFormat) {
case "hex":
if (!Address.isHexAddress(address)) {
throw "Invalid hex address"
}
if (address.startsWith("0x")) {
address = address.substr(2)
}
return this.tronWeb.address.fromHex(address)
}
break
}
throw "Invalid address formats"
}
/**
* doesnt work on the older version
* @deprecated
*/
async coinTRX(): Promise<number> {
let wallet_trx_coin = 0
wallet_trx_coin = await this.tronWeb.trx.getBalance(this.getAccountAddress())
return wallet_trx_coin
}
/**
* the working version of get balance of coin trx the simple way
* @param cb function callback
* @param cberr function callback
*/
getCoinTRX(cb, cberr): void {
this.tronWeb.trx.getBalance(this.getAccountAddress(), (err, x) => {
if (err == null) {
cb(x)
} else {
cberr(err)
}
})
}
async getCoin(trc20_coin: string): Promise<number> {
return await this.getThirdTokenBalanceSun(this.getAccountAddress(), trc20_coin)
}
async getCoinFlo(trc20_coin: string): Promise<number> {
return await this.getThirdTokenBalanceFloat(this.getAccountAddress(), trc20_coin)
}
async coinDPFlo(): Promise<number> {
return await this.getCoinFlo("TXHvwxYbqsDqTCQ9KxNFj4SkuXy7EF2AHR")
}
async coinCOLAFlo(): Promise<number> {
return await this.getCoinFlo("TSNWgunSeGUQqBKK4bM31iLw3bn9SBWWTG")
}
async coinBTCFlo(): Promise<number> {
return await this.getCoinFlo("TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9")
}
async coinETHFlo(): Promise<number> {
return await this.getCoinFlo("THb4CqiFdwNHsWsQCs4JhzwjMWys4aqCbF")
}
async coinSUNFlo(): Promise<number> {
return await this.getCoinFlo("TKkeiboTkxXKJpbmVFbv4a8ov5rAfRDMf9")
}
async coinUSDTFlo(): Promise<number> {
return await this.getCoinFlo("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
}
async coinDP(): Promise<number> {
return await this.getCoin("TXHvwxYbqsDqTCQ9KxNFj4SkuXy7EF2AHR")
}
async coinCOLA(): Promise<number> {
return await this.getCoin("TSNWgunSeGUQqBKK4bM31iLw3bn9SBWWTG")
}
async coinBTC(): Promise<number> {
return await this.getCoin("TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9")
}
async coinETH(): Promise<number> {
return await this.getCoin("THb4CqiFdwNHsWsQCs4JhzwjMWys4aqCbF")
}
async coinSUN(): Promise<number> {
return await this.getCoin("TKkeiboTkxXKJpbmVFbv4a8ov5rAfRDMf9")
}
async coinUSDT(): Promise<number> {
return await this.getCoin("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
}
async getMyCoinDetail(trc20_coin: string): Promise<CoinDetail> {
return await this.getCoinDetail(this.getAccountAddress(), trc20_coin)
}
async coinDPDetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("TXHvwxYbqsDqTCQ9KxNFj4SkuXy7EF2AHR")
}
async coinCOLADetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("TSNWgunSeGUQqBKK4bM31iLw3bn9SBWWTG")
}
async coinBTCDetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9")
}
async coinETHDetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("THb4CqiFdwNHsWsQCs4JhzwjMWys4aqCbF")
}
async coinSUNDetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("TKkeiboTkxXKJpbmVFbv4a8ov5rAfRDMf9")
}
async coinUSDTDetail(): Promise<CoinDetail> {
return await this.getMyCoinDetail("TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t")
}
/**
* get TRC20 token in balance
* @param address
* @param trc20
*/
async getCoinDetail(address: string, trc20: string): Promise<CoinDetail> {
if (!this.isLoggedIn()) {
throw "wallet is not login"
}
if (!this.tokens.hasOwnProperty(trc20)) {
await this.initCoinDetail(trc20, address)
} else {
let contract = this.contracts[trc20]
if (!contract) {
contract = await this.NewToken(trc20)
this.contracts[trc20] = contract
}
const b = await contract.balanceOf(address)
this.tokens[trc20].setHolder(address, txtUnit(b))
}
// @ts-ignore
return this.tokens[trc20];
}
// @ts-ignore
async initCoinDetail(trc20: string, me: string): Promise<CoinDetail> {
const contract = await this.NewToken(trc20)
const a = await contract.balanceOf(me)
const d = await contract.decimals()
const n = await contract.name()
const s = await contract.symbol()
const detail = new CoinDetail(trc20, d, s, n)
detail.setHolder(me, txtUnit(a))
this.tokens[trc20] = detail
this.contracts[trc20] = contract
return detail
}
async getContractToken(trc20: string): Promise<TokenTrc20> {
let contract = this.contracts[trc20]
if (!contract) {
if (this.debug) {
console.log("new contract token ...")
}
contract = await this.NewToken(trc20)
this.contracts[trc20] = contract
}
return contract
}
// @ts-ignore
async sendCoin(amount: any, toaddress: string,): Promise<void> {
await this.tronWeb.trx.sendTransaction(toaddress, amount, {}, (err, receipt) => {
if (err === undefined) {
if (this.debug) {
console.log('- Output:', receipt, '\n');
}
}
})
}
async sendTrc10Token(amount: any, tokenID: number, toaddress: string): Promise<void> {
const receipt = await this.tronWeb.trx.sendToken(toaddress, amount, tokenID, {})
if (this.debug) {
console.log('- Output:', receipt, '\n');
}
}
public async sendToken(amount: any, toaddress: string, trc20: string): Promise<void> {
const contract = await this.NewToken(trc20);
// @ts-ignore
const send_amount = String(amount);
await contract.transfer(toaddress, send_amount);
}
public async approveToken(trc20: string, spender_address: string, amount_sun: any): Promise<void> {
const contract = await this.NewToken(trc20);
const am = String(amount_sun)
await contract.approve(spender_address, am)
}
public async getMyTokenBalance(trc20_coin: string): Promise<number> {
return await this.getTokenBalanceSun(this.getAccountAddress(), trc20_coin)
}
async getTokenBalanceSun(address: string, trc20: string): Promise<number> {
const detail = await this.getCoinDetail(address, trc20)
return detail.balance(address)
}
async getUpdateAllowanceAmount(ins: CoinDetail, myaddress: string, spender: string): Promise<number> {
if (!this.isLoggedIn()) {
throw "wallet is not login"
}
const contract = await this.NewToken(ins.address)
const allowance = await contract.allowance(myaddress, spender)
const nm = txtUnit(allowance)
ins.setSpender(myaddress, spender, nm)
return ins.showAllowance(myaddress, spender)
}
async getThirdTokenBalanceSun(address: string, trc20_address: string): Promise<number> {
const conver = await this.getCoinDetail(address, trc20_address)
return conver.balance(address)
}
async getThirdTokenBalanceFloat(address: string, trc20_address: string): Promise<number> {
const conver = await this.getCoinDetail(address, trc20_address)
return conver.byFloat(address)
}
/**
* to approve prespending TRC20 token on the go..
* @param trc20_address
* @param spender_address
* @param amount_sun
* @constructor
*/
async ApproveSpendingToken(trc20_address: string, spender_address: string, amount_sun: number): Promise<boolean> {
const token = await this.NewToken(trc20_address)
return await token.approve(spender_address, String(amount_sun))
}
async NewToken(trc20_address: string): Promise<TokenTrc20> {
const contract = new TokenTrc20(this.tronWeb)
contract.setDebug(false)
await contract.init(trc20_address)
return contract
}
getListedCoins(): TronLinkToken {
return this.tokens
}
explainTrc20(payload: TronTRC20Token): number {
const me = this.getAccountAddress()
return payload.holder[me]
}
setCallbackFunctionCall(function_selector: string, caller: TronLinkEventCaller) {
this.selected_function_human_operation = function_selector
this.selected_function_caller = caller
}
__signOp(payload: TronLinkTunnelMessage): boolean {
if (this.selected_function_human_operation == payload.data.input.function_selector) {
this.selected_function_caller.signer(payload)
return true
} else {
return false
}
}
__signReply(payload: TronLinkTabReply): boolean {
if (this.selected_function_caller != undefined && this.selected_function_human_operation != "") {
this.selected_function_caller.reply(payload)
this.selected_function_human_operation = ""
return true
} else {
return false
}
}
__debugMessage(data_message_raw: any): boolean {
if (this.selected_function_caller) {
this.selected_function_caller.debug(data_message_raw)
return true
} else {
return false
}
}
eventListener(message: any, tronLinkInitialData: boolean | any, vueInstance: Vue) {
if (message.action === 'setNode') {
// @ts-ignore
vueInstance.announce_node_name(message.data.node.fullNode)
vueInstance.$emit("notify_tron_node_change", message.data.node.fullNode)
}
if (message.action === 'setAccount') {
if (message.hasOwnProperty("data")) {
// @ts-ignore
if (vueInstance.hasOwnProperty("account_name") && vueInstance.account_name !== message.data.name) {
vueInstance.$emit("notify_tron_account_set", message.data.name, message.data.address)
}
if (message.data.name === false) {
vueInstance.$emit("notify_tron_account_logout")
}
}
}
if (message.action === 'tunnel') {
if (message.data.hasOwnProperty("action") && message.data.action === 'sign') {
if (message.data.hasOwnProperty("input") && message.data.input.hasOwnProperty("function_selector")) {
if (!this.__signOp(message.data)) {
vueInstance.$emit("notify_tron_opensign", message.uuid, message.data.input.function_selector, message.data)
}
} else {
if (!this.__signOp(message.data)) {
vueInstance.$emit("notify_tron_opensign", message.uuid, message.data)
}
}
}
}
if (message.action === 'tabReply') {
/**
* response from the wallet sign action
*/
if (message.data.hasOwnProperty("success")) {
if (message.data.success === true) {
if (!this.__signReply(message.data)) {
vueInstance.$emit("notify_tron_sign_success_broadcast", message.data, message.uuid)
}
} else {
this.removeAllFunctionCalls()
}
}
if (!tronLinkInitialData) {
if (typeof message === "object" && message.hasOwnProperty("data")) {
if (message.data.hasOwnProperty("data")) {
tronLinkInitialData = message.data.data;
if (message.data.hasOwnProperty("node")) {
// @ts-ignore
vueInstance.announce_node_name(message.data.node.full_node)
}
vueInstance.$emit("notify_tron_initialization", tronLinkInitialData)
} else {
console.log(message.data)
}
}
}
}
// @ts-ignore
if (vueInstance.hasOwnProperty("_debug_tronlink") && vueInstance._debug_tronlink) {
console.group("TronLink Message 🖼")
console.log("Action:", message.action)
console.log(message.data)
this.__debugMessage(message)
console.groupEnd()
}
}
}