@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.
Files changed (80) hide show
  1. package/dist/events/state-machine.d.ts +26 -0
  2. package/dist/events/state-machine.d.ts.map +1 -0
  3. package/dist/events/state-machine.js +21 -0
  4. package/dist/events/state-machine.js.map +1 -0
  5. package/dist/index.d.ts +7 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/rest/abi.d.ts +23 -0
  10. package/dist/rest/abi.d.ts.map +1 -0
  11. package/dist/rest/abi.js +28 -0
  12. package/dist/rest/abi.js.map +1 -0
  13. package/dist/rest/address.d.ts +45 -0
  14. package/dist/rest/address.d.ts.map +1 -0
  15. package/dist/rest/address.js +124 -0
  16. package/dist/rest/address.js.map +1 -0
  17. package/dist/rest/trongrid-client.d.ts +57 -0
  18. package/dist/rest/trongrid-client.d.ts.map +1 -0
  19. package/dist/rest/trongrid-client.js +133 -0
  20. package/dist/rest/trongrid-client.js.map +1 -0
  21. package/dist/shared/error-utils.d.ts +9 -0
  22. package/dist/shared/error-utils.d.ts.map +1 -0
  23. package/dist/shared/error-utils.js +52 -0
  24. package/dist/shared/error-utils.js.map +1 -0
  25. package/dist/tron-connector.d.ts +85 -0
  26. package/dist/tron-connector.d.ts.map +1 -0
  27. package/dist/tron-connector.js +456 -0
  28. package/dist/tron-connector.js.map +1 -0
  29. package/dist/types.d.ts +8 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +2 -0
  32. package/dist/types.js.map +1 -0
  33. package/dist/wallets/base.d.ts +87 -0
  34. package/dist/wallets/base.d.ts.map +1 -0
  35. package/dist/wallets/base.js +118 -0
  36. package/dist/wallets/base.js.map +1 -0
  37. package/dist/wallets/bitget.d.ts +8 -0
  38. package/dist/wallets/bitget.d.ts.map +1 -0
  39. package/dist/wallets/bitget.js +14 -0
  40. package/dist/wallets/bitget.js.map +1 -0
  41. package/dist/wallets/okx.d.ts +4 -0
  42. package/dist/wallets/okx.d.ts.map +1 -0
  43. package/dist/wallets/okx.js +10 -0
  44. package/dist/wallets/okx.js.map +1 -0
  45. package/dist/wallets/registry.d.ts +8 -0
  46. package/dist/wallets/registry.d.ts.map +1 -0
  47. package/dist/wallets/registry.js +18 -0
  48. package/dist/wallets/registry.js.map +1 -0
  49. package/dist/wallets/tokenpocket.d.ts +9 -0
  50. package/dist/wallets/tokenpocket.d.ts.map +1 -0
  51. package/dist/wallets/tokenpocket.js +15 -0
  52. package/dist/wallets/tokenpocket.js.map +1 -0
  53. package/dist/wallets/tronlink.d.ts +8 -0
  54. package/dist/wallets/tronlink.d.ts.map +1 -0
  55. package/dist/wallets/tronlink.js +15 -0
  56. package/dist/wallets/tronlink.js.map +1 -0
  57. package/dist/wallets/trust.d.ts +9 -0
  58. package/dist/wallets/trust.d.ts.map +1 -0
  59. package/dist/wallets/trust.js +15 -0
  60. package/dist/wallets/trust.js.map +1 -0
  61. package/package.json +34 -0
  62. package/src/events/state-machine.ts +44 -0
  63. package/src/index.ts +17 -0
  64. package/src/rest/abi.test.ts +25 -0
  65. package/src/rest/abi.ts +33 -0
  66. package/src/rest/address.test.ts +55 -0
  67. package/src/rest/address.ts +140 -0
  68. package/src/rest/trongrid-client.test.ts +169 -0
  69. package/src/rest/trongrid-client.ts +205 -0
  70. package/src/shared/error-utils.ts +60 -0
  71. package/src/tron-connector.test.ts +612 -0
  72. package/src/tron-connector.ts +568 -0
  73. package/src/types.ts +11 -0
  74. package/src/wallets/base.ts +184 -0
  75. package/src/wallets/bitget.ts +17 -0
  76. package/src/wallets/okx.ts +10 -0
  77. package/src/wallets/registry.ts +26 -0
  78. package/src/wallets/tokenpocket.ts +15 -0
  79. package/src/wallets/tronlink.ts +15 -0
  80. 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
+ }