diff --git a/apps/recovery-relay/components/WithdrawModal/CreateTransaction/index.tsx b/apps/recovery-relay/components/WithdrawModal/CreateTransaction/index.tsx
index 08ab9852..ccf7990b 100644
--- a/apps/recovery-relay/components/WithdrawModal/CreateTransaction/index.tsx
+++ b/apps/recovery-relay/components/WithdrawModal/CreateTransaction/index.tsx
@@ -428,7 +428,7 @@ export const CreateTransaction = ({ asset, inboundRelayParams, setSignTxResponse
theme.palette.error.main}>
Insufficient balance for transaction
- ) : prepareQuery.data?.insufficientFeeBalance === true && prepareQuery.data?.insufficientBalance !== true ? (
+ ) : prepareQuery.data?.insufficientBalanceForTokenTransfer === true && prepareQuery.data?.insufficientBalance !== true ? (
theme.palette.error.main}>
Insufficient fee asset balance for token transaction
@@ -445,8 +445,8 @@ export const CreateTransaction = ({ asset, inboundRelayParams, setSignTxResponse
prepareQuery.data?.insufficientBalance !== undefined &&
prepareQuery.data.insufficientBalance) ||
(prepareQuery.data &&
- prepareQuery.data?.insufficientFeeBalance !== undefined &&
- prepareQuery.data.insufficientFeeBalance)
+ prepareQuery.data?.insufficientBalanceForTokenTransfer !== undefined &&
+ prepareQuery.data.insufficientBalanceForTokenTransfer)
}
>
Prepare Transaction
diff --git a/apps/recovery-relay/lib/wallets/Jetton/index.ts b/apps/recovery-relay/lib/wallets/Jetton/index.ts
index 24895532..63773500 100644
--- a/apps/recovery-relay/lib/wallets/Jetton/index.ts
+++ b/apps/recovery-relay/lib/wallets/Jetton/index.ts
@@ -1,6 +1,6 @@
import { Ton as BaseTon } from '@fireblocks/wallet-derivation';
import { JettonMaster, TonClient, WalletContractV4 } from '@ton/ton';
-import { Address, beginCell, Cell, fromNano, toNano } from '@ton/core';
+import { Address, beginCell, Cell, toNano } from '@ton/core';
import { AccountData } from '../types';
import { defaultTonWalletV4R2code } from '../TON/tonParams';
import axios from 'axios';
@@ -28,7 +28,7 @@ export class Jetton extends BaseTon implements LateInitConnectedWallet {
}
public getLateInitLabel(): string {
- return 'Ton client wallet';
+ return 'Ton wallet client';
}
public setRPCUrl(url: string): void {
@@ -136,7 +136,7 @@ export class Jetton extends BaseTon implements LateInitConnectedWallet {
feeRate,
extraParams,
insufficientBalance: jettonBalance <= 0,
- insufficientFeeBalance: tonBalance < feeRate,
+ insufficientBalanceForTokenTransfer: tonBalance < feeRate,
} as AccountData;
return preperedData;
diff --git a/apps/recovery-relay/lib/wallets/index.ts b/apps/recovery-relay/lib/wallets/index.ts
index e29ad57e..4d13eedf 100644
--- a/apps/recovery-relay/lib/wallets/index.ts
+++ b/apps/recovery-relay/lib/wallets/index.ts
@@ -1,3 +1,4 @@
+import { getAllJettons } from '@fireblocks/asset-config';
import { Cardano } from './ADA';
import { Cosmos } from './ATOM';
import { Bitcoin, BitcoinCash, BitcoinSV, DASH, DogeCoin, LiteCoin, ZCash } from './BTCBased';
@@ -40,6 +41,19 @@ import { Ton } from './TON';
import { Jetton } from './Jetton';
export { ConnectedWallet } from './ConnectedWallet';
+const fillJettons = () => {
+ const jettonsList = getAllJettons();
+ const jettons = jettonsList.reduce(
+ (prev, curr) => ({
+ ...prev,
+ [curr]: Jetton,
+ }),
+ {},
+ ) as any;
+ Object.keys(jettons).forEach((key) => (jettons[key] === undefined ? delete jettons[key] : {}));
+ return jettons;
+};
+
export const WalletClasses = {
ALGO: Algorand,
ALGO_TEST: Algorand,
@@ -122,9 +136,7 @@ export const WalletClasses = {
CELESTIA_TEST: Celestia,
TON: Ton,
TON_TEST: Ton,
- USDT_TON: Jetton,
- NOTCOIN_TON: Jetton,
- DOGS_TON: Jetton,
+ ...fillJettons(),
} as const;
type WalletClass = (typeof WalletClasses)[keyof typeof WalletClasses];
diff --git a/apps/recovery-relay/lib/wallets/types.ts b/apps/recovery-relay/lib/wallets/types.ts
index 2afd0cef..9ada6b11 100644
--- a/apps/recovery-relay/lib/wallets/types.ts
+++ b/apps/recovery-relay/lib/wallets/types.ts
@@ -28,7 +28,7 @@ export type AccountData = {
extraParams?: Map;
endpoint?: string;
insufficientBalance?: boolean;
- insufficientFeeBalance?: boolean;
+ insufficientBalanceForTokenTransfer?: boolean;
};
export type TxPayload = {
diff --git a/apps/recovery-utility/renderer/components/Modals/WithdrawModal/SignTransaction/index.tsx b/apps/recovery-utility/renderer/components/Modals/WithdrawModal/SignTransaction/index.tsx
index cd2e1077..0c70b7a0 100644
--- a/apps/recovery-utility/renderer/components/Modals/WithdrawModal/SignTransaction/index.tsx
+++ b/apps/recovery-utility/renderer/components/Modals/WithdrawModal/SignTransaction/index.tsx
@@ -12,6 +12,7 @@ import {
getLogger,
sanatize,
useWrappedState,
+ getDerivationMapKey,
} from '@fireblocks/recovery-shared';
import { AssetConfig } from '@fireblocks/asset-config';
import { CallMade, CallReceived, LeakAdd, Toll } from '@mui/icons-material';
@@ -75,7 +76,7 @@ export const SignTransaction = ({ txId, account, asset, inboundRelayParams }: Pr
const derivation = account.wallets
.get(asset.id)
- ?.derivations.get(`${inboundRelayParams?.unsignedTx.assetId}-${inboundRelayParams?.unsignedTx.from}`);
+ ?.derivations.get(getDerivationMapKey(inboundRelayParams?.unsignedTx.assetId, inboundRelayParams?.unsignedTx.from));
if (!derivation) {
throw new Error('Derivation not found');
diff --git a/apps/recovery-utility/renderer/context/Workspace.tsx b/apps/recovery-utility/renderer/context/Workspace.tsx
index f901a940..b33dbae8 100644
--- a/apps/recovery-utility/renderer/context/Workspace.tsx
+++ b/apps/recovery-utility/renderer/context/Workspace.tsx
@@ -68,8 +68,9 @@ export const WorkspaceProvider = ({ children }: Props) => {
deriveWallet: (input) => {
let transferableToken = false;
const config = getAssetConfig(input.assetId);
- if (config?.address && isTransferableToken(input.assetId)) {
+ if (isTransferableToken(input.assetId)) {
transferableToken = true;
+ logger.info('Found a transferable token:', input.assetId);
}
const nativeAssetId = (
transferableToken ? input.assetId : config?.nativeAsset ?? input.assetId
diff --git a/apps/recovery-utility/renderer/lib/wallets/Jetton/index.ts b/apps/recovery-utility/renderer/lib/wallets/Jetton/index.ts
index 4328439d..71b22c9e 100644
--- a/apps/recovery-utility/renderer/lib/wallets/Jetton/index.ts
+++ b/apps/recovery-utility/renderer/lib/wallets/Jetton/index.ts
@@ -14,7 +14,7 @@ export class Jetton extends BaseTon implements SigningWallet {
throw new Error('Jetton: Missing jetton parameters');
}
- const JettonTransferOpcode = 0x0f8a7ea5;
+ const jettonTransferOpcode = 0x0f8a7ea5;
const decimals = extraParams?.get('decimals');
const normalizingFactor = 10 ** decimals;
const amountToWithdraw = amount * normalizingFactor; // amount is the wallet balance
@@ -22,7 +22,7 @@ export class Jetton extends BaseTon implements SigningWallet {
let internalMessageMemo = undefined;
// create the tx payload
const internalMessageBody = beginCell()
- .storeUint(JettonTransferOpcode, 32) // opcode for jetton transfer
+ .storeUint(jettonTransferOpcode, 32) // opcode for jetton transfer
.storeUint(0, 64) // query id
.storeCoins(amountToWithdraw) // jetton balance
.storeAddress(Address.parse(to)) // tx destination
diff --git a/apps/recovery-utility/renderer/lib/wallets/index.ts b/apps/recovery-utility/renderer/lib/wallets/index.ts
index 9ee11d4f..c33e0125 100644
--- a/apps/recovery-utility/renderer/lib/wallets/index.ts
+++ b/apps/recovery-utility/renderer/lib/wallets/index.ts
@@ -1,5 +1,5 @@
// import { Bitcoin } from './BTC';
-import { assets } from '@fireblocks/asset-config';
+import { assets, getAllJettons } from '@fireblocks/asset-config';
import { ERC20, ETC } from '@fireblocks/wallet-derivation';
import { Ripple } from './XRP';
import { Cosmos } from './ATOM';
@@ -41,14 +41,11 @@ const fillEVMs = () => {
};
const fillJettons = () => {
- const jettons = Object.keys(assets).reduce(
- (o, assetId) => ({
- ...o,
- [assets[assetId].id]: assets[assetId].protocol === 'TON' && assets[assetId].address ? Jetton : undefined,
- }),
- {},
- ) as any;
- Object.keys(jettons).forEach((key) => (jettons[key] === undefined ? delete jettons[key] : {}));
+ const jettonsList = getAllJettons();
+ const jettons: { [key: string]: any } = {};
+ for (const jetton of jettonsList) {
+ jettons[jetton] = Jetton;
+ }
return jettons;
};
@@ -111,9 +108,6 @@ export const WalletClasses = {
HBAR_TEST: Hedera,
TON: Ton,
TON_TEST: Ton,
- // USDT_TON: Jetton,
- // NOTCOIN_TON: Jetton,
- // DOGS_TON: Jetton,
...fillJettons(),
...fillEVMs(),
diff --git a/packages/asset-config/README.md b/packages/asset-config/README.md
index af6ddfbe..883aee2e 100644
--- a/packages/asset-config/README.md
+++ b/packages/asset-config/README.md
@@ -50,6 +50,11 @@ For your convinience we have provided base methods for common types of chains:
- `evm(baseExplorerUrl: string, rpcUrl?: string)` to create a basic EVM chain, simply provide the `baseExplorerUrl` (the URL of an explorer) and optionally `rpcUrl` as the URL of the RPC to communicate with
- `btc(baseExplorerUrl: string, segwit: boolean)` to create a basic BTC chain (ZCash, LTC, etc are all considered such) simply provide the `baseExplorerUrl` (the URL of an explorer) and optionally `segwit` should be false, as only BTC is relevant for this field
+### Add a new Jetton token
+
+To add support for withdrawals of a listed Jetton, make sure the token is listed in [globalAssets](/Users/tomerhorviz/Documents/recovery/packages/asset-config/data/globalAssets.ts) and in [patches](packages/asset-config/config/patches.ts).
+The Jetton master contract address must be present in the 'globalAssets' list as the 'address' parameter.
+
### Token or new Base Asset Support
In case a token has bad data, alternatively a token is missing or you want to add a new base asset, it can be added by performing the following steps:
diff --git a/packages/asset-config/assets.ts b/packages/asset-config/assets.ts
index 584c44b1..9f377548 100644
--- a/packages/asset-config/assets.ts
+++ b/packages/asset-config/assets.ts
@@ -12,3 +12,13 @@ export const assets = globalAssets.reduce(
}),
{},
);
+
+export function getAllJettons(): string[] {
+ const jettons = [];
+ for (const asset of globalAssets) {
+ if (asset.protocol === 'TON' && asset.address) {
+ jettons.push(asset.id);
+ }
+ }
+ return jettons;
+}
diff --git a/packages/asset-config/index.ts b/packages/asset-config/index.ts
index 7c0e0a5a..06c48055 100644
--- a/packages/asset-config/index.ts
+++ b/packages/asset-config/index.ts
@@ -1,10 +1,10 @@
import { orderId, orderAssetById } from './config/sort';
import { isNativeAssetId, isDerivableAssetId, isTestnetAsset } from './util';
-import { assets } from './assets';
+import { assets, getAllJettons } from './assets';
export { getAssetConfig, getNativeAssetConfig, getDerivableAssetConfig, isExplorerUrl } from './util';
-export { assets };
+export { assets, getAllJettons };
export type * from './types';