Skip to content

Commit

Permalink
Release/5.18.0 (#1222)
Browse files Browse the repository at this point in the history
* before we close the sign transaction window, complete metrics upload (#1209)

* Better UX for contract IDs (#1122)

* adds new component TruncateMiddle, handles dynamic truncation based on parent width

* adds font prop and tweaks operation pair to allow for width measuring

* tweaks container styles, adds use in keyval list

* adds copy to all contract IDs and keys from outside sources

* removes unused ref from previosu tries

* adds tests for truncateString helper

* fixes tests after dom changes on contract IDs

* adds copy value component, replaces inline copy instances. Uses boolean namign pattern. Only hides generic domain icon when domain is not present in asset detail

* fixes lint warnings

* uses truncated display value in KeyVal CopyValues

* Feature/multiple allow list (#1210)

* add migration for assetslist; create UI for displaying assets lists

* add translations

* adds internal getTokenDetails call, moves server and tx builder helpers to shared namespace

* replaces all inline calls to get token details with internal helper call

* replaces some instances of sorobanClient from context

* removes remaining uses of soroban client from context, remove soroban context

* adds soroban rpc not supported error

* adds sizes to error and loading asset icons to fix layout shift and align these states

* renames getIndexerTokenDetails to getTokenDetails, tweaks loading state in review auth and tweaks height setter in SlideUpModal

* Feature/check multiple tokenlist (#1221)

* first pass at adding multiple asset lists

* add verification badge

* add asset notifcation tooltip

* Added translations

* rm consoles

* update yarn

* reset debounce param

* use getTokenDetails

* fix tests

* fixes keyboard navigation for onboarding - create new wallet flow

* adds key handling for recover account form in onboarding

* adds native-like-outline mixin

* Feature/modify asset list (#1224)

* add ability to edit/delete asset lists

* Added translations

* break if unable to load schema

* add comments

* make sure to check for isEnabled when verifying (#1225)

* make sure to check for isEnabled when verifying

* don't assign the func outside of the conditional

* Feature/delete asset list modal (#1226)

* add delete asset list modal

* Added translations

* add view padding offset

* Bugfix/copy fix token list (#1227)

* copy fix for asset select token list verification

* Added translations

* fix submit error (#1228)

* default to selected network if network is verifiable (#1229)

* default to selected network if network is verifiable

* remove extraneous check

* Feature/redesign settings (#1232)

* add settings icons using svgr

* Added translations

* fix jest tests

* rollback ledger testing

* rm extra spaces

* Validate asset list on every fetch (#1234)

* Added translations

* rm console logs

* asset list UI cleanup (#1235)

* break once we found the contract in asset list (#1237)

* add a test add token asset list verification (#1236)

* address design QA (#1238)

* address design QA

* dispatch click event for createPortal button

* Bugfix/product qa 5.18.0 (#1239)

* don't reset isEnabled state; better error messaging

* add shadows to scrollable area

* Bugfix/design fixes 5.18.0 (#1240)

* add enabled/disabled sections and fix submit error

* Added translations

---------

Co-authored-by: aristides <[email protected]>
  • Loading branch information
piyalbasu and aristidesstaffieri authored Apr 23, 2024
1 parent 4fd2163 commit a733a59
Show file tree
Hide file tree
Showing 113 changed files with 3,561 additions and 1,106 deletions.
9 changes: 9 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ module.exports = {
"react/jsx-filename-extension": ["error", { extensions: [".tsx", ".jsx"] }],
"jsdoc/newline-after-description": "off",
"max-len": "off",
"no-await-in-loop": "off",
"import/no-unresolved": [
"error",
{
// Ignore Webpack query parameters, not supported by eslint-plugin-import
// https://github.com/import-js/eslint-plugin-import/issues/2562
ignore: ["\\?react$"],
},
],
},
settings: {
"import/resolver": {
Expand Down
151 changes: 140 additions & 11 deletions @shared/api/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { DataProvider } from "@stellar/wallet-sdk";
import BigNumber from "bignumber.js";
import { INDEXER_URL } from "@shared/constants/mercury";
import { AssetsListItem, AssetsLists } from "@shared/constants/soroban/token";
import {
getBalance,
getDecimals,
Expand All @@ -36,12 +37,18 @@ import {
NETWORKS,
} from "../constants/stellar";
import { SERVICE_TYPES } from "../constants/services";
import { SorobanRpcNotSupportedError } from "../constants/errors";
import { APPLICATION_STATE } from "../constants/applicationState";
import { WalletType } from "../constants/hardwareWallet";
import { sendMessageToBackground } from "./helpers/extensionMessaging";
import { getIconUrlFromIssuer } from "./helpers/getIconUrlFromIssuer";
import { getDomainFromIssuer } from "./helpers/getDomainFromIssuer";
import { stellarSdkServer, submitTx } from "./helpers/stellarSdkServer";
import { isCustomNetwork } from "@shared/helpers/stellar";
import {
buildSorobanServer,
getNewTxBuilder,
} from "@shared/helpers/soroban/server";

const TRANSACTIONS_LIMIT = 100;

Expand Down Expand Up @@ -518,13 +525,9 @@ export const getSorobanTokenBalance = async (
export const getAccountBalancesStandalone = async ({
publicKey,
networkDetails,
sorobanClientServer,
sorobanClientTxBuilder,
}: {
publicKey: string;
networkDetails: NetworkDetails;
sorobanClientServer: SorobanRpc.Server;
sorobanClientTxBuilder: () => Promise<TransactionBuilder>;
}): Promise<AccountBalancesInterface> => {
const { network, networkUrl, networkPassphrase } = networkDetails;

Expand Down Expand Up @@ -583,6 +586,12 @@ export const getAccountBalancesStandalone = async ({
const tokensWithNoBalance = [];

if (tokenIdList.length) {
if (!networkDetails.sorobanRpcUrl) {
throw new SorobanRpcNotSupportedError();
}

const server = buildSorobanServer(networkDetails.sorobanRpcUrl);

const params = [new Address(publicKey).toScVal()];

for (let i = 0; i < tokenIdList.length; i += 1) {
Expand All @@ -596,13 +605,13 @@ export const getAccountBalancesStandalone = async ({
try {
/* eslint-disable no-await-in-loop */
const { balance, symbol, ...rest } = await getSorobanTokenBalance(
sorobanClientServer,
server,
tokenId,
{
balance: await sorobanClientTxBuilder(),
name: await sorobanClientTxBuilder(),
decimals: await sorobanClientTxBuilder(),
symbol: await sorobanClientTxBuilder(),
balance: await getNewTxBuilder(publicKey, networkDetails, server),
name: await getNewTxBuilder(publicKey, networkDetails, server),
decimals: await getNewTxBuilder(publicKey, networkDetails, server),
symbol: await getNewTxBuilder(publicKey, networkDetails, server),
},
params,
);
Expand Down Expand Up @@ -687,6 +696,79 @@ export const getIndexerAccountHistory = async ({
}
};

export const getAccountHistory = async (
publicKey: string,
networkDetails: NetworkDetails,
) => {
if (isCustomNetwork(networkDetails)) {
return await getAccountHistoryStandalone({
publicKey,
networkDetails,
});
}
return await getIndexerAccountHistory({
publicKey,
networkDetails,
});
};

export const getTokenDetails = async ({
contractId,
publicKey,
networkDetails,
}: {
contractId: string;
publicKey: string;
networkDetails: NetworkDetails;
}): Promise<{ name: string; decimals: number; symbol: string } | null> => {
try {
if (isCustomNetwork(networkDetails)) {
if (!networkDetails.sorobanRpcUrl) {
throw new SorobanRpcNotSupportedError();
}

// You need one Tx Builder per call in Soroban right now
const server = buildSorobanServer(networkDetails.sorobanRpcUrl);
const name = await getName(
contractId,
server,
await getNewTxBuilder(publicKey, networkDetails, server),
);
const symbol = await getSymbol(
contractId,
server,
await getNewTxBuilder(publicKey, networkDetails, server),
);
const decimals = await getDecimals(
contractId,
server,
await getNewTxBuilder(publicKey, networkDetails, server),
);

return {
name,
symbol,
decimals,
};
}

const response = await fetch(
`${INDEXER_URL}/token-details/${contractId}?pub_key=${publicKey}&network=${networkDetails.network}`,
);
const data = await response.json();
if (!response.ok) {
throw new Error(data);
}
return data;
} catch (error) {
console.error(error);
captureException(
`Failed to fetch token details - ${JSON.stringify(error)}`,
);
return null;
}
};

export const getAssetIcons = async ({
balances,
networkDetails,
Expand Down Expand Up @@ -910,7 +992,7 @@ export const submitFreighterSorobanTransaction = async ({
}

if (!networkDetails.sorobanRpcUrl) {
throw new Error("soroban rpc not supported");
throw new SorobanRpcNotSupportedError();
}

const serverUrl = networkDetails.sorobanRpcUrl || "";
Expand Down Expand Up @@ -1162,7 +1244,9 @@ export const editCustomNetwork = async ({
return response;
};

export const loadSettings = (): Promise<Settings & IndexerSettings> =>
export const loadSettings = (): Promise<
Settings & IndexerSettings & { assetsLists: AssetsLists }
> =>
sendMessageToBackground({
type: SERVICE_TYPES.LOAD_SETTINGS,
});
Expand Down Expand Up @@ -1231,3 +1315,48 @@ export const removeTokenId = async ({
});
return resp.tokenIdList;
};

export const addAssetsList = async ({
assetsList,
network,
}: {
assetsList: AssetsListItem;
network: NETWORKS;
}) => {
let response = {
error: "",
assetsLists: {} as AssetsLists,
};

response = await sendMessageToBackground({
type: SERVICE_TYPES.ADD_ASSETS_LIST,
assetsList,
network,
});

return { assetsLists: response.assetsLists, error: response.error };
};

export const modifyAssetsList = async ({
assetsList,
network,
isDeleteAssetsList,
}: {
assetsList: AssetsListItem;
network: NETWORKS;
isDeleteAssetsList: boolean;
}) => {
let response = {
error: "",
assetsLists: {} as AssetsLists,
};

response = await sendMessageToBackground({
type: SERVICE_TYPES.MODIFY_ASSETS_LIST,
assetsList,
network,
isDeleteAssetsList,
});

return { assetsLists: response.assetsLists, error: response.error };
};
2 changes: 1 addition & 1 deletion @shared/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"compilerOptions": {
"baseUrl": "."
},
"include": ["."]
"include": [".", "../helpers/stellar.ts"]
}
10 changes: 7 additions & 3 deletions @shared/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import BigNumber from "bignumber.js";
import { Horizon } from "stellar-sdk";
import { Types } from "@stellar/wallet-sdk";
import { AssetBalance, NativeBalance } from "@stellar/wallet-sdk/dist/types";

import { SERVICE_TYPES, EXTERNAL_SERVICE_TYPES } from "../constants/services";
import { APPLICATION_STATE } from "../constants/applicationState";
import { WalletType } from "../constants/hardwareWallet";
import { NetworkDetails } from "../constants/stellar";
import { AssetBalance, NativeBalance } from "@stellar/wallet-sdk/dist/types";
import { AssetsLists, AssetsListItem } from "../constants/soroban/token";

export enum ActionStatus {
IDLE = "IDLE",
Expand Down Expand Up @@ -53,11 +54,14 @@ export interface Response {
isSorobanPublicEnabled: boolean;
isRpcHealthy: boolean;
userNotification: UserNotification;
assetsLists: AssetsLists;
assetsList: AssetsListItem;
isDeleteAssetsList: boolean;
settingsState: SettingsState;
networkDetails: NetworkDetails;
sorobanRpcUrl: string;
networksList: NetworkDetails[];
allAccounts: Array<Account>;
allAccounts: Account[];
migratedAccounts: MigratedAccount[];
accountName: string;
assetCode: string;
Expand All @@ -66,7 +70,7 @@ export interface Response {
network: string;
networkIndex: number;
networkName: string;
recentAddresses: Array<string>;
recentAddresses: string[];
hardwareWalletType: WalletType;
bipPath: string;
blockedDomains: BlockedDomains;
Expand Down
4 changes: 4 additions & 0 deletions @shared/constants/errors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export class NoExtensionInstalledError extends Error {
message = "Freighter does not appear to be installed.";
}

export class SorobanRpcNotSupportedError extends Error {
message = "No Soroban RPC available";
}
2 changes: 2 additions & 0 deletions @shared/constants/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export enum SERVICE_TYPES {
GET_MIGRATABLE_ACCOUNTS = "GET_MIGRATABLE_ACCOUNTS",
GET_MIGRATED_MNEMONIC_PHRASE = "GET_MIGRATED_MNEMONIC_PHRASE",
MIGRATE_ACCOUNTS = "MIGRATE_ACCOUNTS",
ADD_ASSETS_LIST = "ADD_ASSETS_LIST",
MODIFY_ASSETS_LIST = "MODIFY_ASSETS_LIST",
}

export enum EXTERNAL_SERVICE_TYPES {
Expand Down
37 changes: 37 additions & 0 deletions @shared/constants/soroban/token.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NETWORKS } from "@shared/constants/stellar";

// https://github.com/stellar/soroban-examples/blob/main/token/src/contract.rs
export enum SorobanTokenInterface {
transfer = "transfer",
Expand Down Expand Up @@ -26,3 +28,38 @@ export interface SorobanToken {
symbol: string;
decimals: number;
}

export type AssetsListKey = NETWORKS.PUBLIC | NETWORKS.TESTNET;

export type AssetsLists = {
[K in AssetsListKey]: AssetsListItem[];
};

export interface AssetsListItem {
url: string;
isEnabled: boolean;
}

export const DEFAULT_ASSETS_LISTS: AssetsLists = {
[NETWORKS.PUBLIC]: [
{
url: "https://api.stellar.expert/explorer/public/asset-list/top50",
isEnabled: true,
},
{
url:
"https://raw.githubusercontent.com/soroswap/token-list/main/tokenList.json",
isEnabled: true,
},
{
url: "https://lobstr.co/api/v1/sep/assets/curated.json",
isEnabled: true,
},
],
[NETWORKS.TESTNET]: [
{
url: "https://api.stellar.expert/explorer/testnet/asset-list/top50",
isEnabled: true,
},
],
};
22 changes: 22 additions & 0 deletions @shared/helpers/soroban/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import {
Operation,
SorobanRpc,
scValToNative,
BASE_FEE,
TransactionBuilder,
} from "stellar-sdk";
import { NetworkDetails } from "@shared/constants/stellar";

export const simulateTx = async <ArgType>(
tx: Transaction<Memo<MemoType>, Operation[]>,
Expand All @@ -19,3 +22,22 @@ export const simulateTx = async <ArgType>(

throw new Error("Invalid response from simulateTransaction");
};

export const buildSorobanServer = (serverUrl: string) => {
return new SorobanRpc.Server(serverUrl, {
allowHttp: serverUrl.startsWith("http://"),
});
};

export const getNewTxBuilder = async (
publicKey: string,
networkDetails: NetworkDetails,
server: SorobanRpc.Server,
fee = BASE_FEE,
) => {
const sourceAccount = await server.getAccount(publicKey);
return new TransactionBuilder(sourceAccount, {
fee,
networkPassphrase: networkDetails.networkPassphrase,
});
};
9 changes: 9 additions & 0 deletions @shared/helpers/stellar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { NetworkDetails } from "@shared/constants/stellar";

export const CUSTOM_NETWORK = "STANDALONE";

export const isCustomNetwork = (networkDetails: NetworkDetails) => {
const { network } = networkDetails;

return network === CUSTOM_NETWORK;
};
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Freighter

Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser. Learn more at [freighter.app](https://www.freighter.app/).
Freighter is a non-custodial wallet extension that enables you to sign Stellar transactions via your browser. Learn more at [freighter.app](https://www.freighter.app/).

## Yarn Workspaces

Expand Down
Loading

0 comments on commit a733a59

Please sign in to comment.