Skip to content
This repository was archived by the owner on May 11, 2026. It is now read-only.
Closed
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
19 changes: 4 additions & 15 deletions src/helpers/alias.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { uniq } from 'lodash';
import db from './mysql';

const DEFAULT_ALIAS_EXPIRY_DAYS = 30;
export const DEFAULT_ALIAS_EXPIRY_DAYS = 30;

// These types can always be executed with an alias
const TYPES_EXECUTABLE_BY_ALIAS = [
Expand Down Expand Up @@ -38,25 +38,14 @@ type ExecutableType =
| (typeof OPTIONAL_TYPES_EXECUTABLE_BY_ALIAS)[number]
| (typeof TYPES_EXECUTABLE_BY_STARKNET_ALIAS)[number];

/**
* Checks if an alias relationship exists and is not expired
* @param address - The original address
* @param alias - The alias address to check
* @param expiryDays - Number of days after which alias expires (default: 30)
* @returns Promise<boolean> - True if valid alias exists
*/
export async function isExistingAlias(
address: string,
alias: string,
expiryDays = DEFAULT_ALIAS_EXPIRY_DAYS
): Promise<boolean> {
export async function isExistingAlias(address: string, alias: string): Promise<boolean> {
const query = `SELECT 1
FROM aliases
WHERE address = ? AND alias = ?
AND created > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL ? DAY))
AND expiration > UNIX_TIMESTAMP(NOW())
LIMIT 1`;

const results = await db.queryAsync(query, [address, alias, expiryDays]);
const results = await db.queryAsync(query, [address, alias]);
return results.length > 0;
}

Expand Down
20 changes: 13 additions & 7 deletions src/writer/alias.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import snapshot from '@snapshot-labs/snapshot.js';
import { DEFAULT_ALIAS_EXPIRY_DAYS } from '../helpers/alias';
import log from '../helpers/log';
import db from '../helpers/mysql';
import { jsonParse } from '../helpers/utils';
Expand All @@ -14,12 +15,16 @@ export async function verify(message): Promise<any> {
return Promise.reject('alias cannot be the same as the address');
}

const existing = await db.queryAsync(
'SELECT 1 FROM aliases WHERE address = ? AND alias = ? LIMIT 1',
[message.address, msg.payload.alias]
);
if (existing.length > 0) {
return Promise.reject('alias already exists');
const results = await db.queryAsync('SELECT address FROM aliases WHERE alias = ?', [
msg.payload.alias
]);
for (const row of results) {
if (row.address === message.address) {
return Promise.reject('alias already exists');
}
}
if (results.length > 0) {
return Promise.reject('alias is already linked to another address');
}

return true;
Expand All @@ -32,7 +37,8 @@ export async function action(message, ipfs, receipt, id): Promise<void> {
ipfs,
address: message.address,
alias: msg.payload.alias,
created: msg.timestamp
created: msg.timestamp,
expiration: msg.timestamp + DEFAULT_ALIAS_EXPIRY_DAYS * 86400
};
await db.queryAsync('INSERT INTO aliases SET ?', params);
}
14 changes: 11 additions & 3 deletions test/fixtures/alias.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
import { DEFAULT_ALIAS_EXPIRY_DAYS } from '../../src/helpers/alias';

const now = Math.floor(Date.now() / 1000);
const EXPIRY_SECONDS = DEFAULT_ALIAS_EXPIRY_DAYS * 86400;

export const aliasesSqlFixtures: Record<string, any>[] = [
{
id: '1',
ipfs: 'Qm...',
address: '0x0000000000000000000000000000000000000000',
alias: '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3',
created: Math.floor(Date.now() / 1000)
created: now,
expiration: now + EXPIRY_SECONDS
},
{
id: '2',
ipfs: 'Qm...',
address: '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0',
alias: '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3',
created: Math.floor(Date.now() / 1000)
created: now,
expiration: now + EXPIRY_SECONDS
},
{
id: '3',
ipfs: 'Qm...',
address: '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0',
alias: '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f4',
created: 1
created: 1,
expiration: 1 + EXPIRY_SECONDS
}
];
16 changes: 16 additions & 0 deletions test/integration/helpers/alias.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ describe('alias', () => {
).rejects.toMatch('alias already exists');
});

it('should reject when alias is already linked to another address', async () => {
const alias = aliasesSqlFixtures[0].alias;
const differentAddress = '0x0000000000000000000000000000000000000099';
const msg = {
version: '0.1.4',
timestamp: Math.floor(Date.now() / 1000),
type: 'alias',
from: differentAddress,
payload: { alias }
};

await expect(
verify({ address: differentAddress, from: differentAddress, msg: JSON.stringify(msg) })
).rejects.toMatch('alias is already linked to another address');
});

it('should pass when alias does not exist', async () => {
const msg = {
version: '0.1.4',
Expand Down
1 change: 1 addition & 0 deletions test/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ CREATE TABLE aliases (
address VARCHAR(100) NOT NULL,
alias VARCHAR(100) NOT NULL,
created INT(11) NOT NULL,
expiration INT(11) NOT NULL,
PRIMARY KEY (address, alias),
INDEX ipfs (ipfs)
);
Expand Down
Loading