@mapprotocol/common-contracts 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -100
- package/package.json +18 -3
- package/script/base/Base.s.sol +231 -0
- package/script/base/interfaces/IFactory.sol +7 -0
- package/utils/deployer.ts +15 -3
- package/utils/dist/addressCodec.d.ts +14 -0
- package/utils/dist/addressCodec.js +61 -0
- package/utils/dist/codeHash.d.ts +24 -0
- package/utils/dist/codeHash.js +60 -0
- package/utils/dist/deployRecord.d.ts +37 -0
- package/utils/dist/deployRecord.js +104 -0
- package/utils/dist/deployer.d.ts +48 -0
- package/utils/dist/deployer.js +80 -0
- package/utils/dist/evmHelper.d.ts +33 -0
- package/utils/dist/evmHelper.js +83 -0
- package/utils/dist/factory.d.ts +36 -0
- package/utils/dist/factory.js +187 -0
- package/utils/dist/index.d.ts +17 -0
- package/utils/dist/index.js +45 -0
- package/utils/dist/tronHelper.d.ts +127 -0
- package/utils/dist/tronHelper.js +291 -0
- package/utils/dist/verifier.d.ts +24 -0
- package/utils/dist/verifier.js +229 -0
- package/utils/verifier.ts +72 -41
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @mapprotocol/common-contracts/utils
|
|
4
|
+
*
|
|
5
|
+
* Shared TypeScript utilities for MAP Protocol contract operations.
|
|
6
|
+
*
|
|
7
|
+
* Quick start:
|
|
8
|
+
* const deployer = createDeployer(hre, { autoVerify: true });
|
|
9
|
+
* await deployer.deploy("MyContract", [arg1], "optional_salt");
|
|
10
|
+
* await deployer.deployProxy("MyContract", [initArg], "optional_salt");
|
|
11
|
+
* await deployer.upgrade("MyContract", proxyAddr);
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.waitForTx = exports.sendAndWait = exports.isTronNetwork = exports.tronToHex = exports.tronFromHex = exports.TronClient = exports.isSolanaChain = exports.isTronAddress = exports.isBase58 = exports.addressToHex = exports.getCustomProxyCodeHash = exports.getProxyCodeHash = exports.getCodeHash = exports.verify = exports.saveDeployment = exports.hasDeployment = exports.getDeploymentByKey = exports.resolveDeploymentPath = exports.createDeployer = void 0;
|
|
15
|
+
// Unified deployer — recommended entry point for deploy/upgrade/verify
|
|
16
|
+
var deployer_1 = require("./deployer");
|
|
17
|
+
Object.defineProperty(exports, "createDeployer", { enumerable: true, get: function () { return deployer_1.createDeployer; } });
|
|
18
|
+
// Deploy record — deploy.json address management
|
|
19
|
+
var deployRecord_1 = require("./deployRecord");
|
|
20
|
+
Object.defineProperty(exports, "resolveDeploymentPath", { enumerable: true, get: function () { return deployRecord_1.resolveDeploymentPath; } });
|
|
21
|
+
Object.defineProperty(exports, "getDeploymentByKey", { enumerable: true, get: function () { return deployRecord_1.getDeploymentByKey; } });
|
|
22
|
+
Object.defineProperty(exports, "hasDeployment", { enumerable: true, get: function () { return deployRecord_1.hasDeployment; } });
|
|
23
|
+
Object.defineProperty(exports, "saveDeployment", { enumerable: true, get: function () { return deployRecord_1.saveDeployment; } });
|
|
24
|
+
// Contract verification
|
|
25
|
+
var verifier_1 = require("./verifier");
|
|
26
|
+
Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return verifier_1.verify; } });
|
|
27
|
+
// Code hash for CREATE2 address prediction
|
|
28
|
+
var codeHash_1 = require("./codeHash");
|
|
29
|
+
Object.defineProperty(exports, "getCodeHash", { enumerable: true, get: function () { return codeHash_1.getCodeHash; } });
|
|
30
|
+
Object.defineProperty(exports, "getProxyCodeHash", { enumerable: true, get: function () { return codeHash_1.getProxyCodeHash; } });
|
|
31
|
+
Object.defineProperty(exports, "getCustomProxyCodeHash", { enumerable: true, get: function () { return codeHash_1.getCustomProxyCodeHash; } });
|
|
32
|
+
// Address encoding
|
|
33
|
+
var addressCodec_1 = require("./addressCodec");
|
|
34
|
+
Object.defineProperty(exports, "addressToHex", { enumerable: true, get: function () { return addressCodec_1.addressToHex; } });
|
|
35
|
+
Object.defineProperty(exports, "isBase58", { enumerable: true, get: function () { return addressCodec_1.isBase58; } });
|
|
36
|
+
Object.defineProperty(exports, "isTronAddress", { enumerable: true, get: function () { return addressCodec_1.isTronAddress; } });
|
|
37
|
+
Object.defineProperty(exports, "isSolanaChain", { enumerable: true, get: function () { return addressCodec_1.isSolanaChain; } });
|
|
38
|
+
// Tron utilities
|
|
39
|
+
var tronHelper_1 = require("./tronHelper");
|
|
40
|
+
Object.defineProperty(exports, "TronClient", { enumerable: true, get: function () { return tronHelper_1.TronClient; } });
|
|
41
|
+
Object.defineProperty(exports, "tronFromHex", { enumerable: true, get: function () { return tronHelper_1.tronFromHex; } });
|
|
42
|
+
Object.defineProperty(exports, "tronToHex", { enumerable: true, get: function () { return tronHelper_1.tronToHex; } });
|
|
43
|
+
Object.defineProperty(exports, "isTronNetwork", { enumerable: true, get: function () { return tronHelper_1.isTronNetwork; } });
|
|
44
|
+
Object.defineProperty(exports, "sendAndWait", { enumerable: true, get: function () { return tronHelper_1.sendAndWait; } });
|
|
45
|
+
Object.defineProperty(exports, "waitForTx", { enumerable: true, get: function () { return tronHelper_1.waitForTx; } });
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/** Convert hex address to Tron base58 format. Returns as-is if already base58. */
|
|
2
|
+
export declare function tronFromHex(hex: string): string;
|
|
3
|
+
/** Convert Tron base58 address to 0x-prefixed hex. Returns as-is if already hex. */
|
|
4
|
+
export declare function tronToHex(addr: string): string;
|
|
5
|
+
/** Check if a network name or chainId belongs to Tron (case-insensitive). */
|
|
6
|
+
export declare function isTronNetwork(networkOrChainId: string | number): boolean;
|
|
7
|
+
export interface TronAddress {
|
|
8
|
+
hex: string;
|
|
9
|
+
base58: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* TronClient — encapsulates tronWeb instance, provides high-level contract operations.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* // From hardhat runtime (recommended in tasks)
|
|
16
|
+
* let client = TronClient.fromHre(hre);
|
|
17
|
+
*
|
|
18
|
+
* // Manual — with rpc and private key
|
|
19
|
+
* let client = new TronClient("https://api.trongrid.io", "your_private_key");
|
|
20
|
+
*
|
|
21
|
+
* // Read-only — no private key
|
|
22
|
+
* let client = new TronClient("https://api.trongrid.io");
|
|
23
|
+
*
|
|
24
|
+
* // Contract interaction
|
|
25
|
+
* let gw = await client.getContract(artifacts, "Gateway", addr);
|
|
26
|
+
* let wtoken = await gw.wToken().call(); // read
|
|
27
|
+
* await gw.setWtoken(client.toHex(wtoken)).sendAndWait(); // write + wait
|
|
28
|
+
*
|
|
29
|
+
* // Deploy
|
|
30
|
+
* let { hex, base58 } = await client.deploy(artifacts, "Gateway");
|
|
31
|
+
* let { proxy, implementation } = await client.deployProxy(artifacts, "Gateway", [admin]);
|
|
32
|
+
*
|
|
33
|
+
* // Upgrade
|
|
34
|
+
* await client.upgradeProxy(artifacts, "Gateway", proxyAddr);
|
|
35
|
+
*/
|
|
36
|
+
export declare class TronClient {
|
|
37
|
+
private tronWeb;
|
|
38
|
+
private connected;
|
|
39
|
+
/**
|
|
40
|
+
* Create a TronClient with explicit rpcUrl.
|
|
41
|
+
* @param rpcUrl - Tron full host URL (e.g. "https://api.trongrid.io")
|
|
42
|
+
* @param privateKey - optional, omit for read-only operations
|
|
43
|
+
*/
|
|
44
|
+
constructor(rpcUrl: string, privateKey?: string);
|
|
45
|
+
/**
|
|
46
|
+
* Create TronClient from hardhat runtime environment.
|
|
47
|
+
* Reads rpcUrl and privateKey from hre.network.config. Verifies RPC connectivity.
|
|
48
|
+
*/
|
|
49
|
+
static fromHre(hre: any): TronClient;
|
|
50
|
+
/** Verify RPC is reachable. Uses getNowBlock which is widely supported. */
|
|
51
|
+
private _checkConnection;
|
|
52
|
+
/** Lazy connection check — called before first contract operation. */
|
|
53
|
+
private _ensureConnected;
|
|
54
|
+
/** Get the default operator address in base58 format. */
|
|
55
|
+
get defaultAddress(): string;
|
|
56
|
+
/** Convert Tron base58 address to 0x hex. */
|
|
57
|
+
toHex(addr: string): string;
|
|
58
|
+
/** Convert 0x hex to Tron base58 address. */
|
|
59
|
+
fromHex(hex: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Get a contract instance. Write methods have .sendAndWait() attached.
|
|
62
|
+
* @param artifacts - hardhat artifacts (hre.artifacts)
|
|
63
|
+
* @param contractName - contract name (e.g. "Gateway")
|
|
64
|
+
* @param addr - contract address (base58 or hex)
|
|
65
|
+
*/
|
|
66
|
+
getContract(artifacts: any, contractName: string, addr: string): Promise<any>;
|
|
67
|
+
/**
|
|
68
|
+
* Deploy contract. If salt is provided, uses CREATE2 factory.
|
|
69
|
+
* @param artifacts - hardhat artifacts
|
|
70
|
+
* @param contractName - contract name to deploy
|
|
71
|
+
* @param args - constructor arguments
|
|
72
|
+
* @param salt - optional CREATE2 salt for deterministic address
|
|
73
|
+
* @param feeLimit - Tron fee limit (default 15 TRX)
|
|
74
|
+
*/
|
|
75
|
+
deploy(artifacts: any, contractName: string, args?: any[], salt?: string, feeLimit?: number): Promise<TronAddress>;
|
|
76
|
+
/**
|
|
77
|
+
* Deploy implementation + ERC1967 proxy. If salt is provided, proxy uses factory.
|
|
78
|
+
* @param artifacts - hardhat artifacts
|
|
79
|
+
* @param contractName - implementation contract name
|
|
80
|
+
* @param initArgs - initialize() function arguments
|
|
81
|
+
* @param salt - optional CREATE2 salt for proxy
|
|
82
|
+
* @param feeLimit - Tron fee limit
|
|
83
|
+
*/
|
|
84
|
+
deployProxy(artifacts: any, contractName: string, initArgs?: any[], salt?: string, feeLimit?: number): Promise<{
|
|
85
|
+
proxy: TronAddress;
|
|
86
|
+
implementation: TronAddress;
|
|
87
|
+
}>;
|
|
88
|
+
/**
|
|
89
|
+
* Upgrade a UUPS proxy to a new implementation.
|
|
90
|
+
* @param artifacts - hardhat artifacts
|
|
91
|
+
* @param contractName - new implementation contract name
|
|
92
|
+
* @param proxyAddr - proxy address to upgrade
|
|
93
|
+
* @param feeLimit - Tron fee limit
|
|
94
|
+
*/
|
|
95
|
+
upgradeProxy(artifacts: any, contractName: string, proxyAddr: string, feeLimit?: number): Promise<TronAddress>;
|
|
96
|
+
/**
|
|
97
|
+
* Wait for a transaction to be confirmed on-chain.
|
|
98
|
+
* @param txId - transaction hash from .send()
|
|
99
|
+
*/
|
|
100
|
+
waitForTx(txId: string, retries?: number, interval?: number): Promise<any>;
|
|
101
|
+
/** Wrap contract methods — adds .sendAndWait() to write methods. */
|
|
102
|
+
private _wrapContract;
|
|
103
|
+
}
|
|
104
|
+
/** @internal Deploy contract on Tron. If salt is provided, uses CREATE2 factory. */
|
|
105
|
+
export declare function tronDeploy(tronWeb: any, artifacts: any, contractName: string, args?: any[], salt?: string, feeLimit?: number): Promise<TronAddress>;
|
|
106
|
+
/** @internal Deploy implementation + ERC1967 proxy on Tron. */
|
|
107
|
+
export declare function tronDeployProxy(tronWeb: any, artifacts: any, contractName: string, initArgs?: any[], salt?: string, feeLimit?: number): Promise<{
|
|
108
|
+
proxy: TronAddress;
|
|
109
|
+
implementation: TronAddress;
|
|
110
|
+
}>;
|
|
111
|
+
/** @internal Upgrade a UUPS proxy to a new implementation on Tron. */
|
|
112
|
+
export declare function tronUpgradeProxy(tronWeb: any, artifacts: any, contractName: string, proxyAddr: string, feeLimit?: number): Promise<TronAddress>;
|
|
113
|
+
/**
|
|
114
|
+
* Send a tron contract call and wait for on-chain confirmation.
|
|
115
|
+
* @param methodCall - tronweb contract method call (e.g. contract.setWtoken(addr))
|
|
116
|
+
* @param tronWeb - tronweb instance for querying tx status
|
|
117
|
+
* @param opts - send options (feeLimit, callValue, etc.)
|
|
118
|
+
*/
|
|
119
|
+
export declare function sendAndWait(methodCall: any, tronWeb: any, opts?: Record<string, any>): Promise<any>;
|
|
120
|
+
/**
|
|
121
|
+
* Wait for a Tron transaction to be confirmed on-chain.
|
|
122
|
+
* @param tronWeb - tronweb instance
|
|
123
|
+
* @param txId - transaction hash returned by .send()
|
|
124
|
+
* @param retries - max poll attempts (default 20)
|
|
125
|
+
* @param interval - poll interval in ms (default 3000)
|
|
126
|
+
*/
|
|
127
|
+
export declare function waitForTx(tronWeb: any, txId: string, retries?: number, interval?: number): Promise<any>;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TronClient = void 0;
|
|
4
|
+
exports.tronFromHex = tronFromHex;
|
|
5
|
+
exports.tronToHex = tronToHex;
|
|
6
|
+
exports.isTronNetwork = isTronNetwork;
|
|
7
|
+
exports.tronDeploy = tronDeploy;
|
|
8
|
+
exports.tronDeployProxy = tronDeployProxy;
|
|
9
|
+
exports.tronUpgradeProxy = tronUpgradeProxy;
|
|
10
|
+
exports.sendAndWait = sendAndWait;
|
|
11
|
+
exports.waitForTx = waitForTx;
|
|
12
|
+
let TronWeb = require("tronweb");
|
|
13
|
+
// ============================================================
|
|
14
|
+
// Pure address conversion — no RPC, no private key needed
|
|
15
|
+
// ============================================================
|
|
16
|
+
/** Convert hex address to Tron base58 format. Returns as-is if already base58. */
|
|
17
|
+
function tronFromHex(hex) {
|
|
18
|
+
if (hex.startsWith("T") && hex.length === 34)
|
|
19
|
+
return hex;
|
|
20
|
+
return TronWeb.address.fromHex(hex);
|
|
21
|
+
}
|
|
22
|
+
/** Convert Tron base58 address to 0x-prefixed hex. Returns as-is if already hex. */
|
|
23
|
+
function tronToHex(addr) {
|
|
24
|
+
if (addr.startsWith("0x") && addr.length === 42)
|
|
25
|
+
return addr;
|
|
26
|
+
return TronWeb.address.toHex(addr).replace(/^(41)/, "0x");
|
|
27
|
+
}
|
|
28
|
+
// Tron chainIds: mainnet 728126428, nile testnet 3448148188
|
|
29
|
+
const TRON_CHAIN_IDS = [728126428, 3448148188];
|
|
30
|
+
/** Check if a network name or chainId belongs to Tron (case-insensitive). */
|
|
31
|
+
function isTronNetwork(networkOrChainId) {
|
|
32
|
+
if (typeof networkOrChainId === "number") {
|
|
33
|
+
return TRON_CHAIN_IDS.includes(networkOrChainId);
|
|
34
|
+
}
|
|
35
|
+
return networkOrChainId.toLowerCase().startsWith("tron");
|
|
36
|
+
}
|
|
37
|
+
// ============================================================
|
|
38
|
+
// TronClient
|
|
39
|
+
// ============================================================
|
|
40
|
+
/**
|
|
41
|
+
* TronClient — encapsulates tronWeb instance, provides high-level contract operations.
|
|
42
|
+
*
|
|
43
|
+
* Usage:
|
|
44
|
+
* // From hardhat runtime (recommended in tasks)
|
|
45
|
+
* let client = TronClient.fromHre(hre);
|
|
46
|
+
*
|
|
47
|
+
* // Manual — with rpc and private key
|
|
48
|
+
* let client = new TronClient("https://api.trongrid.io", "your_private_key");
|
|
49
|
+
*
|
|
50
|
+
* // Read-only — no private key
|
|
51
|
+
* let client = new TronClient("https://api.trongrid.io");
|
|
52
|
+
*
|
|
53
|
+
* // Contract interaction
|
|
54
|
+
* let gw = await client.getContract(artifacts, "Gateway", addr);
|
|
55
|
+
* let wtoken = await gw.wToken().call(); // read
|
|
56
|
+
* await gw.setWtoken(client.toHex(wtoken)).sendAndWait(); // write + wait
|
|
57
|
+
*
|
|
58
|
+
* // Deploy
|
|
59
|
+
* let { hex, base58 } = await client.deploy(artifacts, "Gateway");
|
|
60
|
+
* let { proxy, implementation } = await client.deployProxy(artifacts, "Gateway", [admin]);
|
|
61
|
+
*
|
|
62
|
+
* // Upgrade
|
|
63
|
+
* await client.upgradeProxy(artifacts, "Gateway", proxyAddr);
|
|
64
|
+
*/
|
|
65
|
+
class TronClient {
|
|
66
|
+
/**
|
|
67
|
+
* Create a TronClient with explicit rpcUrl.
|
|
68
|
+
* @param rpcUrl - Tron full host URL (e.g. "https://api.trongrid.io")
|
|
69
|
+
* @param privateKey - optional, omit for read-only operations
|
|
70
|
+
*/
|
|
71
|
+
constructor(rpcUrl, privateKey) {
|
|
72
|
+
this.connected = false;
|
|
73
|
+
const opts = { fullHost: rpcUrl };
|
|
74
|
+
if (privateKey) {
|
|
75
|
+
// TronWeb doesn't accept 0x prefix on private keys
|
|
76
|
+
opts.privateKey = privateKey.startsWith("0x") ? privateKey.slice(2) : privateKey;
|
|
77
|
+
}
|
|
78
|
+
this.tronWeb = new TronWeb(opts);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create TronClient from hardhat runtime environment.
|
|
82
|
+
* Reads rpcUrl and privateKey from hre.network.config. Verifies RPC connectivity.
|
|
83
|
+
*/
|
|
84
|
+
static fromHre(hre) {
|
|
85
|
+
const config = hre.network.config;
|
|
86
|
+
let rpcUrl = config.url;
|
|
87
|
+
let privateKey = Array.isArray(config.accounts) ? config.accounts[0] : undefined;
|
|
88
|
+
if (!rpcUrl)
|
|
89
|
+
throw new Error(`no rpc url configured for network ${hre.network.name}`);
|
|
90
|
+
// Hardhat config uses JSON-RPC path (e.g. /jsonrpc), TronWeb needs base URL
|
|
91
|
+
rpcUrl = rpcUrl.replace(/\/(jsonrpc|wallet|solidity)\/?$/i, "");
|
|
92
|
+
// TronWeb doesn't accept 0x prefix on private keys
|
|
93
|
+
if (privateKey && privateKey.startsWith("0x")) {
|
|
94
|
+
privateKey = privateKey.slice(2);
|
|
95
|
+
}
|
|
96
|
+
return new TronClient(rpcUrl, privateKey);
|
|
97
|
+
}
|
|
98
|
+
/** Verify RPC is reachable. Uses getNowBlock which is widely supported. */
|
|
99
|
+
async _checkConnection() {
|
|
100
|
+
if (this.connected)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
// getNowBlock calls /wallet/getnowblock — more universally supported than getNodeInfo
|
|
104
|
+
await this.tronWeb.trx.getCurrentBlock();
|
|
105
|
+
this.connected = true;
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
const url = this.tronWeb.fullNode?.host || "unknown";
|
|
109
|
+
throw new Error(`TronClient: cannot connect to ${url}. ` +
|
|
110
|
+
`Ensure the URL is a valid TronWeb full host (e.g. "https://api.trongrid.io") and is reachable. ` +
|
|
111
|
+
`Error: ${e.message || e}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Lazy connection check — called before first contract operation. */
|
|
115
|
+
async _ensureConnected() {
|
|
116
|
+
if (!this.connected)
|
|
117
|
+
await this._checkConnection();
|
|
118
|
+
}
|
|
119
|
+
/** Get the default operator address in base58 format. */
|
|
120
|
+
get defaultAddress() {
|
|
121
|
+
return this.tronWeb.defaultAddress.base58;
|
|
122
|
+
}
|
|
123
|
+
/** Convert Tron base58 address to 0x hex. */
|
|
124
|
+
toHex(addr) {
|
|
125
|
+
return tronToHex(addr);
|
|
126
|
+
}
|
|
127
|
+
/** Convert 0x hex to Tron base58 address. */
|
|
128
|
+
fromHex(hex) {
|
|
129
|
+
return tronFromHex(hex);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get a contract instance. Write methods have .sendAndWait() attached.
|
|
133
|
+
* @param artifacts - hardhat artifacts (hre.artifacts)
|
|
134
|
+
* @param contractName - contract name (e.g. "Gateway")
|
|
135
|
+
* @param addr - contract address (base58 or hex)
|
|
136
|
+
*/
|
|
137
|
+
async getContract(artifacts, contractName, addr) {
|
|
138
|
+
await this._ensureConnected();
|
|
139
|
+
console.log("operator address is:", this.defaultAddress);
|
|
140
|
+
const artifact = await artifacts.readArtifact(contractName);
|
|
141
|
+
const contract = await this.tronWeb.contract(artifact.abi, addr);
|
|
142
|
+
return this._wrapContract(contract);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Deploy contract. If salt is provided, uses CREATE2 factory.
|
|
146
|
+
* @param artifacts - hardhat artifacts
|
|
147
|
+
* @param contractName - contract name to deploy
|
|
148
|
+
* @param args - constructor arguments
|
|
149
|
+
* @param salt - optional CREATE2 salt for deterministic address
|
|
150
|
+
* @param feeLimit - Tron fee limit (default 15 TRX)
|
|
151
|
+
*/
|
|
152
|
+
async deploy(artifacts, contractName, args = [], salt = "", feeLimit = 15000000000) {
|
|
153
|
+
await this._ensureConnected();
|
|
154
|
+
return tronDeploy(this.tronWeb, artifacts, contractName, args, salt, feeLimit);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Deploy implementation + ERC1967 proxy. If salt is provided, proxy uses factory.
|
|
158
|
+
* @param artifacts - hardhat artifacts
|
|
159
|
+
* @param contractName - implementation contract name
|
|
160
|
+
* @param initArgs - initialize() function arguments
|
|
161
|
+
* @param salt - optional CREATE2 salt for proxy
|
|
162
|
+
* @param feeLimit - Tron fee limit
|
|
163
|
+
*/
|
|
164
|
+
async deployProxy(artifacts, contractName, initArgs = [], salt = "", feeLimit = 15000000000) {
|
|
165
|
+
await this._ensureConnected();
|
|
166
|
+
return tronDeployProxy(this.tronWeb, artifacts, contractName, initArgs, salt, feeLimit);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Upgrade a UUPS proxy to a new implementation.
|
|
170
|
+
* @param artifacts - hardhat artifacts
|
|
171
|
+
* @param contractName - new implementation contract name
|
|
172
|
+
* @param proxyAddr - proxy address to upgrade
|
|
173
|
+
* @param feeLimit - Tron fee limit
|
|
174
|
+
*/
|
|
175
|
+
async upgradeProxy(artifacts, contractName, proxyAddr, feeLimit = 15000000000) {
|
|
176
|
+
await this._ensureConnected();
|
|
177
|
+
return tronUpgradeProxy(this.tronWeb, artifacts, contractName, proxyAddr, feeLimit);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Wait for a transaction to be confirmed on-chain.
|
|
181
|
+
* @param txId - transaction hash from .send()
|
|
182
|
+
*/
|
|
183
|
+
async waitForTx(txId, retries = 20, interval = 3000) {
|
|
184
|
+
return waitForTx(this.tronWeb, txId, retries, interval);
|
|
185
|
+
}
|
|
186
|
+
/** Wrap contract methods — adds .sendAndWait() to write methods. */
|
|
187
|
+
_wrapContract(contract) {
|
|
188
|
+
const tronWeb = this.tronWeb;
|
|
189
|
+
return new Proxy(contract, {
|
|
190
|
+
get(target, prop) {
|
|
191
|
+
const original = target[prop];
|
|
192
|
+
if (typeof original !== "function")
|
|
193
|
+
return original;
|
|
194
|
+
return (...args) => {
|
|
195
|
+
const methodCall = original.apply(target, args);
|
|
196
|
+
if (methodCall && typeof methodCall.send === "function") {
|
|
197
|
+
methodCall.sendAndWait = (opts) => sendAndWait(methodCall, tronWeb, opts);
|
|
198
|
+
}
|
|
199
|
+
return methodCall;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
exports.TronClient = TronClient;
|
|
206
|
+
// ============================================================
|
|
207
|
+
// Low-level functions (used internally by TronClient)
|
|
208
|
+
// ============================================================
|
|
209
|
+
/** @internal Deploy contract on Tron. If salt is provided, uses CREATE2 factory. */
|
|
210
|
+
async function tronDeploy(tronWeb, artifacts, contractName, args = [], salt = "", feeLimit = 15000000000) {
|
|
211
|
+
if (salt) {
|
|
212
|
+
const { tronDeployByFactory } = require("./factory");
|
|
213
|
+
const hex = await tronDeployByFactory(tronWeb, artifacts, contractName, salt, args, feeLimit);
|
|
214
|
+
return { hex, base58: tronFromHex(hex) };
|
|
215
|
+
}
|
|
216
|
+
const artifact = await artifacts.readArtifact(contractName);
|
|
217
|
+
console.log("deploy address is:", tronWeb.defaultAddress.base58);
|
|
218
|
+
const instance = await tronWeb.contract().new({
|
|
219
|
+
abi: artifact.abi,
|
|
220
|
+
bytecode: artifact.bytecode,
|
|
221
|
+
feeLimit,
|
|
222
|
+
callValue: 0,
|
|
223
|
+
parameters: args,
|
|
224
|
+
});
|
|
225
|
+
const rawAddress = instance.address; // 41-prefixed hex
|
|
226
|
+
const hex = rawAddress.replace(/^41/, "0x");
|
|
227
|
+
const base58 = tronWeb.address.fromHex(rawAddress);
|
|
228
|
+
console.log(`${contractName} deployed: ${base58} (${hex})`);
|
|
229
|
+
return { hex, base58 };
|
|
230
|
+
}
|
|
231
|
+
/** @internal Deploy implementation + ERC1967 proxy on Tron. */
|
|
232
|
+
async function tronDeployProxy(tronWeb, artifacts, contractName, initArgs = [], salt = "", feeLimit = 15000000000) {
|
|
233
|
+
const implementation = await tronDeploy(tronWeb, artifacts, contractName, [], "", feeLimit);
|
|
234
|
+
console.log(`${contractName} implementation: ${implementation.base58} (${implementation.hex})`);
|
|
235
|
+
// Wait for implementation to be fully confirmed before deploying proxy
|
|
236
|
+
if (salt) {
|
|
237
|
+
console.log("waiting for implementation to be indexed...");
|
|
238
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
239
|
+
}
|
|
240
|
+
const artifact = await artifacts.readArtifact(contractName);
|
|
241
|
+
const iface = new (require("ethers").Interface)(artifact.abi);
|
|
242
|
+
const initData = iface.encodeFunctionData("initialize", initArgs);
|
|
243
|
+
const proxy = await tronDeploy(tronWeb, artifacts, "ERC1967Proxy", [implementation.hex, initData], salt, feeLimit);
|
|
244
|
+
console.log(`${contractName} proxy: ${proxy.base58} (${proxy.hex})`);
|
|
245
|
+
return { proxy, implementation };
|
|
246
|
+
}
|
|
247
|
+
/** @internal Upgrade a UUPS proxy to a new implementation on Tron. */
|
|
248
|
+
async function tronUpgradeProxy(tronWeb, artifacts, contractName, proxyAddr, feeLimit = 15000000000) {
|
|
249
|
+
const impl = await tronDeploy(tronWeb, artifacts, contractName, [], "", feeLimit);
|
|
250
|
+
console.log(`${contractName} new implementation: ${impl.base58} (${impl.hex})`);
|
|
251
|
+
const artifact = await artifacts.readArtifact("BaseImplementation");
|
|
252
|
+
const proxyContract = await tronWeb.contract(artifact.abi, proxyAddr);
|
|
253
|
+
const oldImpl = await proxyContract.getImplementation().call();
|
|
254
|
+
console.log(`old implementation: ${tronFromHex(oldImpl)}`);
|
|
255
|
+
await sendAndWait(proxyContract.upgradeToAndCall(impl.hex, "0x"), tronWeb, { feeLimit });
|
|
256
|
+
const newImpl = await proxyContract.getImplementation().call();
|
|
257
|
+
console.log(`${contractName} upgraded: ${tronFromHex(oldImpl)} -> ${tronFromHex(newImpl)}`);
|
|
258
|
+
return impl;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Send a tron contract call and wait for on-chain confirmation.
|
|
262
|
+
* @param methodCall - tronweb contract method call (e.g. contract.setWtoken(addr))
|
|
263
|
+
* @param tronWeb - tronweb instance for querying tx status
|
|
264
|
+
* @param opts - send options (feeLimit, callValue, etc.)
|
|
265
|
+
*/
|
|
266
|
+
async function sendAndWait(methodCall, tronWeb, opts = {}) {
|
|
267
|
+
const txId = await methodCall.send(opts);
|
|
268
|
+
return waitForTx(tronWeb, txId);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Wait for a Tron transaction to be confirmed on-chain.
|
|
272
|
+
* @param tronWeb - tronweb instance
|
|
273
|
+
* @param txId - transaction hash returned by .send()
|
|
274
|
+
* @param retries - max poll attempts (default 20)
|
|
275
|
+
* @param interval - poll interval in ms (default 3000)
|
|
276
|
+
*/
|
|
277
|
+
async function waitForTx(tronWeb, txId, retries = 20, interval = 3000) {
|
|
278
|
+
console.log(`waiting for tx ${txId}...`);
|
|
279
|
+
for (let i = 0; i < retries; i++) {
|
|
280
|
+
const result = await tronWeb.trx.getTransactionInfo(txId);
|
|
281
|
+
if (result && result.id) {
|
|
282
|
+
if (result.receipt?.result === "SUCCESS") {
|
|
283
|
+
console.log(`tx confirmed in block ${result.blockNumber}`);
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
throw new Error(`tx failed: ${result.receipt?.result || "UNKNOWN"}`);
|
|
287
|
+
}
|
|
288
|
+
await new Promise(r => setTimeout(r, interval));
|
|
289
|
+
}
|
|
290
|
+
throw new Error(`tx not confirmed after ${retries} retries: ${txId}`);
|
|
291
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface VerifyOptions {
|
|
2
|
+
address: string;
|
|
3
|
+
contractName: string;
|
|
4
|
+
contractPath?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Constructor arguments as raw values — auto-encoded via ethers `encodeDeploy`.
|
|
7
|
+
* Example: ["0xAbC123...", "0xDeF456...", 200]
|
|
8
|
+
* Use this for most cases. Mutually exclusive with constructorParams.
|
|
9
|
+
*/
|
|
10
|
+
constructorArgs?: any[];
|
|
11
|
+
/**
|
|
12
|
+
* Pre-encoded constructor params as hex string (without 0x prefix).
|
|
13
|
+
* Use this when you already have the ABI-encoded bytes, e.g. from `cast abi-encode`.
|
|
14
|
+
* Takes priority over constructorArgs if both are provided.
|
|
15
|
+
*/
|
|
16
|
+
constructorParams?: string;
|
|
17
|
+
compiler?: string;
|
|
18
|
+
optimizer?: boolean;
|
|
19
|
+
optimizerRuns?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Unified contract verification — auto-routes to EVM (hardhat verify) or Tron (TronScan API)
|
|
23
|
+
*/
|
|
24
|
+
export declare function verify(hre: any, opts: VerifyOptions): Promise<void>;
|