@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,184 @@
|
|
|
1
|
+
import type { SignedTronTransaction } from '../rest/trongrid-client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The subset of an injected wallet's `tronWeb` we rely on. Each wallet ships
|
|
5
|
+
* its own `tronWeb` (with the user's keys wired in) inside its provider; the
|
|
6
|
+
* crypto runs there, at zero bundle cost to us.
|
|
7
|
+
*/
|
|
8
|
+
export interface InjectedTronWeb {
|
|
9
|
+
defaultAddress?: {
|
|
10
|
+
base58?: string | false
|
|
11
|
+
hex?: string | false
|
|
12
|
+
}
|
|
13
|
+
trx: {
|
|
14
|
+
/** Sign an unsigned transaction object. Returns the signed transaction. */
|
|
15
|
+
sign(transaction: unknown): Promise<SignedTronTransaction>
|
|
16
|
+
/** Sign a plain string message (TIP-191). Present on all 5 target wallets. */
|
|
17
|
+
signMessageV2?(message: string): Promise<string>
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The shape every supported wallet exposes at its window namespace. Wallets
|
|
23
|
+
* differ in where this object lives (see each wrapper), not in its surface.
|
|
24
|
+
*/
|
|
25
|
+
export interface InjectedTronProvider {
|
|
26
|
+
tronWeb?: InjectedTronWeb
|
|
27
|
+
/** Account-request entry point (`tron_requestAccounts`). */
|
|
28
|
+
request?(args: { method: string; params?: unknown }): Promise<unknown>
|
|
29
|
+
on?(event: string, handler: (...args: unknown[]) => void): void
|
|
30
|
+
removeListener?(event: string, handler: (...args: unknown[]) => void): void
|
|
31
|
+
}
|
|
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
|
+
|
|
53
|
+
/** Safely walk `window` down a path of keys (e.g. ['okxwallet','tronLink']). */
|
|
54
|
+
export function readWindowPath(
|
|
55
|
+
path: readonly string[]
|
|
56
|
+
): InjectedTronProvider | undefined {
|
|
57
|
+
if (typeof window === 'undefined') return undefined
|
|
58
|
+
let node: unknown = window
|
|
59
|
+
for (const key of path) {
|
|
60
|
+
if (node == null || typeof node !== 'object') return undefined
|
|
61
|
+
node = (node as Record<string, unknown>)[key]
|
|
62
|
+
}
|
|
63
|
+
if (node == null || typeof node !== 'object') return undefined
|
|
64
|
+
return node as InjectedTronProvider
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A provider counts as present/detectable once it exposes a `request` method
|
|
69
|
+
* (the connect entry point) or already carries a `tronWeb` instance.
|
|
70
|
+
*
|
|
71
|
+
* Important: we must NOT require `tronWeb` here. Wallets like TronLink inject
|
|
72
|
+
* `window.tronLink` with `request` immediately but only populate `tronWeb`
|
|
73
|
+
* (and the account) AFTER the user approves `tron_requestAccounts`. Requiring
|
|
74
|
+
* `tronWeb` for detection would make the wallet un-discoverable until it's
|
|
75
|
+
* connected — a chicken-and-egg that hides it from the wallet list entirely.
|
|
76
|
+
*/
|
|
77
|
+
export function isProviderReady(
|
|
78
|
+
provider: InjectedTronProvider | undefined
|
|
79
|
+
): provider is InjectedTronProvider {
|
|
80
|
+
return (
|
|
81
|
+
!!provider && (typeof provider.request === 'function' || !!provider.tronWeb)
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* After `connect`, poll briefly for the wallet's account address. TronLink (and
|
|
87
|
+
* the TronLink-compatible wallets) populate `tronWeb.defaultAddress.base58` a
|
|
88
|
+
* tick or two after `tron_requestAccounts` resolves, so a single synchronous
|
|
89
|
+
* read can miss it. Resolves the base58 address, or `undefined` on timeout.
|
|
90
|
+
*/
|
|
91
|
+
export function waitForWalletAddress(
|
|
92
|
+
provider: InjectedTronProvider,
|
|
93
|
+
timeoutMs = 3000,
|
|
94
|
+
pollIntervalMs = 50
|
|
95
|
+
): Promise<string | undefined> {
|
|
96
|
+
const read = (): string | undefined => {
|
|
97
|
+
const base58 = provider.tronWeb?.defaultAddress?.base58
|
|
98
|
+
return typeof base58 === 'string' && base58.length > 0 ? base58 : undefined
|
|
99
|
+
}
|
|
100
|
+
const immediate = read()
|
|
101
|
+
if (immediate) return Promise.resolve(immediate)
|
|
102
|
+
|
|
103
|
+
return new Promise(resolve => {
|
|
104
|
+
let settled = false
|
|
105
|
+
const finish = (value: string | undefined) => {
|
|
106
|
+
if (settled) return
|
|
107
|
+
settled = true
|
|
108
|
+
clearInterval(timer)
|
|
109
|
+
clearTimeout(deadline)
|
|
110
|
+
resolve(value)
|
|
111
|
+
}
|
|
112
|
+
const timer = setInterval(() => {
|
|
113
|
+
const address = read()
|
|
114
|
+
if (address) finish(address)
|
|
115
|
+
}, pollIntervalMs)
|
|
116
|
+
const deadline = setTimeout(() => finish(undefined), timeoutMs)
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Pick the first *ready* provider among the candidates (in preference order).
|
|
122
|
+
* If none is ready yet, return the first one that merely exists, so
|
|
123
|
+
* `detectProvider` keeps polling it — re-evaluated each tick, so a path that
|
|
124
|
+
* becomes ready later still wins. Used by wallets exposed at more than one
|
|
125
|
+
* window namespace (casing/legacy variants).
|
|
126
|
+
*/
|
|
127
|
+
export function firstReadyOf(
|
|
128
|
+
...candidates: Array<InjectedTronProvider | undefined>
|
|
129
|
+
): InjectedTronProvider | undefined {
|
|
130
|
+
for (const candidate of candidates) {
|
|
131
|
+
if (isProviderReady(candidate)) return candidate
|
|
132
|
+
}
|
|
133
|
+
return candidates.find(candidate => candidate != null)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Resolve a wallet's provider, waiting up to `timeoutMs` for it to finish
|
|
138
|
+
* injecting. Polling covers all wallets; an optional `readyEventName` provides
|
|
139
|
+
* a fast path for wallets that announce readiness (TronLink's TIP-6963-style
|
|
140
|
+
* signal). Resolves `undefined` if the wallet never appears.
|
|
141
|
+
*/
|
|
142
|
+
export function detectProvider(
|
|
143
|
+
wrapper: TronWalletWrapper,
|
|
144
|
+
timeoutMs = 3000,
|
|
145
|
+
pollIntervalMs = 50
|
|
146
|
+
): Promise<InjectedTronProvider | undefined> {
|
|
147
|
+
const immediate = wrapper.resolveProvider()
|
|
148
|
+
if (isProviderReady(immediate)) return Promise.resolve(immediate)
|
|
149
|
+
|
|
150
|
+
// No browser context (SSR/non-browser): no wallet can ever appear, so resolve
|
|
151
|
+
// immediately instead of polling out the full timeout.
|
|
152
|
+
if (typeof window === 'undefined') return Promise.resolve(undefined)
|
|
153
|
+
|
|
154
|
+
return new Promise(resolve => {
|
|
155
|
+
let settled = false
|
|
156
|
+
// Declared up front (not `const` after `finish`) so `finish` never
|
|
157
|
+
// forward-references an uninitialized binding, even under future refactors.
|
|
158
|
+
let timer: ReturnType<typeof setInterval>
|
|
159
|
+
let deadline: ReturnType<typeof setTimeout>
|
|
160
|
+
|
|
161
|
+
const onReady = () => tryResolve()
|
|
162
|
+
const finish = (result: InjectedTronProvider | undefined) => {
|
|
163
|
+
if (settled) return
|
|
164
|
+
settled = true
|
|
165
|
+
clearInterval(timer)
|
|
166
|
+
clearTimeout(deadline)
|
|
167
|
+
if (wrapper.readyEventName && typeof window !== 'undefined') {
|
|
168
|
+
window.removeEventListener(wrapper.readyEventName, onReady)
|
|
169
|
+
}
|
|
170
|
+
resolve(result)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function tryResolve() {
|
|
174
|
+
const provider = wrapper.resolveProvider()
|
|
175
|
+
if (isProviderReady(provider)) finish(provider)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (wrapper.readyEventName && typeof window !== 'undefined') {
|
|
179
|
+
window.addEventListener(wrapper.readyEventName, onReady)
|
|
180
|
+
}
|
|
181
|
+
timer = setInterval(tryResolve, pollIntervalMs)
|
|
182
|
+
deadline = setTimeout(() => finish(undefined), timeoutMs)
|
|
183
|
+
})
|
|
184
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf, type TronWalletWrapper } from './base'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Bitget Wallet (formerly BitKeep) — injects at `window.bitkeep`. The Tron
|
|
5
|
+
* provider lives under `window.bitkeep.tronLink`; older builds exposed it on
|
|
6
|
+
* `window.bitkeep` directly, so we fall back to that.
|
|
7
|
+
*/
|
|
8
|
+
export const bitget: TronWalletWrapper = {
|
|
9
|
+
id: 'bitget',
|
|
10
|
+
displayName: 'Bitget Wallet',
|
|
11
|
+
resolveProvider() {
|
|
12
|
+
return firstReadyOf(
|
|
13
|
+
readWindowPath(['bitkeep', 'tronLink']),
|
|
14
|
+
readWindowPath(['bitkeep'])
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { readWindowPath, type TronWalletWrapper } from './base'
|
|
2
|
+
|
|
3
|
+
/** OKX Wallet — exposes a TronLink-compatible provider at `window.okxwallet.tronLink`. */
|
|
4
|
+
export const okx: TronWalletWrapper = {
|
|
5
|
+
id: 'okx',
|
|
6
|
+
displayName: 'OKX Wallet',
|
|
7
|
+
resolveProvider() {
|
|
8
|
+
return readWindowPath(['okxwallet', 'tronLink'])
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { TronWalletId } from '@meshconnect/uwc-types'
|
|
2
|
+
import type { TronWalletWrapper } from './base'
|
|
3
|
+
import { tronlink } from './tronlink'
|
|
4
|
+
import { okx } from './okx'
|
|
5
|
+
import { trust } from './trust'
|
|
6
|
+
import { bitget } from './bitget'
|
|
7
|
+
import { tokenpocket } from './tokenpocket'
|
|
8
|
+
|
|
9
|
+
export type { TronWalletId } from '@meshconnect/uwc-types'
|
|
10
|
+
|
|
11
|
+
/** All supported wallet wrappers, keyed by id. */
|
|
12
|
+
export const TRON_WALLET_REGISTRY: Record<TronWalletId, TronWalletWrapper> = {
|
|
13
|
+
tronlink,
|
|
14
|
+
bitget,
|
|
15
|
+
okx,
|
|
16
|
+
tokenpocket,
|
|
17
|
+
trust
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const ALL_TRON_WALLET_IDS: readonly TronWalletId[] = Object.freeze(
|
|
21
|
+
Object.keys(TRON_WALLET_REGISTRY) as TronWalletId[]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
export function isTronWalletId(value: string): value is TronWalletId {
|
|
25
|
+
return (ALL_TRON_WALLET_IDS as readonly string[]).includes(value)
|
|
26
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readWindowPath, type TronWalletWrapper } from './base'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TokenPocket — injects at `window.tokenpocket`, exposing its Tron provider at
|
|
5
|
+
* `window.tokenpocket.tron`. We target that nested path specifically rather
|
|
6
|
+
* than the shared `window.tronLink` global TokenPocket also populates, so it is
|
|
7
|
+
* never mis-detected as TronLink.
|
|
8
|
+
*/
|
|
9
|
+
export const tokenpocket: TronWalletWrapper = {
|
|
10
|
+
id: 'tokenpocket',
|
|
11
|
+
displayName: 'TokenPocket',
|
|
12
|
+
resolveProvider() {
|
|
13
|
+
return readWindowPath(['tokenpocket', 'tron'])
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf, type TronWalletWrapper } from './base'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TronLink — `window.tronLink` (legacy) or `window.tron` (TIP-1193).
|
|
5
|
+
* The only target wallet that announces readiness, via the
|
|
6
|
+
* `tronLink#initialized` window event.
|
|
7
|
+
*/
|
|
8
|
+
export const tronlink: TronWalletWrapper = {
|
|
9
|
+
id: 'tronlink',
|
|
10
|
+
displayName: 'TronLink',
|
|
11
|
+
readyEventName: 'tronLink#initialized',
|
|
12
|
+
resolveProvider() {
|
|
13
|
+
return firstReadyOf(readWindowPath(['tronLink']), readWindowPath(['tron']))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { readWindowPath, firstReadyOf, type TronWalletWrapper } from './base'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trust Wallet — TronLink-compatible provider. The repo's existing wallet
|
|
5
|
+
* metadata uses `window.trustWallet.tronLink` (capital W), so we prefer that,
|
|
6
|
+
* then the all-lowercase `window.trustwallet.tronLink` that some extension
|
|
7
|
+
* versions expose, to avoid casing-related false negatives.
|
|
8
|
+
*/
|
|
9
|
+
export const trust: TronWalletWrapper = {
|
|
10
|
+
id: 'trust',
|
|
11
|
+
displayName: 'Trust Wallet',
|
|
12
|
+
resolveProvider() {
|
|
13
|
+
return firstReadyOf(
|
|
14
|
+
readWindowPath(['trustWallet', 'tronLink']),
|
|
15
|
+
readWindowPath(['trustwallet', 'tronLink'])
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
}
|