Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release / 5.4.510 #3773

Merged
merged 7 commits into from
Dec 4, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import type { TokenRow, } from '../../api/ada/lib/storage/database/primitives/ta
import BigNumber from 'bignumber.js';

export default class TxBuilderActions {
updateReceiver: Action<void | string> = new Action();
updateReceiver: Action<{|
address: void | string,
handle?: void | {| handle: string, nameServer: string |},
|}> = new Action();
updateAmount: Action<?BigNumber> = new Action();
updateMemo: Action<void | string> = new Action();
addToken: Action<{|
Expand Down
18 changes: 13 additions & 5 deletions packages/yoroi-extension/app/api/ada/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ export type CreateUnsignedTxRequest = {|
},
absSlotNumber: BigNumber,
receiver: string,
receiverHandle?: {| handle: string, nameServer: string |},
filter: ElementOf<IGetAllUtxosResponse> => boolean,
tokens: SendTokenList,
metadata: Array<TransactionMetadata> | void,
Expand Down Expand Up @@ -329,6 +330,7 @@ export type CreateUnsignedTxForUtxosRequest = {|
absSlotNumber: BigNumber,
receivers: Array<{|
...Address,
+addressHandle?: {| handle: string, nameServer: string |},
...InexactSubset<Addressing>,
|}>,
network: $ReadOnly<NetworkRow>,
Expand Down Expand Up @@ -863,11 +865,13 @@ export default class AdaApi {

const { protocolParameters } = request;

let signRequestReceiver;
if (hasSendAllDefault(request.tokens)) {
if (request.receivers.length !== 1) {
throw new Error(`${nameof(this.createUnsignedTxForUtxos)} wrong output size for sendAll`);
}
const receiver = request.receivers[0];
signRequestReceiver = { address: receiver.address, handle: receiver.addressHandle };
unsignedTxResponse = shelleySendAllUnsignedTx(
receiver,
request.utxos,
Expand Down Expand Up @@ -903,23 +907,25 @@ export default class AdaApi {
throw new Error(`${nameof(this.createUnsignedTxForUtxos)} needs exactly one change address`);
}
const changeAddr = changeAddresses[0];
const otherAddresses: Array<{| ...Address, |}> = request.receivers.reduce(
const otherAddresses: Array<{| ...Address, +addressHandle?: {| handle: string, nameServer: string |}, |}> = request.receivers.reduce(
(arr, next) => {
if (next.addressing == null) {
arr.push({ address: next.address });
arr.push({ address: next.address, addressHandle: next.addressHandle });
return arr;
}
return arr;
},
([]: Array<{| ...Address, |}>)
([]: Array<{| ...Address, +addressHandle?: {| handle: string, nameServer: string |}, |}>)
);
if (otherAddresses.length > 1) {
throw new Error(`${nameof(this.createUnsignedTxForUtxos)} can't send to more than one address`);
}
const receiver = otherAddresses[0];
signRequestReceiver = { address: receiver.address, handle: receiver.addressHandle };
unsignedTxResponse = await shelleyNewAdaUnsignedTx(
otherAddresses.length === 1
? [{
address: otherAddresses[0].address,
address: receiver.address,
amount: builtSendTokenList(
request.defaultToken,
request.tokens,
Expand Down Expand Up @@ -966,6 +972,7 @@ export default class AdaApi {
neededHashes: new Set(),
wits: new Set(),
},
receiver: signRequestReceiver,
});
} catch (error) {
Logger.error(
Expand All @@ -984,7 +991,8 @@ export default class AdaApi {
const addressedUtxo = asAddressedUtxo(filteredUtxos);

const receivers = [{
address: request.receiver
address: request.receiver,
addressHandle: request.receiverHandle,
}];

// note: we need to create a change address IFF we're not sending all of the default asset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type TrezorTCatalystRegistrationTxSignData =
export class HaskellShelleyTxSignRequest
implements ISignRequest<RustModule.WalletV4.TransactionBuilder> {

receiver: ?{| address: string, handle: {| handle: string, nameServer: string |} | void |};
senderUtxos: Array<CardanoAddressedUtxo>;
unsignedTx: RustModule.WalletV4.TransactionBuilder;
changeAddr: Array<{| ...Address, ...Value, ...Addressing |}>;
Expand Down Expand Up @@ -75,6 +76,7 @@ implements ISignRequest<RustModule.WalletV4.TransactionBuilder> {
void | TrezorTCatalystRegistrationTxSignData;
ledgerNanoCatalystRegistrationTxSignData?:
void | LedgerNanoCatalystRegistrationTxSignData;
receiver?: ?{| address: string, handle: {| handle: string, nameServer: string |} | void |},
|}) {
this.senderUtxos = data.senderUtxos;
this.unsignedTx = data.unsignedTx;
Expand All @@ -86,6 +88,7 @@ implements ISignRequest<RustModule.WalletV4.TransactionBuilder> {
data.trezorTCatalystRegistrationTxSignData;
this.ledgerNanoCatalystRegistrationTxSignData =
data.ledgerNanoCatalystRegistrationTxSignData;
this.receiver = data.receiver;
}

txId(): string {
Expand Down Expand Up @@ -241,6 +244,10 @@ implements ISignRequest<RustModule.WalletV4.TransactionBuilder> {
})).toArray();
}

receiverWithHandle(): null | {| address: string, handle: void | {| handle: string, nameServer: string |} |} {
return this.receiver ?? null;
}

receivers(includeChange: boolean): Array<string> {
const outputStrings = iterateLenGet(this.unsignedTx.build().outputs())
.map(o => toHexOrBase58(o.address())).toArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ type TxMetadata = {
};

export function sendAllUnsignedTx(
receiver: {| ...Address, ...InexactSubset<Addressing> |},
receiver: { ...Address, ...InexactSubset<Addressing>, ... },
allUtxos: Array<CardanoAddressedUtxo>,
absSlotNumber: BigNumber,
protocolParams: {|
Expand Down Expand Up @@ -288,7 +288,7 @@ function addUtxoInput(
}

export function sendAllUnsignedTxFromUtxo(
receiver: {| ...Address, ...InexactSubset<Addressing> |},
receiver: { ...Address, ...InexactSubset<Addressing>, ... },
allUtxos: Array<RemoteUnspentOutput>,
absSlotNumber: BigNumber,
protocolParams: {|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ type Props = {|
+onSubmit: void => void,
+totalInput: ?MultiToken,
+isClassicTheme: boolean,
+updateReceiver: (void | string) => void,
+updateReceiver: (void | string, void | {| handle: string, nameServer: string |}) => void,
+updateAmount: (?BigNumber) => void,
+updateMemo: (void | string) => void,
+shouldSendAll: boolean,
Expand Down Expand Up @@ -245,6 +245,7 @@ type State = {|
|},
domainResolverMessage: ?string,
domainResolverIsLoading: boolean,
lastValidatedValue: ?string,
|};

@observer
Expand All @@ -260,6 +261,7 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
domainResolverResult: null,
domainResolverMessage: null,
domainResolverIsLoading: false,
lastValidatedValue: null,
};
maxStep: number = SEND_FORM_STEP.RECEIVER;

Expand Down Expand Up @@ -332,10 +334,12 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
isDomainResolvable: boolean,
domainResolverMessage: ?string,
resolvedAddress: ?string,
resolvedNameServer: ?string,
|}> {
let isDomainResolvable = false;
let domainResolverMessage = null;
let resolvedAddress = null;
let resolvedNameServer = null;
const { resolveDomainAddress } = this.props;
if (resolveDomainAddress != null) {
isDomainResolvable = isResolvableDomain(handle);
Expand All @@ -347,6 +351,7 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
domainResolverMessage = this.context.intl.formatMessage(messages.receiverFieldLabelUnresolvedAddress);
} else if (res.address != null) {
resolvedAddress = res.address;
resolvedNameServer = res.nameServer;
domainResolverResult = {
handle,
address: res.address,
Expand All @@ -372,6 +377,7 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
isDomainResolvable,
domainResolverMessage,
resolvedAddress,
resolvedNameServer,
};
}

Expand All @@ -385,44 +391,57 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
value: this.props.uriParams ? this.props.uriParams.address : '',
validators: [
async ({ field }) => {
let receiverValue = field.value;
if (receiverValue === '') {
this.props.updateReceiver();
this.setState({
domainResolverResult: null,
domainResolverMessage: null,
domainResolverIsLoading: false,
});
return [false, this.context.intl.formatMessage(globalMessages.fieldIsRequired)];
}
const updateReceiver = (isValid: boolean) => {
if (isValid) {
this.props.updateReceiver(getAddressPayload(receiverValue, this.props.selectedNetwork));
} else {
const inputFieldValue = field.value;
let handle = undefined;
let receiverValue = inputFieldValue;
try {
if (receiverValue === '') {
this.props.updateReceiver();
this.setState({
domainResolverResult: null,
domainResolverMessage: null,
domainResolverIsLoading: false,
});
return [false, this.context.intl.formatMessage(globalMessages.fieldIsRequired)];
}
};
const updateReceiver = (isValid: boolean) => {
if (isValid) {
this.props.updateReceiver(
getAddressPayload(receiverValue, this.props.selectedNetwork),
handle,
);
} else {
this.props.updateReceiver();
}
};

// DOMAIN RESOLVER
const { isDomainResolvable, domainResolverMessage, resolvedAddress } = await this.resolveDomainAddress(
receiverValue
);
if (resolvedAddress != null) {
receiverValue = resolvedAddress;
}
////////////////////
// DOMAIN RESOLVER
const { isDomainResolvable, domainResolverMessage, resolvedAddress, resolvedNameServer } =
// $FlowIgnore[incompatible-call]
await this.resolveDomainAddress(receiverValue);

const isValid = isValidReceiveAddress(receiverValue, this.props.selectedNetwork);
if (isValid === true) {
updateReceiver(true);
return [isValid];
if (resolvedAddress != null) {
handle = { handle: receiverValue, nameServer: resolvedNameServer };
receiverValue = resolvedAddress;
}
////////////////////

const isValid = isValidReceiveAddress(receiverValue, this.props.selectedNetwork);
if (isValid === true) {
updateReceiver(true);
return [isValid];
}
const [result, errorMessage, errorType] = isValid;
updateReceiver(result);
const fieldError = isDomainResolvable
? domainResolverMessage
: this.context.intl.formatMessage(errorType === 1 ? messages.receiverFieldLabelInvalidAddress : errorMessage);
return [isValid[0], fieldError];
} finally {
this.setState({
lastValidatedValue: inputFieldValue,
});
}
const [result, errorMessage, errorType] = isValid;
updateReceiver(result);
const fieldError = isDomainResolvable
? domainResolverMessage
: this.context.intl.formatMessage(errorType === 1 ? messages.receiverFieldLabelInvalidAddress : errorMessage);
return [isValid[0], fieldError];
},
],
},
Expand Down Expand Up @@ -940,14 +959,6 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
trezorSend={this.props.trezorSend}
selectedExplorer={this.props.selectedExplorer}
selectedWallet={this.props.selectedWallet}
receiverHandle={
domainResolverResult
? {
nameServer: domainResolverResult.nameServer,
handle: domainResolverResult.handle,
}
: null
}
/>
);
default:
Expand All @@ -962,6 +973,8 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
const { maxSendableAmount } = this.props;

const receiverField = form.$('receiver');
const isValidatedValue = receiverField.value === this.state.lastValidatedValue;
const isValidValue = isValidatedValue && receiverField.isValid;

switch (step) {
case SEND_FORM_STEP.RECEIVER:
Expand All @@ -971,7 +984,7 @@ export default class WalletSendFormRevamp extends Component<Props, State> {
variant="primary"
size="medium"
onClick={() => this.onUpdateStep(SEND_FORM_STEP.AMOUNT)}
disabled={invalidMemo || !receiverField.isValid}
disabled={invalidMemo || !isValidValue}
id="wallet:send:enterAddressStep-nextToAddAssets-button"
>
{intl.formatMessage(globalMessages.nextButtonLabel)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ type Props = {|
+staleTx: boolean,
+selectedExplorer: SelectedExplorer,
+amount: MultiToken,
+receivers: Array<string>,
+receiverHandle: ?{|
nameServer: string,
handle: string,
|},
+receiver: {| address: string, handle: {| handle: string, nameServer: string |} | void |},
+totalAmount: MultiToken,
+transactionFee: MultiToken,
+transactionSize: ?string,
Expand Down Expand Up @@ -439,7 +435,7 @@ export default class WalletSendPreviewStep extends Component<Props, State> {
const { form } = this;
const { intl } = this.context;
const walletPasswordField = form.$('walletPassword');
const { amount, receivers, isSubmitting, walletType } = this.props;
const { amount, receiver, isSubmitting, walletType } = this.props;
const { passwordError } = this.state;

const staleTxWarning = (
Expand All @@ -452,8 +448,6 @@ export default class WalletSendPreviewStep extends Component<Props, State> {
</div>
);

const { receiverHandle } = this.props;

return (
<div className={styles.component}>
<Box
Expand All @@ -465,7 +459,7 @@ export default class WalletSendPreviewStep extends Component<Props, State> {
<Box width="506px" mx="auto">
{this.renderError()}
{this.props.staleTx ? <div className={styles.staleTxWarning}>{staleTxWarning}</div> : null}
{receiverHandle ? (
{receiver.handle != null ? (
<div style={{ marginBottom: '20px' }}>
<Box mb="8px">
<Typography component="div" variant="body1" color="ds.text_gray_medium">
Expand All @@ -482,7 +476,7 @@ export default class WalletSendPreviewStep extends Component<Props, State> {
}}
id="wallet:send:confrimTransactionStep-receiverHandleInfo-text"
>
{receiverHandle.nameServer}: {receiverHandle.handle}
{receiver.handle?.nameServer}: {receiver.handle?.handle}
</Typography>
</Box>
</div>
Expand All @@ -503,7 +497,7 @@ export default class WalletSendPreviewStep extends Component<Props, State> {
}}
id="wallet:send:confrimTransactionStep-receiverAddress-text"
>
{this.props.addressToDisplayString(receivers[0])}
{this.props.addressToDisplayString(receiver.address)}
</Typography>
</Box>
</div>
Expand Down
Loading
Loading