From b427c6e661c6f2ddb5cda7eb62727e6f7ef52c43 Mon Sep 17 00:00:00 2001 From: Lazy Nina <> Date: Fri, 5 Jan 2024 13:54:29 -0500 Subject: [PATCH 1/5] Add newline to make graphite happy --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 853840f5..00c6be9d 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,4 @@ After proper configuration of `environment.ts` and `environment.prod.ts`, run `n ## Format Formatting will happen upon commit. Developers can also run `npm run format` or `npx npm run format` if npm isn't installed to format all source files + From f2039cc9cf49da8bad4f2b08d3ba34ab5f6ba4f3 Mon Sep 17 00:00:00 2001 From: Jon Pollock <135658176+poolcoke@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:30:44 -0800 Subject: [PATCH 2/5] Lockups (#299) * 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 <> --- src/app/approve/approve.component.ts | 141 ++++++++++++++++++++++++++- src/app/identity.service.ts | 20 ++++ src/lib/bindata/transcoders.ts | 57 ++++++++++- src/lib/bindata/util.ts | 18 ++++ src/lib/deso/transaction.ts | 129 ++++++++++++++++++++++++ 5 files changed, 361 insertions(+), 4 deletions(-) diff --git a/src/app/approve/approve.component.ts b/src/app/approve/approve.component.ts index b8ed327d..1fe9606a 100644 --- a/src/app/approve/approve.component.ts +++ b/src/app/approve/approve.component.ts @@ -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'; @@ -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`; @@ -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( @@ -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 ); @@ -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. @@ -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; } diff --git a/src/app/identity.service.ts b/src/app/identity.service.ts index 21d75fac..673956f2 100644 --- a/src/app/identity.service.ts +++ b/src/app/identity.service.ts @@ -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'; @@ -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: @@ -531,6 +550,7 @@ export class IdentityService { case TransactionMetadataAccessGroup: case TransactionMetadataAccessGroupMembers: case TransactionMetadataNewMessage: + case TransactionMetadataUnjailValidator: return AccessLevel.ApproveLarge; } diff --git a/src/lib/bindata/transcoders.ts b/src/lib/bindata/transcoders.ts index 5974e7ab..6cccfab0 100644 --- a/src/lib/bindata/transcoders.ts +++ b/src/lib/bindata/transcoders.ts @@ -1,4 +1,9 @@ -import { bufToUvarint64, uvarint64ToBuf } from './util'; +import { + bufToUvarint64, + bufToVarint64, + uvarint64ToBuf, + varint64ToBuf, +} from './util'; import { TransactionNonce } from '../deso/transaction'; export interface Transcoder { @@ -19,6 +24,11 @@ export const Uvarint64: Transcoder = { write: (uint) => uvarint64ToBuf(uint), }; +export const Varint64: Transcoder = { + read: (bytes) => bufToVarint64(bytes), + write: (int) => varint64ToBuf(int), +}; + export const Boolean: Transcoder = { read: (bytes) => [bytes.readUInt8(0) != 0, bytes.slice(1)], write: (bool) => { @@ -50,6 +60,31 @@ export const VarBuffer: Transcoder = { write: (bytes) => Buffer.concat([uvarint64ToBuf(bytes.length), bytes]), }; +export const VarBufferArray: Transcoder = { + 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 = { read: (bytes) => { return TransactionNonce.fromBytes(bytes) as [TransactionNonce, Buffer]; @@ -71,6 +106,26 @@ export function Optional(transcoder: Transcoder): Transcoder { }; } +export function BoolOptional( + transcoder: Transcoder +): Transcoder { + 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 => ({ read: (bytes) => { let [count, buffer] = bufToUvarint64(bytes); diff --git a/src/lib/bindata/util.ts b/src/lib/bindata/util.ts index 9a11ea93..33669541 100644 --- a/src/lib/bindata/util.ts +++ b/src/lib/bindata/util.ts @@ -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]; +}; diff --git a/src/lib/deso/transaction.ts b/src/lib/deso/transaction.ts index cd7416bd..b202fa6b 100644 --- a/src/lib/deso/transaction.ts +++ b/src/lib/deso/transaction.ts @@ -2,6 +2,7 @@ import { BinaryRecord, Transcode } from '../bindata'; import { ArrayOf, Boolean, + BoolOptional, ChunkBuffer, Enum, FixedBuffer, @@ -11,6 +12,8 @@ import { Uint8, Uvarint64, VarBuffer, + VarBufferArray, + Varint64, } from '../bindata/transcoders'; export class TransactionInput extends BinaryRecord { @@ -581,6 +584,122 @@ export class TransactionMetadataNewMessage extends BinaryRecord { newMessageOperation: number = 0; } +export class TransactionMetadataRegisterAsValidator extends TransactionMetadata { + @Transcode(VarBufferArray) + domains: Buffer[] = []; + + @Transcode(Boolean) + disableDelegatedStake: boolean = false; + + @Transcode(Uvarint64) + delegatedStakeCommissionBasisPoints: number = 0; + + // TODO: Technically this is a bls public key, + // but under the hood it's really just a byte array. + // The challenge is converting this into something human + // readable in the UI. + @Transcode(VarBuffer) + votingPublicKey: Buffer = Buffer.alloc(0); + + // TODO: Technically this is a bls signature, + // but under the hood it's really just a byte array. + // The challenge is converting this into something human + // readable in the UI. + @Transcode(VarBuffer) + votingAuthorization: Buffer = Buffer.alloc(0); +} + +export class TransactionMetadataUnregisterAsValidator extends TransactionMetadata {} + +export class TransactionMetadataStake extends TransactionMetadata { + @Transcode(VarBuffer) + validatorPublicKey: Buffer = Buffer.alloc(0); + + @Transcode(Uint8) + rewardMethod: number = 0; + + // TODO: We may want a better way to handle uint256s. + @Transcode(BoolOptional(VarBuffer)) + stakeAmountNanos: Buffer = Buffer.alloc(0); +} + +export class TransactionMetadataUnstake extends TransactionMetadata { + @Transcode(VarBuffer) + validatorPublicKey: Buffer = Buffer.alloc(0); + + // TODO: We may want a better way to handle uint256s. + @Transcode(BoolOptional(VarBuffer)) + unstakeAmountNanos: Buffer = Buffer.alloc(0); +} + +export class TransactionMetadataUnlockStake extends TransactionMetadata { + @Transcode(VarBuffer) + validatorPublicKey: Buffer = Buffer.alloc(0); + + @Transcode(Uvarint64) + startEpochNumber: number = 0; + + @Transcode(Uvarint64) + endEpochNumber: number = 0; +} + +export class TransactionMetadataUnjailValidator extends TransactionMetadata {} + +export class TransactionMetadataCoinLockup extends TransactionMetadata { + @Transcode(VarBuffer) + profilePublicKey: Buffer = Buffer.alloc(0); + + @Transcode(VarBuffer) + recipientPublicKey: Buffer = Buffer.alloc(0); + + @Transcode(Varint64) + unlockTimestampNanoSecs: number = 0; + + @Transcode(Varint64) + vestingEndTimestampNanoSecs: number = 0; + + // TODO: We may want a better way to handle uint256s. + @Transcode(BoolOptional(VarBuffer)) + lockupAmountBaseUnits: Buffer = Buffer.alloc(0); +} + +export class TransactionMetadataUpdateCoinLockupParams extends TransactionMetadata { + @Transcode(Varint64) + lockupYieldDurationNanoSecs: number = 0; + + @Transcode(Uvarint64) + lockupYieldAPYBasisPoints: number = 0; + + @Transcode(Boolean) + removeYieldCurvePoint: boolean = false; + + @Transcode(Boolean) + newLockupTransferRestrictions: boolean = false; + + @Transcode(Uint8) + lockupTransferRestrictionStatus: number = 0; +} + +export class TransactionMetadataCoinLockupTransfer extends TransactionMetadata { + @Transcode(VarBuffer) + recipientPublicKey: Buffer = Buffer.alloc(0); + + @Transcode(VarBuffer) + profilePublicKey: Buffer = Buffer.alloc(0); + + @Transcode(Varint64) + unlockTimestampNanoSecs: number = 0; + + // TODO: We may want a better way to handle uint256s. + @Transcode(BoolOptional(VarBuffer)) + lockedCoinsToTransferBaseUnits: Buffer = Buffer.alloc(0); +} + +export class TransactionMetadataCoinUnlock extends TransactionMetadata { + @Transcode(VarBuffer) + profilePublicKey: Buffer = Buffer.alloc(0); +} + export const TransactionTypeMetadataMap = { 1: TransactionMetadataBlockReward, 2: TransactionMetadataBasicTransfer, @@ -614,6 +733,16 @@ export const TransactionTypeMetadataMap = { 31: TransactionMetadataAccessGroup, 32: TransactionMetadataAccessGroupMembers, 33: TransactionMetadataNewMessage, + 34: TransactionMetadataRegisterAsValidator, + 35: TransactionMetadataUnregisterAsValidator, + 36: TransactionMetadataStake, + 37: TransactionMetadataUnstake, + 38: TransactionMetadataUnlockStake, + 39: TransactionMetadataUnjailValidator, + 40: TransactionMetadataCoinLockup, + 41: TransactionMetadataUpdateCoinLockupParams, + 42: TransactionMetadataCoinLockupTransfer, + 43: TransactionMetadataCoinUnlock, }; export class Transaction extends BinaryRecord { From e448bf47d1260a96396cf0a678725ab719872f8b Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:26:44 -0500 Subject: [PATCH 3/5] PoS Spending Limits UI (#298) --- src/app/app.module.ts | 4 + src/app/backend-api.service.ts | 43 +++++- ...ction-spending-limit-lockup.component.html | 29 ++++ ...ction-spending-limit-lockup.component.scss | 0 ...saction-spending-limit-lockup.component.ts | 44 ++++++ ...tion-spending-limit-section.component.html | 129 ++++++++++++++++++ ...action-spending-limit-section.component.ts | 106 ++++++++++++-- ...action-spending-limit-stake.component.html | 20 +++ ...action-spending-limit-stake.component.scss | 0 ...nsaction-spending-limit-stake.component.ts | 71 ++++++++++ .../transaction-spending-limit.component.html | 24 ++++ .../transaction-spending-limit.component.ts | 98 +++++++++---- src/lib/deso/transaction.ts | 1 + src/lib/pipes/truncate-deso-address.pipe.ts | 2 +- 14 files changed, 534 insertions(+), 37 deletions(-) create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.html create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.scss create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.ts create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.html create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.scss create mode 100644 src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 23933e92..3e88bb5f 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -60,6 +60,8 @@ import { TransactionSpendingLimitDaoCoinLimitOrderComponent } from './transactio import { TransactionSpendingLimitNftComponent } from './transaction-spending-limit/transaction-spending-limit-nft/transaction-spending-limit-nft.component'; import { TransactionSpendingLimitSectionComponent } from './transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component'; import { TransactionSpendingLimitComponent } from './transaction-spending-limit/transaction-spending-limit.component'; +import { TransactionSpendingLimitStakeComponent } from './transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component'; +import { TransactionSpendingLimitLockupComponent } from './transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component'; @NgModule({ declarations: [ @@ -107,6 +109,8 @@ import { TransactionSpendingLimitComponent } from './transaction-spending-limit/ RecoverySecretComponent, BackupSeedDialogComponent, RemoveAccountDialogComponent, + TransactionSpendingLimitStakeComponent, + TransactionSpendingLimitLockupComponent, ], imports: [ BrowserModule, diff --git a/src/app/backend-api.service.ts b/src/app/backend-api.service.ts index 710b6b3f..e7de70dc 100644 --- a/src/app/backend-api.service.ts +++ b/src/app/backend-api.service.ts @@ -147,7 +147,8 @@ export type LimitOperationString = | NFTLimitOperationString | AssociationOperationString | AccessGroupOperationString - | AccessGroupMemberOperationString; + | AccessGroupMemberOperationString + | LockupLimitOperationString; export type CreatorCoinOperationLimitMap = CoinOperationLimitMap; export type DAOCoinOperationLimitMap = @@ -236,6 +237,42 @@ export type AccessGroupMemberLimitMapItem = { OpCount: number; }; +export type StakeLimitMapItem = { + ValidatorPublicKeyBase58Check: string; + StakeLimit: string; // Hex string +}; + +export type UnstakeLimitMapItem = { + ValidatorPublicKeyBase58Check: string; + UnstakeLimit: string; // Hex string +}; + +export type UnlockStakeLimitMapItem = { + ValidatorPublicKeyBase58Check: string; + OpCount: number; +}; + +export enum LockupLimitScopeType { + ANY = 'AnyCoins', + SCOPED = 'ScopedCoins', +} + +export enum LockupLimitOperationString { + ANY = 'Any', + COIN_LOCKUP = 'CoinLockup', + UPDATE_COIN_LOCKUP_YIELD_CURVE = 'UpdateCoinLockupYieldCurve', + UPDATE_COIN_LOCKUP_TRANSFER_RESTRICTIONS = 'UpdateCoinLockupTransferRestrictions', + COIN_LOCKUP_TRANSFER = 'CoinLockupTransferOperationString', + COIN_UNLOCK = 'CoinLockupUnlock', +} + +export type LockupLimitMapItem = { + ProfilePublicKeyBase58Check: string; + ScopeType: LockupLimitScopeType; + Operation: LockupLimitOperationString; + OpCount: number; +}; + export interface TransactionSpendingLimitResponse { GlobalDESOLimit: number; // TODO: make enum for transaction type string @@ -247,6 +284,10 @@ export interface TransactionSpendingLimitResponse { AssociationLimitMap?: AssociationLimitMapItem[]; AccessGroupLimitMap?: AccessGroupLimitMapItem[]; AccessGroupMemberLimitMap?: AccessGroupMemberLimitMapItem[]; + StakeLimitMap?: StakeLimitMapItem[]; + UnstakeLimitMap?: UnstakeLimitMapItem[]; + UnlockStakeLimitMap?: UnlockStakeLimitMapItem[]; + LockupLimitMap?: LockupLimitMapItem[]; IsUnlimited?: boolean; DerivedKeyMemo?: string; } diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.html b/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.html new file mode 100644 index 00000000..528cc23c --- /dev/null +++ b/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.html @@ -0,0 +1,29 @@ +
+
+ + {{ + appUser?.ProfileEntryResponse?.Username || + lockupLimitMapItem?.ProfilePublicKeyBase58Check || + (lockupLimitMapItem?.ScopeType === LockupLimitScopeType.ANY + ? 'Any Profile' + : 'DESO') | truncateAddressOrUsername + }} +
+
+ + {{ getOperationString() }} + +
+
+ + {{ globalVars.formatTxCountLimit(lockupLimitMapItem?.OpCount) }} + +
+
diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.scss b/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.ts b/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.ts new file mode 100644 index 00000000..ab3f12b2 --- /dev/null +++ b/src/app/transaction-spending-limit/transaction-spending-limit-lockup/transaction-spending-limit-lockup.component.ts @@ -0,0 +1,44 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { GlobalVarsService } from 'src/app/global-vars.service'; +import { + LockupLimitMapItem, + LockupLimitOperationString, + LockupLimitScopeType, + User, +} from '../../backend-api.service'; +import { TransactionSpendingLimitComponent } from '../transaction-spending-limit.component'; + +@Component({ + selector: 'app-transaction-spending-limit-lockup', + templateUrl: './transaction-spending-limit-lockup.component.html', + styleUrls: ['./transaction-spending-limit-lockup.component.scss'], +}) +export class TransactionSpendingLimitLockupComponent implements OnInit { + @Input() lockupLimitMapItem: LockupLimitMapItem | undefined; + @Input() appUser: User | undefined; + TransactionSpendingLimitComponent = TransactionSpendingLimitComponent; + LockupLimitScopeType = LockupLimitScopeType; + + constructor(public globalVars: GlobalVarsService) {} + + ngOnInit(): void {} + + getOperationString(): string { + switch (this.lockupLimitMapItem?.Operation) { + case LockupLimitOperationString.ANY: + return 'Any'; + case LockupLimitOperationString.COIN_LOCKUP: + return 'Lockup'; + case LockupLimitOperationString.COIN_LOCKUP_TRANSFER: + return 'Transfer'; + case LockupLimitOperationString.UPDATE_COIN_LOCKUP_YIELD_CURVE: + return 'Update lockup yield curve'; + case LockupLimitOperationString.UPDATE_COIN_LOCKUP_TRANSFER_RESTRICTIONS: + return 'Update transfer restriction'; + case LockupLimitOperationString.COIN_UNLOCK: + return 'Unlock coins'; + default: + return ''; + } + } +} diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.html b/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.html index ac6436d2..d0e8ec70 100644 --- a/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.html +++ b/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.html @@ -220,6 +220,135 @@ > + +
+
Validator
+
Amount
+
+
+ +
+
+ +
+
+ +
+
Validator
+
Amount
+
+
+ +
+
+ +
+
+ +
+
Validator
+
Txn Limit
+
+
+ +
+
+ +
+
+ +
+
Profile
+
Operation
+
Txn Limit
+
+
+ +
+
+ +
+
diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.ts b/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.ts index 712de2fa..7895e00b 100644 --- a/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.ts +++ b/src/app/transaction-spending-limit/transaction-spending-limit-section/transaction-spending-limit-section.component.ts @@ -9,9 +9,15 @@ import { DAOCoinLimitOrderLimitItem, DAOCoinLimitOrderLimitMap, DAOCoinOperationLimitMap, + LockupLimitMapItem, + LockupLimitOperationString, + LockupLimitScopeType, NFTLimitOperationString, NFTOperationLimitMap, OperationToCountMap, + StakeLimitMapItem, + UnlockStakeLimitMapItem, + UnstakeLimitMapItem, User, } from '../../backend-api.service'; import { GlobalVarsService } from '../../global-vars.service'; @@ -31,7 +37,11 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { | DAOCoinLimitOrderLimitMap | AssociationLimitMapItem[] | AccessGroupLimitMapItem[] - | AccessGroupMemberLimitMapItem[] = {}; + | AccessGroupMemberLimitMapItem[] + | StakeLimitMapItem[] + | UnstakeLimitMapItem[] + | UnlockStakeLimitMapItem[] + | LockupLimitMapItem[] = {}; @Input() sectionTitle: string = ''; @Input() userMap: { [k: string]: User } = {}; @@ -44,6 +54,12 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { | OperationToCountMap | undefined; anyNFTItem: OperationToCountMap | undefined; + anyLockupLimitItems: LockupLimitMapItem[] = []; + anyValidatorItem: + | StakeLimitMapItem + | UnstakeLimitMapItem + | UnlockStakeLimitMapItem + | undefined; coinLimitMap: CreatorCoinOperationLimitMap | DAOCoinOperationLimitMap = {}; txnLimitMap: { [k: string]: number } = {}; @@ -53,6 +69,10 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { associationLimitMap: AssociationLimitMapItem[] = []; accessGroupLimitMap: AccessGroupLimitMapItem[] = []; accessGroupMemberLimitMap: AccessGroupMemberLimitMapItem[] = []; + stakeLimitMap: StakeLimitMapItem[] = []; + unstakeLimitMap: UnstakeLimitMapItem[] = []; + unlockStakeLimitMap: UnlockStakeLimitMapItem[] = []; + lockupLimitMap: LockupLimitMapItem[] = []; constructor(public globalVars: GlobalVarsService) {} @@ -113,6 +133,47 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { case TransactionSpendingLimitComponent.AccessGroupMemberSection: this.accessGroupMemberLimitMap = this .sectionMap as AccessGroupMemberLimitMapItem[]; + break; + case TransactionSpendingLimitComponent.StakeSection: + this.stakeLimitMap = this.sectionMap as StakeLimitMapItem[]; + this.anyValidatorItem = this.stakeLimitMap.find( + (item) => item.ValidatorPublicKeyBase58Check === '' + ); + this.stakeLimitMap = this.stakeLimitMap.filter( + (item) => item.ValidatorPublicKeyBase58Check !== '' + ); + break; + case TransactionSpendingLimitComponent.UnstakeSection: + this.unstakeLimitMap = this.sectionMap as UnstakeLimitMapItem[]; + this.anyValidatorItem = this.unstakeLimitMap.find( + (item) => item.ValidatorPublicKeyBase58Check === '' + ); + this.unstakeLimitMap = this.unstakeLimitMap.filter( + (item) => item.ValidatorPublicKeyBase58Check !== '' + ); + break; + case TransactionSpendingLimitComponent.UnlockStakeSection: + this.unlockStakeLimitMap = this.sectionMap as UnlockStakeLimitMapItem[]; + this.anyValidatorItem = this.unlockStakeLimitMap.find( + (item) => item.ValidatorPublicKeyBase58Check === '' + ); + this.unlockStakeLimitMap = this.unlockStakeLimitMap.filter( + (item) => item.ValidatorPublicKeyBase58Check !== '' + ); + break; + case TransactionSpendingLimitComponent.LockupSection: + this.lockupLimitMap = this.sectionMap as LockupLimitMapItem[]; + this.anyLockupLimitItems = this.lockupLimitMap.filter( + (item) => + item.ProfilePublicKeyBase58Check === '' && + item.ScopeType === LockupLimitScopeType.ANY + ); + this.lockupLimitMap = this.lockupLimitMap.filter( + (item) => + item.ProfilePublicKeyBase58Check !== '' || + item.ScopeType !== LockupLimitScopeType.ANY + ); + break; } this.showAll = this.getSectionMapLength() <= this.defaultNumShown; @@ -136,6 +197,12 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { return 'Access Group'; case TransactionSpendingLimitComponent.AccessGroupMemberSection: return 'Access Group Member'; + case TransactionSpendingLimitComponent.StakeSection: + case TransactionSpendingLimitComponent.UnstakeSection: + case TransactionSpendingLimitComponent.UnlockStakeSection: + return 'Validator'; + case TransactionSpendingLimitComponent.LockupSection: + return 'Lockup'; default: return ''; } @@ -148,18 +215,33 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { return !!this.anyCreatorItem; case TransactionSpendingLimitComponent.NFTLimitsSection: return !!this.anyNFTItem; + case TransactionSpendingLimitComponent.StakeSection: + case TransactionSpendingLimitComponent.UnstakeSection: + case TransactionSpendingLimitComponent.UnlockStakeSection: + return !!this.anyValidatorItem; + case TransactionSpendingLimitComponent.LockupSection: + return !!this.anyLockupLimitItems.length; } return false; } sectionSummary(): string { - const operationsStr = - this.sectionTitle !== - TransactionSpendingLimitComponent.TransactionLimitsSection && - this.sectionTitle !== - TransactionSpendingLimitComponent.DAOCoinLimitOrderLimitSection - ? 'operations on ' - : ''; + let operationsStr = 'operations on '; + switch (this.sectionTitle) { + case TransactionSpendingLimitComponent.TransactionLimitsSection: + case TransactionSpendingLimitComponent.DAOCoinLimitOrderLimitSection: + operationsStr = ''; + break; + case TransactionSpendingLimitComponent.StakeSection: + operationsStr = 'stake operations on '; + break; + case TransactionSpendingLimitComponent.UnstakeSection: + operationsStr = 'unstake operations on '; + break; + case TransactionSpendingLimitComponent.UnlockStakeSection: + operationsStr = 'unlock stake operations on '; + break; + } const keyLen = this.getSectionMapLength(); const sectionItemType = this.sectionItemType(); return `This app can execute the following ${operationsStr}${keyLen} specific ${sectionItemType}${ @@ -181,6 +263,14 @@ export class TransactionSpendingLimitSectionComponent implements OnInit { return this.accessGroupLimitMap.length; case TransactionSpendingLimitComponent.AccessGroupMemberSection: return this.accessGroupMemberLimitMap.length; + case TransactionSpendingLimitComponent.StakeSection: + return this.stakeLimitMap.length; + case TransactionSpendingLimitComponent.UnstakeSection: + return this.unstakeLimitMap.length; + case TransactionSpendingLimitComponent.UnlockStakeSection: + return this.unlockStakeLimitMap.length; + case TransactionSpendingLimitComponent.LockupSection: + return this.lockupLimitMap.length; default: return this.globalVars.ObjectKeyLength(this.sectionMap); } diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.html b/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.html new file mode 100644 index 00000000..a2ac5c52 --- /dev/null +++ b/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.html @@ -0,0 +1,20 @@ +
+
+ + {{ + appUser?.ProfileEntryResponse?.Username || + stakeLimitMapItem?.ValidatorPublicKeyBase58Check || + 'Any Validator' | truncateAddressOrUsername + }} +
+ + {{ getOpCountString() }} + +
diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.scss b/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.ts b/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.ts new file mode 100644 index 00000000..23927a3b --- /dev/null +++ b/src/app/transaction-spending-limit/transaction-spending-limit-stake/transaction-spending-limit-stake.component.ts @@ -0,0 +1,71 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { GlobalVarsService } from 'src/app/global-vars.service'; +import { + StakeLimitMapItem, + UnlockStakeLimitMapItem, + UnstakeLimitMapItem, + User, +} from '../../backend-api.service'; +import { TransactionSpendingLimitComponent } from '../transaction-spending-limit.component'; + +@Component({ + selector: 'app-transaction-spending-limit-stake', + templateUrl: './transaction-spending-limit-stake.component.html', + styleUrls: ['./transaction-spending-limit-stake.component.scss'], +}) +export class TransactionSpendingLimitStakeComponent implements OnInit { + @Input() stakeLimitMapItem: + | StakeLimitMapItem + | UnstakeLimitMapItem + | UnlockStakeLimitMapItem + | undefined; + @Input() operationName: string = ''; + @Input() appUser: User | undefined; + TransactionSpendingLimitComponent = TransactionSpendingLimitComponent; + + constructor(public globalVars: GlobalVarsService) {} + + ngOnInit(): void {} + + getOpCountString(): string { + switch (this.operationName) { + case 'Stake': + return ( + this.hexNanosToUnitString( + (this.stakeLimitMapItem as StakeLimitMapItem)?.StakeLimit as string + ) + ' DESO' + ); + case 'Unstake': + return ( + this.hexNanosToUnitString( + (this.stakeLimitMapItem as UnstakeLimitMapItem) + ?.UnstakeLimit as string + ) + ' DESO' + ); + case 'Unlock Stake': + return ( + this.stakeLimitMapItem as UnlockStakeLimitMapItem + )?.OpCount.toString(); + default: + return ''; + } + } + + hexNanosToUnitString(baseUnits: string): string { + return this.nanosToUnitString(parseInt(baseUnits, 16)); + } + + nanosToUnitString(baseUnits: number): string { + return this.toFixedLengthDecimalString(baseUnits / 1e9); + } + + toFixedLengthDecimalString(num: number): string { + // Change nanos into a formatted string of units. This combination of toFixed and regex removes trailing zeros. + // If we do a regular toString(), some numbers can be represented in E notation which doesn't look as good. + const formattedNum = num.toFixed(9).replace(/^(\d*\.\d*?[1-9]?)0+$/, '$1'); + // Integers may have a trailing decimal place, so if we end with a decimal place, we slice off the last character. + return formattedNum.endsWith('.') + ? formattedNum.slice(0, formattedNum.length - 1) + : formattedNum; + } +} diff --git a/src/app/transaction-spending-limit/transaction-spending-limit.component.html b/src/app/transaction-spending-limit/transaction-spending-limit.component.html index fcb2e54f..b9cb58c8 100644 --- a/src/app/transaction-spending-limit/transaction-spending-limit.component.html +++ b/src/app/transaction-spending-limit/transaction-spending-limit.component.html @@ -134,5 +134,29 @@ [userMap]="userMap" *ngIf="transactionSpendingLimitResponse.AccessGroupMemberLimitMap" > + + + + diff --git a/src/app/transaction-spending-limit/transaction-spending-limit.component.ts b/src/app/transaction-spending-limit/transaction-spending-limit.component.ts index 8b0df624..6c03ee57 100644 --- a/src/app/transaction-spending-limit/transaction-spending-limit.component.ts +++ b/src/app/transaction-spending-limit/transaction-spending-limit.component.ts @@ -7,7 +7,11 @@ import { CoinLimitOperationString, CoinOperationLimitMap, DAOCoinLimitOrderLimitMap, + LockupLimitMapItem, + StakeLimitMapItem, TransactionSpendingLimitResponse, + UnlockStakeLimitMapItem, + UnstakeLimitMapItem, User, } from '../backend-api.service'; import { GlobalVarsService } from '../global-vars.service'; @@ -35,6 +39,10 @@ export class TransactionSpendingLimitComponent implements OnInit { static AssociationSection = 'Associations'; static AccessGroupSection = 'Access Groups'; static AccessGroupMemberSection = 'Access Group Members'; + static StakeSection = 'Stake'; + static UnstakeSection = 'Unstake'; + static UnlockStakeSection = 'Unlock Stake'; + static LockupSection = 'Lockup'; TransactionSpendingLimitComponent = TransactionSpendingLimitComponent; @@ -48,32 +56,35 @@ export class TransactionSpendingLimitComponent implements OnInit { ...new Set( this.getPublicKeysFromCoinOperationLimitMap( this.transactionSpendingLimitResponse?.CreatorCoinOperationLimitMap - ) - .concat( - this.getPublicKeysFromCoinOperationLimitMap( - this.transactionSpendingLimitResponse?.DAOCoinOperationLimitMap - ) - ) - .concat( - this.getPublicKeysFromDAOCoinLimitOrderLimitMap( - this.transactionSpendingLimitResponse?.DAOCoinLimitOrderLimitMap - ) - ) - .concat( - this.getPublicKeysFromAssociationLimitMap( - this.transactionSpendingLimitResponse?.AssociationLimitMap - ) - ) - .concat( - this.getPublicKeysFromAccessGroupLimitMap( - this.transactionSpendingLimitResponse?.AccessGroupLimitMap - ) - ) - .concat( - this.getPublicKeysFromAccessGroupLimitMap( - this.transactionSpendingLimitResponse?.AccessGroupMemberLimitMap - ) + ).concat( + this.getPublicKeysFromCoinOperationLimitMap( + this.transactionSpendingLimitResponse?.DAOCoinOperationLimitMap + ), + this.getPublicKeysFromDAOCoinLimitOrderLimitMap( + this.transactionSpendingLimitResponse?.DAOCoinLimitOrderLimitMap + ), + this.getPublicKeysFromAssociationLimitMap( + this.transactionSpendingLimitResponse?.AssociationLimitMap + ), + this.getPublicKeysFromAccessGroupLimitMap( + this.transactionSpendingLimitResponse?.AccessGroupLimitMap + ), + this.getPublicKeysFromAccessGroupLimitMap( + this.transactionSpendingLimitResponse?.AccessGroupMemberLimitMap + ), + this.getPublicKeysFromStakeLimitMap( + this.transactionSpendingLimitResponse?.StakeLimitMap + ), + this.getPublicKeysFromStakeLimitMap( + this.transactionSpendingLimitResponse?.UnstakeLimitMap + ), + this.getPublicKeysFromStakeLimitMap( + this.transactionSpendingLimitResponse?.UnlockStakeLimitMap + ), + this.getPublicKeysFromLockupLimitMap( + this.transactionSpendingLimitResponse?.LockupLimitMap ) + ) ), ]; @@ -134,8 +145,41 @@ export class TransactionSpendingLimitComponent implements OnInit { return []; } let allPublicKeys = new Set(); - accessGroupLimitMap.forEach((item) => - allPublicKeys.add(item.AccessGroupOwnerPublicKeyBase58Check) + accessGroupLimitMap.forEach( + (item: AccessGroupLimitMapItem | AccessGroupMemberLimitMapItem) => + allPublicKeys.add(item.AccessGroupOwnerPublicKeyBase58Check) + ); + return Array.from(allPublicKeys); + } + + getPublicKeysFromStakeLimitMap( + stakeLimitMap: + | StakeLimitMapItem[] + | UnstakeLimitMapItem[] + | UnlockStakeLimitMapItem[] + | undefined + ): string[] { + if (!stakeLimitMap) { + return []; + } + let allPublicKeys = new Set(); + stakeLimitMap.forEach( + ( + item: StakeLimitMapItem | UnstakeLimitMapItem | UnlockStakeLimitMapItem + ) => allPublicKeys.add(item.ValidatorPublicKeyBase58Check) + ); + return Array.from(allPublicKeys); + } + + getPublicKeysFromLockupLimitMap( + lockupLimitMap: LockupLimitMapItem[] | undefined + ): string[] { + if (!lockupLimitMap) { + return []; + } + let allPublicKeys = new Set(); + lockupLimitMap.forEach((item: LockupLimitMapItem) => + allPublicKeys.add(item.ProfilePublicKeyBase58Check) ); return Array.from(allPublicKeys); } diff --git a/src/lib/deso/transaction.ts b/src/lib/deso/transaction.ts index b202fa6b..85052bc6 100644 --- a/src/lib/deso/transaction.ts +++ b/src/lib/deso/transaction.ts @@ -418,6 +418,7 @@ export class TransactionDAOCoinLimitOrderLimitMapItem extends BinaryRecord { value: number = 0; } +// TODO: does this need to be updated? Where is it really used? export class TransactionSpendingLimit extends BinaryRecord { @Transcode(Uvarint64) globalDESOLimit: number = 0; diff --git a/src/lib/pipes/truncate-deso-address.pipe.ts b/src/lib/pipes/truncate-deso-address.pipe.ts index 7c009648..ad5bfccc 100644 --- a/src/lib/pipes/truncate-deso-address.pipe.ts +++ b/src/lib/pipes/truncate-deso-address.pipe.ts @@ -6,7 +6,7 @@ import { Pipe, PipeTransform } from '@angular/core'; export class TruncateAddressOrUsernamePipe implements PipeTransform { transform(key: string | undefined) { if (!key) return ''; - if (key.length <= 12) { + if (key.length <= 15) { return key; } return `${key.substring(0, 7)}...${key.substring( From 495f3f2736e53c9fa8f372663dd780d5127b2b13 Mon Sep 17 00:00:00 2001 From: Lazy Nina <81658138+lazynina@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:27:56 -0500 Subject: [PATCH 4/5] Update computation of expiration block height (#300) * PoS Spending Limits UI * Update computation of expiration block height --- Dockerfile | 3 --- src/app/account.service.ts | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9792b2bd..00bb52bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,6 @@ COPY ./package.json . COPY ./package-lock.json . COPY ./.npmrc . -# use yarn to upgrade npm -RUN yarn global add npm@7 - # install frontend dependencies before copying the frontend code # into the container so we get docker cache benefits RUN npm install diff --git a/src/app/account.service.ts b/src/app/account.service.ts index 84d5b8b8..bd9e5e69 100644 --- a/src/app/account.service.ts +++ b/src/app/account.service.ts @@ -351,8 +351,8 @@ export class AccountService { const btcDepositAddress = 'Not implemented yet'; const ethDepositAddress = 'Not implemented yet'; - // days * (24 hours / day) * (60 minutes / hour) * (1 block / 5 minutes) = blocks - const numBlocksBeforeExpiration = (numDaysBeforeExpiration * 24 * 60) / 5; + // days * (24 hours / day) * (60 minutes / hour) * (60 seconds / minute) * (1 block / second) = blocks + const numBlocksBeforeExpiration = numDaysBeforeExpiration * 24 * 60 * 60; // By default, we authorize this derived key for 8640 blocks, which is about 30 days. const expirationBlock = blockHeight + numBlocksBeforeExpiration; From 5a2fec69fcda1cb0ecef1766c3395c6aa40b9e62 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Wed, 28 Feb 2024 22:43:22 -0500 Subject: [PATCH 5/5] Configure to run with pos devnet --- Caddyfile | 46 ++++++++++++++-------------- src/environments/environment.prod.ts | 4 +-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Caddyfile b/Caddyfile index c9d7e6d8..74ed1f5d 100644 --- a/Caddyfile +++ b/Caddyfile @@ -28,28 +28,28 @@ header @html Cache-Control no-store header @html Content-Security-Policy " default-src 'self'; connect-src - {$DOMAIN:https://node.deso.org}/api/v0/get-users-stateless - {$DOMAIN:https://node.deso.org}/api/v0/get-app-state - {$DOMAIN:https://node.deso.org}/api/v0/jumio-begin - {$DOMAIN:https://node.deso.org}/api/v0/jumio-flow-finished - {$DOMAIN:https://node.deso.org}/api/v0/get-referral-info-for-referral-hash - {$DOMAIN:https://node.deso.org}/api/v0/get-user-derived-keys - {$DOMAIN:https://node.deso.org}/api/v0/get-transaction-spending - {$DOMAIN:https://node.deso.org}/api/v0/send-phone-number-verification-text - {$DOMAIN:https://node.deso.org}/api/v0/submit-phone-number-verification-code - {$DOMAIN:https://node.deso.org}/api/v0/get-transaction-spending-limit-hex-string - {$DOMAIN:https://node.deso.org}/api/v0/get-transaction-spending-limit-response-from-hex/ - {$DOMAIN:https://node.deso.org}/api/v0/get-single-post - {$DOMAIN:https://node.deso.org}/api/v0/get-exchange-rate - {$DOMAIN:https://node.deso.org}/api/v0/query-eth-rpc - {$DOMAIN:https://node.deso.org}/api/v0/submit-eth-tx - {$DOMAIN:https://node.deso.org}/api/v0/get-access-bytes - {$DOMAIN:https://node.deso.org}/api/v0/send-starter-deso-for-metamask-account - {$DOMAIN:https://node.deso.org}/api/v0/authorize-derived-key - {$DOMAIN:https://node.deso.org}/api/v0/get-txn - {$DOMAIN:https://node.deso.org}/api/v0/verify-captcha - {$DOMAIN:https://node.deso.org}/api/v0/get-bulk-messaging-public-keys - {$DOMAIN:https://node.deso.org}/api/v0/submit-transaction + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-users-stateless + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-app-state + {$DOMAIN:https://devnet-0.deso.run}/api/v0/jumio-begin + {$DOMAIN:https://devnet-0.deso.run}/api/v0/jumio-flow-finished + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-referral-info-for-referral-hash + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-user-derived-keys + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-transaction-spending + {$DOMAIN:https://devnet-0.deso.run}/api/v0/send-phone-number-verification-text + {$DOMAIN:https://devnet-0.deso.run}/api/v0/submit-phone-number-verification-code + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-transaction-spending-limit-hex-string + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-transaction-spending-limit-response-from-hex/ + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-single-post + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-exchange-rate + {$DOMAIN:https://devnet-0.deso.run}/api/v0/query-eth-rpc + {$DOMAIN:https://devnet-0.deso.run}/api/v0/submit-eth-tx + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-access-bytes + {$DOMAIN:https://devnet-0.deso.run}/api/v0/send-starter-deso-for-metamask-account + {$DOMAIN:https://devnet-0.deso.run}/api/v0/authorize-derived-key + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-txn + {$DOMAIN:https://devnet-0.deso.run}/api/v0/verify-captcha + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-bulk-messaging-public-keys + {$DOMAIN:https://devnet-0.deso.run}/api/v0/submit-transaction https://test.deso.org/api/v0/get-users-stateless https://test.deso.org/api/v0/get-app-state https://test.deso.org/api/v0/jumio-begin @@ -81,7 +81,7 @@ header @html Content-Security-Policy " https://explorer-api.walletconnect.com/ wss://relay.walletconnect.com/; img-src 'self' - {$DOMAIN:https://node.deso.org}/api/v0/get-single-profile-picture/ + {$DOMAIN:https://devnet-0.deso.run}/api/v0/get-single-profile-picture/ https://test.deso.org/api/v0/get-single-profile-picture/ i.imgur.com images.deso.org diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index aaaf87e9..c1aa902b 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,7 +1,7 @@ export const environment = { production: true, - hostname: 'identity.deso.org', - nodeURL: 'https://node.deso.org', + hostname: 'identity.deso.run', + nodeURL: 'https://devnet-0.deso.run', fullAccessHostnames: [ 'bitclout.com', 'bitclout.green',