Skip to content
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
141 changes: 141 additions & 0 deletions src/backend-types/deso-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4616,6 +4616,42 @@ export interface 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;
};

// struct2ts:types/generated/types.TransactionSpendingLimitResponse
export interface TransactionSpendingLimitResponse {
GlobalDESOLimit?: number;
Expand All @@ -4627,6 +4663,10 @@ export interface TransactionSpendingLimitResponse {
AssociationLimitMap?: AssociationLimitMapItem[];
AccessGroupLimitMap?: AccessGroupLimitMapItem[];
AccessGroupMemberLimitMap?: AccessGroupMemberLimitMapItem[];
StakeLimitMap?: StakeLimitMapItem[];
UnstakeLimitMap?: UnstakeLimitMapItem[];
UnlockStakeLimitMap?: UnlockStakeLimitMapItem[];
LockupLimitMap?: LockupLimitMapItem[];
IsUnlimited?: boolean;
}

Expand Down Expand Up @@ -5587,3 +5627,104 @@ export interface GetVideoStatusResponse {
}

export type DiamondLevelString = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';

export interface RegisterAsValidatorRequest {
TransactorPublicKeyBase58Check: string;
Domains: string[];
DelegatedStakeCommissionBasisPoints: number;
DisableDelegatedStake: boolean;
VotingPublicKey: string;
VotingAuthorization: string;
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface UnregisterAsValidatorRequest {
TransactorPublicKeyBase58Check: string;
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface UnjailValidatorRequest {
TransactorPublicKeyBase58Check: string;
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface ValidatorTxnResponse {
SpendAmountNanos: number;
TotalInputNanos: number;
ChangeAmountNanos: number;
FeeNanos: number;
Transaction: MsgDeSoTxn;
TransactionHex: string;
TxnHashHex: string;
}

export interface ValidatorResponse {
ValidatorPublicKeyBase58Check: string;
Domains: string[];
DisableDelegatedStake: boolean;
VotingPublicKey: string;
VotingAuthorization: string;
TotalStakeAmountNanos: string; // HEX STRING
Status: string;
LastActiveAtEpochNumber: number;
JailedAtEpochNumber: number;
ExtraData: Record<string, string>;
}

export enum StakeRewardMethod {
PayToBalance = 'PAY_TO_BALANCE',
Restake = 'RESTAKE',
}

export interface StakeRequest {
TransactorPublicKeyBase58Check: string;
ValidatorPublicKeyBase58Check: string;
RewardMethod: StakeRewardMethod;
StakeAmountNanos: string; // HEX STRING
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface UnstakeRequest {
TransactorPublicKeyBase58Check: string;
ValidatorPublicKeyBase58Check: string;
UnstakeAmountNanos: string; // HEX STRING
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface UnlockStakeRequest {
TransactorPublicKeyBase58Check: string;
ValidatorPublicKeyBase58Check: string;
StartEpochNumber: number;
EndEpochNumber: number;
ExtraData: Record<string, string>;
MinFeeRateNanosPerKB: number;
TransactionFees: TransactionFee[];
}

export interface StakeTxnResponse {
SpendAmountNanos: number;
TotalInputNanos: number;
ChangeAmountNanos: number;
FeeNanos: number;
Transaction: MsgDeSoTxn;
TransactionHex: string;
TxnHashHex: string;
}

export interface StakeEntryResponse {
StakerPublicKeyBase58Check: string;
ValidatorPublicKeyBase58Check: string;
RewardMethod: StakeRewardMethod;
StakeAmountNanos: string; // HEX string
ExtraData: Record<string, string>;
}
74 changes: 74 additions & 0 deletions src/identity/permissions-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,79 @@ export function compareTransactionSpendingLimits(
: ['NFTOperationLimitMap', '', '0', path[path.length - 1]];
}
break;
// TODO: support for making sure a derived key has these limits...
// @jacksondean - this is a little more annoying since
// stake and unstake limits don't have an op count, but rather a deso limit.
case 'StakeLimitMap':
if (
actualPermissions?.StakeLimitMap?.find((map) => {
return (
map.ValidatorPublicKeyBase58Check === '' &&
expectedPermissions?.StakeLimitMap?.[Number(path[1])]
?.StakeLimit &&
parseInt(map.StakeLimit, 16) >=
parseInt(
expectedPermissions?.StakeLimitMap?.[Number(path[1])]
?.StakeLimit,
16
)
);
})
) {
return;
}
break;
case 'UnstakeLimitMap':
if (
actualPermissions?.UnstakeLimitMap?.find((map) => {
return (
map.ValidatorPublicKeyBase58Check === '' &&
expectedPermissions?.UnstakeLimitMap?.[Number(path[1])]
?.UnstakeLimit &&
parseInt(map.UnstakeLimit, 16) >=
parseInt(
expectedPermissions?.UnstakeLimitMap?.[Number(path[1])]
?.UnstakeLimit,
16
)
);
})
) {
return;
}
break;
case 'UnlockStakeLimitMap':
if (
actualPermissions?.UnlockStakeLimitMap?.find((map) => {
return (
map.ValidatorPublicKeyBase58Check === '' &&
map.OpCount >=
normalizeCount(
expectedPermissions?.UnlockStakeLimitMap?.[Number(path[1])]
?.OpCount
)
);
})
) {
return;
}
break;
case 'LockupLimitMap':
if (
actualPermissions?.LockupLimitMap?.find((map) => {
return (
map.ProfilePublicKeyBase58Check === '' &&
map.OpCount >=
normalizeCount(
expectedPermissions?.LockupLimitMap?.[Number(path[1])]
?.OpCount
)
);
})
) {
return;
}
break;
}

const actualVal = getDeepValue(actualPermissions, path);
Expand Down Expand Up @@ -166,6 +239,7 @@ export function buildTransactionSpendingLimitResponse(
}
});
}
// TODO: support for new PoS Spending limits maps.

result.TransactionCountLimitMap = result.TransactionCountLimitMap ?? {};

Expand Down
21 changes: 11 additions & 10 deletions src/identity/transaction-transcoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
VarBuffer,
instanceToType,
VarBufferArray,
BoolOptional,
} from './transcoders.js';
export class TransactionInput extends BinaryRecord {
@Transcode(FixedBuffer(32))
Expand Down Expand Up @@ -602,7 +603,7 @@ export class TransactionMetadataNewMessage extends BinaryRecord {

export class TransactionMetadataRegisterAsValidator extends BinaryRecord {
@Transcode(VarBufferArray)
domains: Buffer[] = [];
domains: Uint8Array[] = [];

@Transcode(Boolean)
disableDelegatedStake = false;
Expand All @@ -615,42 +616,42 @@ export class TransactionMetadataRegisterAsValidator extends BinaryRecord {
// The challenge is converting this into something human
// readable in the UI.
@Transcode(VarBuffer)
votingPublicKey: Buffer = Buffer.alloc(0);
votingPublicKey: Uint8Array = new Uint8Array(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);
votingAuthorization: Uint8Array = new Uint8Array(0);
}

export class TransactionMetadataUnregisterAsValidator extends BinaryRecord {}

export class TransactionMetadataStake extends BinaryRecord {
@Transcode(VarBuffer)
validatorPublicKey: Buffer = Buffer.alloc(0);
validatorPublicKey: Uint8Array = new Uint8Array(0);

@Transcode(Uint8)
rewardMethod = 0;

// TODO: We may want a better way to handle uint256s.
@Transcode(Optional(VarBuffer))
stakeAmountNanos: Buffer = Buffer.alloc(0);
@Transcode(BoolOptional(VarBuffer))
stakeAmountNanos: Uint8Array = new Uint8Array(0);
}

export class TransactionMetadataUnstake extends BinaryRecord {
@Transcode(VarBuffer)
validatorPublicKey: Buffer = Buffer.alloc(0);
validatorPublicKey: Uint8Array = new Uint8Array(0);

// TODO: We may want a better way to handle uint256s.
@Transcode(Optional(VarBuffer))
unstakeAmountNanos: Buffer = Buffer.alloc(0);
@Transcode(BoolOptional(VarBuffer))
unstakeAmountNanos: Uint8Array = new Uint8Array(0);
}

export class TransactionMetadataUnlockStake extends BinaryRecord {
@Transcode(VarBuffer)
validatorPublicKey: Buffer = Buffer.alloc(0);
validatorPublicKey: Uint8Array = new Uint8Array(0);

@Transcode(Uvarint64)
startEpochNumber = 0;
Expand Down
20 changes: 20 additions & 0 deletions src/identity/transcoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ export function Optional<T>(transcoder: Transcoder<T>): Transcoder<T | null> {
};
}

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

export const ChunkBuffer = (width: number): Transcoder<Uint8Array[]> => ({
read: (bytes) => {
const countAndBuffer = bufToUvarint64(bytes);
Expand Down
16 changes: 16 additions & 0 deletions src/identity/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import {
AccessGroupLimitMapItem,
AccessGroupMemberLimitMapItem,
AssociationLimitMapItem,
LockupLimitMapItem,
StakeLimitMapItem,
TransactionSpendingLimitResponse,
TransactionType,
UnlockStakeLimitMapItem,
UnstakeLimitMapItem,
} from '../backend-types/index.js';
export type Network = 'mainnet' | 'testnet';

Expand Down Expand Up @@ -61,6 +65,18 @@ export interface TransactionSpendingLimitResponseOptions {
AccessGroupMemberLimitMapItem,
'OpCount'
> & { OpCount: number | 'UNLIMITED' })[];
StakeLimitMap?: (Omit<StakeLimitMapItem, 'StakeLimit'> & {
StakeLimit: string | 'UNLIMITED'; // TODO: handle unlimited for DESO limit.
})[];
UnstakeLimitMap?: (Omit<UnstakeLimitMapItem, 'UnstakeLimit'> & {
UnstakeLimit: string | 'UNLIMITED'; // TODO: handle unlimited for DESO limit.
})[];
UnlockStakeLimitMap?: (Omit<UnlockStakeLimitMapItem, 'OpCount'> & {
OpCount: number | 'UNLIMITED';
})[];
LockupLimitMap?: (Omit<LockupLimitMapItem, 'OpCount'> & {
OpCount: number | 'UNLIMITED';
})[];
IsUnlimited?: boolean;
}

Expand Down
Loading