Skip to content

Commit d4db1a7

Browse files
authored
Merge pull request #514 from tronprotocol/release/v6.0.0-beta.3
Release/v6.0.0 beta.3
2 parents ac0deaa + e40a968 commit d4db1a7

File tree

16 files changed

+193
-58
lines changed

16 files changed

+193
-58
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
Change Log
22
=========
33

4+
__6.0.0-beta.3__
5+
- Support recovering transaction signer address by `trx.ecRecover`.
6+
- Support both base58 format and hex format address field in keys of `updateAccountPermissions` params.
7+
- Support type for contract instance.
8+
49
__6.0.0-beta.2__
510
- Bump ethers from 6.8.0 to 6.11.1
611
- Bump ethereum-cryptography from 2.1.2 to 2.1.3

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,14 @@ docker run -it --rm \
112112

113113
## Creating an Instance
114114

115-
First off, in your javascript file, define TronWeb:
115+
First of all, in your typescript file, define TronWeb:
116116

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

121+
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)
122+
121123
When you instantiate TronWeb you can define
122124

123125
* fullNode

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tronweb",
3-
"version": "6.0.0-beta.2",
3+
"version": "6.0.0-beta.3",
44
"description": "JavaScript SDK that encapsulates the TRON HTTP API",
55
"main": "./lib/commonjs/index.js",
66
"module": "./lib/esm/index.js",

src/lib/TransactionBuilder/TransactionBuilder.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,10 @@ export class TransactionBuilder {
21132113
if ('type' in _ownerPermissions) {
21142114
delete _ownerPermissions.type;
21152115
}
2116+
_ownerPermissions.keys = _ownerPermissions.keys?.map(({ address, weight }) => ({
2117+
address: this.tronWeb.address.toHex(address),
2118+
weight,
2119+
}));
21162120
data.owner = _ownerPermissions as Permission;
21172121
}
21182122
if (witnessPermission) {
@@ -2121,6 +2125,10 @@ export class TransactionBuilder {
21212125
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
21222126
// @ts-ignore
21232127
_witnessPermissions.type = 'Witness';
2128+
_witnessPermissions.keys = _witnessPermissions.keys.map(({ address, weight }) => ({
2129+
address: this.tronWeb.address.toHex(address),
2130+
weight,
2131+
}));
21242132
data.witness = _witnessPermissions;
21252133
}
21262134
if (activesPermissions) {
@@ -2131,6 +2139,12 @@ export class TransactionBuilder {
21312139
// @ts-ignore
21322140
activePermissions.type = 'Active';
21332141
});
2142+
_activesPermissions.forEach((_activesPermission) => {
2143+
_activesPermission.keys = _activesPermission.keys.map(({ address, weight }) => ({
2144+
address: this.tronWeb.address.toHex(address),
2145+
weight,
2146+
}));
2147+
});
21342148
data.actives = _activesPermissions as Permission[];
21352149
}
21362150

src/lib/contract/index.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import type { ContractAbiInterface } from '../../types/ABI.js';
55
import { Address } from '../../types/Trx.js';
66
import { CreateSmartContractOptions } from '../../types/TransactionBuilder.js';
77

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

129
export class Contract {
1310
tronWeb: TronWeb;
@@ -17,9 +14,10 @@ export class Contract {
1714
bytecode?: false | string;
1815
deployed?: boolean;
1916
lastBlock?: false | number;
20-
methods: Record<any, any>;
21-
methodInstances: Record<any, any>;
17+
methods: Record<string | number | symbol, (...args: any) => ReturnType<Method['onMethod']>>;
18+
methodInstances: Record<string | number | symbol, Method>;
2219
props: any[];
20+
[key: string | number | symbol]: any;
2321

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

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

5553
loadAbi(abi: ContractAbiInterface) {
5654
this.abi = abi;
5755
this.methods = {};
5856

59-
this.props.forEach((prop) => delete (this as unknown as IContract)[prop]);
57+
this.props.forEach((prop: string) => delete (this as any)[prop]);
6058

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

7977
if (!this.hasProperty(name)) {
80-
(this as unknown as IContract)[name] = methodCall;
78+
(this as any)[name] = methodCall;
8179
this.props.push(name);
8280
}
8381

8482
if (!this.hasProperty(functionSelector!)) {
85-
(this as unknown as IContract)[functionSelector!] = methodCall;
83+
(this as any)[functionSelector!] = methodCall;
8684
this.props.push(functionSelector);
8785
}
8886

8987
if (!this.hasProperty(signature)) {
90-
(this as unknown as IContract)[signature] = methodCall;
88+
(this as any)[signature] = methodCall;
9189
this.props.push(signature);
9290
}
9391
});

src/lib/trx.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { keccak256, toUtf8Bytes, recoverAddress, SigningKey, Signature } from '.
44
import { ADDRESS_PREFIX } from '../utils/address.js';
55
import { Validator } from '../paramValidator/index.js';
66
import { txCheck } from '../utils/transaction.js';
7+
import { ecRecover } from '../utils/crypto.js';
78
import { Block } from '../types/APIResponse.js';
89
import {
910
Token,
@@ -508,6 +509,27 @@ export class Trx {
508509
return contract;
509510
}
510511

512+
ecRecover(transaction: SignedTransaction) {
513+
return Trx.ecRecover(transaction);
514+
}
515+
516+
static ecRecover(transaction: SignedTransaction): Address | Address[] {
517+
if (!txCheck(transaction)) {
518+
throw new Error('Invalid transaction');
519+
}
520+
if (!transaction.signature?.length) {
521+
throw new Error('Transaction is not signed');
522+
}
523+
if (transaction.signature.length === 1) {
524+
const tronAddress = ecRecover(transaction.txID, transaction.signature[0]);
525+
return TronWeb.address.fromHex(tronAddress);
526+
}
527+
return transaction.signature.map((sig) => {
528+
const tronAddress = ecRecover(transaction.txID, sig);
529+
return TronWeb.address.fromHex(tronAddress);
530+
});
531+
}
532+
511533
async verifyMessage(message: string, signature: string, address = this.tronWeb.defaultAddress.base58, useTronHeader = true) {
512534
if (!utils.isHex(message)) {
513535
throw new Error('Expected hex message input');

src/tronweb.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const DEFAULT_VERSION = '4.7.1';
2222

2323
const FEE_LIMIT = 150000000;
2424

25-
const version = '6.0.0-beta.2';
25+
const version = '6.0.0-beta.3';
2626

2727
function isValidOptions(options: unknown): options is TronWebOptions {
2828
return (

src/utils/crypto.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { ADDRESS_PREFIX, ADDRESS_PREFIX_BYTE, ADDRESS_SIZE } from './address.js'
22
import { base64EncodeToString, base64DecodeFromString, hexStr2byteArray } from './code.js';
33
import { encode58, decode58 } from './base58.js';
44
import { BytesLike, byte2hexStr, byteArray2hexStr } from './bytes.js';
5-
import { keccak256, sha256, SigningKey } from './ethersUtils.js';
5+
import { keccak256, sha256, SigningKey, recoverAddress, arrayify, Signature } from './ethersUtils.js';
66
import { TypedDataEncoder } from './typedData.js';
77
import { secp256k1 as secp } from 'ethereum-cryptography/secp256k1';
88
import type { TypedDataDomain, TypedDataField } from 'ethers';
@@ -66,6 +66,15 @@ export function signTransaction(priKeyBytes: string | BytesLike, transaction: an
6666
return transaction;
6767
}
6868

69+
export function ecRecover(signedData: string, signature: string) {
70+
signedData = '0x' + signedData.replace(/^0x/, '');
71+
signature = '0x' + signature.replace(/^0x/, '');
72+
73+
const recovered = recoverAddress(arrayify(signedData), Signature.from(signature));
74+
const tronAddress = ADDRESS_PREFIX + recovered.substring(2);
75+
return tronAddress;
76+
}
77+
6978
export function arrayToBase64String(a: number[]) {
7079
return btoa(String.fromCharCode(...a));
7180
}

test/index.test.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { assert } from 'chai';
22
import Config from './helpers/config.js';
3-
import { TronWeb, providers } from './setup/TronWeb.js';
3+
import { Contract, TronWeb, providers } from './setup/TronWeb.js';
44
import tronWebBuilder from './helpers/tronWebBuilder.js';
55
import BigNumber from 'bignumber.js';
66
import broadcaster from './helpers/broadcaster.js';
77
import wait from './helpers/wait.js';
88
import { Address } from '../src/types/Trx.js';
9-
import { IContract } from '../src/lib/contract/index.js';
109
import { RawAxiosRequestHeaders } from 'axios';
1110

1211
const HttpProvider = providers.HttpProvider;
@@ -754,7 +753,7 @@ describe('TronWeb Instance', function () {
754753
};
755754
let tronWeb: TronWeb;
756755
let contractAddress;
757-
let contract: IContract;
756+
let contract: Contract;
758757

759758
before(async function () {
760759
tronWeb = tronWebBuilder.createInstance();
@@ -814,13 +813,13 @@ describe('TronWeb Instance', function () {
814813
);
815814

816815
contractAddress = result.receipt.transaction.contract_address!;
817-
contract = (await tronWeb.contract().at(contractAddress)) as unknown as IContract;
816+
contract = await tronWeb.contract().at(contractAddress);
818817
});
819818

820819
it('should emit an unconfirmed event and get it', async function () {
821820
this.timeout(60000);
822821
tronWeb.setPrivateKey(accounts.pks[1]);
823-
let txId = await contract.emitNow(accounts.hex[2], 2000).send({
822+
let txId = await contract.methods.emitNow(accounts.hex[2], 2000).send({
824823
from: accounts.hex[1],
825824
});
826825
let events;
@@ -845,7 +844,7 @@ describe('TronWeb Instance', function () {
845844
};
846845
let tronWeb: TronWeb;
847846
let contractAddress: Address;
848-
let contract: IContract;
847+
let contract: Contract;
849848
let eventLength = 0;
850849

851850
before(async function () {
@@ -906,15 +905,15 @@ describe('TronWeb Instance', function () {
906905
);
907906

908907
contractAddress = result.receipt.transaction.contract_address!;
909-
contract = (await tronWeb.contract().at(contractAddress)) as unknown as IContract;
908+
contract = await tronWeb.contract().at(contractAddress);
910909
});
911910

912911
// available on trongrid
913912
it.skip('should emit an event and wait for it', async function () {
914913
this.timeout(60000);
915914
await wait(120); // wait for abi syncing.
916915
tronWeb.setPrivateKey(accounts.pks[3]);
917-
await contract.emitNow(accounts.hex[4], 4000).send({
916+
await contract.methods.emitNow(accounts.hex[4], 4000).send({
918917
from: accounts.hex[3],
919918
});
920919
eventLength++;

0 commit comments

Comments
 (0)