Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,16 @@
"count": 2
}
},
"packages/tron-wallet-snap/src/services/assets/AssetsRepository.ts": {
"import-x/no-extraneous-dependencies": {
"count": 1
}
},
"packages/tron-wallet-snap/src/services/assets/AssetsService.ts": {
"import-x/no-extraneous-dependencies": {
"count": 2
}
},
"packages/tron-wallet-snap/src/services/assets/AssetsService.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
Expand Down
54 changes: 10 additions & 44 deletions packages/tron-wallet-snap/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- **BREAKING** Bump `@metamask/keyring-api` from `^23.7.0` to `^24.1.0` ([#214](https://github.com/MetaMask/internal-snaps/pull/214))
- **BREAKING** Bump `@metamask/keyring-snap-sdk` from `^9.2.1` to `^10.0.0` ([#214](https://github.com/MetaMask/internal-snaps/pull/214))
- **BREAKING** Bump `@metamask/snaps-sdk` from `^11.2.0` to `^12.0.1` ([#214](https://github.com/MetaMask/internal-snaps/pull/214))

## [3.2.0]

### Added

- Use Core's `AssetsController` as the source of truth for fungible assets when the Tron assets migration feature flag is enabled ([#145](https://github.com/MetaMask/internal-snaps/pull/145))
- **BREAKING** Implement Keyring API v2 (`KeyringSnapRpc` interface): rename `listAccounts` → `getAccounts`, `listAccountAssets` → `getAccountAssets`, `listAccountTransactions` → `getAccountTransactions`; `getAccount` now throws instead of returning `undefined`; add `exportAccount` with hexadecimal private key export using `sensitive()` for redaction; remove v1-only methods `createAccount`, `discoverAccounts`, `filterAccountChains`, and `updateAccount`. ([#56](https://github.com/MetaMask/internal-snaps/pull/56))
- Add `bip44:discover` support to `createAccounts`: checks on-chain activity across all Tron networks before persisting; returns `[]` if no activity to signal end-of-discovery to the client. ([#56](https://github.com/MetaMask/internal-snaps/pull/56))
- Add `endowment:keyring` capabilities to manifest declaring the `tron:728126428` scope, hexadecimal private key export, and BIP-44 derivation strategies. ([#56](https://github.com/MetaMask/internal-snaps/pull/56))
- Wire Core messenger endowment and instantiate `RemoteFeatureFlagsProvider` and `AssetsProvider` from `@metamask/snap-networks-utils` v1.0.0 (plumbing only; no Core routing yet).
- Route fungible asset reads through the shared `AssetsProvider` from `@metamask/snap-networks-utils` using account-scoped `AssetsController:getAccountAssetByID`, `AssetsController:getAccountAssetsByIDs`, and `AssetsController:getAccountAssetsByScope` actions based on migration stage (TRX, TRC10, TRC20). Protocol assets (energy, bandwidth, staking, lock/withdrawal, rewards) remain Snap-owned. Resolution order: remote feature flags → Off default.

### Changed

- Reduce BIP-44 account discovery to a single entropy fetch by reusing the coin-type deriver for the on-chain activity check ([#149](https://github.com/MetaMask/internal-snaps/pull/149))
- Reduce extension RPC round trips in `keyring_createAccounts` from 5 to at most 4 ([#149](https://github.com/MetaMask/internal-snaps/pull/149))
- `mergeKeyringAccounts` now returns the merge result instead of requiring a post-merge state re-read, and the existing-accounts read runs in parallel with the BIP-32 entropy fetch.
- `snap_getBip32Entropy` is now called even when all requested indices already exist (this path only occurs on idempotent retries); no new permissions are required.

### Fixed

- Fix account deletion failing against keyring v2 clients by removing the `AccountDeleted` event emission from `keyring_deleteAccount` ([#149](https://github.com/MetaMask/internal-snaps/pull/149))
- v2 clients reject v1 lifecycle events, which aborted the deletion before the account was removed from state. Deletion is client-initiated in v2, so no event is needed.
- Coalesce concurrent account synchronization runs for the same accounts so stacked triggers (cronjob and background events) share one run instead of duplicating network fetches, state writes, and keyring events ([#149](https://github.com/MetaMask/internal-snaps/pull/149))
- Bump `@metamask/utils` from `^11.9.0` to `^11.11.9` ([#161](https://github.com/MetaMask/internal-snaps/pull/161))
- Estimate native TRX/TRC-10 sends that activate a new account as 1 TRX plus 100 Bandwidth (or 0.1 TRX when staked Bandwidth is insufficient), instead of TransferContract byte size ([#175](https://github.com/MetaMask/internal-snaps/pull/175))
- Fix SUN → USDT swaps routed through Rango and SunSwap displaying a zero SUN amount in transaction activity ([#134](https://github.com/MetaMask/internal-snaps/pull/134))

## [3.1.0]

### Added

- Add Core messenger plumbing (`coreMessenger`, `RemoteFeatureFlagsProvider`, `AssetsProvider`) for upcoming AssetsController migration ([#95](https://github.com/MetaMask/internal-snaps/pull/95))

### Fixed

- Scope `bip44:discover` activity checks and account creation to the networks declared in the snap manifest, preventing unnecessary calls to testnet APIs during discovery ([#135](https://github.com/MetaMask/internal-snaps/pull/135))

## [3.0.0]

### Added

- **BREAKING** Implement Keyring API v2 (`KeyringSnapRpc` interface) ([#56](https://github.com/MetaMask/internal-snaps/pull/56), [#101](https://github.com/MetaMask/internal-snaps/pull/101), [#105](https://github.com/MetaMask/internal-snaps/pull/105))
- Move assets handler logic (metadata, conversions, market data, historical prices) into `AssetsService`; slim `SnapAssetsAdapter` to snap-owned fetch/save/read only. Cron asset sync uses `syncSnapOwnedAssets` for protocol assets.
- Update `snap.manifest.json` bundle shasum ([#82](https://github.com/MetaMask/internal-snaps/pull/82))

### Fixed
### Removed

- Disclose the mandatory 9999 TRX `WitnessCreateContract` account-upgrade burn on confirmation ([#73](https://github.com/MetaMask/internal-snaps/pull/73))
- Assets migration feature-flag routing. Fungible reads (`getAccountAssetByID`, `getAccountAssetsByIDs`, `getAccountAssetsByScope`) now always use Core `AssetsController` via `AssetsProvider`; snap-owned protocol assets remain on the Snap adapter. Removed `RemoteFeatureFlagController:getState` messenger endowment.

## [2.0.0]

Expand All @@ -67,8 +36,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump `@metamask/snaps-sdk` from `^11.1.1` to `^11.2.0` ([#43](https://github.com/MetaMask/internal-snaps/pull/43))
- Bump `@metamask/superstruct` from `^3.2.1` to `^3.4.1` ([#43](https://github.com/MetaMask/internal-snaps/pull/43))

[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/tron-wallet-snap@3.2.0...HEAD
[3.2.0]: https://github.com/MetaMask/internal-snaps/compare/@metamask/tron-wallet-snap@3.1.0...@metamask/tron-wallet-snap@3.2.0
[3.1.0]: https://github.com/MetaMask/internal-snaps/compare/@metamask/tron-wallet-snap@3.0.0...@metamask/tron-wallet-snap@3.1.0
[3.0.0]: https://github.com/MetaMask/internal-snaps/compare/@metamask/tron-wallet-snap@2.0.0...@metamask/tron-wallet-snap@3.0.0
[Unreleased]: https://github.com/MetaMask/internal-snaps/compare/@metamask/tron-wallet-snap@2.0.0...HEAD
[2.0.0]: https://github.com/MetaMask/internal-snaps/releases/tag/@metamask/tron-wallet-snap@2.0.0
24 changes: 4 additions & 20 deletions packages/tron-wallet-snap/snap.manifest.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"version": "3.2.0",
"version": "2.0.0",
"description": "Manage Tron using MetaMask",
"proposedName": "Tron",
"repository": {
"type": "git",
"url": "https://github.com/MetaMask/internal-snaps.git"
},
"source": {
"shasum": "QnhXo3QTBC3XgD/9FKIEjyoSnVdVtZ3uGansykUe9uc=",
"shasum": "ac/9ewd8ZZXTLl5K5ZMg5PSsUeITzUwYtvfHPNjKQu4=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -23,22 +23,7 @@
},
"initialPermissions": {
"endowment:keyring": {
"allowedOrigins": ["https://portfolio.metamask.io"],
"capabilities": {
"scopes": ["tron:728126428"],
"privateKey": {
"exportFormats": [
{
"encoding": "hexadecimal"
}
]
},
"bip44": {
"deriveIndex": true,
"deriveIndexRange": true,
"discover": true
}
}
"allowedOrigins": ["https://portfolio.metamask.io"]
},
"snap_getBip32Entropy": [
{
Expand Down Expand Up @@ -66,13 +51,12 @@
},
"endowment:messenger": {
"actions": [
"RemoteFeatureFlagController:getState",
"AssetsController:getAccountAssetByID",
"AssetsController:getAccountAssetsByIDs",
"AssetsController:getAccountAssetsByScope"
]
}
},
"platformVersion": "12.0.1",
"platformVersion": "11.2.0",
"manifestVersion": "0.1"
}
68 changes: 8 additions & 60 deletions packages/tron-wallet-snap/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import {
AssetsProvider,
RemoteFeatureFlagsProvider,
} from '@metamask/snap-networks-utils';
import type {
AssetsProviderMessenger,
RemoteFeatureFlagsProviderMessenger,
} from '@metamask/snap-networks-utils';
import { AssetsProvider } from '@metamask/snap-networks-utils';
import type { AssetsProviderMessenger } from '@metamask/snap-networks-utils';
import { getMessenger } from '@metamask/snaps-sdk';

import { InMemoryCache } from './caching/InMemoryCache';
import { StateCache } from './caching/StateCache';
import { PriceApiClient } from './clients/price-api/PriceApiClient';
import { SecurityAlertsApiClient } from './clients/security-alerts-api/SecurityAlertsApiClient';
import { SnapClient } from './clients/snap/SnapClient';
import { TokenApiClient } from './clients/token-api/TokenApiClient';
import { TronHttpClient } from './clients/tron-http/TronHttpClient';
import { TrongridApiClient } from './clients/trongrid/TrongridApiClient';
import { TronWebFactory } from './clients/tronweb/TronWebFactory';
Expand All @@ -27,8 +20,6 @@ import { AccountsRepository } from './services/accounts/AccountsRepository';
import { AccountsService } from './services/accounts/AccountsService';
import { CoreAssetsAdapter } from './services/assets/adapters/CoreAssetsAdapter';
import { SnapAssetsAdapter } from './services/assets/adapters/SnapAssetsAdapter';
import { AssetsRepository } from './services/assets/AssetsRepository';
import { AssetsService } from './services/assets/AssetsService';
import { ConfigProvider } from './services/config';
import { ConfirmationHandler } from './services/confirmation/ConfirmationHandler';
import { FeeCalculatorService } from './services/send/FeeCalculatorService';
Expand All @@ -52,8 +43,8 @@ import logger, { noOpLogger } from './utils/logger';
*
* Dependency injection order:
* 1. Core services (ConfigProvider, State, Connection)
* 2. Repositories (AssetsRepository, TransactionsRepository, AccountsRepository)
* 3. Business services (AssetsService, TransactionsService, AccountsService)
* 2. Repositories (TransactionsRepository, AccountsRepository)
* 3. Business services (TransactionsService, AccountsService)
* 4. Handlers (AssetsHandler, CronHandler, KeyringHandler, RpcHandler, UserInputHandler)
*/
export const configProvider = new ConfigProvider();
Expand All @@ -62,7 +53,6 @@ const state = new State({
encrypted: false,
defaultState: {
keyringAccounts: {},
assets: {},
tokenPrices: {},
transactions: {},
mapInterfaceNameToId: {},
Expand All @@ -73,7 +63,6 @@ const snapClient = new SnapClient({ logger });

// Repositories - depend on State
const accountsRepository = new AccountsRepository(state);
const assetsRepository = new AssetsRepository(state);
const transactionsRepository = new TransactionsRepository(state);

// Clients
Expand All @@ -95,16 +84,10 @@ const tronWebFactory = new TronWebFactory({
const priceCache = new InMemoryCache(noOpLogger);
const priceApiClient = new PriceApiClient(configProvider, priceCache);

// Token API client
const tokenApiClient = new TokenApiClient(configProvider);

/**
* Core controllers plumbing
*/
const coreMessenger = getMessenger<CoreMessenger>();
const remoteFeatureFlagsProvider = new RemoteFeatureFlagsProvider({
messenger: coreMessenger as RemoteFeatureFlagsProviderMessenger,
});
const assetsProvider = new AssetsProvider({
messenger: coreMessenger as AssetsProviderMessenger,
});
Expand All @@ -115,36 +98,6 @@ const securityAlertsApiClient = new SecurityAlertsApiClient(
logger,
);

const snapAssetsAdapter = new SnapAssetsAdapter({
logger,
state,
assetsRepository,
trongridApiClient,
tronHttpClient,
priceApiClient,
tokenApiClient,
snapClient,
configProvider,
});
const coreAssetsAdapter = new CoreAssetsAdapter({
getAccountAssetByID: assetsProvider.getAccountAssetByID.bind(assetsProvider),
getAccountAssetsByIDs:
assetsProvider.getAccountAssetsByIDs.bind(assetsProvider),
getAccountAssetsByScope:
assetsProvider.getAccountAssetsByScope.bind(assetsProvider),
getAddressInfo:
trongridApiClient.getAccountInfoByAddress.bind(trongridApiClient),
getAddressResources: tronHttpClient.getAccountResources.bind(tronHttpClient),
getAddressStakingRewards: tronHttpClient.getReward.bind(tronHttpClient),
});

// Business Services
const assetsService = new AssetsService({
snapAdapter: snapAssetsAdapter,
coreAdapter: coreAssetsAdapter,
remoteFeatureFlagsProvider,
});

const transactionsService = new TransactionsService({
logger,
transactionsRepository,
Expand All @@ -159,7 +112,6 @@ const accountsService = new AccountsService({
snapClient,
accountsRepository,
configProvider,
assetsService,
transactionsService,
});

Expand All @@ -179,7 +131,7 @@ const sendService = new SendService({
logger,
snapClient,
accountsService,
assetsService,
assetsProvider,
tronWebFactory,
feeCalculatorService,
transactionExpirationRefresherService,
Expand Down Expand Up @@ -208,7 +160,7 @@ const confirmationHandler = new ConfirmationHandler({
snapClient,
state,
tronWebFactory,
assetsService,
assetsProvider,
feeCalculatorService,
logger,
});
Expand All @@ -218,13 +170,13 @@ const confirmationHandler = new ConfirmationHandler({
*/
const assetsHandler = new AssetsHandler({
logger,
assetsService,
assetsProvider,
});
const clientRequestHandler = new ClientRequestHandler({
logger,
snapClient,
accountsService,
assetsService,
assetsProvider,
sendService,
tronWebFactory,
feeCalculatorService,
Expand Down Expand Up @@ -271,7 +223,6 @@ export type SnapExecutionContext = {
state: State<UnencryptedStateValue>;
priceApiClient: PriceApiClient;
feeCalculatorService: FeeCalculatorService;
assetsService: AssetsService;
accountsService: AccountsService;
transactionsService: TransactionsService;
sendService: SendService;
Expand All @@ -285,7 +236,6 @@ export type SnapExecutionContext = {
* Core messenger plumbing.
*/
coreMessenger: CoreMessengerClient;
remoteFeatureFlagsProvider: RemoteFeatureFlagsProvider;
assetsProvider: AssetsProvider;
/**
* Handlers
Expand All @@ -309,7 +259,6 @@ const snapContext: SnapExecutionContext = {
state,
priceApiClient,
feeCalculatorService,
assetsService,
accountsService,
transactionsService,
sendService,
Expand All @@ -320,7 +269,6 @@ const snapContext: SnapExecutionContext = {
transactionScanService,
transactionExpirationRefresherService,
coreMessenger,
remoteFeatureFlagsProvider,
assetsProvider,
/**
* Handlers
Expand Down
18 changes: 9 additions & 9 deletions packages/tron-wallet-snap/src/handlers/assets/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ import type {
OnAssetsMarketDataResponse,
} from '@metamask/snaps-sdk';

import type { AssetsService } from '../../services/assets/AssetsService';
import type { PriceApiClient } from '../../clients/price-api/PriceApiClient';

export class AssetsHandler {
readonly #logger: Logger;

readonly #assetsService: AssetsService;
readonly #priceApiClient: PriceApiClient;

constructor({
logger,
assetsService,
priceApiClient,
}: {
logger: Logger;
assetsService: AssetsService;
priceApiClient: PriceApiClient;
}) {
this.#logger = logger.withPrefix('[🪙 AssetsHandler]');
this.#assetsService = assetsService;
this.#priceApiClient = priceApiClient;
}

async onAssetHistoricalPrice(
Expand All @@ -35,7 +35,7 @@ export class AssetsHandler {

const { from, to } = params;

const historicalPrice = await this.#assetsService.getHistoricalPrice(
const historicalPrice = await this.#priceApiClient.getHistoricalPrice(
from,
to,
);
Expand All @@ -53,7 +53,7 @@ export class AssetsHandler {
const { conversions } = params;

const conversionRates =
await this.#assetsService.getMultipleTokenConversions(conversions);
await this.#priceApiClient.getMultipleTokenConversions(conversions);

return {
conversionRates,
Expand All @@ -63,15 +63,15 @@ export class AssetsHandler {
async onAssetsLookup(
params: OnAssetsLookupArguments,
): Promise<OnAssetsLookupResponse> {
const assets = await this.#assetsService.getAssetsMetadata(params.assets);
const assets = await this.#priceApiClient.getAssetsMetadata(params.assets);

return { assets };
}

async onAssetsMarketData(
params: OnAssetsMarketDataArguments,
): Promise<OnAssetsMarketDataResponse> {
const marketData = await this.#assetsService.getMultipleTokensMarketData(
const marketData = await this.#priceApiClient.getMultipleTokensMarketData(
params.assets,
);

Expand Down
Loading
Loading