Skip to content

Commit

Permalink
web-ui: Trezor Enhancements
Browse files Browse the repository at this point in the history
Improve the tests, also, avoid spending TPoS contract collaterals, they need to
be manually cancelled.

Also, add a note about the TPoS integration working only for Trezor T, explaining that
the contract is only created, and the coins to stake need to be sent to the staking address
after that, which leads to remove the amount input.
  • Loading branch information
AlexITC committed Mar 28, 2021
1 parent 77bc6b4 commit 579f28b
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 242 deletions.
1 change: 1 addition & 0 deletions web-ui/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export class AppComponent implements OnInit {
'label.path': 'Path',
'label.generatedTransaction': 'Generated transaction id',
'label.createContract': 'Create TPoS contract',
'label.tposContractNotice': 'For now, this only works on Trezor T, once the contract gets created, send the amount you desire to stake to the contract Staking address, refresh the page after some minutes if you do not see such address',


'label.address': 'Address',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ select.second-position {
color: black;
}

.red-text {
color: red;
}

.trezor-span {
grid-column: 2 / span 2;
font-size: 20px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

<tab heading="TPOS">
<label class="first-position"> {{ 'label.createContract' | translate }}</label>
<label class="first-position red-text"> {{ 'label.tposContractNotice' | translate }}</label>

<form [formGroup]="tposContractFormControl" name="tposContractFormControl" (keyup.enter)="sendTPOS()" novalidate
autocomplete="off">
Expand All @@ -88,18 +89,6 @@
class="text-danger">Merchant address is required</span>
</div>
</div>
<div class="row">

<div class="form-group col-md-6 col-xs-8">
<label for="AmountXSN">{{ 'label.amount' | translate }}</label>
<input class="form-control" (change)="precise(amountXSN)" #amountXSN type="number" min="0"
step="0.00000001" placeholder="Enter amount in xsn" formControlName="contractAmount"
name="contractAmount">
<span
*ngIf="tposContractFormControl.get('contractAmount').invalid && tposContractFormControl.get('contractAmount').touched"
class="text-danger">Amount is required</span>
</div>
</div>

<div class="row">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ export class TrezorConnectComponent implements OnInit {
createFormGroup(): FormGroup {
return new FormGroup({
merchantAddress: new FormControl('', [Validators.required]),
contractAmount: new FormControl('', [Validators.required]),
commissionPercent: new FormControl('', [Validators.required])
});
}
Expand All @@ -92,7 +91,7 @@ export class TrezorConnectComponent implements OnInit {
'showOnTrezor': false
};
});
const response = await TrezorConnect.getAddress({ bundle: bundle });
const response: any = await TrezorConnect.getAddress({ bundle: bundle });

if (response.success) {
this.showAllButton = false;
Expand Down Expand Up @@ -178,7 +177,8 @@ export class TrezorConnectComponent implements OnInit {
outputs: outputs,
refTxs: txs,
coin: 'Stakenet'
}).then(async (result) => {
}).then(async (result: any) => {
console.log('signTrezorTransaction', result);
if (result.payload.error) {
this.notificationService.error(result);
} else {
Expand All @@ -189,22 +189,31 @@ export class TrezorConnectComponent implements OnInit {
}


/**
* Right now this only creates the TPoS contract transaction by sending 1 XSN to the staking address.
*
* Once the contract transaction gets confirmed, its important to send the coins to stake to the
* staking address.
*/
async sendTPOS() {
if (!this.validateTposForm()) {
return;
}

const contractForm = this.tposContractFormControl.getRawValue();
const fee = TransactionFees[0].amount; // 1000 satoshis
const contractAmount = contractForm.contractAmount;
const fee = 1000; // 1000 satoshis
const collateral = convertToSatoshis(1); // The collateral is one xsn
const generatedInputs = this.generateInputs(collateral + fee);

if (generatedInputs.error) {
this.notificationService.error(generatedInputs.error);
return;
}
console.log('sendTPOS -> generatedInputs', generatedInputs);

// TODO: Check that the address has no history because reusing addresses has caused
// the contract to be invalid (don't know why), otherwise, generate another address.
//
// A new legacy address is required for each new tpos contract.
const tposAddress = await this.generateNextAddress(44);
if (tposAddress === undefined) {
Expand All @@ -220,12 +229,13 @@ export class TrezorConnectComponent implements OnInit {
}

const firstOutPoint = generatedInputs.inputs[0].prev_hash + ':' + generatedInputs.inputs[0].prev_index;
const messageSigned = await TrezorConnect.signMessage({
const messageSigned: any = await TrezorConnect.signMessage({
path: tposAddress.path,
message: firstOutPoint
message: firstOutPoint,
coin: 'Stakenet'
});

if (messageSigned.payload.error) {
if (!messageSigned.success) {
this.notificationService.error(messageSigned.payload.error);
return;
}
Expand Down Expand Up @@ -256,12 +266,10 @@ export class TrezorConnectComponent implements OnInit {
op_return_data: contract.tposContractEncoded,
script_type: 'PAYTOOPRETURN',
};

outputs.push(tposContract);
console.log('sendTPOS -> contract output', tposContract);

const hashTransactions = generatedInputs.inputs.map((x) => {
return x.prev_hash;
});
const hashTransactions = generatedInputs.inputs.map((x) => x.prev_hash);

// push the transaction to explorer
this.getRefTransactions(hashTransactions).subscribe(async txs => {
Expand All @@ -272,7 +280,9 @@ export class TrezorConnectComponent implements OnInit {
coin: 'Stakenet'
};

const trezorResult = await this.signTrezorTransaction(tposTransaction);
console.log('sendTPOS -> tposTransaction', tposTransaction);
const trezorResult: any = await this.signTrezorTransaction(tposTransaction);

if (trezorResult.payload.error) {
this.notificationService.error(trezorResult.payload.error);
} else {
Expand All @@ -283,10 +293,8 @@ export class TrezorConnectComponent implements OnInit {
generatedInputs.inputs.forEach(input => {
this.removeUTXO(input.prev_hash, input.prev_index);
});
this.signTransaction(tposAddress.address, contractAmount, fee);
}
});

}

verifyAddress(trezorAddress: TrezorAddress): void {
Expand Down Expand Up @@ -317,7 +325,7 @@ export class TrezorConnectComponent implements OnInit {
}

private async getTrezorAddress(path: string): Promise<TrezorAddress> {
const result = await TrezorConnect.getAddress({ path: path, coin: 'Stakenet', showOnTrezor: false });
const result: any = await TrezorConnect.getAddress({ path: path, coin: 'Stakenet', showOnTrezor: false });
return result.payload;
}

Expand All @@ -337,10 +345,10 @@ export class TrezorConnectComponent implements OnInit {
const selectedUtxos = selectUtxos(this.utxos, satoshis);
if (selectedUtxos.utxos.length === 0) {
return {
error: 'No utoxs'
error: 'Not enough coins, note that TPoS contracts need to be cancelled manually to free the 1 XSN collateral'
};
}
const change = selectedUtxos.total - satoshis;
const change = selectedUtxos.satoshis - satoshis;
const inputs = selectedUtxos.utxos.map(utxo => toTrezorInput(this.trezorAddresses, utxo));
const addressToChange = selectedUtxos.utxos[selectedUtxos.utxos.length - 1].address;

Expand All @@ -357,7 +365,7 @@ export class TrezorConnectComponent implements OnInit {
);
}

precise(elem) {
precise(elem: { value: string; }) {
elem.value = Number(elem.value).toFixed(8);
}

Expand Down
18 changes: 18 additions & 0 deletions web-ui/src/app/models/tpos-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ export class TposContract {
merchantCommission: number;
time: number;
state: string;

constructor(
txid: string,
index: number,
owner: string,
merchant: string,
merchantCommission: number,
time: number,
state: string) {

this.txid = txid;
this.index = index;
this.owner = owner;
this.merchant = merchant;
this.merchantCommission = merchantCommission;
this.time = time;
this.state = state;
}
}


Expand Down
1 change: 1 addition & 0 deletions web-ui/src/app/services/transactions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class TransactionsService {
const body = {
hex: hex
};
console.log('Pushing transaction', hex);

return this.http.post<any>(url, body, httpOptions).toPromise();
}
Expand Down
Loading

0 comments on commit 579f28b

Please sign in to comment.