Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
Merge branch 'develop' into PE-4423-Remove-Extra-Network-Join-Code
Browse files Browse the repository at this point in the history
  • Loading branch information
dtfiedler authored Aug 23, 2023
2 parents 967202f + dee872a commit 6d43314
Show file tree
Hide file tree
Showing 15 changed files with 538 additions and 14 deletions.
9 changes: 7 additions & 2 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ const Ajv = require('ajv');
const standaloneCode = require('ajv/dist/standalone').default;
const { build } = require('esbuild');
const replace = require('replace-in-file');
const { auctionBidSchema, buyRecordSchema } = require('./schemas');
const {
auctionBidSchema,
buyRecordSchema,
increaseUndernameCountSchema,
} = require('./schemas');

// build our validation source code
const ajv = new Ajv({
schemas: [auctionBidSchema, buyRecordSchema],
schemas: [auctionBidSchema, buyRecordSchema, increaseUndernameCountSchema],
code: { source: true, esm: true },
allErrors: true,
});

const moduleCode = standaloneCode(ajv, {
validateBuyRecord: '#/definitions/buyRecord',
validateAuctionBid: '#/definitions/auctionBid',
validateIncreaseUndernameCount: '#/definitions/increaseUndernameCount',
});

// Now you can write the module code to file
Expand Down
3 changes: 3 additions & 0 deletions schemas/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const { buyRecordSchema } = require('./buyRecord');
const { auctionBidSchema } = require('./auction');
const { increaseUndernameCountSchema } = require('./undernames');

module.exports = {
auctionBidSchema,
buyRecordSchema,
increaseUndernameCountSchema,
};
25 changes: 25 additions & 0 deletions schemas/undernames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const increaseUndernameCountSchema = {
$id: '#/definitions/increaseUndernameCount',
type: 'object',
properties: {
function: {
type: 'string',
const: 'increaseUndernameCount',
},
name: {
type: 'string',
pattern: '^([a-zA-Z0-9][a-zA-Z0-9-]{0,49}[a-zA-Z0-9]|[a-zA-Z0-9]{1})$',
},
qty: {
type: 'number',
minimum: 1,
maximum: 9990, // should be updated with contants "DEFAULT_UNDERNAME_COUNT" and "MAX_ALLOWED_UNDERNAMES"
},
},
required: ['name', 'qty'],
additionalProperties: false,
};

module.exports = {
increaseUndernameCountSchema,
};
17 changes: 15 additions & 2 deletions src/actions/write/buyRecord.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ARNS_NAME_RESERVED_MESSAGE,
DEFAULT_UNDERNAME_COUNT,
INVALID_INPUT_MESSAGE,
INVALID_SHORT_NAME,
INVALID_YEARS_MESSAGE,
Expand Down Expand Up @@ -165,8 +166,19 @@ export const buyRecord = (
// calculate the total fee (initial registration + annual)
const totalRegistrationFee =
type === 'lease'
? calculateTotalRegistrationFee(name, fees, purchasedTier, years)
: calculatePermabuyFee(name, fees, purchasedTier);
? calculateTotalRegistrationFee(
name,
fees,
purchasedTier,
years,
+SmartWeave.block.timestamp,
)
: calculatePermabuyFee(
name,
fees,
purchasedTier,
+SmartWeave.block.timestamp,
);

if (balances[caller] < totalRegistrationFee) {
throw new ContractError(
Expand Down Expand Up @@ -198,6 +210,7 @@ export const buyRecord = (
tier,
type,
startTimestamp: +SmartWeave.block.timestamp,
undernames: DEFAULT_UNDERNAME_COUNT,
// only include timestamp on lease
...(type === 'lease' ? { endTimestamp } : {}),
};
Expand Down
9 changes: 7 additions & 2 deletions src/actions/write/extendRecord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {
TIERS,
} from '../../constants';
import { ContractResult, IOState, PstAction } from '../../types';
import { calculateAnnualRenewalFee } from '../../utilities';
import {
calculateAnnualRenewalFee,
walletHasSufficientBalance,
} from '../../utilities';

declare const ContractError;
declare const SmartWeave: any;
Expand Down Expand Up @@ -78,9 +81,11 @@ export const extendRecord = async (
fees,
purchasedTier,
years,
state.records[name].undernames,
state.records[name]?.endTimestamp,
);

if (balances[caller] < totalExtensionAnnualFee) {
if (!walletHasSufficientBalance(balances, caller, totalExtensionAnnualFee)) {
throw new ContractError(
`Caller balance not high enough to extend this name lease for ${totalExtensionAnnualFee} token(s) for ${years}!`,
);
Expand Down
88 changes: 88 additions & 0 deletions src/actions/write/increaseUndernameCount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
ARNS_NAME_DOES_NOT_EXIST_MESSAGE,
INSUFFICIENT_FUNDS_MESSAGE,
INVALID_INPUT_MESSAGE,
MAX_ALLOWED_UNDERNAMES,
MAX_UNDERNAME_MESSAGE,
SECONDS_IN_GRACE_PERIOD,
} from '../../constants';
import { ContractResult, IOState, PstAction } from '../../types';
import {
calculateProRatedUndernameCost,
walletHasSufficientBalance,
} from '../../utilities';
import { validateIncreaseUndernameCount } from '../../validations.mjs';

declare const ContractError;
declare const SmartWeave: any;

export class IncreaseUndernameCount {
function = 'increaseUndernameCount';
name: string;
qty: number;

constructor(input: any) {
// validate using ajv validator
if (!validateIncreaseUndernameCount(input)) {
throw new ContractError(
`${INVALID_INPUT_MESSAGE} for ${this.function}: ${(
validateIncreaseUndernameCount as any
).errors
.map((e) => {
const key = e.instancePath.replace('/', '');
const value = input[key];
return `${key} ('${value}') ${e.message}`;
})
.join(', ')}`,
);
}
const { name, qty } = input;
this.name = name.trim().toLowerCase();
this.qty = qty;
}
}
// Increases the lease time for an existing record
export const increaseUndernameCount = async (
state: IOState,
{ caller, input }: PstAction,
): Promise<ContractResult> => {
const { name, qty } = new IncreaseUndernameCount(input);

const { balances } = state;

const record = state.records[name];
const currentBlockTime = +SmartWeave.block.timestamp;
const undernameCost = calculateProRatedUndernameCost(
qty,
currentBlockTime,
record.type,
record?.endTimestamp,
);

if (qty + record.undernames > MAX_ALLOWED_UNDERNAMES) {
throw new ContractError(MAX_UNDERNAME_MESSAGE);
}
// Check if the user has enough tokens to increase the undername count
if (!walletHasSufficientBalance(balances, caller, undernameCost)) {
throw new ContractError(
`${INSUFFICIENT_FUNDS_MESSAGE}: caller has ${balances[
caller
].toLocaleString()} but needs to have ${undernameCost.toLocaleString()} to pay for this undername increase of ${qty} for ${name}.`,
);
}
// check if record exists
if (!record) {
throw new ContractError(ARNS_NAME_DOES_NOT_EXIST_MESSAGE);
}
// This name's lease has expired and cannot be extended
if (record.endTimestamp + SECONDS_IN_GRACE_PERIOD <= currentBlockTime) {
throw new ContractError(
`This name has expired and must renewed before its undername support can be extended.`,
);
}
// TODO: move cost to protocol balance
state.records[name].undernames += qty;
state.balances[caller] -= undernameCost;

return { state };
};
18 changes: 16 additions & 2 deletions src/actions/write/submitAuctionBid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ARNS_NAME_RESERVED_MESSAGE,
DEFAULT_UNDERNAME_COUNT,
INSUFFICIENT_FUNDS_MESSAGE,
INVALID_INPUT_MESSAGE,
INVALID_SHORT_NAME,
Expand Down Expand Up @@ -189,8 +190,19 @@ export const submitAuctionBid = (
const serviceTier = tierHistory.find((t: ServiceTier) => t.id === tier)!;
const registrationFee =
type === 'lease'
? calculateTotalRegistrationFee(name, fees, serviceTier, years!)
: calculatePermabuyFee(name, fees, serviceTier);
? calculateTotalRegistrationFee(
name,
fees,
serviceTier,
years!,
+SmartWeave.block.timestamp,
)
: calculatePermabuyFee(
name,
fees,
serviceTier,
+SmartWeave.block.timestamp,
);

// no current auction, create one and vault the balance from the user
if (!auctions[name]) {
Expand Down Expand Up @@ -275,6 +287,7 @@ export const submitAuctionBid = (
type: existingAuction.type,
startTimestamp: +SmartWeave.block.timestamp,
// only include timestamp on lease
undernames: DEFAULT_UNDERNAME_COUNT,
// something to think about - what if a ticking of state never comes? what do we set endTimestamp to?
...(existingAuction.type === 'lease' ? { endTimestamp } : {}),
};
Expand Down Expand Up @@ -332,6 +345,7 @@ export const submitAuctionBid = (
tier: existingAuction.tier,
type: existingAuction.type,
startTimestamp: +SmartWeave.block.timestamp, // overwrite initial start timestamp
undernames: DEFAULT_UNDERNAME_COUNT,
// only include timestamp on lease, endTimestamp is easy in this situation since it was a second interaction that won it
...(existingAuction.type === 'lease' ? { endTimestamp } : {}),
};
Expand Down
8 changes: 6 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { AuctionSettings } from './types';

export const MAX_YEARS = 5; // the maximum amount of years an arns name could be leased for
export const MAX_NAME_LENGTH = 51; // the maximum length of an arns name
export const NAMESPACE_LENGTH = 62; // browser domains are max 63 characters between periods, but we need to leave 1 character for the underscore seperator between the undernames and arns name
export const MAX_NAME_LENGTH = 51; // the maximum length of an arns name - gateway sandbox domains are 52 characters, so to prevent overlap we stop 1 character short, where the 52nd character would be an underscore (which sandbox domains do not use) to prevent overlap
export const MAX_NOTE_LENGTH = 256; // the maximum size of a note field
export const MAX_GATEWAY_LABEL_LENGTH = 16; // the maximum size of a label field
export const MAX_PORT_NUMBER = 65535; // the default end port of tcp/udp port numbers
Expand All @@ -21,10 +22,12 @@ export const SHORT_NAME_RESERVATION_UNLOCK_TIMESTAMP = 1704092400000; // January
export const MAX_ALLOWED_EVOLUTION_DELAY = 720 * 30;
export const MINIMUM_ALLOWED_EVOLUTION_DELAY = 3; // 3 blocks for testing purposes, but should be 720 * 7; // 720 blocks per day times 7 days
export const MINIMUM_ALLOWED_NAME_LENGTH = 5; // names less than 5 characters are reserved for auction
export const UNDERNAMES_COUNT = 10;
export const RARITY_MULTIPLIER_HALVENING = 25;
export const PERMABUY_LEASE_FEE_LENGTH = 10;
export const ALLOWED_ACTIVE_TIERS = [1, 2, 3];
export const ANNUAL_PERCENTAGE_FEE = 0.1; // 10% of cost of name
export const DEFAULT_UNDERNAME_COUNT = 10;
export const MAX_ALLOWED_UNDERNAMES = 10_000; // when modifying these, update the undernames schema
export const UNDERNAME_REGISTRATION_IO_FEE = 1; // 1 IO token per undername
export const NON_CONTRACT_OWNER_MESSAGE = `Caller is not the owner of the ArNS!`;
export const INVALID_ARNS_NAME_MESSAGE = 'Invalid ArNS Record Name';
Expand All @@ -46,6 +49,7 @@ export const INVALID_ID_TIER_MESSAGE =
'Invalid tier ID. Must be present in state before it can be used as a current tier.';
export const INVALID_YEARS_MESSAGE = `Invalid number of years. Must be an integer and less than or equal to ${MAX_YEARS}`;
export const INVALID_SHORT_NAME = `Name is less than ${MINIMUM_ALLOWED_NAME_LENGTH} characters. It will be available for auction after ${SHORT_NAME_RESERVATION_UNLOCK_TIMESTAMP}.`;
export const MAX_UNDERNAME_MESSAGE = `Name has reached undername limit of ${MAX_ALLOWED_UNDERNAMES}`;
export const CURRENT_TIERS = [
'a27dbfe4-6992-4276-91fb-5b97ae8c3ffa',
'93685bbb-8246-4e7e-bef8-d2e7e6c5d44a',
Expand Down
3 changes: 3 additions & 0 deletions src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { finalizeLeave } from './actions/write/finalizeLeave';
import { finalizeOperatorStakeDecrease } from './actions/write/finalizeOperatorStakeDecrease';
import { foundationAction } from './actions/write/foundationAction';
import { increaseOperatorStake } from './actions/write/increaseOperatorStake';
import { increaseUndernameCount } from './actions/write/increaseUndernameCount';
import { initiateLeave } from './actions/write/initiateLeave';
import { initiateOperatorStakeDecrease } from './actions/write/initiateOperatorStakeDecrease';
import { joinNetwork } from './actions/write/joinNetwork';
Expand Down Expand Up @@ -47,6 +48,8 @@ export async function handle(
return buyRecord(state, action);
case 'extendRecord':
return extendRecord(state, action);
case 'increaseUndernameCount':
return increaseUndernameCount(state, action);
case 'evolve':
return evolve(state, action);
case 'balance':
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export type ArNSName = {
endTimestamp?: number; // At what unix time (seconds since epoch) the lease ends
tier: string; // The id of the tier selected at time of purchased
type: 'lease' | 'permabuy';
undernames: number;
};

export type ReservedName = {
Expand Down
Loading

0 comments on commit 6d43314

Please sign in to comment.