Skip to content

Commit

Permalink
feat: Add more address type cases in addressHelper (all covered excep…
Browse files Browse the repository at this point in the history
…t multi). Fix issue in computing bech32 for account in OutputView. Add nova own Bech32Address component.
  • Loading branch information
msarcev committed Feb 8, 2024
1 parent 027aeee commit ef13fb5
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 52 deletions.
12 changes: 6 additions & 6 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion api/src/models/api/nova/IAddressDetails.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable import/no-unresolved */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { AddressType } from "@iota/sdk-nova";

export interface IAddressDetails {
Expand All @@ -6,5 +8,5 @@ export interface IAddressDetails {
type?: AddressType;
label?: string;
restricted: boolean;
capabilities?: boolean[];
capabilities?: number[];
}
10 changes: 2 additions & 8 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 2 additions & 10 deletions client/src/app/components/nova/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Utils } from "@iota/sdk-wasm-nova/web";
import classNames from "classnames";
import React, { useState } from "react";
import { useHistory, Link } from "react-router-dom";
import Bech32Address from "../stardust/address/Bech32Address";
import Bech32Address from "../nova/address/Bech32Address";
import { useNetworkInfoNova } from "~helpers/nova/networkInfo";
import OutputView from "./OutputView";
import DropdownIcon from "~assets/dropdown-arrow.svg?react";
Expand Down Expand Up @@ -57,15 +57,7 @@ const Input: React.FC<InputProps> = ({ input, network }) => {
<React.Fragment>
<div className="card--label"> Address</div>
<div className="card--value">
<Bech32Address
network={network}
history={history}
addressDetails={input.address}
advancedMode
hideLabel
truncateAddress={false}
labelPosition="bottom"
/>
<Bech32Address network={network} history={history} addressDetails={input.address} advancedMode hideLabel />
</div>
<div className="card--label"> Transaction Id</div>
<div className="card--value">
Expand Down
21 changes: 8 additions & 13 deletions client/src/app/components/nova/OutputView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
TokenSchemeType,
SimpleTokenScheme,
DelegationOutput,
AddressType,
Utils,
} from "@iota/sdk-wasm-nova/web";
import UnlockConditionView from "./UnlockConditionView";
Expand All @@ -22,7 +21,6 @@ import { Link } from "react-router-dom";
import { useNetworkInfoNova } from "~/helpers/nova/networkInfo";
import FeatureView from "./FeaturesView";
import TruncatedId from "../stardust/TruncatedId";
import { AddressHelper } from "~/helpers/nova/addressHelper";
import "./OutputView.scss";

interface OutputViewProps {
Expand All @@ -38,7 +36,7 @@ const OutputView: React.FC<OutputViewProps> = ({ outputId, output, showCopyAmoun
const [isFormattedBalance, setIsFormattedBalance] = useState(true);
const { bech32Hrp, name: network } = useNetworkInfoNova((s) => s.networkInfo);

const aliasOrNftBech32 = buildAddressForAliasOrNft(outputId, output, bech32Hrp);
const aliasOrNftBech32 = buildAddressForAliasOrNft(output, bech32Hrp);
const outputIdTransactionPart = `${outputId.slice(0, 8)}....${outputId.slice(-8, -4)}`;
const outputIdIndexPart = outputId.slice(-4);

Expand Down Expand Up @@ -216,21 +214,18 @@ const OutputView: React.FC<OutputViewProps> = ({ outputId, output, showCopyAmoun
);
};

function buildAddressForAliasOrNft(outputId: string, output: Output, bech32Hrp: string): string {
let address: string = "";
let addressType: number = 0;
function buildAddressForAliasOrNft(output: Output, bech32Hrp: string): string {
let bech32: string = "";

if (output.type === OutputType.Account) {
const accountId = Utils.computeAccountId(outputId);
address = accountId;
addressType = AddressType.Account;
const accountId = (output as AccountOutput).accountId;
bech32 = Utils.accountIdToBech32(accountId, bech32Hrp);
} else if (output.type === OutputType.Nft) {
const nftId = Utils.computeNftId(outputId);
address = nftId;
addressType = AddressType.Nft;
const nftId = (output as NftOutput).nftId;
bech32 = Utils.nftIdToBech32(nftId, bech32Hrp);
}

return AddressHelper.buildAddress(bech32Hrp, address, addressType).bech32;
return bech32;
}

function getOutputTypeName(type: OutputType): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AccountAddress } from "@iota/sdk-wasm-nova/web";
import React from "react";
import { useAccountAddressState } from "~/helpers/nova/hooks/useAccountAddressState";
import Spinner from "../../Spinner";
import Bech32Address from "../../stardust/address/Bech32Address";
import Bech32Address from "../../nova/address/Bech32Address";
import AssociatedOutputs from "./section/association/AssociatedOutputs";

interface AccountAddressViewProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AnchorAddress } from "@iota/sdk-wasm-nova/web";
import React from "react";
import { useAnchorAddressState } from "~/helpers/nova/hooks/useAnchorAddressState";
import Spinner from "../../Spinner";
import Bech32Address from "../../stardust/address/Bech32Address";
import Bech32Address from "./Bech32Address";
import AssociatedOutputs from "./section/association/AssociatedOutputs";

interface AnchorAddressViewProps {
Expand Down
55 changes: 55 additions & 0 deletions client/src/app/components/nova/address/Bech32Address.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from "react";
import * as H from "history";
import { IAddressDetails } from "~/models/api/nova/IAddressDetails";
import TruncatedId from "../../stardust/TruncatedId";

interface Bech32AddressProps {
network?: string;
history?: H.History;
addressDetails?: IAddressDetails;
advancedMode: boolean;
hideLabel?: boolean;
}

const Bech32Address: React.FC<Bech32AddressProps> = ({ network, history, addressDetails, advancedMode, hideLabel }) => {
return (
<div className="bech32-address">
{addressDetails?.bech32 && (
<div className="section--data">
{!hideLabel && <div className="label">{addressDetails.label} Address</div>}
<div className="value row middle code">
{history && (
<button
type="button"
className="margin-r-t"
onClick={() => history?.push(`/${network}/addr/${addressDetails?.bech32}`)}
>
<TruncatedId id={addressDetails.bech32} showCopyButton />
</button>
)}
{!history && <TruncatedId id={addressDetails.bech32} showCopyButton />}
</div>
</div>
)}
{advancedMode && addressDetails?.label && addressDetails?.hex && (
<div className="section--data">
<div className="label">{addressDetails.label} Id</div>
<div className="value row middle code">
{history && (
<button
type="button"
className="margin-r-t"
onClick={() => history?.push(`/${network}/addr/${addressDetails?.bech32}`)}
>
<TruncatedId id={addressDetails?.hex} showCopyButton />
</button>
)}
{!history && <TruncatedId id={addressDetails?.hex} showCopyButton />}
</div>
</div>
)}
</div>
);
};

export default Bech32Address;
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Ed25519Address } from "@iota/sdk-wasm-nova/web";
import React from "react";
import { useEd25519AddressState } from "~/helpers/nova/hooks/useEd25519AddressState";
import Bech32Address from "../../stardust/address/Bech32Address";
import Bech32Address from "./Bech32Address";
import AssociatedOutputs from "./section/association/AssociatedOutputs";

interface Ed25519AddressViewProps {
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/components/nova/address/NftAddressView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { NftAddress } from "@iota/sdk-wasm-nova/web";
import React from "react";
import { useNftAddressState } from "~/helpers/nova/hooks/useNftAddressState";
import Spinner from "../../Spinner";
import Bech32Address from "../../stardust/address/Bech32Address";
import Bech32Address from "./Bech32Address";
import AssociatedOutputs from "./section/association/AssociatedOutputs";

interface NftAddressViewProps {
Expand Down
66 changes: 57 additions & 9 deletions client/src/helpers/nova/addressHelper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { Address, AddressType, AccountAddress, Ed25519Address, NftAddress, AnchorAddress, Utils } from "@iota/sdk-wasm-nova/web";
import {
Address,
AddressType,
AccountAddress,
Ed25519Address,
NftAddress,
AnchorAddress,
Utils,
ImplicitAccountCreationAddress,
RestrictedAddress,
} from "@iota/sdk-wasm-nova/web";
import { HexHelper } from "../stardust/hexHelper";
import { IAddressDetails } from "~models/api/nova/IAddressDetails";
import { plainToInstance } from "class-transformer";

export class AddressHelper {
/**
Expand Down Expand Up @@ -35,7 +46,7 @@ export class AddressHelper {
// We assume this is hex and either use the hint or assume ed25519
hex = addressString;
type = typeHint ?? AddressType.Ed25519;
bech32 = Utils.hexToBech32(hex, hrp);
bech32 = this.computeBech32FromHexAndType(hex, type, hrp);
}

return {
Expand All @@ -47,28 +58,65 @@ export class AddressHelper {
};
}

private static buildAddressFromTypes(address: Address, hrp: string): IAddressDetails {
private static buildAddressFromTypes(
address: Address,
hrp: string,
restricted: boolean = false,
capabilities?: number[],
): IAddressDetails {
let hex: string = "";
let bech32: string = "";

if (address.type === AddressType.Ed25519) {
hex = HexHelper.stripPrefix((address as Ed25519Address).pubKeyHash);
hex = (address as Ed25519Address).pubKeyHash;
} else if (address.type === AddressType.Account) {
hex = HexHelper.stripPrefix((address as AccountAddress).accountId);
hex = (address as AccountAddress).accountId;
} else if (address.type === AddressType.Nft) {
hex = HexHelper.stripPrefix((address as NftAddress).nftId);
hex = (address as NftAddress).nftId;
} else if (address.type === AddressType.Anchor) {
hex = HexHelper.stripPrefix((address as AnchorAddress).anchorId);
hex = (address as AnchorAddress).anchorId;
} else if (address.type === AddressType.ImplicitAccountCreation) {
const implicitAccountCreationAddress = plainToInstance(ImplicitAccountCreationAddress, address);
const innerAddress = implicitAccountCreationAddress.address();
hex = (innerAddress as Ed25519Address).pubKeyHash;
} else if (address.type === AddressType.Restricted) {
const restrictedAddress = plainToInstance(RestrictedAddress, address);
const innerAddress = restrictedAddress.address;

return this.buildAddressFromTypes(innerAddress, hrp, true, Array.from(restrictedAddress.getAllowedCapabilities()));
}

bech32 = this.computeBech32FromHexAndType(hex, address.type, hrp);

return {
bech32: Utils.hexToBech32(HexHelper.addPrefix(hex), hrp),
bech32,
hex,
type: address.type,
label: AddressHelper.typeLabel(address.type),
restricted: false,
restricted,
capabilities,
};
}

private static computeBech32FromHexAndType(hex: string, addressType: AddressType, hrp: string) {
let bech32 = "";

if (addressType === AddressType.Ed25519) {
bech32 = Utils.hexToBech32(hex, hrp);
} else if (addressType === AddressType.Account) {
bech32 = Utils.accountIdToBech32(hex, hrp);
} else if (addressType === AddressType.Nft) {
bech32 = Utils.nftIdToBech32(hex, hrp);
} else if (addressType === AddressType.Anchor) {
// TODO Utils.anchorIdToBech32 does not exist ???
bech32 = Utils.accountIdToBech32(hex, hrp);
} else if (addressType === AddressType.ImplicitAccountCreation) {
bech32 = Utils.hexToBech32(hex, hrp);
}

return bech32;
}

/**
* Convert the address type number to a label.
* @param addressType The address type to get the label for.
Expand Down
2 changes: 1 addition & 1 deletion client/src/models/api/nova/IAddressDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export interface IAddressDetails {
type?: AddressType;
label?: string;
restricted?: boolean;
capabilities?: boolean[];
capabilities?: number[];
}

0 comments on commit ef13fb5

Please sign in to comment.