Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added SIP48 implementation #46

Merged
merged 2 commits into from
Mar 15, 2023
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
5 changes: 4 additions & 1 deletion packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ This version is a major breakthrough with a lots of significant and breaking cha
- `transferAssetOwnership`,
- `getTransactionByReferenceHash`
- `calculateDistributionFee`,
- `getAssetsByOwner`
- `getAssetsByOwner`,
- `searchAliasesByName`,
- `getTopLevelDomains`
- `buyTopLevelDomain`

- New Transaction Subtype Enums for Assets
- `getAccountTransactions` can resolve asset distributions now!
Expand Down
56 changes: 55 additions & 1 deletion packages/core/src/api/__tests__/aliasApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
getAliasesOnSale,
buyAlias,
sellAlias,
getAliasByName
getAliasByName, buyTopLevelDomain, getTopLevelDomains
} from '../factories';
import {mockSignAndBroadcastTransaction, createChainService} from '../../__tests__/helpers';
import {searchAliasesByName} from '../factories/alias/searchAliasesByName';
import {AttachmentMessage} from '../../typings/attachment';

describe('Alias Api', () => {

Expand Down Expand Up @@ -159,4 +161,56 @@ describe('Alias Api', () => {
expect(asset).toEqual({'transaction': 'transactionId'});
});
});

describe('searchAliasesByName', () => {
it('should search as expected', async () => {
httpMock = HttpMockBuilder.create().onGetReply(200, {'aliases': []},
'relPath?requestType=getAliasesByName&aliasName=aliasName&timestamp=10000&firstIndex=0&lastIndex=150'
).build();
const service = createChainService(httpMock, 'relPath');
const result = await searchAliasesByName(service)({
aliasName: 'aliasName',
timestamp: 10000,
firstIndex: 0,
lastIndex: 150
});
expect(result.aliases).toHaveLength(0);
});
});

describe('getTLDS', () => {
it('should get as expected', async () => {
httpMock = HttpMockBuilder.create().onGetReply(200, {'tlds': []},
'relPath?requestType=getTLDs&timestamp=10000&firstIndex=0&lastIndex=150'
).build();
const service = createChainService(httpMock, 'relPath');
const result = await getTopLevelDomains(service)({
timestamp: 10000,
firstIndex: 0,
lastIndex: 150
});
expect(result.tlds).toHaveLength(0);
});
});

describe('buyTopLevelDomain', () => {
it('should buy as expected', async () => {
httpMock = HttpMockBuilder.create().onPostReply(200, {
broadcasted: true,
unsignedTransactionBytes: 'unsignedHexMessage'
},
'relPath?requestType=setTLD&message=Some%20message&messageIsText=true&tld=tld&amountNQT=10000000000000&deadline=1440&feeNQT=100000&publicKey=senderPublicKey'
).build();
const service = createChainService(httpMock, 'relPath');
const result = await buyTopLevelDomain(service)({
feePlanck: '100000',
amountPlanck: '10000000000000',
tld: 'tld',
attachment: new AttachmentMessage({message: 'Some message', messageIsText: true}),
deadline: 1440,
senderPublicKey: 'senderPublicKey'
});
expect(result.unsignedTransactionBytes).toBe('unsignedHexMessage');
});
});
});
14 changes: 13 additions & 1 deletion packages/core/src/api/composeApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,16 @@ import {
setRewardRecipient,
getRewardRecipient, addCommitment, removeCommitment,
} from './factories/account';
import {getAliasById, getAliasByName, getAliasesOnSale, sellAlias, buyAlias} from './factories/alias';
import {
getAliasById,
getAliasByName,
getAliasesOnSale,
sellAlias,
buyAlias,
searchAliasesByName,
getTopLevelDomains,
buyTopLevelDomain
} from './factories/alias';
import {
callContractMethod,
getAllContractIds,
Expand Down Expand Up @@ -213,6 +222,9 @@ export function composeApi(settings: ApiSettings): Api {
buyAlias,
sellAlias,
getAliases,
searchAliasesByName,
getTopLevelDomains,
buyTopLevelDomain
}).withContractApi({
getContract,
getContractsByAccount,
Expand Down
34 changes: 34 additions & 0 deletions packages/core/src/api/factories/alias/buyTopLevelDomain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2023 Signum Network
*/
import {ChainService} from '../../../service/chainService';
import {UnsignedTransaction} from '../../../typings/unsignedTransaction';
import {signIfPrivateKey} from '../../../internal/signIfPrivateKey';
import {DefaultDeadline} from '../../../constants';
import {BuyTopLevelDomainArgs} from '../../../typings/args';
import {createParametersFromAttachment} from '../../../internal';

/**
* Use with [[ApiComposer]] and belongs to [[AliasApi]].
*
* See details at [[AliasApi.buyTopLevelDomain]]
*
* @module core.api.factories
*/
export const buyTopLevelDomain = (service: ChainService) =>
(args: BuyTopLevelDomainArgs) =>
signIfPrivateKey(service, args, async (a: BuyTopLevelDomainArgs) => {
let parameters = {
tld: a.tld,
amountNQT: a.amountPlanck,
deadline: a.deadline || DefaultDeadline,
feeNQT: a.feePlanck,
publicKey: a.senderPublicKey,
referencedTransactionFullHash: a.referencedTransactionFullHash,
};

if (args.attachment) {
parameters = createParametersFromAttachment(a.attachment, parameters);
}
return service.send<UnsignedTransaction>('setTLD', parameters);
});
2 changes: 1 addition & 1 deletion packages/core/src/api/factories/alias/getAliasById.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ import {AliasList} from '../../../typings/aliasList';
export const getAliasById = (service: ChainService):
(aliasId: string) => Promise<AliasList> =>
(aliasId: string): Promise<AliasList> => service.query('getAlias', {
alias:aliasId,
alias: aliasId,
});
8 changes: 5 additions & 3 deletions packages/core/src/api/factories/alias/getAliasByName.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/**
* Copyright (c) 2019 Burst Apps Team
* Modified (c) 2023 Signum Network
*/
import {ChainService} from '../../../service/chainService';
import {AliasList} from '../../../typings/aliasList';
Expand All @@ -11,7 +12,8 @@ import {AliasList} from '../../../typings/aliasList';
* @module core.api.factories
*/
export const getAliasByName = (service: ChainService):
(aliasName: string) => Promise<AliasList> =>
(aliasName: string): Promise<AliasList> => service.query('getAlias', {
aliasName
(aliasName: string, tld?: string) => Promise<AliasList> =>
(aliasName: string, tld?: string): Promise<AliasList> => service.query('getAlias', {
aliasName,
tld
});
16 changes: 16 additions & 0 deletions packages/core/src/api/factories/alias/getTopLevelDomains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) 2023 Signum Network
*/
import {ChainService} from '../../../service/chainService';
import {GetTopLevelDomainsArgs} from '../../../typings/args/getTopLevelDomainsArgs';
import {TopLevelDomainList} from '../../../typings/topLevelDomainList';

/**
* Use with [[ApiComposer]] and belongs to [[AliasApi]].
*
* See details at [[AliasApi.getTopLevelDomains]]
* @module core.api.factories
*/
export const getTopLevelDomains = (service: ChainService):
(args: GetTopLevelDomainsArgs) => Promise<TopLevelDomainList> =>
(args: GetTopLevelDomainsArgs): Promise<TopLevelDomainList> => service.query('getTLDs', args);
3 changes: 3 additions & 0 deletions packages/core/src/api/factories/alias/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ export * from './getAliasByName';
export * from './getAliasesOnSale';
export * from './buyAlias';
export * from './sellAlias';
export * from './getTopLevelDomains';
export * from './buyTopLevelDomain';
export * from './searchAliasesByName';
17 changes: 17 additions & 0 deletions packages/core/src/api/factories/alias/searchAliasesByName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) 2019 Burst Apps Team
* Modified (c) 2023 Signum Network
*/
import {ChainService} from '../../../service/chainService';
import {AliasList} from '../../../typings/aliasList';
import { SearchAliasesByNameArgs } from '../../../typings/args/searchAliasesByNameArgs';

/**
* Use with [[ApiComposer]] and belongs to [[AliasApi]].
*
* See details at [[AliasApi.searchAliasesByName]]
* @module core.api.factories
*/
export const searchAliasesByName = (service: ChainService):
(args: SearchAliasesByNameArgs) => Promise<AliasList> =>
(args): Promise<AliasList> => service.query('getAliasesByName', args);
1 change: 1 addition & 0 deletions packages/core/src/constants/transactionArbitrarySubtype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export enum TransactionArbitrarySubtype {
AccountInfo,
AliasSale,
AliasBuy,
TopLevelDomainAssignment
}

Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,22 @@ describe('rebuildTransactionPostData', () => {
});
});
});
describe('setTLD', () => {
const requestType = 'setTLD';
it('should rebuild data correctly', () => {
const transactionBytes = '01289da31c10140004d794aa453a5bbdb8d580f1d9a76b6d7a25cde0ed38c098550ea0f784d9317a000000000000000000a0724e18090000002d3101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055f4070086134aea12e0d25404cfe1531b543c7c010c313233737061636573686970';
const rebuiltData = {
tld: '123spaceship',
amountNQT: '10000000000000',
feeNQT: '20000000',
publicKey: '04d794aa453a5bbdb8d580f1d9a76b6d7a25cde0ed38c098550ea0f784d9317a',
deadline: 20
};
const output = rebuildTransactionPostData(transactionBytes);
expect(output.requestType).toEqual(requestType);
expect(output.rebuiltData).toEqual(rebuiltData);
});
});
describe('setAccountInfo', () => {
const requestType = 'setAccountInfo';
it('should rebuild data correctly - Plus very long and utf-8 data', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,26 @@ describe('verifyTransaction', function () {
}).not.toThrow();
});
});
describe('setTLD', function () {
it('should pass verification as expected', () => {
const requestType = 'setTLD';
const formData = {
tld: '123spaceship',
amountNQT: '10000000000000',
feeNQT: '20000000',
publicKey: '04d794aa453a5bbdb8d580f1d9a76b6d7a25cde0ed38c098550ea0f784d9317a',
deadline: 20
};

const testResponse = {
'broadcasted': false,
'unsignedTransactionBytes': '01289da31c10140004d794aa453a5bbdb8d580f1d9a76b6d7a25cde0ed38c098550ea0f784d9317a000000000000000000a0724e18090000002d3101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055f4070086134aea12e0d25404cfe1531b543c7c010c313233737061636573686970',
'transactionJSON': {},
'requestProcessingTime': 8
};
expect(() => {
verifyTransaction(requestType, formData, testResponse);
}).not.toThrow();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ const AttachmentSpecV1: AttachmentSpec = new Map<string, AttachmentField[]>([
{type: 'ShortString*1', parameterName: 'description'},
{type: 'CreationBytes*1'},
]],
['setTLD', [
{type: 'ByteString*1', parameterName: 'tld'},
]],
]);

const AttachmentSpecV2: AttachmentSpec = new Map<string, AttachmentField[]>([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const DecodeRequestType = [
{type: 1, subtype: 5, requestType: 'setAccountInfo', hasAttachment: true},
{type: 1, subtype: 6, requestType: 'sellAlias', hasAttachment: true},
{type: 1, subtype: 7, requestType: 'buyAlias', hasAttachment: true},
{type: 1, subtype: 8, requestType: 'setTLD', hasAttachment: true},
{type: 2, subtype: 0, requestType: 'issueAsset', hasAttachment: true},
{type: 2, subtype: 1, requestType: 'transferAsset', hasAttachment: true},
{type: 2, subtype: 2, requestType: 'placeAskOrder', hasAttachment: true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {rebuildTransactionPostData} from './rebuildTransactionPostData';
// Type 22 (automated transactions): OK
const methodsToVerify = new Set([
'sendMoney', 'sendMoneyMulti', 'sendMoneyMultiSame',
'sendMessage', 'setAlias', 'setAccountInfo',
'sendMessage', 'setAlias', 'setTLD', 'setAccountInfo',
'issueAsset', 'transferAsset', 'transferAssetOwnership', 'placeAskOrder', 'placeBidOrder', 'cancelAskOrder',
'mintAsset', 'addAssetTreasuryAccount', 'distributeToAssetHolders', 'cancelBidOrder', 'transferAssetMulti',
'setRewardRecipient', 'addCommitment', 'removeCommitment',
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/typings/alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ export interface Alias {
*/
aliasURI: string;
timestamp: number;

/**
* The id of the Top Level Domain (tld) aka namespace for this alias. Default is '0', which points to 'signum'
*/
tld?: string;
/**
* The name of the Top Level Domain (tld) aka namespace for this alias. Default is 'signum'
*/
tldName?: string;

/**
* Numbers of aliases within the namespace/ top level domain.
*/
numberOfAlias?: number;
}
31 changes: 29 additions & 2 deletions packages/core/src/typings/api/aliasApi.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import {TransactionId} from '../transactionId';
import {Alias} from '../alias';
import {UnsignedTransaction} from '../unsignedTransaction';
import {SetAliasArgs} from '../args/setAliasArgs';
import {AliasList} from '../aliasList';
import {BuyAliasArgs, GetAliasesOnSaleArgs, SellAliasArgs} from '../args';
import {
BuyAliasArgs,
BuyTopLevelDomainArgs,
GetAliasesOnSaleArgs,
SellAliasArgs,
SetAliasArgs,
GetTopLevelDomainsArgs,
SearchAliasesByNameArgs
} from '../args';
import {TopLevelDomainList} from '../topLevelDomainList';

/**
* Alias API
Expand All @@ -27,10 +35,12 @@ export interface AliasApi {
/**
* Get alias by name, i.e. get basic account info for given alias name
* @param {string} aliasName The alias name
* @param {string} tld optional Top Level Domain. If not given, the default domain 'signum' is being used
* @return {Promise<Alias>} The Alias object
*/
getAliasByName: (
aliasName: string,
tld?: string,
) => Promise<Alias>;

/**
Expand Down Expand Up @@ -64,4 +74,21 @@ export interface AliasApi {
* @return The Transaction Id or Unsigned Bytes as Hex String if no private key was sent
*/
sellAlias: (args: SellAliasArgs) => Promise<TransactionId | UnsignedTransaction>;

/**
* Searches for aliases by their name or part of the name
* @param args The args
*/
searchAliasesByName: (args: SearchAliasesByNameArgs) => Promise<AliasList>;
/**
* Gets all registered Top Level Domains
* @param args The args
*/
getTopLevelDomains: (args: GetTopLevelDomainsArgs) => Promise<TopLevelDomainList>;

/**
* Buys a Top Level Domain (TLD)
* @param args The args
*/
buyTopLevelDomain: (args: BuyTopLevelDomainArgs) => Promise<TransactionId | UnsignedTransaction>;
}
2 changes: 2 additions & 0 deletions packages/core/src/typings/args/buyAliasArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import {DefaultSendArgs} from './defaultSendArgs';
* @param alias The alias Id
* @param aliasName Alternative to alias Id
* @param amountPlanck The amount for buy in Planck
* @param tld The name of the Top Level Domain (TLD) aka namespace where this alias belongs to
* @module core
*/
export interface BuyAliasArgs extends DefaultSendArgs {
aliasId: string;
aliasName?: string;
amountPlanck: string;
tld?: string;
}
14 changes: 14 additions & 0 deletions packages/core/src/typings/args/buyTopLevelDomainArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {DefaultSendArgs} from './defaultSendArgs';


/**
* The argument object for [[AccountApi.setTopLevelDomain]]
*
* @param tld The name of the Top Level Domain (max. 40 chars only digits and letters)
* @param amountPlanck The amount in planck according SIP-48
* @module core
*/
export interface BuyTopLevelDomainArgs extends DefaultSendArgs {
tld: string;
amountPlanck: string;
}
Loading