Skip to content

Commit

Permalink
Merge pull request #3773 from Emurgo/release/5.4.510
Browse files Browse the repository at this point in the history
Release / 5.4.510
  • Loading branch information
vsubhuman authored Dec 4, 2024
2 parents 413a23f + d111a08 commit 34bf407
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 82 deletions.
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

0 comments on commit 34bf407

Please sign in to comment.