@meshconnect/uwc-tron-connector 0.1.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/dist/events/state-machine.d.ts +26 -0
- package/dist/events/state-machine.d.ts.map +1 -0
- package/dist/events/state-machine.js +21 -0
- package/dist/events/state-machine.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/rest/abi.d.ts +23 -0
- package/dist/rest/abi.d.ts.map +1 -0
- package/dist/rest/abi.js +28 -0
- package/dist/rest/abi.js.map +1 -0
- package/dist/rest/address.d.ts +45 -0
- package/dist/rest/address.d.ts.map +1 -0
- package/dist/rest/address.js +124 -0
- package/dist/rest/address.js.map +1 -0
- package/dist/rest/trongrid-client.d.ts +57 -0
- package/dist/rest/trongrid-client.d.ts.map +1 -0
- package/dist/rest/trongrid-client.js +133 -0
- package/dist/rest/trongrid-client.js.map +1 -0
- package/dist/shared/error-utils.d.ts +9 -0
- package/dist/shared/error-utils.d.ts.map +1 -0
- package/dist/shared/error-utils.js +52 -0
- package/dist/shared/error-utils.js.map +1 -0
- package/dist/tron-connector.d.ts +85 -0
- package/dist/tron-connector.d.ts.map +1 -0
- package/dist/tron-connector.js +456 -0
- package/dist/tron-connector.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wallets/base.d.ts +87 -0
- package/dist/wallets/base.d.ts.map +1 -0
- package/dist/wallets/base.js +118 -0
- package/dist/wallets/base.js.map +1 -0
- package/dist/wallets/bitget.d.ts +8 -0
- package/dist/wallets/bitget.d.ts.map +1 -0
- package/dist/wallets/bitget.js +14 -0
- package/dist/wallets/bitget.js.map +1 -0
- package/dist/wallets/okx.d.ts +4 -0
- package/dist/wallets/okx.d.ts.map +1 -0
- package/dist/wallets/okx.js +10 -0
- package/dist/wallets/okx.js.map +1 -0
- package/dist/wallets/registry.d.ts +8 -0
- package/dist/wallets/registry.d.ts.map +1 -0
- package/dist/wallets/registry.js +18 -0
- package/dist/wallets/registry.js.map +1 -0
- package/dist/wallets/tokenpocket.d.ts +9 -0
- package/dist/wallets/tokenpocket.d.ts.map +1 -0
- package/dist/wallets/tokenpocket.js +15 -0
- package/dist/wallets/tokenpocket.js.map +1 -0
- package/dist/wallets/tronlink.d.ts +8 -0
- package/dist/wallets/tronlink.d.ts.map +1 -0
- package/dist/wallets/tronlink.js +15 -0
- package/dist/wallets/tronlink.js.map +1 -0
- package/dist/wallets/trust.d.ts +9 -0
- package/dist/wallets/trust.d.ts.map +1 -0
- package/dist/wallets/trust.js +15 -0
- package/dist/wallets/trust.js.map +1 -0
- package/package.json +34 -0
- package/src/events/state-machine.ts +44 -0
- package/src/index.ts +17 -0
- package/src/rest/abi.test.ts +25 -0
- package/src/rest/abi.ts +33 -0
- package/src/rest/address.test.ts +55 -0
- package/src/rest/address.ts +140 -0
- package/src/rest/trongrid-client.test.ts +169 -0
- package/src/rest/trongrid-client.ts +205 -0
- package/src/shared/error-utils.ts +60 -0
- package/src/tron-connector.test.ts +612 -0
- package/src/tron-connector.ts +568 -0
- package/src/types.ts +11 -0
- package/src/wallets/base.ts +184 -0
- package/src/wallets/bitget.ts +17 -0
- package/src/wallets/okx.ts +10 -0
- package/src/wallets/registry.ts +26 -0
- package/src/wallets/tokenpocket.ts +15 -0
- package/src/wallets/tronlink.ts +15 -0
- package/src/wallets/trust.ts +18 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { SignedTronTransaction } from '../rest/trongrid-client';
|
|
2
|
+
/**
|
|
3
|
+
* The subset of an injected wallet's `tronWeb` we rely on. Each wallet ships
|
|
4
|
+
* its own `tronWeb` (with the user's keys wired in) inside its provider; the
|
|
5
|
+
* crypto runs there, at zero bundle cost to us.
|
|
6
|
+
*/
|
|
7
|
+
export interface InjectedTronWeb {
|
|
8
|
+
defaultAddress?: {
|
|
9
|
+
base58?: string | false;
|
|
10
|
+
hex?: string | false;
|
|
11
|
+
};
|
|
12
|
+
trx: {
|
|
13
|
+
/** Sign an unsigned transaction object. Returns the signed transaction. */
|
|
14
|
+
sign(transaction: unknown): Promise<SignedTronTransaction>;
|
|
15
|
+
/** Sign a plain string message (TIP-191). Present on all 5 target wallets. */
|
|
16
|
+
signMessageV2?(message: string): Promise<string>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The shape every supported wallet exposes at its window namespace. Wallets
|
|
21
|
+
* differ in where this object lives (see each wrapper), not in its surface.
|
|
22
|
+
*/
|
|
23
|
+
export interface InjectedTronProvider {
|
|
24
|
+
tronWeb?: InjectedTronWeb;
|
|
25
|
+
/** Account-request entry point (`tron_requestAccounts`). */
|
|
26
|
+
request?(args: {
|
|
27
|
+
method: string;
|
|
28
|
+
params?: unknown;
|
|
29
|
+
}): Promise<unknown>;
|
|
30
|
+
on?(event: string, handler: (...args: unknown[]) => void): void;
|
|
31
|
+
removeListener?(event: string, handler: (...args: unknown[]) => void): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One wrapper per wallet. Keeps every per-wallet quirk — namespace path, ready
|
|
35
|
+
* signal — isolated to a single ~30-line file, so a wallet change is a local
|
|
36
|
+
* patch (and a single wallet can be flag-disabled without touching the rest).
|
|
37
|
+
*/
|
|
38
|
+
export interface TronWalletWrapper {
|
|
39
|
+
/** Stable id; matches `WalletMetadata.id` callers pass in. */
|
|
40
|
+
id: string;
|
|
41
|
+
/** Human-readable name; surfaced via `getAvailableWallets`. */
|
|
42
|
+
displayName: string;
|
|
43
|
+
/** Read the provider from its window namespace, or undefined if absent. */
|
|
44
|
+
resolveProvider(): InjectedTronProvider | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Window event that fires when the wallet finishes injecting, if it has one.
|
|
47
|
+
* Lets detection resolve immediately instead of waiting on the poll tick.
|
|
48
|
+
* TronLink is currently the only target wallet that emits one.
|
|
49
|
+
*/
|
|
50
|
+
readyEventName?: string;
|
|
51
|
+
}
|
|
52
|
+
/** Safely walk `window` down a path of keys (e.g. ['okxwallet','tronLink']). */
|
|
53
|
+
export declare function readWindowPath(path: readonly string[]): InjectedTronProvider | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* A provider counts as present/detectable once it exposes a `request` method
|
|
56
|
+
* (the connect entry point) or already carries a `tronWeb` instance.
|
|
57
|
+
*
|
|
58
|
+
* Important: we must NOT require `tronWeb` here. Wallets like TronLink inject
|
|
59
|
+
* `window.tronLink` with `request` immediately but only populate `tronWeb`
|
|
60
|
+
* (and the account) AFTER the user approves `tron_requestAccounts`. Requiring
|
|
61
|
+
* `tronWeb` for detection would make the wallet un-discoverable until it's
|
|
62
|
+
* connected — a chicken-and-egg that hides it from the wallet list entirely.
|
|
63
|
+
*/
|
|
64
|
+
export declare function isProviderReady(provider: InjectedTronProvider | undefined): provider is InjectedTronProvider;
|
|
65
|
+
/**
|
|
66
|
+
* After `connect`, poll briefly for the wallet's account address. TronLink (and
|
|
67
|
+
* the TronLink-compatible wallets) populate `tronWeb.defaultAddress.base58` a
|
|
68
|
+
* tick or two after `tron_requestAccounts` resolves, so a single synchronous
|
|
69
|
+
* read can miss it. Resolves the base58 address, or `undefined` on timeout.
|
|
70
|
+
*/
|
|
71
|
+
export declare function waitForWalletAddress(provider: InjectedTronProvider, timeoutMs?: number, pollIntervalMs?: number): Promise<string | undefined>;
|
|
72
|
+
/**
|
|
73
|
+
* Pick the first *ready* provider among the candidates (in preference order).
|
|
74
|
+
* If none is ready yet, return the first one that merely exists, so
|
|
75
|
+
* `detectProvider` keeps polling it — re-evaluated each tick, so a path that
|
|
76
|
+
* becomes ready later still wins. Used by wallets exposed at more than one
|
|
77
|
+
* window namespace (casing/legacy variants).
|
|
78
|
+
*/
|
|
79
|
+
export declare function firstReadyOf(...candidates: Array<InjectedTronProvider | undefined>): InjectedTronProvider | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a wallet's provider, waiting up to `timeoutMs` for it to finish
|
|
82
|
+
* injecting. Polling covers all wallets; an optional `readyEventName` provides
|
|
83
|
+
* a fast path for wallets that announce readiness (TronLink's TIP-6963-style
|
|
84
|
+
* signal). Resolves `undefined` if the wallet never appears.
|
|
85
|
+
*/
|
|
86
|
+
export declare function detectProvider(wrapper: TronWalletWrapper, timeoutMs?: number, pollIntervalMs?: number): Promise<InjectedTronProvider | undefined>;
|
|
87
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/wallets/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE;QACf,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;QACvB,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KACrB,CAAA;IACD,GAAG,EAAE;QACH,2EAA2E;QAC3E,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAA;QAC1D,8EAA8E;QAC9E,aAAa,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;KACjD,CAAA;CACF;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,4DAA4D;IAC5D,OAAO,CAAC,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACtE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;IAC/D,cAAc,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAA;CAC5E;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAA;IACV,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAA;IACnB,2EAA2E;IAC3E,eAAe,IAAI,oBAAoB,GAAG,SAAS,CAAA;IACnD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,oBAAoB,GAAG,SAAS,CASlC;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,oBAAoB,GAAG,SAAS,GACzC,QAAQ,IAAI,oBAAoB,CAIlC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,oBAAoB,EAC9B,SAAS,SAAO,EAChB,cAAc,SAAK,GAClB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,UAAU,EAAE,KAAK,CAAC,oBAAoB,GAAG,SAAS,CAAC,GACrD,oBAAoB,GAAG,SAAS,CAKlC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,iBAAiB,EAC1B,SAAS,SAAO,EAChB,cAAc,SAAK,GAClB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAsC3C"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/** Safely walk `window` down a path of keys (e.g. ['okxwallet','tronLink']). */
|
|
2
|
+
export function readWindowPath(path) {
|
|
3
|
+
if (typeof window === 'undefined')
|
|
4
|
+
return undefined;
|
|
5
|
+
let node = window;
|
|
6
|
+
for (const key of path) {
|
|
7
|
+
if (node == null || typeof node !== 'object')
|
|
8
|
+
return undefined;
|
|
9
|
+
node = node[key];
|
|
10
|
+
}
|
|
11
|
+
if (node == null || typeof node !== 'object')
|
|
12
|
+
return undefined;
|
|
13
|
+
return node;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A provider counts as present/detectable once it exposes a `request` method
|
|
17
|
+
* (the connect entry point) or already carries a `tronWeb` instance.
|
|
18
|
+
*
|
|
19
|
+
* Important: we must NOT require `tronWeb` here. Wallets like TronLink inject
|
|
20
|
+
* `window.tronLink` with `request` immediately but only populate `tronWeb`
|
|
21
|
+
* (and the account) AFTER the user approves `tron_requestAccounts`. Requiring
|
|
22
|
+
* `tronWeb` for detection would make the wallet un-discoverable until it's
|
|
23
|
+
* connected — a chicken-and-egg that hides it from the wallet list entirely.
|
|
24
|
+
*/
|
|
25
|
+
export function isProviderReady(provider) {
|
|
26
|
+
return (!!provider && (typeof provider.request === 'function' || !!provider.tronWeb));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* After `connect`, poll briefly for the wallet's account address. TronLink (and
|
|
30
|
+
* the TronLink-compatible wallets) populate `tronWeb.defaultAddress.base58` a
|
|
31
|
+
* tick or two after `tron_requestAccounts` resolves, so a single synchronous
|
|
32
|
+
* read can miss it. Resolves the base58 address, or `undefined` on timeout.
|
|
33
|
+
*/
|
|
34
|
+
export function waitForWalletAddress(provider, timeoutMs = 3000, pollIntervalMs = 50) {
|
|
35
|
+
const read = () => {
|
|
36
|
+
const base58 = provider.tronWeb?.defaultAddress?.base58;
|
|
37
|
+
return typeof base58 === 'string' && base58.length > 0 ? base58 : undefined;
|
|
38
|
+
};
|
|
39
|
+
const immediate = read();
|
|
40
|
+
if (immediate)
|
|
41
|
+
return Promise.resolve(immediate);
|
|
42
|
+
return new Promise(resolve => {
|
|
43
|
+
let settled = false;
|
|
44
|
+
const finish = (value) => {
|
|
45
|
+
if (settled)
|
|
46
|
+
return;
|
|
47
|
+
settled = true;
|
|
48
|
+
clearInterval(timer);
|
|
49
|
+
clearTimeout(deadline);
|
|
50
|
+
resolve(value);
|
|
51
|
+
};
|
|
52
|
+
const timer = setInterval(() => {
|
|
53
|
+
const address = read();
|
|
54
|
+
if (address)
|
|
55
|
+
finish(address);
|
|
56
|
+
}, pollIntervalMs);
|
|
57
|
+
const deadline = setTimeout(() => finish(undefined), timeoutMs);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Pick the first *ready* provider among the candidates (in preference order).
|
|
62
|
+
* If none is ready yet, return the first one that merely exists, so
|
|
63
|
+
* `detectProvider` keeps polling it — re-evaluated each tick, so a path that
|
|
64
|
+
* becomes ready later still wins. Used by wallets exposed at more than one
|
|
65
|
+
* window namespace (casing/legacy variants).
|
|
66
|
+
*/
|
|
67
|
+
export function firstReadyOf(...candidates) {
|
|
68
|
+
for (const candidate of candidates) {
|
|
69
|
+
if (isProviderReady(candidate))
|
|
70
|
+
return candidate;
|
|
71
|
+
}
|
|
72
|
+
return candidates.find(candidate => candidate != null);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Resolve a wallet's provider, waiting up to `timeoutMs` for it to finish
|
|
76
|
+
* injecting. Polling covers all wallets; an optional `readyEventName` provides
|
|
77
|
+
* a fast path for wallets that announce readiness (TronLink's TIP-6963-style
|
|
78
|
+
* signal). Resolves `undefined` if the wallet never appears.
|
|
79
|
+
*/
|
|
80
|
+
export function detectProvider(wrapper, timeoutMs = 3000, pollIntervalMs = 50) {
|
|
81
|
+
const immediate = wrapper.resolveProvider();
|
|
82
|
+
if (isProviderReady(immediate))
|
|
83
|
+
return Promise.resolve(immediate);
|
|
84
|
+
// No browser context (SSR/non-browser): no wallet can ever appear, so resolve
|
|
85
|
+
// immediately instead of polling out the full timeout.
|
|
86
|
+
if (typeof window === 'undefined')
|
|
87
|
+
return Promise.resolve(undefined);
|
|
88
|
+
return new Promise(resolve => {
|
|
89
|
+
let settled = false;
|
|
90
|
+
// Declared up front (not `const` after `finish`) so `finish` never
|
|
91
|
+
// forward-references an uninitialized binding, even under future refactors.
|
|
92
|
+
let timer;
|
|
93
|
+
let deadline;
|
|
94
|
+
const onReady = () => tryResolve();
|
|
95
|
+
const finish = (result) => {
|
|
96
|
+
if (settled)
|
|
97
|
+
return;
|
|
98
|
+
settled = true;
|
|
99
|
+
clearInterval(timer);
|
|
100
|
+
clearTimeout(deadline);
|
|
101
|
+
if (wrapper.readyEventName && typeof window !== 'undefined') {
|
|
102
|
+
window.removeEventListener(wrapper.readyEventName, onReady);
|
|
103
|
+
}
|
|
104
|
+
resolve(result);
|
|
105
|
+
};
|
|
106
|
+
function tryResolve() {
|
|
107
|
+
const provider = wrapper.resolveProvider();
|
|
108
|
+
if (isProviderReady(provider))
|
|
109
|
+
finish(provider);
|
|
110
|
+
}
|
|
111
|
+
if (wrapper.readyEventName && typeof window !== 'undefined') {
|
|
112
|
+
window.addEventListener(wrapper.readyEventName, onReady);
|
|
113
|
+
}
|
|
114
|
+
timer = setInterval(tryResolve, pollIntervalMs);
|
|
115
|
+
deadline = setTimeout(() => finish(undefined), timeoutMs);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/wallets/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type TronWalletWrapper } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Bitget Wallet (formerly BitKeep) — injects at `window.bitkeep`. The Tron
|
|
4
|
+
* provider lives under `window.bitkeep.tronLink`; older builds exposed it on
|
|
5
|
+
* `window.bitkeep` directly, so we fall back to that.
|
|
6
|
+
*/
|
|
7
|
+
export declare const bitget: TronWalletWrapper;
|
|
8
|
+
//# sourceMappingURL=bitget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitget.d.ts","sourceRoot":"","sources":["../../src/wallets/bitget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,iBASpB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Bitget Wallet (formerly BitKeep) — injects at `window.bitkeep`. The Tron
|
|
4
|
+
* provider lives under `window.bitkeep.tronLink`; older builds exposed it on
|
|
5
|
+
* `window.bitkeep` directly, so we fall back to that.
|
|
6
|
+
*/
|
|
7
|
+
export const bitget = {
|
|
8
|
+
id: 'bitget',
|
|
9
|
+
displayName: 'Bitget Wallet',
|
|
10
|
+
resolveProvider() {
|
|
11
|
+
return firstReadyOf(readWindowPath(['bitkeep', 'tronLink']), readWindowPath(['bitkeep']));
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=bitget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitget.js","sourceRoot":"","sources":["../../src/wallets/bitget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAA0B,MAAM,QAAQ,CAAA;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAsB;IACvC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,eAAe;IAC5B,eAAe;QACb,OAAO,YAAY,CACjB,cAAc,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,EACvC,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,CAC5B,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"okx.d.ts","sourceRoot":"","sources":["../../src/wallets/okx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE/D,0FAA0F;AAC1F,eAAO,MAAM,GAAG,EAAE,iBAMjB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { readWindowPath } from './base';
|
|
2
|
+
/** OKX Wallet — exposes a TronLink-compatible provider at `window.okxwallet.tronLink`. */
|
|
3
|
+
export const okx = {
|
|
4
|
+
id: 'okx',
|
|
5
|
+
displayName: 'OKX Wallet',
|
|
6
|
+
resolveProvider() {
|
|
7
|
+
return readWindowPath(['okxwallet', 'tronLink']);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=okx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"okx.js","sourceRoot":"","sources":["../../src/wallets/okx.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA0B,MAAM,QAAQ,CAAA;AAE/D,0FAA0F;AAC1F,MAAM,CAAC,MAAM,GAAG,GAAsB;IACpC,EAAE,EAAE,KAAK;IACT,WAAW,EAAE,YAAY;IACzB,eAAe;QACb,OAAO,cAAc,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAA;IAClD,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TronWalletId } from '@meshconnect/uwc-types';
|
|
2
|
+
import type { TronWalletWrapper } from './base';
|
|
3
|
+
export type { TronWalletId } from '@meshconnect/uwc-types';
|
|
4
|
+
/** All supported wallet wrappers, keyed by id. */
|
|
5
|
+
export declare const TRON_WALLET_REGISTRY: Record<TronWalletId, TronWalletWrapper>;
|
|
6
|
+
export declare const ALL_TRON_WALLET_IDS: readonly TronWalletId[];
|
|
7
|
+
export declare function isTronWalletId(value: string): value is TronWalletId;
|
|
8
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/wallets/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAO/C,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAE1D,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,iBAAiB,CAMxE,CAAA;AAED,eAAO,MAAM,mBAAmB,EAAE,SAAS,YAAY,EAEtD,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,YAAY,CAEnE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { tronlink } from './tronlink';
|
|
2
|
+
import { okx } from './okx';
|
|
3
|
+
import { trust } from './trust';
|
|
4
|
+
import { bitget } from './bitget';
|
|
5
|
+
import { tokenpocket } from './tokenpocket';
|
|
6
|
+
/** All supported wallet wrappers, keyed by id. */
|
|
7
|
+
export const TRON_WALLET_REGISTRY = {
|
|
8
|
+
tronlink,
|
|
9
|
+
bitget,
|
|
10
|
+
okx,
|
|
11
|
+
tokenpocket,
|
|
12
|
+
trust
|
|
13
|
+
};
|
|
14
|
+
export const ALL_TRON_WALLET_IDS = Object.freeze(Object.keys(TRON_WALLET_REGISTRY));
|
|
15
|
+
export function isTronWalletId(value) {
|
|
16
|
+
return ALL_TRON_WALLET_IDS.includes(value);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/wallets/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAI3C,kDAAkD;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAA4C;IAC3E,QAAQ;IACR,MAAM;IACN,GAAG;IACH,WAAW;IACX,KAAK;CACN,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAA4B,MAAM,CAAC,MAAM,CACvE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAmB,CACpD,CAAA;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAQ,mBAAyC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACnE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type TronWalletWrapper } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* TokenPocket — injects at `window.tokenpocket`, exposing its Tron provider at
|
|
4
|
+
* `window.tokenpocket.tron`. We target that nested path specifically rather
|
|
5
|
+
* than the shared `window.tronLink` global TokenPocket also populates, so it is
|
|
6
|
+
* never mis-detected as TronLink.
|
|
7
|
+
*/
|
|
8
|
+
export declare const tokenpocket: TronWalletWrapper;
|
|
9
|
+
//# sourceMappingURL=tokenpocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenpocket.d.ts","sourceRoot":"","sources":["../../src/wallets/tokenpocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,iBAMzB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readWindowPath } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* TokenPocket — injects at `window.tokenpocket`, exposing its Tron provider at
|
|
4
|
+
* `window.tokenpocket.tron`. We target that nested path specifically rather
|
|
5
|
+
* than the shared `window.tronLink` global TokenPocket also populates, so it is
|
|
6
|
+
* never mis-detected as TronLink.
|
|
7
|
+
*/
|
|
8
|
+
export const tokenpocket = {
|
|
9
|
+
id: 'tokenpocket',
|
|
10
|
+
displayName: 'TokenPocket',
|
|
11
|
+
resolveProvider() {
|
|
12
|
+
return readWindowPath(['tokenpocket', 'tron']);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=tokenpocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenpocket.js","sourceRoot":"","sources":["../../src/wallets/tokenpocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA0B,MAAM,QAAQ,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAsB;IAC5C,EAAE,EAAE,aAAa;IACjB,WAAW,EAAE,aAAa;IAC1B,eAAe;QACb,OAAO,cAAc,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAA;IAChD,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type TronWalletWrapper } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* TronLink — `window.tronLink` (legacy) or `window.tron` (TIP-1193).
|
|
4
|
+
* The only target wallet that announces readiness, via the
|
|
5
|
+
* `tronLink#initialized` window event.
|
|
6
|
+
*/
|
|
7
|
+
export declare const tronlink: TronWalletWrapper;
|
|
8
|
+
//# sourceMappingURL=tronlink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tronlink.d.ts","sourceRoot":"","sources":["../../src/wallets/tronlink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,iBAOtB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* TronLink — `window.tronLink` (legacy) or `window.tron` (TIP-1193).
|
|
4
|
+
* The only target wallet that announces readiness, via the
|
|
5
|
+
* `tronLink#initialized` window event.
|
|
6
|
+
*/
|
|
7
|
+
export const tronlink = {
|
|
8
|
+
id: 'tronlink',
|
|
9
|
+
displayName: 'TronLink',
|
|
10
|
+
readyEventName: 'tronLink#initialized',
|
|
11
|
+
resolveProvider() {
|
|
12
|
+
return firstReadyOf(readWindowPath(['tronLink']), readWindowPath(['tron']));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=tronlink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tronlink.js","sourceRoot":"","sources":["../../src/wallets/tronlink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAA0B,MAAM,QAAQ,CAAA;AAE7E;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAsB;IACzC,EAAE,EAAE,UAAU;IACd,WAAW,EAAE,UAAU;IACvB,cAAc,EAAE,sBAAsB;IACtC,eAAe;QACb,OAAO,YAAY,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IAC7E,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type TronWalletWrapper } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Trust Wallet — TronLink-compatible provider. The repo's existing wallet
|
|
4
|
+
* metadata uses `window.trustWallet.tronLink` (capital W), so we prefer that,
|
|
5
|
+
* then the all-lowercase `window.trustwallet.tronLink` that some extension
|
|
6
|
+
* versions expose, to avoid casing-related false negatives.
|
|
7
|
+
*/
|
|
8
|
+
export declare const trust: TronWalletWrapper;
|
|
9
|
+
//# sourceMappingURL=trust.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.d.ts","sourceRoot":"","sources":["../../src/wallets/trust.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAE7E;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,iBASnB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf } from './base';
|
|
2
|
+
/**
|
|
3
|
+
* Trust Wallet — TronLink-compatible provider. The repo's existing wallet
|
|
4
|
+
* metadata uses `window.trustWallet.tronLink` (capital W), so we prefer that,
|
|
5
|
+
* then the all-lowercase `window.trustwallet.tronLink` that some extension
|
|
6
|
+
* versions expose, to avoid casing-related false negatives.
|
|
7
|
+
*/
|
|
8
|
+
export const trust = {
|
|
9
|
+
id: 'trust',
|
|
10
|
+
displayName: 'Trust Wallet',
|
|
11
|
+
resolveProvider() {
|
|
12
|
+
return firstReadyOf(readWindowPath(['trustWallet', 'tronLink']), readWindowPath(['trustwallet', 'tronLink']));
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=trust.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trust.js","sourceRoot":"","sources":["../../src/wallets/trust.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAA0B,MAAM,QAAQ,CAAA;AAE7E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAsB;IACtC,EAAE,EAAE,OAAO;IACX,WAAW,EAAE,cAAc;IAC3B,eAAe;QACb,OAAO,YAAY,CACjB,cAAc,CAAC,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,EAC3C,cAAc,CAAC,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAC5C,CAAA;IACH,CAAC;CACF,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meshconnect/uwc-tron-connector",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Mesh-owned Tron wallet connector for Universal Wallet Connector — zero third-party Tron runtime deps; signs via the wallet's injected tronWeb, builds/broadcasts via the Tron full-node HTTP API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@meshconnect/uwc-types": "0.15.1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.9.3"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"dev": "tsc --watch",
|
|
30
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
31
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
32
|
+
"type-check": "tsc --noEmit"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal connection state machine + subscription surface.
|
|
3
|
+
*
|
|
4
|
+
* The connector exposes a single `onStateChange` callback rather than the
|
|
5
|
+
* full wallet event set — enough for `core` to react to disconnects and
|
|
6
|
+
* account changes without leaking per-wallet event shapes.
|
|
7
|
+
*/
|
|
8
|
+
import type { TronWalletId } from '@meshconnect/uwc-types'
|
|
9
|
+
|
|
10
|
+
export type TronConnectionStatus = 'disconnected' | 'connecting' | 'connected'
|
|
11
|
+
|
|
12
|
+
export interface TronConnectionState {
|
|
13
|
+
status: TronConnectionStatus
|
|
14
|
+
/** Active wallet id, when connected/connecting. */
|
|
15
|
+
walletId?: TronWalletId
|
|
16
|
+
/** Active account address (base58), when connected. */
|
|
17
|
+
address?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type TronStateListener = (state: TronConnectionState) => void
|
|
21
|
+
|
|
22
|
+
export class TronStateMachine {
|
|
23
|
+
private state: TronConnectionState = { status: 'disconnected' }
|
|
24
|
+
private readonly listeners = new Set<TronStateListener>()
|
|
25
|
+
|
|
26
|
+
get(): TronConnectionState {
|
|
27
|
+
return this.state
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set(next: TronConnectionState): void {
|
|
31
|
+
this.state = next
|
|
32
|
+
for (const listener of this.listeners) {
|
|
33
|
+
listener(next)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Subscribe to state transitions. Returns an unsubscribe function. */
|
|
38
|
+
subscribe(listener: TronStateListener): () => void {
|
|
39
|
+
this.listeners.add(listener)
|
|
40
|
+
return () => {
|
|
41
|
+
this.listeners.delete(listener)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { TronConnector } from './tron-connector'
|
|
2
|
+
export {
|
|
3
|
+
ALL_TRON_WALLET_IDS,
|
|
4
|
+
TRON_WALLET_REGISTRY,
|
|
5
|
+
isTronWalletId
|
|
6
|
+
} from './wallets/registry'
|
|
7
|
+
export type { TronWalletWrapper, InjectedTronProvider } from './wallets/base'
|
|
8
|
+
export type {
|
|
9
|
+
TronConnectionState,
|
|
10
|
+
TronConnectionStatus,
|
|
11
|
+
TronStateListener
|
|
12
|
+
} from './events/state-machine'
|
|
13
|
+
export type {
|
|
14
|
+
UnsignedTronTransaction,
|
|
15
|
+
SignedTronTransaction
|
|
16
|
+
} from './rest/trongrid-client'
|
|
17
|
+
export type { TronConnectorConfig, TronGridConfig, TronWalletId } from './types'
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { encodeTrc20TransferParams, TRC20_TRANSFER_SELECTOR } from './abi'
|
|
3
|
+
|
|
4
|
+
const USDT_BASE58 = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
|
|
5
|
+
const USDT_EVM_HEX = 'a614f803b6fd780986a42c78ec9c7f77e6ded13c'
|
|
6
|
+
|
|
7
|
+
describe('encodeTrc20TransferParams', () => {
|
|
8
|
+
it('encodes address + amount as two left-padded 32-byte words', () => {
|
|
9
|
+
const encoded = encodeTrc20TransferParams(USDT_BASE58, 1_000_000)
|
|
10
|
+
expect(encoded).toHaveLength(128)
|
|
11
|
+
expect(encoded.slice(0, 64)).toBe(USDT_EVM_HEX.padStart(64, '0'))
|
|
12
|
+
// 1_000_000 == 0xf4240
|
|
13
|
+
expect(encoded.slice(64)).toBe('f4240'.padStart(64, '0'))
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('handles bigint amounts beyond Number.MAX_SAFE_INTEGER', () => {
|
|
17
|
+
const amount = 123456789012345678901234567890n
|
|
18
|
+
const encoded = encodeTrc20TransferParams(USDT_BASE58, amount)
|
|
19
|
+
expect(encoded.slice(64)).toBe(amount.toString(16).padStart(64, '0'))
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('exposes the canonical selector string', () => {
|
|
23
|
+
expect(TRC20_TRANSFER_SELECTOR).toBe('transfer(address,uint256)')
|
|
24
|
+
})
|
|
25
|
+
})
|
package/src/rest/abi.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { tronAddressToEvmHex } from './address'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ABI-encode the arguments for `transfer(address,uint256)` (TRC20 / TEP-20).
|
|
5
|
+
*
|
|
6
|
+
* The full-node `/wallet/triggersmartcontract` endpoint takes the function
|
|
7
|
+
* selector as a literal string and the *arguments* as a hex `parameter` blob.
|
|
8
|
+
* Each argument is left-padded to a 32-byte (64-hex-char) word:
|
|
9
|
+
* - address: the bare 20-byte body, left-padded to 32 bytes.
|
|
10
|
+
* - uint256: the amount, left-padded to 32 bytes.
|
|
11
|
+
*
|
|
12
|
+
* @param to recipient address (base58 or hex)
|
|
13
|
+
* @param amount token amount in base units
|
|
14
|
+
* @returns 128-hex-char parameter string (no `0x` prefix)
|
|
15
|
+
*/
|
|
16
|
+
export function encodeTrc20TransferParams(
|
|
17
|
+
to: string,
|
|
18
|
+
amount: number | bigint
|
|
19
|
+
): string {
|
|
20
|
+
const addressWord = tronAddressToEvmHex(to).padStart(64, '0')
|
|
21
|
+
const amountWord = BigInt(amount).toString(16).padStart(64, '0')
|
|
22
|
+
return addressWord + amountWord
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Function selector string the full node hashes for a TRC20 transfer. */
|
|
26
|
+
export const TRC20_TRANSFER_SELECTOR = 'transfer(address,uint256)'
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The 4-byte selector (8 hex chars) for `transfer(address,uint256)` —
|
|
30
|
+
* `keccak256("transfer(address,uint256)")[:4]`, same as ERC-20. Used to
|
|
31
|
+
* reconstruct and verify the full call data the node built before signing.
|
|
32
|
+
*/
|
|
33
|
+
export const TRC20_TRANSFER_SELECTOR_HASH = 'a9059cbb'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
tronAddressToHex,
|
|
4
|
+
tronAddressToEvmHex,
|
|
5
|
+
assertValidTronChecksum
|
|
6
|
+
} from './address'
|
|
7
|
+
|
|
8
|
+
// USDT-TRON contract — a well-known, stable base58 ↔ hex pair.
|
|
9
|
+
const USDT_BASE58 = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
|
|
10
|
+
const USDT_HEX = '41a614f803b6fd780986a42c78ec9c7f77e6ded13c'
|
|
11
|
+
const USDT_EVM_HEX = 'a614f803b6fd780986a42c78ec9c7f77e6ded13c'
|
|
12
|
+
|
|
13
|
+
describe('tronAddressToHex', () => {
|
|
14
|
+
it('decodes a base58 address to its 21-byte hex form', () => {
|
|
15
|
+
expect(tronAddressToHex(USDT_BASE58)).toBe(USDT_HEX)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('passes through an already-hex address (normalised, lowercased)', () => {
|
|
19
|
+
expect(tronAddressToHex(USDT_HEX.toUpperCase())).toBe(USDT_HEX)
|
|
20
|
+
expect(tronAddressToHex(`0x${USDT_HEX}`)).toBe(USDT_HEX)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('throws on an invalid base58 character', () => {
|
|
24
|
+
expect(() => tronAddressToHex('T0OIl')).toThrow(/invalid base58/)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('throws when the decoded payload is the wrong length', () => {
|
|
28
|
+
// Valid base58 chars, but far too short to be a 25-byte Tron address.
|
|
29
|
+
expect(() => tronAddressToHex('abc')).toThrow(/25 bytes/)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('tronAddressToEvmHex', () => {
|
|
34
|
+
it('strips the 0x41 prefix, leaving the 20-byte body', () => {
|
|
35
|
+
expect(tronAddressToEvmHex(USDT_BASE58)).toBe(USDT_EVM_HEX)
|
|
36
|
+
expect(tronAddressToEvmHex(USDT_BASE58).length).toBe(40)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('assertValidTronChecksum', () => {
|
|
41
|
+
it('accepts a valid base58 address', async () => {
|
|
42
|
+
await expect(assertValidTronChecksum(USDT_BASE58)).resolves.toBeUndefined()
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('rejects a base58 address with a corrupted checksum', async () => {
|
|
46
|
+
// USDT address with the final char changed — same length/prefix, bad checksum.
|
|
47
|
+
await expect(
|
|
48
|
+
assertValidTronChecksum('TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6u')
|
|
49
|
+
).rejects.toThrow(/checksum/)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('passes through hex form (no base58 checksum present)', async () => {
|
|
53
|
+
await expect(assertValidTronChecksum(USDT_HEX)).resolves.toBeUndefined()
|
|
54
|
+
})
|
|
55
|
+
})
|