Skip to content

Commit

Permalink
Merge pull request #511 from start940315/release/v6.0.0-beta.3
Browse files Browse the repository at this point in the history
Release/v6.0.0 beta.3
  • Loading branch information
unicornonea committed May 7, 2024
2 parents ac0deaa + 519d5a0 commit e40a968
Show file tree
Hide file tree
Showing 16 changed files with 193 additions and 58 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
=========

__6.0.0-beta.3__
- Support recovering transaction signer address by `trx.ecRecover`.
- Support both base58 format and hex format address field in keys of `updateAccountPermissions` params.
- Support type for contract instance.

__6.0.0-beta.2__
- Bump ethers from 6.8.0 to 6.11.1
- Bump ethereum-cryptography from 2.1.2 to 2.1.3
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ docker run -it --rm \

## Creating an Instance

First off, in your javascript file, define TronWeb:
First of all, in your typescript file, define TronWeb:

```js
const TronWeb = require('tronweb')
```typescript
import { TronWeb, utils as TronWebUtils, Trx, TransactionBuilder, Contract, Event, Plugin } from 'tronweb';
```

Please note that this is not the same as v5.x. If you want to dive into more differences, check out [migration guide](https://tronweb.network/docu/docs/6.0.0-beta.3/Migrating%20from%20v5)

When you instantiate TronWeb you can define

* fullNode
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tronweb",
"version": "6.0.0-beta.2",
"version": "6.0.0-beta.3",
"description": "JavaScript SDK that encapsulates the TRON HTTP API",
"main": "./lib/commonjs/index.js",
"module": "./lib/esm/index.js",
Expand Down
14 changes: 14 additions & 0 deletions src/lib/TransactionBuilder/TransactionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,10 @@ export class TransactionBuilder {
if ('type' in _ownerPermissions) {
delete _ownerPermissions.type;
}
_ownerPermissions.keys = _ownerPermissions.keys?.map(({ address, weight }) => ({
address: this.tronWeb.address.toHex(address),
weight,
}));
data.owner = _ownerPermissions as Permission;
}
if (witnessPermission) {
Expand All @@ -2121,6 +2125,10 @@ export class TransactionBuilder {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
_witnessPermissions.type = 'Witness';
_witnessPermissions.keys = _witnessPermissions.keys.map(({ address, weight }) => ({
address: this.tronWeb.address.toHex(address),
weight,
}));
data.witness = _witnessPermissions;
}
if (activesPermissions) {
Expand All @@ -2131,6 +2139,12 @@ export class TransactionBuilder {
// @ts-ignore
activePermissions.type = 'Active';
});
_activesPermissions.forEach((_activesPermission) => {
_activesPermission.keys = _activesPermission.keys.map(({ address, weight }) => ({
address: this.tronWeb.address.toHex(address),
weight,
}));
});
data.actives = _activesPermissions as Permission[];
}

Expand Down
18 changes: 8 additions & 10 deletions src/lib/contract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import type { ContractAbiInterface } from '../../types/ABI.js';
import { Address } from '../../types/Trx.js';
import { CreateSmartContractOptions } from '../../types/TransactionBuilder.js';

export interface IContract {
[key: string | number | symbol]: (...args: any[]) => ReturnType<Method['onMethod']>;
}

export class Contract {
tronWeb: TronWeb;
Expand All @@ -17,9 +14,10 @@ export class Contract {
bytecode?: false | string;
deployed?: boolean;
lastBlock?: false | number;
methods: Record<any, any>;
methodInstances: Record<any, any>;
methods: Record<string | number | symbol, (...args: any) => ReturnType<Method['onMethod']>>;
methodInstances: Record<string | number | symbol, Method>;
props: any[];
[key: string | number | symbol]: any;

constructor(tronWeb: TronWeb, abi: ContractAbiInterface = [], address: Address) {
if (!tronWeb || !(tronWeb instanceof TronWeb)) throw new Error('Expected instance of TronWeb');
Expand Down Expand Up @@ -49,14 +47,14 @@ export class Contract {

hasProperty(property: number | string | symbol) {
// eslint-disable-next-line no-prototype-builtins
return this.hasOwnProperty(property) || (this as unknown as IContract).__proto__.hasOwnProperty(property);
return this.hasOwnProperty(property) || (this as any).__proto__.hasOwnProperty(property);
}

loadAbi(abi: ContractAbiInterface) {
this.abi = abi;
this.methods = {};

this.props.forEach((prop) => delete (this as unknown as IContract)[prop]);
this.props.forEach((prop: string) => delete (this as any)[prop]);

abi.forEach((func) => {
// Don't build a method for constructor function. That's handled through contract create.
Expand All @@ -77,17 +75,17 @@ export class Contract {
this.methodInstances[signature] = method;

if (!this.hasProperty(name)) {
(this as unknown as IContract)[name] = methodCall;
(this as any)[name] = methodCall;
this.props.push(name);
}

if (!this.hasProperty(functionSelector!)) {
(this as unknown as IContract)[functionSelector!] = methodCall;
(this as any)[functionSelector!] = methodCall;
this.props.push(functionSelector);
}

if (!this.hasProperty(signature)) {
(this as unknown as IContract)[signature] = methodCall;
(this as any)[signature] = methodCall;
this.props.push(signature);
}
});
Expand Down
22 changes: 22 additions & 0 deletions src/lib/trx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { keccak256, toUtf8Bytes, recoverAddress, SigningKey, Signature } from '.
import { ADDRESS_PREFIX } from '../utils/address.js';
import { Validator } from '../paramValidator/index.js';
import { txCheck } from '../utils/transaction.js';
import { ecRecover } from '../utils/crypto.js';
import { Block } from '../types/APIResponse.js';
import {
Token,
Expand Down Expand Up @@ -508,6 +509,27 @@ export class Trx {
return contract;
}

ecRecover(transaction: SignedTransaction) {
return Trx.ecRecover(transaction);
}

static ecRecover(transaction: SignedTransaction): Address | Address[] {
if (!txCheck(transaction)) {
throw new Error('Invalid transaction');
}
if (!transaction.signature?.length) {
throw new Error('Transaction is not signed');
}
if (transaction.signature.length === 1) {
const tronAddress = ecRecover(transaction.txID, transaction.signature[0]);
return TronWeb.address.fromHex(tronAddress);
}
return transaction.signature.map((sig) => {
const tronAddress = ecRecover(transaction.txID, sig);
return TronWeb.address.fromHex(tronAddress);
});
}

async verifyMessage(message: string, signature: string, address = this.tronWeb.defaultAddress.base58, useTronHeader = true) {
if (!utils.isHex(message)) {
throw new Error('Expected hex message input');
Expand Down
2 changes: 1 addition & 1 deletion src/tronweb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const DEFAULT_VERSION = '4.7.1';

const FEE_LIMIT = 150000000;

const version = '6.0.0-beta.2';
const version = '6.0.0-beta.3';

function isValidOptions(options: unknown): options is TronWebOptions {
return (
Expand Down
11 changes: 10 additions & 1 deletion src/utils/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ADDRESS_PREFIX, ADDRESS_PREFIX_BYTE, ADDRESS_SIZE } from './address.js'
import { base64EncodeToString, base64DecodeFromString, hexStr2byteArray } from './code.js';
import { encode58, decode58 } from './base58.js';
import { BytesLike, byte2hexStr, byteArray2hexStr } from './bytes.js';
import { keccak256, sha256, SigningKey } from './ethersUtils.js';
import { keccak256, sha256, SigningKey, recoverAddress, arrayify, Signature } from './ethersUtils.js';
import { TypedDataEncoder } from './typedData.js';
import { secp256k1 as secp } from 'ethereum-cryptography/secp256k1';
import type { TypedDataDomain, TypedDataField } from 'ethers';
Expand Down Expand Up @@ -66,6 +66,15 @@ export function signTransaction(priKeyBytes: string | BytesLike, transaction: an
return transaction;
}

export function ecRecover(signedData: string, signature: string) {
signedData = '0x' + signedData.replace(/^0x/, '');
signature = '0x' + signature.replace(/^0x/, '');

const recovered = recoverAddress(arrayify(signedData), Signature.from(signature));
const tronAddress = ADDRESS_PREFIX + recovered.substring(2);
return tronAddress;
}

export function arrayToBase64String(a: number[]) {
return btoa(String.fromCharCode(...a));
}
Expand Down
15 changes: 7 additions & 8 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { assert } from 'chai';
import Config from './helpers/config.js';
import { TronWeb, providers } from './setup/TronWeb.js';
import { Contract, TronWeb, providers } from './setup/TronWeb.js';
import tronWebBuilder from './helpers/tronWebBuilder.js';
import BigNumber from 'bignumber.js';
import broadcaster from './helpers/broadcaster.js';
import wait from './helpers/wait.js';
import { Address } from '../src/types/Trx.js';
import { IContract } from '../src/lib/contract/index.js';
import { RawAxiosRequestHeaders } from 'axios';

const HttpProvider = providers.HttpProvider;
Expand Down Expand Up @@ -754,7 +753,7 @@ describe('TronWeb Instance', function () {
};
let tronWeb: TronWeb;
let contractAddress;
let contract: IContract;
let contract: Contract;

before(async function () {
tronWeb = tronWebBuilder.createInstance();
Expand Down Expand Up @@ -814,13 +813,13 @@ describe('TronWeb Instance', function () {
);

contractAddress = result.receipt.transaction.contract_address!;
contract = (await tronWeb.contract().at(contractAddress)) as unknown as IContract;
contract = await tronWeb.contract().at(contractAddress);
});

it('should emit an unconfirmed event and get it', async function () {
this.timeout(60000);
tronWeb.setPrivateKey(accounts.pks[1]);
let txId = await contract.emitNow(accounts.hex[2], 2000).send({
let txId = await contract.methods.emitNow(accounts.hex[2], 2000).send({
from: accounts.hex[1],
});
let events;
Expand All @@ -845,7 +844,7 @@ describe('TronWeb Instance', function () {
};
let tronWeb: TronWeb;
let contractAddress: Address;
let contract: IContract;
let contract: Contract;
let eventLength = 0;

before(async function () {
Expand Down Expand Up @@ -906,15 +905,15 @@ describe('TronWeb Instance', function () {
);

contractAddress = result.receipt.transaction.contract_address!;
contract = (await tronWeb.contract().at(contractAddress)) as unknown as IContract;
contract = await tronWeb.contract().at(contractAddress);
});

// available on trongrid
it.skip('should emit an event and wait for it', async function () {
this.timeout(60000);
await wait(120); // wait for abi syncing.
tronWeb.setPrivateKey(accounts.pks[3]);
await contract.emitNow(accounts.hex[4], 4000).send({
await contract.methods.emitNow(accounts.hex[4], 4000).send({
from: accounts.hex[3],
});
eventLength++;
Expand Down
4 changes: 2 additions & 2 deletions test/lib/contract/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import broadcaster from '../../helpers/broadcaster.js';
import tronWebBuilder from '../../helpers/tronWebBuilder.js';
import { TronWeb } from '../../setup/TronWeb.js';
import contracts from '../../fixtures/contracts';
import { IContract, Contract } from '../../../src/lib/contract';
import { Contract } from '../../../src/lib/contract';

const testCustomError = contracts.testCustomError;

Expand Down Expand Up @@ -41,7 +41,7 @@ describe('#contract.index', function () {
});

it('should revert with custom error', async () => {
const txid = await (customError as unknown as IContract).test(111).send();
const txid = await customError.test(111).send();
await wait(10);
const data = await tronWeb.trx.getTransactionInfo(txid);
const errorData = data.contractResult;
Expand Down
15 changes: 7 additions & 8 deletions test/lib/contract/method.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { IContract } from '../../../src/lib/contract/index.js';
import { Address } from '../../../src/types/Trx.js';
import { assert } from 'chai';
import assertThrow from '../../helpers/assertThrow.js';
import broadcaster from '../../helpers/broadcaster.js';
import tronWebBuilder from '../../helpers/tronWebBuilder.js';
import { TronWeb } from '../../setup/TronWeb.js';
import { Contract, TronWeb } from '../../setup/TronWeb.js';
import contracts from '../../fixtures/contracts.js';
const testRevertContract = contracts.testRevert;
const testSetValContract = contracts.testSetVal;
Expand All @@ -24,8 +23,8 @@ describe('#contract.method', function () {
});

describe('#send()', function () {
let testRevert: IContract;
let testSetVal: IContract;
let testRevert: Contract;
let testSetVal: Contract;

before(async function () {
const tx = await broadcaster(
Expand All @@ -38,7 +37,7 @@ describe('#contract.method', function () {
),
accounts.pks[0]
);
testRevert = (await tronWeb.contract().at(tx.transaction.contract_address)) as unknown as IContract;
testRevert = await tronWeb.contract().at(tx.transaction.contract_address);

const tx2 = await broadcaster(
tronWeb.transactionBuilder.createSmartContract(
Expand All @@ -50,7 +49,7 @@ describe('#contract.method', function () {
),
accounts.pks[0]
);
testSetVal = (await tronWeb.contract().at(tx2.transaction.contract_address)) as unknown as IContract;
testSetVal = await tronWeb.contract().at(tx2.transaction.contract_address);
});

it('should set accounts[2] as the owner and check it with getOwner(1)', async function () {
Expand Down Expand Up @@ -79,7 +78,7 @@ describe('#contract.method', function () {
});

describe('#call()', function () {
let testRevert: IContract;
let testRevert: Contract;

before(async function () {
const tx = await broadcaster(
Expand All @@ -92,7 +91,7 @@ describe('#contract.method', function () {
),
accounts.pks[0]
);
testRevert = (await tronWeb.contract().at(tx.transaction.contract_address)) as unknown as IContract;
testRevert = await tronWeb.contract().at(tx.transaction.contract_address);
await testRevert.setOwner(accounts.b58[2]).send();
});

Expand Down

0 comments on commit e40a968

Please sign in to comment.