Skip to content

Commit

Permalink
Lockups (#299)
Browse files Browse the repository at this point in the history
* Add transcoder for Register as validator transaction. Add support for approve component for this txn type

* Add transcoder for Unregister as validator txn type. Add support for approve component for this new txn type

* Add transcoder for stake transaction metadata. Add support for approve component for this new txn type.

* Add transcoder for Unstake txn type. Add support for approve component for this new txn type.

* Add transcoder for Unlock stake txn type. Add support for approve UI for this new txn type

* Add transcoder for Unjail Validator txn type. Add approve UI support for this new txn type.

* Add support for coin lockup txn types

---------

Co-authored-by: Lazy Nina <>
  • Loading branch information
poolcoke authored Feb 7, 2024
1 parent 7fdd79a commit fd55a7c
Show file tree
Hide file tree
Showing 5 changed files with 361 additions and 4 deletions.
141 changes: 138 additions & 3 deletions src/app/approve/approve.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ import {
TransactionMetadataUpdateNFT,
TransactionMetadataUpdateProfile,
TransactionSpendingLimit,
TransactionMetadataRegisterAsValidator,
TransactionMetadataUnregisterAsValidator,
TransactionMetadataStake,
TransactionMetadataUnstake,
TransactionMetadataUnlockStake,
TransactionMetadataUnjailValidator,
TransactionMetadataCoinLockup,
TransactionMetadataUpdateCoinLockupParams,
TransactionMetadataCoinLockupTransfer,
TransactionMetadataCoinUnlock,
} from '../../lib/deso/transaction';
import { ExtraData } from '../../types/identity';
import { AccountService } from '../account.service';
Expand Down Expand Up @@ -304,12 +314,12 @@ export class ApproveComponent implements OnInit {
);
publicKeys = [daoCoinPublicKey];
if (daoCoinMetadata.operationType === 0) {
const mintAmount = this.hexNanosToUnitString(
const mintAmount = this.hexBaseUnitsToUnitString(
daoCoinMetadata.coinsToMintNanos
);
description = `mint ${mintAmount} ${daoCoinPublicKey} DAO coins`;
} else if (daoCoinMetadata.operationType === 1) {
const burnAmount = this.hexNanosToUnitString(
const burnAmount = this.hexBaseUnitsToUnitString(
daoCoinMetadata.coinsToBurnNanos
);
description = `burn ${burnAmount} ${daoCoinPublicKey} DAO coins`;
Expand All @@ -322,7 +332,7 @@ export class ApproveComponent implements OnInit {
case TransactionMetadataTransferDAOCoin:
const daoCoinTransferMetadata = this.transaction
.metadata as TransactionMetadataTransferDAOCoin;
const daoCoinTransferAmount = this.hexNanosToUnitString(
const daoCoinTransferAmount = this.hexBaseUnitsToUnitString(
daoCoinTransferMetadata.daoCoinToTransferNanos
);
const daoCoinTransferPublicKey = this.base58KeyCheck(
Expand Down Expand Up @@ -388,6 +398,7 @@ export class ApproveComponent implements OnInit {
this.hexScaledExchangeRateToFloat(
daoCoinLimitOrderMetadata.scaledExchangeRateCoinsToSellPerCoinToBuy
);
// TODO: figure out if we need to use hexBaseUnitsToUnitString here.
const quantityToFill = this.hexNanosToUnitString(
daoCoinLimitOrderMetadata.quantityToFillInBaseUnits
);
Expand Down Expand Up @@ -588,6 +599,120 @@ export class ApproveComponent implements OnInit {
description = `unknown messaging action on ${messageType} to ${recipient}`;
}
break;
case TransactionMetadataRegisterAsValidator:
// TODO: Do we want any additional details in the approve component?
description = 'register as a validator';
break;
case TransactionMetadataUnregisterAsValidator:
description = 'unregister as a validator';
break;
case TransactionMetadataStake:
const stakeMetadata = this.transaction
.metadata as TransactionMetadataStake;
const stakeValidatorPublicKey = this.base58KeyCheck(
stakeMetadata.validatorPublicKey
);
publicKeys = [stakeValidatorPublicKey];
const stakeAmountNanos = this.hexNanosToUnitString(
stakeMetadata.stakeAmountNanos
);
description = `stake ${stakeAmountNanos} $DESO to ${stakeValidatorPublicKey}`;
break;
case TransactionMetadataUnstake:
const unstakeMetadata = this.transaction
.metadata as TransactionMetadataUnstake;
const unstakeValidatorPublicKey = this.base58KeyCheck(
unstakeMetadata.validatorPublicKey
);
publicKeys = [unstakeValidatorPublicKey];
const unstakeAmountNanos = this.hexNanosToUnitString(
unstakeMetadata.unstakeAmountNanos
);
description = `unstake ${unstakeAmountNanos} $DESO from ${unstakeValidatorPublicKey}`;
break;
case TransactionMetadataUnlockStake:
const unlockStakeMetadata = this.transaction
.metadata as TransactionMetadataUnlockStake;
const unlockStakeValidatorPublicKey = this.base58KeyCheck(
unlockStakeMetadata.validatorPublicKey
);
publicKeys = [unlockStakeValidatorPublicKey];
description =
`unlock stake from ${unlockStakeValidatorPublicKey}, ` +
`starting from epochs ${unlockStakeMetadata.startEpochNumber} to ${unlockStakeMetadata.endEpochNumber}`;
break;
case TransactionMetadataUnjailValidator:
description = 'unjail your validator';
break;
case TransactionMetadataCoinLockup:
// NOTE: we don't need a special case for DESO right now
// as lockups are not allowed for DESO at this time.
const coinLockupMetadata = this.transaction
.metadata as TransactionMetadataCoinLockup;
const lockupAmount = this.hexBaseUnitsToUnitString(
coinLockupMetadata.lockupAmountBaseUnits
);
const lockupProfilePubKey = this.base58KeyCheck(
coinLockupMetadata.profilePublicKey
);
const lockUpRecipientPubKey = this.base58KeyCheck(
coinLockupMetadata.recipientPublicKey
);
publicKeys = [lockupProfilePubKey, lockUpRecipientPubKey];
description = `lockup ${lockupAmount} of your ${lockupProfilePubKey} coins`;
break;
case TransactionMetadataUpdateCoinLockupParams:
const updateCoinLockupParamsMetadata = this.transaction
.metadata as TransactionMetadataUpdateCoinLockupParams;
description =
`update your coin lockup params\n` +
`${
updateCoinLockupParamsMetadata.removeYieldCurvePoint
? 'Remove'
: 'Add'
} yield curve point with
${
updateCoinLockupParamsMetadata.lockupYieldAPYBasisPoints / 100
}% APY for a lockup of
${
updateCoinLockupParamsMetadata.lockupYieldDurationNanoSecs
} nanoseconds
${
!updateCoinLockupParamsMetadata.newLockupTransferRestrictions
? ''
: 'and update your lockup transfer restrictions'
}`;

break;
case TransactionMetadataCoinLockupTransfer:
// NOTE: we don't need a special case for DESO right now
// as lockups are not allowed for DESO at this time.
const coinLockupTransferMetadata = this.transaction
.metadata as TransactionMetadataCoinLockupTransfer;
const lockupTransferAmount = this.hexBaseUnitsToUnitString(
coinLockupTransferMetadata.lockedCoinsToTransferBaseUnits
);
const lockupTransferProfilePubKey = this.base58KeyCheck(
coinLockupTransferMetadata.profilePublicKey
);
const lockupTransferRecipientPubKey = this.base58KeyCheck(
coinLockupTransferMetadata.recipientPublicKey
);
publicKeys = [
lockupTransferProfilePubKey,
lockupTransferRecipientPubKey,
];
description = `transfer ${lockupTransferAmount} of your locked ${lockupTransferProfilePubKey} coins to ${lockupTransferRecipientPubKey}`;
break;
case TransactionMetadataCoinUnlock:
const coinUnlockMetadata = this.transaction
.metadata as TransactionMetadataCoinUnlock;
const unlockProfilePubKey = this.base58KeyCheck(
coinUnlockMetadata.profilePublicKey
);
publicKeys = [unlockProfilePubKey];
description = `unlock your locked ${unlockProfilePubKey} coins`;
break;
}

// Set the transaction description based on the description populated with public keys.
Expand All @@ -608,14 +733,24 @@ export class ApproveComponent implements OnInit {
return bs58check.encode(Buffer.from([...prefix, ...keyBytes]));
}

// uint256 to DESO nano conversions.
hexNanosToUnitString(nanos: Buffer): string {
return this.nanosToUnitString(parseInt(nanos.toString('hex'), 16));
}

// unit256 to base unit conversions.
hexBaseUnitsToUnitString(baseUnits: Buffer): string {
return this.baseUnitsToUnitString(parseInt(baseUnits.toString('hex'), 16));
}

nanosToUnitString(nanos: number): string {
return this.toFixedLengthDecimalString(nanos / 1e9);
}

baseUnitsToUnitString(baseUnits: number): string {
return this.toFixedLengthDecimalString(baseUnits / 1e18);
}

hexScaledExchangeRateToFloat(hex: Buffer): number {
return parseInt(hex.toString('hex'), 16) / 1e38;
}
Expand Down
20 changes: 20 additions & 0 deletions src/app/identity.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ import {
TransactionMetadataUpdateGlobalParams,
TransactionMetadataUpdateNFT,
TransactionMetadataUpdateProfile,
TransactionMetadataRegisterAsValidator,
TransactionMetadataUnregisterAsValidator,
TransactionMetadataStake,
TransactionMetadataUnstake,
TransactionMetadataUnlockStake,
TransactionMetadataUnjailValidator,
TransactionMetadataCoinLockup,
TransactionMetadataUpdateCoinLockupParams,
TransactionMetadataCoinLockupTransfer,
TransactionMetadataCoinUnlock,
} from '../lib/deso/transaction';
import { SwalHelper } from '../lib/helpers/swal-helper';
import { AccessLevel, PublicUserInfo } from '../types/identity';
Expand Down Expand Up @@ -518,6 +528,15 @@ export class IdentityService {
case TransactionMetadataDAOCoin:
case TransactionMetadataTransferDAOCoin:
case TransactionMetadataDAOCoinLimitOrder:
case TransactionMetadataRegisterAsValidator:
case TransactionMetadataUnregisterAsValidator:
case TransactionMetadataStake:
case TransactionMetadataUnstake:
case TransactionMetadataUnlockStake:
case TransactionMetadataCoinLockup:
case TransactionMetadataUpdateCoinLockupParams:
case TransactionMetadataCoinLockupTransfer:
case TransactionMetadataCoinUnlock:
return AccessLevel.Full;

case TransactionMetadataFollow:
Expand All @@ -531,6 +550,7 @@ export class IdentityService {
case TransactionMetadataAccessGroup:
case TransactionMetadataAccessGroupMembers:
case TransactionMetadataNewMessage:
case TransactionMetadataUnjailValidator:
return AccessLevel.ApproveLarge;
}

Expand Down
57 changes: 56 additions & 1 deletion src/lib/bindata/transcoders.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { bufToUvarint64, uvarint64ToBuf } from './util';
import {
bufToUvarint64,
bufToVarint64,
uvarint64ToBuf,
varint64ToBuf,
} from './util';
import { TransactionNonce } from '../deso/transaction';

export interface Transcoder<T> {
Expand All @@ -19,6 +24,11 @@ export const Uvarint64: Transcoder<number> = {
write: (uint) => uvarint64ToBuf(uint),
};

export const Varint64: Transcoder<number> = {
read: (bytes) => bufToVarint64(bytes),
write: (int) => varint64ToBuf(int),
};

export const Boolean: Transcoder<boolean> = {
read: (bytes) => [bytes.readUInt8(0) != 0, bytes.slice(1)],
write: (bool) => {
Expand Down Expand Up @@ -50,6 +60,31 @@ export const VarBuffer: Transcoder<Buffer> = {
write: (bytes) => Buffer.concat([uvarint64ToBuf(bytes.length), bytes]),
};

export const VarBufferArray: Transcoder<Buffer[]> = {
read: (bytes) => {
let [count, buffer] = bufToUvarint64(bytes);

const result = [];
for (let i = 0; i < count; i++) {
let size;
[size, buffer] = bufToUvarint64(buffer);
result.push(buffer.slice(0, size));
buffer = buffer.slice(size);
}

return [result, buffer];
},
write: (buffers) => {
const count = uvarint64ToBuf(buffers.length);
return Buffer.concat([
count,
...buffers.map((buffer) =>
Buffer.concat([uvarint64ToBuf(buffer.length), buffer])
),
]);
},
};

export const TransactionNonceTranscoder: Transcoder<TransactionNonce | null> = {
read: (bytes) => {
return TransactionNonce.fromBytes(bytes) as [TransactionNonce, Buffer];
Expand All @@ -71,6 +106,26 @@ export function Optional<T>(transcoder: Transcoder<T>): Transcoder<T | null> {
};
}

export function BoolOptional<T>(
transcoder: Transcoder<T>
): Transcoder<T | null> {
return {
read: (bytes: Buffer) => {
const existence = bytes.readUInt8(0) != 0;
if (!existence) {
return [null, bytes.slice(1)];
}
return transcoder.read(bytes.slice(1));
},
write: (value: T | null) => {
if (value === null) {
return Buffer.alloc(1);
}
return Buffer.concat([Buffer.alloc(1, 1), transcoder.write(value)]);
},
};
}

export const ChunkBuffer = (width: number): Transcoder<Buffer[]> => ({
read: (bytes) => {
let [count, buffer] = bufToUvarint64(bytes);
Expand Down
18 changes: 18 additions & 0 deletions src/lib/bindata/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,21 @@ export const uint64ToBufBigEndian = (uint: number): Buffer => {

return new Buffer(result.reverse());
};

// TODO: Verify these are correct....
export const varint64ToBuf = (int: number): Buffer => {
let ux = BigInt(int) << BigInt(1);
if (int < 0) {
ux = ~ux;
}
return uvarint64ToBuf(Number(ux));
};

export const bufToVarint64 = (buffer: Buffer): [number, Buffer] => {
const [ux, n] = bufToUvarint64(buffer);
let x = BigInt(ux) >> BigInt(1);
if (ux & 1) {
x = ~x;
}
return [Number(x), n];
};
Loading

0 comments on commit fd55a7c

Please sign in to comment.