@recoillink/tron-sdk 0.0.0-stage → 26.0.1
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/LICENSE.md +193 -0
- package/README.md +44 -2
- package/dist/clients/protocol.d.ts +27 -0
- package/dist/clients/protocol.d.ts.map +1 -0
- package/dist/clients/protocol.js +53 -0
- package/dist/clients/protocol.js.map +1 -0
- package/dist/clients/provider.d.ts +30 -0
- package/dist/clients/provider.d.ts.map +1 -0
- package/dist/clients/provider.js +268 -0
- package/dist/clients/provider.js.map +1 -0
- package/dist/clients/signer.d.ts +16 -0
- package/dist/clients/signer.d.ts.map +1 -0
- package/dist/clients/signer.js +38 -0
- package/dist/clients/signer.js.map +1 -0
- package/dist/ethers/TronContractFactory.d.ts +32 -0
- package/dist/ethers/TronContractFactory.d.ts.map +1 -0
- package/dist/ethers/TronContractFactory.js +54 -0
- package/dist/ethers/TronContractFactory.js.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.d.ts +74 -0
- package/dist/ethers/TronJsonRpcProvider.d.ts.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.integration.test.d.ts +2 -0
- package/dist/ethers/TronJsonRpcProvider.integration.test.d.ts.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.integration.test.js +46 -0
- package/dist/ethers/TronJsonRpcProvider.integration.test.js.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.js +261 -0
- package/dist/ethers/TronJsonRpcProvider.js.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.test.d.ts +2 -0
- package/dist/ethers/TronJsonRpcProvider.test.d.ts.map +1 -0
- package/dist/ethers/TronJsonRpcProvider.test.js +336 -0
- package/dist/ethers/TronJsonRpcProvider.test.js.map +1 -0
- package/dist/ethers/TronWallet.d.ts +69 -0
- package/dist/ethers/TronWallet.d.ts.map +1 -0
- package/dist/ethers/TronWallet.integration.test.d.ts +2 -0
- package/dist/ethers/TronWallet.integration.test.d.ts.map +1 -0
- package/dist/ethers/TronWallet.integration.test.js +151 -0
- package/dist/ethers/TronWallet.integration.test.js.map +1 -0
- package/dist/ethers/TronWallet.js +295 -0
- package/dist/ethers/TronWallet.js.map +1 -0
- package/dist/ethers/TronWallet.test.d.ts +2 -0
- package/dist/ethers/TronWallet.test.d.ts.map +1 -0
- package/dist/ethers/TronWallet.test.js +216 -0
- package/dist/ethers/TronWallet.test.js.map +1 -0
- package/dist/ethers/index.d.ts +4 -0
- package/dist/ethers/index.d.ts.map +1 -0
- package/dist/ethers/index.js +4 -0
- package/dist/ethers/index.js.map +1 -0
- package/dist/ethers/urlUtils.d.ts +32 -0
- package/dist/ethers/urlUtils.d.ts.map +1 -0
- package/dist/ethers/urlUtils.js +67 -0
- package/dist/ethers/urlUtils.js.map +1 -0
- package/dist/ethers/urlUtils.test.d.ts +2 -0
- package/dist/ethers/urlUtils.test.d.ts.map +1 -0
- package/dist/ethers/urlUtils.test.js +106 -0
- package/dist/ethers/urlUtils.test.js.map +1 -0
- package/dist/factories/index.d.ts +2 -0
- package/dist/factories/index.d.ts.map +1 -0
- package/dist/factories/index.js +8 -0
- package/dist/factories/index.js.map +1 -0
- package/dist/hook/hook-query.d.ts +41 -0
- package/dist/hook/hook-query.d.ts.map +1 -0
- package/dist/hook/hook-query.js +79 -0
- package/dist/hook/hook-query.js.map +1 -0
- package/dist/hook/hook-tx.d.ts +39 -0
- package/dist/hook/hook-tx.d.ts.map +1 -0
- package/dist/hook/hook-tx.js +95 -0
- package/dist/hook/hook-tx.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/ism/ism-query.d.ts +70 -0
- package/dist/ism/ism-query.d.ts.map +1 -0
- package/dist/ism/ism-query.js +137 -0
- package/dist/ism/ism-query.js.map +1 -0
- package/dist/ism/ism-tx.d.ts +67 -0
- package/dist/ism/ism-tx.d.ts.map +1 -0
- package/dist/ism/ism-tx.js +110 -0
- package/dist/ism/ism-tx.js.map +1 -0
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +6 -0
- package/dist/runtime.js.map +1 -0
- package/dist/testing/constants.d.ts +7 -0
- package/dist/testing/constants.d.ts.map +1 -0
- package/dist/testing/constants.js +7 -0
- package/dist/testing/constants.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/node.d.ts +41 -0
- package/dist/testing/node.d.ts.map +1 -0
- package/dist/testing/node.js +119 -0
- package/dist/testing/node.js.map +1 -0
- package/dist/utils/index.d.ts +68 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +141 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.test.d.ts +2 -0
- package/dist/utils/index.test.d.ts.map +1 -0
- package/dist/utils/index.test.js +85 -0
- package/dist/utils/index.test.js.map +1 -0
- package/dist/utils/types.d.ts +94 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +13 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +74 -3
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import chai, { expect } from 'chai';
|
|
2
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
3
|
+
import { utils } from 'ethers';
|
|
4
|
+
import { TronWeb } from 'tronweb';
|
|
5
|
+
import { TRON_EMPTY_ADDRESS, toTronHex } from '../utils/index.js';
|
|
6
|
+
import { TronJsonRpcProvider } from './TronJsonRpcProvider.js';
|
|
7
|
+
chai.use(chaiAsPromised);
|
|
8
|
+
const CONTRACT = '0x19335987d77120c462ca7df51cf29f68a38e6d6c';
|
|
9
|
+
const CONTRACT_HEX = '4119335987d77120c462ca7df51cf29f68a38e6d6c';
|
|
10
|
+
const SELECTOR = '0x7f5a7c7b';
|
|
11
|
+
// Real mainnet EOA and its base58 form (TRH7XVrd…LXaBG).
|
|
12
|
+
const EOA = '0xa7eccdb9be08178f896c26b7bbd8c3d4e844d9ba';
|
|
13
|
+
const EOA_BASE58 = 'TRH7XVrdZk2P5DA8aVaufMNkUZBd8LXaBG';
|
|
14
|
+
// Shared real TronWeb for the pure helpers (address/utf8 conversion) that the
|
|
15
|
+
// provider invokes on the injected instance; only fullNode.request is stubbed.
|
|
16
|
+
const realTronWeb = new TronWeb({ fullHost: 'https://api.trongrid.io' });
|
|
17
|
+
function makeProvider(maxRetries = 1) {
|
|
18
|
+
return new TronJsonRpcProvider('https://node.example.com/jsonrpc', 728126428, maxRetries, 0);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Injects a tronWeb double whose fullNode.request runs `request`. Delegates
|
|
22
|
+
* address/utf8 helpers to a real TronWeb.
|
|
23
|
+
*/
|
|
24
|
+
function stubFullNodeRequest(provider, request) {
|
|
25
|
+
const tronWeb = {
|
|
26
|
+
address: {
|
|
27
|
+
toHex: (a) => realTronWeb.address.toHex(a),
|
|
28
|
+
fromHex: (a) => realTronWeb.address.fromHex(a),
|
|
29
|
+
},
|
|
30
|
+
toUtf8: (hex) => realTronWeb.toUtf8(hex),
|
|
31
|
+
fullNode: { request },
|
|
32
|
+
};
|
|
33
|
+
// CAST: inject the minimal fullNode double into the provider's private
|
|
34
|
+
// `tronWeb` field.
|
|
35
|
+
provider.tronWeb = tronWeb;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Injects a tronWeb double whose fullNode.request returns `response` (and
|
|
39
|
+
* records the request).
|
|
40
|
+
*/
|
|
41
|
+
function stubFullNode(provider, response, captured) {
|
|
42
|
+
stubFullNodeRequest(provider, async (url, payload, method) => {
|
|
43
|
+
if (captured) {
|
|
44
|
+
captured.value = { url, payload, method };
|
|
45
|
+
captured.calls += 1;
|
|
46
|
+
}
|
|
47
|
+
return response;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function stubSend(provider, impl) {
|
|
51
|
+
provider.send = impl;
|
|
52
|
+
}
|
|
53
|
+
// Raw node/transport error as it leaves ethers' `send`, BEFORE `checkError`
|
|
54
|
+
// wraps it. Routing these through the real provider (rather than hand-building
|
|
55
|
+
// the synthetic CALL_EXCEPTION) exercises the exact shape production sees: for
|
|
56
|
+
// the `call` method ethers wraps every failure into a top-level CALL_EXCEPTION
|
|
57
|
+
// (message "missing revert data in call exception", data "0x") nesting this
|
|
58
|
+
// original error under `.error`.
|
|
59
|
+
function nodeError(message, code) {
|
|
60
|
+
const error = new Error(message);
|
|
61
|
+
Object.assign(error, { code });
|
|
62
|
+
return error;
|
|
63
|
+
}
|
|
64
|
+
// A reasonless Tron revert (the missing-selector case): the node returns an
|
|
65
|
+
// "execution reverted" failure that ethers classifies as SERVER_ERROR.
|
|
66
|
+
const REVERT_ERROR = nodeError('execution reverted', utils.Logger.errors.SERVER_ERROR);
|
|
67
|
+
// A revert surfaced only through the JSON-RPC revert code, no revert message.
|
|
68
|
+
const REVERT_CODE_ERROR = nodeError('execution failed', 3);
|
|
69
|
+
// A genuine connectivity failure — same nested code family as REVERT_ERROR but
|
|
70
|
+
// no revert indicator.
|
|
71
|
+
const TRANSPORT_ERROR = nodeError('bad response (status=503)', utils.Logger.errors.SERVER_ERROR);
|
|
72
|
+
const TIMEOUT_ERROR = nodeError('timeout', utils.Logger.errors.TIMEOUT);
|
|
73
|
+
// A node that simply doesn't answer eth_call: a clean numeric JSON-RPC error
|
|
74
|
+
// with no revert indicator, which must fall back to native like any transport
|
|
75
|
+
// failure rather than being mistaken for a revert.
|
|
76
|
+
const METHOD_NOT_FOUND_ERROR = nodeError('the method eth_call does not exist/is not available', -32601);
|
|
77
|
+
function throwingSend(error) {
|
|
78
|
+
return async () => {
|
|
79
|
+
throw error;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function throwingRequest(error) {
|
|
83
|
+
return async () => {
|
|
84
|
+
throw error;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// `wallet/getaccount` bodies as mainnet returns them for `visible: true`. A
|
|
88
|
+
// contract account omits `create_time` entirely, which is why activation keys
|
|
89
|
+
// off the body being non-empty rather than off that field.
|
|
90
|
+
const ACTIVE_EOA_ACCOUNT = {
|
|
91
|
+
address: EOA_BASE58,
|
|
92
|
+
balance: 2_543_000_000,
|
|
93
|
+
create_time: 1_773_619_200_000,
|
|
94
|
+
};
|
|
95
|
+
const ACTIVE_CONTRACT_ACCOUNT = {
|
|
96
|
+
address: 'TCGTQhMDW82v8Ls93zVeq9pFV2JVkdxDuq',
|
|
97
|
+
balance: 0,
|
|
98
|
+
type: 'Contract',
|
|
99
|
+
};
|
|
100
|
+
async function rejectionOf(promise) {
|
|
101
|
+
let thrown;
|
|
102
|
+
try {
|
|
103
|
+
await promise;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
thrown = error;
|
|
107
|
+
}
|
|
108
|
+
expect(thrown, 'expected the call to reject').to.exist;
|
|
109
|
+
return thrown;
|
|
110
|
+
}
|
|
111
|
+
describe('TronJsonRpcProvider', () => {
|
|
112
|
+
describe('perform (eth_call-first with native fallback)', () => {
|
|
113
|
+
it('returns the eth_call result without touching the native endpoint', async () => {
|
|
114
|
+
const provider = makeProvider();
|
|
115
|
+
stubSend(provider, async () => '0x1234');
|
|
116
|
+
const captured = { calls: 0 };
|
|
117
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['dead'] }, captured);
|
|
118
|
+
const result = await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
119
|
+
expect(result).to.equal('0x1234');
|
|
120
|
+
expect(captured.calls).to.equal(0);
|
|
121
|
+
});
|
|
122
|
+
it('rethrows a reverting read (revert message) without touching native', async () => {
|
|
123
|
+
const provider = makeProvider();
|
|
124
|
+
stubSend(provider, throwingSend(REVERT_ERROR));
|
|
125
|
+
const captured = { calls: 0 };
|
|
126
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['dead'] }, captured);
|
|
127
|
+
// ethers wraps the revert as a top-level CALL_EXCEPTION (data="0x"), which
|
|
128
|
+
// the SDK's missing-selector detection recognizes; it must propagate as-is
|
|
129
|
+
// and must NOT fall back to native.
|
|
130
|
+
const thrown = await rejectionOf(provider.call({ to: CONTRACT, data: SELECTOR }));
|
|
131
|
+
expect(thrown).to.have.property('code', utils.Logger.errors.CALL_EXCEPTION);
|
|
132
|
+
expect(thrown).to.have.property('data', '0x');
|
|
133
|
+
expect(captured.calls).to.equal(0);
|
|
134
|
+
});
|
|
135
|
+
it('rethrows a reverting read (JSON-RPC revert code) without touching native', async () => {
|
|
136
|
+
const provider = makeProvider();
|
|
137
|
+
stubSend(provider, throwingSend(REVERT_CODE_ERROR));
|
|
138
|
+
const captured = { calls: 0 };
|
|
139
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['dead'] }, captured);
|
|
140
|
+
const thrown = await rejectionOf(provider.call({ to: CONTRACT, data: SELECTOR }));
|
|
141
|
+
expect(thrown).to.have.property('code', utils.Logger.errors.CALL_EXCEPTION);
|
|
142
|
+
expect(captured.calls).to.equal(0);
|
|
143
|
+
});
|
|
144
|
+
it('falls back to native on a server-error transport failure', async () => {
|
|
145
|
+
const provider = makeProvider();
|
|
146
|
+
stubSend(provider, throwingSend(TRANSPORT_ERROR));
|
|
147
|
+
const captured = { calls: 0 };
|
|
148
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00ff'] }, captured);
|
|
149
|
+
const result = await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
150
|
+
expect(result).to.equal('0x00ff');
|
|
151
|
+
expect(captured.calls).to.equal(1);
|
|
152
|
+
});
|
|
153
|
+
it('falls back to native on a timeout transport failure', async () => {
|
|
154
|
+
const provider = makeProvider();
|
|
155
|
+
stubSend(provider, throwingSend(TIMEOUT_ERROR));
|
|
156
|
+
const captured = { calls: 0 };
|
|
157
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00ff'] }, captured);
|
|
158
|
+
const result = await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
159
|
+
expect(result).to.equal('0x00ff');
|
|
160
|
+
expect(captured.calls).to.equal(1);
|
|
161
|
+
});
|
|
162
|
+
it('falls back to native when the node does not answer eth_call (-32601)', async () => {
|
|
163
|
+
const provider = makeProvider();
|
|
164
|
+
stubSend(provider, throwingSend(METHOD_NOT_FOUND_ERROR));
|
|
165
|
+
const captured = { calls: 0 };
|
|
166
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00ff'] }, captured);
|
|
167
|
+
const result = await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
168
|
+
expect(result).to.equal('0x00ff');
|
|
169
|
+
expect(captured.calls).to.equal(1);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
describe('native constant call (fallback path)', () => {
|
|
173
|
+
// Force the fallback by making eth_call fail with a transport error.
|
|
174
|
+
function fallbackProvider() {
|
|
175
|
+
const provider = makeProvider();
|
|
176
|
+
stubSend(provider, throwingSend(TRANSPORT_ERROR));
|
|
177
|
+
return provider;
|
|
178
|
+
}
|
|
179
|
+
it('returns the decoded data and posts to the raw endpoint', async () => {
|
|
180
|
+
const provider = fallbackProvider();
|
|
181
|
+
const captured = { calls: 0 };
|
|
182
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00ff'] }, captured);
|
|
183
|
+
const result = await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
184
|
+
expect(result).to.equal('0x00ff');
|
|
185
|
+
expect(captured.value?.url).to.equal('wallet/triggerconstantcontract');
|
|
186
|
+
expect(captured.value?.method).to.equal('post');
|
|
187
|
+
expect(captured.value?.payload['contract_address']).to.equal(CONTRACT_HEX);
|
|
188
|
+
expect(captured.value?.payload['data']).to.equal('7f5a7c7b');
|
|
189
|
+
});
|
|
190
|
+
it('throws a CALL_EXCEPTION with 0x data for a reasonless revert (empty constant_result)', async () => {
|
|
191
|
+
const provider = fallbackProvider();
|
|
192
|
+
stubFullNode(provider, {
|
|
193
|
+
result: {
|
|
194
|
+
result: false,
|
|
195
|
+
message: realTronWeb.fromUtf8('REVERT opcode executed'),
|
|
196
|
+
},
|
|
197
|
+
constant_result: [],
|
|
198
|
+
});
|
|
199
|
+
const thrown = await rejectionOf(provider.call({ to: CONTRACT, data: SELECTOR }));
|
|
200
|
+
expect(thrown).to.have.property('code', utils.Logger.errors.CALL_EXCEPTION);
|
|
201
|
+
expect(thrown).to.have.property('data', '0x');
|
|
202
|
+
});
|
|
203
|
+
it('throws a CALL_EXCEPTION with 0x data for a reasonless revert (empty-string constant_result)', async () => {
|
|
204
|
+
const provider = fallbackProvider();
|
|
205
|
+
stubFullNode(provider, {
|
|
206
|
+
result: { result: false },
|
|
207
|
+
constant_result: [''],
|
|
208
|
+
});
|
|
209
|
+
const thrown = await rejectionOf(provider.call({ to: CONTRACT, data: SELECTOR }));
|
|
210
|
+
expect(thrown).to.have.property('code', utils.Logger.errors.CALL_EXCEPTION);
|
|
211
|
+
expect(thrown).to.have.property('data', '0x');
|
|
212
|
+
});
|
|
213
|
+
it('throws a CALL_EXCEPTION carrying the revert data for a revert with data', async () => {
|
|
214
|
+
const provider = fallbackProvider();
|
|
215
|
+
// ABI-encoded Error(string) revert payload.
|
|
216
|
+
const REVERT_DATA = '08c379a00000000000000000000000000000000000000000000000000000000000000020';
|
|
217
|
+
stubFullNode(provider, {
|
|
218
|
+
result: { result: false },
|
|
219
|
+
constant_result: [REVERT_DATA],
|
|
220
|
+
});
|
|
221
|
+
const thrown = await rejectionOf(provider.call({ to: CONTRACT, data: SELECTOR }));
|
|
222
|
+
expect(thrown).to.have.property('code', utils.Logger.errors.CALL_EXCEPTION);
|
|
223
|
+
// Non-empty revert data must NOT be recognized as a missing selector.
|
|
224
|
+
expect(thrown).to.have.property('data', `0x${REVERT_DATA}`);
|
|
225
|
+
});
|
|
226
|
+
it('throws the decoded message on a pre-execution failure (no constant_result)', async () => {
|
|
227
|
+
const provider = fallbackProvider();
|
|
228
|
+
stubFullNode(provider, {
|
|
229
|
+
result: {
|
|
230
|
+
result: false,
|
|
231
|
+
message: realTronWeb.fromUtf8('contract not found'),
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
await expect(provider.call({ to: CONTRACT, data: SELECTOR })).to.be.rejectedWith('Tron constant call failed: contract not found');
|
|
235
|
+
});
|
|
236
|
+
it('throws on a malformed response (no constant_result, no result)', async () => {
|
|
237
|
+
const provider = fallbackProvider();
|
|
238
|
+
stubFullNode(provider, {});
|
|
239
|
+
await expect(provider.call({ to: CONTRACT, data: SELECTOR })).to.be.rejectedWith('Tron constant call failed: unknown error');
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
describe('caller (owner_address)', () => {
|
|
243
|
+
function fallbackProvider() {
|
|
244
|
+
const provider = makeProvider();
|
|
245
|
+
stubSend(provider, throwingSend(TRANSPORT_ERROR));
|
|
246
|
+
return provider;
|
|
247
|
+
}
|
|
248
|
+
it('uses the Tron zero address as caller when `from` is omitted', async () => {
|
|
249
|
+
const provider = fallbackProvider();
|
|
250
|
+
const captured = { calls: 0 };
|
|
251
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00'] }, captured);
|
|
252
|
+
await provider.call({ to: CONTRACT, data: SELECTOR });
|
|
253
|
+
expect(captured.value?.payload['owner_address']).to.equal(toTronHex(realTronWeb, TRON_EMPTY_ADDRESS));
|
|
254
|
+
});
|
|
255
|
+
it('preserves an explicit `from` as the caller', async () => {
|
|
256
|
+
const provider = fallbackProvider();
|
|
257
|
+
const captured = { calls: 0 };
|
|
258
|
+
stubFullNode(provider, { result: { result: true }, constant_result: ['00'] }, captured);
|
|
259
|
+
const from = '0x496ba8ba0871a037ec1617f002f0a4afe5c2bae1';
|
|
260
|
+
await provider.call({ to: CONTRACT, data: SELECTOR, from });
|
|
261
|
+
expect(captured.value?.payload['owner_address']).to.equal(toTronHex(realTronWeb, from));
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
describe('isAccountActive', () => {
|
|
265
|
+
it('posts the base58 address to the raw account endpoint', async () => {
|
|
266
|
+
const provider = makeProvider();
|
|
267
|
+
const captured = { calls: 0 };
|
|
268
|
+
stubFullNode(provider, ACTIVE_EOA_ACCOUNT, captured);
|
|
269
|
+
await provider.isAccountActive(EOA);
|
|
270
|
+
expect(captured.value?.url).to.equal('wallet/getaccount');
|
|
271
|
+
expect(captured.value?.method).to.equal('post');
|
|
272
|
+
expect(captured.value?.payload['address']).to.equal(EOA_BASE58);
|
|
273
|
+
expect(captured.value?.payload['visible']).to.equal(true);
|
|
274
|
+
});
|
|
275
|
+
it('returns true for an activated account', async () => {
|
|
276
|
+
const provider = makeProvider();
|
|
277
|
+
stubFullNode(provider, ACTIVE_EOA_ACCOUNT);
|
|
278
|
+
expect(await provider.isAccountActive(EOA)).to.be.true;
|
|
279
|
+
});
|
|
280
|
+
it('returns true for a contract account, which carries no create_time', async () => {
|
|
281
|
+
const provider = makeProvider();
|
|
282
|
+
stubFullNode(provider, ACTIVE_CONTRACT_ACCOUNT);
|
|
283
|
+
expect(await provider.isAccountActive(CONTRACT)).to.be.true;
|
|
284
|
+
});
|
|
285
|
+
it('returns false for an unactivated account (empty response)', async () => {
|
|
286
|
+
const provider = makeProvider();
|
|
287
|
+
stubFullNode(provider, {});
|
|
288
|
+
expect(await provider.isAccountActive(EOA)).to.be.false;
|
|
289
|
+
});
|
|
290
|
+
it('throws on a missing response body', async () => {
|
|
291
|
+
const provider = makeProvider();
|
|
292
|
+
// The node answered with no JSON body at all, which must not read as a
|
|
293
|
+
// missing account.
|
|
294
|
+
stubFullNodeRequest(provider, async () => undefined);
|
|
295
|
+
const thrown = await rejectionOf(provider.isAccountActive(EOA));
|
|
296
|
+
expect(thrown).to.have.property('message', `Tron account lookup returned no response body for ${EOA_BASE58}`);
|
|
297
|
+
});
|
|
298
|
+
it('throws on a node-level error response', async () => {
|
|
299
|
+
const provider = makeProvider();
|
|
300
|
+
stubFullNode(provider, { Error: 'Invalid address' });
|
|
301
|
+
const thrown = await rejectionOf(provider.isAccountActive(EOA));
|
|
302
|
+
expect(thrown).to.have.property('message', 'Tron account lookup failed: Invalid address');
|
|
303
|
+
});
|
|
304
|
+
it('rejects on a transport failure instead of reporting inactive', async () => {
|
|
305
|
+
const provider = makeProvider();
|
|
306
|
+
stubFullNodeRequest(provider, throwingRequest(TRANSPORT_ERROR));
|
|
307
|
+
const thrown = await rejectionOf(provider.isAccountActive(EOA));
|
|
308
|
+
expect(thrown).to.equal(TRANSPORT_ERROR);
|
|
309
|
+
});
|
|
310
|
+
it('retries a transient failure before resolving', async () => {
|
|
311
|
+
const provider = makeProvider(2);
|
|
312
|
+
let calls = 0;
|
|
313
|
+
stubFullNodeRequest(provider, async () => {
|
|
314
|
+
calls += 1;
|
|
315
|
+
if (calls === 1) {
|
|
316
|
+
throw TRANSPORT_ERROR;
|
|
317
|
+
}
|
|
318
|
+
return ACTIVE_EOA_ACCOUNT;
|
|
319
|
+
});
|
|
320
|
+
expect(await provider.isAccountActive(EOA)).to.be.true;
|
|
321
|
+
expect(calls).to.equal(2);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
describe('toTronHex', () => {
|
|
326
|
+
it('resolves base58 addresses through TronWeb', () => {
|
|
327
|
+
expect(toTronHex(realTronWeb, 'T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb')).to.equal('410000000000000000000000000000000000000000');
|
|
328
|
+
});
|
|
329
|
+
it('passes through already-41-prefixed hex', () => {
|
|
330
|
+
expect(toTronHex(realTronWeb, CONTRACT_HEX)).to.equal(CONTRACT_HEX);
|
|
331
|
+
});
|
|
332
|
+
it('prefixes 0x hex with the Tron 41 byte', () => {
|
|
333
|
+
expect(toTronHex(realTronWeb, CONTRACT)).to.equal(CONTRACT_HEX);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
//# sourceMappingURL=TronJsonRpcProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TronJsonRpcProvider.test.js","sourceRoot":"","sources":["../../src/ethers/TronJsonRpcProvider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Wallet, providers } from 'ethers';
|
|
2
|
+
import { TronWeb, Types } from 'tronweb';
|
|
3
|
+
import { TransactionRequest } from '@ethersproject/providers';
|
|
4
|
+
/** Union of possible TronWeb transaction types */
|
|
5
|
+
export type TronTransaction = Types.CreateSmartContractTransaction | Types.Transaction | Types.SignedTransaction;
|
|
6
|
+
/**
|
|
7
|
+
* Extended transaction response that includes Tron-specific fields.
|
|
8
|
+
*/
|
|
9
|
+
export interface TronTransactionResponse extends providers.TransactionResponse {
|
|
10
|
+
/** Raw TronWeb transaction object */
|
|
11
|
+
tronTransaction: TronTransaction;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* TronWallet extends ethers Wallet to handle Tron's transaction format.
|
|
15
|
+
*
|
|
16
|
+
* Takes a single Tron node URL (e.g. http://localhost:9090) and derives:
|
|
17
|
+
* - JSON-RPC provider at {url}/jsonrpc for ethers compatibility
|
|
18
|
+
* - TronWeb HTTP client at {url} for transaction building/signing
|
|
19
|
+
*
|
|
20
|
+
* Tron's JSON-RPC doesn't support eth_sendRawTransaction, so we override
|
|
21
|
+
* sendTransaction to use TronWeb for building, signing, and broadcasting.
|
|
22
|
+
*
|
|
23
|
+
* Gas estimation is handled by ethers (via eth_estimateGas), and we convert
|
|
24
|
+
* gasLimit to Tron's feeLimit using: feeLimit = gasLimit × gasPrice.
|
|
25
|
+
*/
|
|
26
|
+
export declare class TronWallet extends Wallet {
|
|
27
|
+
/**
|
|
28
|
+
* Static counter to ensure unique txIDs across all wallet instances.
|
|
29
|
+
* Must be static because connect() creates new instances, and Tron txIDs
|
|
30
|
+
* are derived from transaction content + expiration. Without a shared counter,
|
|
31
|
+
* two instances could generate identical txIDs in the same block.
|
|
32
|
+
*/
|
|
33
|
+
private static txCounter;
|
|
34
|
+
private readonly originalTronUrl;
|
|
35
|
+
private tronWeb;
|
|
36
|
+
private tronAddress;
|
|
37
|
+
private tronAddressHex;
|
|
38
|
+
private txBuilder;
|
|
39
|
+
constructor(privateKey: string, tronUrl: string);
|
|
40
|
+
/**
|
|
41
|
+
* Override connect to preserve TronWallet type.
|
|
42
|
+
* Base Wallet.connect() returns a plain Wallet, losing Tron behavior.
|
|
43
|
+
*/
|
|
44
|
+
connect(_provider: providers.Provider): TronWallet;
|
|
45
|
+
/** Convert Tron address (base58 or 41-hex) to ethers 0x address */
|
|
46
|
+
toEvmAddress(tronAddress: string): string;
|
|
47
|
+
/** Tron doesn't use nonces */
|
|
48
|
+
getTransactionCount(_blockTag?: providers.BlockTag): Promise<number>;
|
|
49
|
+
sendTransaction(transaction: providers.TransactionRequest): Promise<TronTransactionResponse>;
|
|
50
|
+
private makeUnique;
|
|
51
|
+
}
|
|
52
|
+
export declare class TronTransactionBuilder extends TronWeb {
|
|
53
|
+
private tronAddress;
|
|
54
|
+
private tronAddressHex;
|
|
55
|
+
private confirmationTimeoutMs?;
|
|
56
|
+
private confirmationPollMs;
|
|
57
|
+
constructor(tronWebUrl: string, tronAddress: string, _jsonRpcUrl?: string, headers?: Record<string, string>, confirmationTimeoutMs?: number, confirmationPollMs?: number);
|
|
58
|
+
getTransactionResponse(evmTx: TransactionRequest, tronTx: TronTransaction, txHash?: string): TronTransactionResponse;
|
|
59
|
+
private waitForTransactionReceipt;
|
|
60
|
+
/** Convert a Tron `41`-prefixed (or bare) hex address to a checksummed EVM address. */
|
|
61
|
+
private tronHexToEvmAddress;
|
|
62
|
+
private buildReceipt;
|
|
63
|
+
private toEthersReceipt;
|
|
64
|
+
buildTransaction(tx: providers.TransactionRequest): Promise<TronTransaction>;
|
|
65
|
+
private buildDeployment;
|
|
66
|
+
private buildContractCall;
|
|
67
|
+
private buildTransfer;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=TronWallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TronWallet.d.ts","sourceRoot":"","sources":["../../src/ethers/TronWallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,MAAM,EAAU,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE9D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAezC,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAO9D,kDAAkD;AAClD,MAAM,MAAM,eAAe,GACvB,KAAK,CAAC,8BAA8B,GACpC,KAAK,CAAC,WAAW,GACjB,KAAK,CAAC,iBAAiB,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,uBAAwB,SAAQ,SAAS,CAAC,mBAAmB;IAC5E,qCAAqC;IACrC,eAAe,EAAE,eAAe,CAAC;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,UAAW,SAAQ,MAAM;IACpC;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS,CAAK;IAE7B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAyB;IAE1C,YAAY,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EA4B9C;IAED;;;OAGG;IACM,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,GAAG,UAAU,CAE1D;IAED,mEAAmE;IACnE,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAIxC;IAED,8BAA8B;IACf,mBAAmB,CAChC,SAAS,CAAC,EAAE,SAAS,CAAC,QAAQ,GAC7B,OAAO,CAAC,MAAM,CAAC,CAEjB;IAEc,eAAe,CAC5B,WAAW,EAAE,SAAS,CAAC,kBAAkB,GACxC,OAAO,CAAC,uBAAuB,CAAC,CAoBlC;YAEa,UAAU;CAyBzB;AAED,qBAAa,sBAAuB,SAAQ,OAAO;IACjD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,kBAAkB,CAAS;IAEnC,YACE,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,qBAAqB,CAAC,EAAE,MAAM,EAC9B,kBAAkB,GAAE,MAAgC,EAarD;IAED,sBAAsB,CACpB,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,MAAM,GACd,uBAAuB,CAyCzB;YAEa,yBAAyB;IA4DvC,uFAAuF;IACvF,OAAO,CAAC,mBAAmB;YAQb,YAAY;IAkB1B,OAAO,CAAC,eAAe;IA+CjB,gBAAgB,CACpB,EAAE,EAAE,SAAS,CAAC,kBAAkB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAmB1B;YAEa,eAAe;YAsBf,iBAAiB;YA0BjB,aAAa;CAW5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TronWallet.integration.test.d.ts","sourceRoot":"","sources":["../../src/ethers/TronWallet.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { BigNumber } from 'ethers';
|
|
3
|
+
import { assert } from '@recoillink/utils';
|
|
4
|
+
import { runTronNode, stopTronNode, } from '../testing/node.js';
|
|
5
|
+
import { TestStorage__factory } from '@recoillink/core/tron/typechain/factories/contracts/test/TestStorage__factory.js';
|
|
6
|
+
import { TronContractFactory } from './TronContractFactory.js';
|
|
7
|
+
import { TronJsonRpcProvider } from './TronJsonRpcProvider.js';
|
|
8
|
+
import { TronWallet } from './TronWallet.js';
|
|
9
|
+
const TEST_CHAIN = {
|
|
10
|
+
name: 'tron-test',
|
|
11
|
+
chainId: 3360022319,
|
|
12
|
+
domainId: 3360022319,
|
|
13
|
+
port: 19090,
|
|
14
|
+
};
|
|
15
|
+
describe('TronWallet Integration Tests', function () {
|
|
16
|
+
this.timeout(120_000); // 2 minutes for container startup
|
|
17
|
+
let node;
|
|
18
|
+
let wallet;
|
|
19
|
+
before(async () => {
|
|
20
|
+
node = await runTronNode(TEST_CHAIN);
|
|
21
|
+
const tronUrl = `http://127.0.0.1:${TEST_CHAIN.port}/jsonrpc`;
|
|
22
|
+
const privateKey = node.privateKeys[0];
|
|
23
|
+
assert(privateKey, 'TRE did not expose a funded private key');
|
|
24
|
+
wallet = new TronWallet(privateKey, tronUrl);
|
|
25
|
+
});
|
|
26
|
+
after(async () => {
|
|
27
|
+
if (wallet?.provider instanceof TronJsonRpcProvider) {
|
|
28
|
+
wallet.provider.removeAllListeners();
|
|
29
|
+
}
|
|
30
|
+
if (node) {
|
|
31
|
+
await stopTronNode(node);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
describe('TRX Transfer', () => {
|
|
35
|
+
it('should transfer TRX to another address', async () => {
|
|
36
|
+
// Generate a random recipient address
|
|
37
|
+
const recipientPrivateKey = '0x1111111111111111111111111111111111111111111111111111111111111111';
|
|
38
|
+
const recipientWallet = new TronWallet(recipientPrivateKey, `http://127.0.0.1:${TEST_CHAIN.port}/jsonrpc`);
|
|
39
|
+
const recipientAddress = recipientWallet.address;
|
|
40
|
+
// Get initial balances
|
|
41
|
+
const senderBalanceBefore = await wallet.provider.getBalance(wallet.address);
|
|
42
|
+
const recipientBalanceBefore = await wallet.provider.getBalance(recipientAddress);
|
|
43
|
+
// Transfer 1 TRX (1,000,000 SUN)
|
|
44
|
+
const transferAmount = BigNumber.from(1_000_000);
|
|
45
|
+
const tx = await wallet.sendTransaction({
|
|
46
|
+
to: recipientAddress,
|
|
47
|
+
value: transferAmount,
|
|
48
|
+
});
|
|
49
|
+
// Wait for confirmation
|
|
50
|
+
const receipt = await tx.wait();
|
|
51
|
+
expect(receipt.status).to.equal(1);
|
|
52
|
+
// Verify balances changed
|
|
53
|
+
const senderBalanceAfter = await wallet.provider.getBalance(wallet.address);
|
|
54
|
+
const recipientBalanceAfter = await wallet.provider.getBalance(recipientAddress);
|
|
55
|
+
expect(recipientBalanceAfter.sub(recipientBalanceBefore)).to.deep.equal(transferAmount);
|
|
56
|
+
expect(senderBalanceBefore.gt(senderBalanceAfter)).to.be.true;
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('TronContractFactory', () => {
|
|
60
|
+
let contract;
|
|
61
|
+
const INITIAL_VALUE = 100;
|
|
62
|
+
it('should get deploy transaction and estimate gas', async () => {
|
|
63
|
+
const factory = new TronContractFactory(new TestStorage__factory(), wallet);
|
|
64
|
+
// Get deploy transaction (pure ethers, no network call)
|
|
65
|
+
const deployTx = factory.getDeployTransaction(INITIAL_VALUE, wallet.address);
|
|
66
|
+
expect(deployTx.data).to.be.a('string');
|
|
67
|
+
expect(deployTx.data).to.match(/^0x/);
|
|
68
|
+
// Estimate gas via Tron JSON-RPC
|
|
69
|
+
const estimatedGas = await wallet.estimateGas(deployTx);
|
|
70
|
+
expect(estimatedGas.gt(0)).to.be.true;
|
|
71
|
+
});
|
|
72
|
+
it('should deploy with gas limit override (like handleDeploy)', async () => {
|
|
73
|
+
const factory = new TronContractFactory(new TestStorage__factory(), wallet);
|
|
74
|
+
// Simulate handleDeploy flow: estimate then deploy with buffered gas limit
|
|
75
|
+
const deployTx = factory.getDeployTransaction(INITIAL_VALUE, wallet.address);
|
|
76
|
+
const estimatedGas = await wallet.estimateGas(deployTx);
|
|
77
|
+
const bufferedGasLimit = estimatedGas.mul(120).div(100); // 20% buffer
|
|
78
|
+
const deployed = await factory.deploy(INITIAL_VALUE, wallet.address, {
|
|
79
|
+
gasLimit: bufferedGasLimit,
|
|
80
|
+
});
|
|
81
|
+
expect(deployed.address).to.be.a('string');
|
|
82
|
+
expect(deployed.address).to.match(/^0x[a-fA-F0-9]{40}$/);
|
|
83
|
+
// Verify we can interact with the deployed contract
|
|
84
|
+
const value = await deployed.get();
|
|
85
|
+
expect(value.toNumber()).to.equal(INITIAL_VALUE);
|
|
86
|
+
});
|
|
87
|
+
it('should deploy a contract with constructor args', async () => {
|
|
88
|
+
const factory = new TronContractFactory(new TestStorage__factory(), wallet);
|
|
89
|
+
contract = await factory.deploy(INITIAL_VALUE, wallet.address);
|
|
90
|
+
expect(contract.address).to.be.a('string');
|
|
91
|
+
expect(contract.address).to.match(/^0x[a-fA-F0-9]{40}$/);
|
|
92
|
+
});
|
|
93
|
+
it('should have correct initial value from constructor', async () => {
|
|
94
|
+
const value = await contract.get();
|
|
95
|
+
expect(value.toNumber()).to.equal(INITIAL_VALUE);
|
|
96
|
+
});
|
|
97
|
+
it('should have correct owner from constructor', async () => {
|
|
98
|
+
const owner = await contract.owner();
|
|
99
|
+
expect(owner.toLowerCase()).to.equal(wallet.address.toLowerCase());
|
|
100
|
+
});
|
|
101
|
+
it('should set a value', async () => {
|
|
102
|
+
const newValue = 42;
|
|
103
|
+
const tx = await contract.set(newValue);
|
|
104
|
+
const receipt = await tx.wait();
|
|
105
|
+
expect(receipt.status).to.equal(1);
|
|
106
|
+
});
|
|
107
|
+
it('should get the updated value', async () => {
|
|
108
|
+
const value = await contract.get();
|
|
109
|
+
expect(value.toNumber()).to.equal(42);
|
|
110
|
+
});
|
|
111
|
+
it('should read value property directly', async () => {
|
|
112
|
+
const value = await contract.value();
|
|
113
|
+
expect(value.toNumber()).to.equal(42);
|
|
114
|
+
});
|
|
115
|
+
it('should update value and read again', async () => {
|
|
116
|
+
const newValue = 123;
|
|
117
|
+
const tx = await contract.set(newValue);
|
|
118
|
+
await tx.wait();
|
|
119
|
+
const value = await contract.get();
|
|
120
|
+
expect(value.toNumber()).to.equal(newValue);
|
|
121
|
+
});
|
|
122
|
+
it('should reject wait() when a mined tx reverts on-chain', async () => {
|
|
123
|
+
// wait() only rejects for a tx that passes pre-flight checks (TronWeb
|
|
124
|
+
// build + broadcast) yet fails during on-chain execution. TronWallet
|
|
125
|
+
// forwards raw calldata to triggerSmartContract, which does not reject a
|
|
126
|
+
// revert at build time, so calling a selector that matches no function
|
|
127
|
+
// reverts in the Solidity dispatcher (TestStorage has no fallback): the
|
|
128
|
+
// tx passes build and broadcast but mines with receipt.result ===
|
|
129
|
+
// 'REVERT', which assertTronReceiptSuccess must surface as a rejection. A
|
|
130
|
+
// generous gasLimit keeps the failure a REVERT rather than
|
|
131
|
+
// OUT_OF_ENERGY, which the TRE node rejects at broadcast before mining.
|
|
132
|
+
const tx = await wallet.sendTransaction({
|
|
133
|
+
to: contract.address,
|
|
134
|
+
data: '0xdeadbeef',
|
|
135
|
+
gasLimit: BigNumber.from(100_000),
|
|
136
|
+
});
|
|
137
|
+
let error;
|
|
138
|
+
try {
|
|
139
|
+
await tx.wait();
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
error = e;
|
|
143
|
+
}
|
|
144
|
+
if (!(error instanceof Error)) {
|
|
145
|
+
expect.fail('Expected wait() to reject with an Error');
|
|
146
|
+
}
|
|
147
|
+
expect(error.message).to.match(/Tron Transaction Failed/);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=TronWallet.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TronWallet.integration.test.js","sourceRoot":"","sources":["../../src/ethers/TronWallet.integration.test.ts"],"names":[],"mappings":"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"}
|