Skip to content

Commit

Permalink
Merge pull request #261 from blockfrost/feat/get_adahandle
Browse files Browse the repository at this point in the history
Feat/get adahandle
  • Loading branch information
iccicci authored Nov 18, 2024
2 parents 4088edf + bf32bf2 commit f3af33c
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 1 deletion.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"lovelaces",
"memoizee",
"nixify",
"preprod",
"tailwindcss",
"timelock",
"txid",
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ For each of these commands the client receives an immediate response
- [`ESTIMATE_FEE`](#estimate_fee) - estimate transaction submission fee
- [`GET_ACCOUNT_INFO`](#get_account_info) - get general information about an account
- [`GET_ACCOUNT_UTXO`](#get_account_utxo) - get unspent UTxOs of an account
- [`GET_ADA_HANDLE`](#get_ada_handle) - resolves an Ada Handle
- [`GET_BALANCE_HISTORY`](#get_balance_history) - get balance history of an account
- [`GET_BLOCK`](#get_block) - get details of a block
- [`GET_TRANSACTION`](#get_transaction) - get details of a transaction
Expand Down Expand Up @@ -468,6 +469,32 @@ Response:
}
```

### GET_ADA_HANDLE

Resolves an Ada Handle providing the address holding it.

Input message:

```ts
{
"id": number | string;
"command": "GET_ADA_HANDLE";
"params": {
"name": string; // Ada Handle name
}
}
```

Response output message `data` type:

```ts
{
id: number | string;
type: 'message';
data: string | null;
}
```

### GET_BLOCK

Retrieves detailed information about a specific block using its hash or height.
Expand Down
36 changes: 36 additions & 0 deletions src/methods/get-ada-handle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { prepareMessage } from '../utils/message.js';
import { blockfrostAPI } from '../utils/blockfrost-api.js';
import { MessageId } from '../types/message.js';
import { BlockfrostServerError } from '@blockfrost/blockfrost-js';

const policyID = 'f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a';

export default async (id: MessageId, clientId: string, name: string): Promise<string> => {
let data: { address: string } | null;

try {
const result = await blockfrostAPI.assetsAddresses(
policyID + Buffer.from(name, 'utf8').toString('hex'),
);

if (result.length > 1) {
throw new Error('Double minted Ada Handle detected');
}

if (result.length === 0) {
data = null;
} else {
const { address } = result[0];

data = { address };
}
} catch (error) {
if (error instanceof BlockfrostServerError && error.status_code === 404) {
data = null;
} else {
throw error;
}
}

return prepareMessage({ id, clientId, data });
};
8 changes: 8 additions & 0 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { SubscribedAddress, events, onBlock, startEmitter } from './events.js';
import getServerInfo from './methods/get-server-info.js';
import getAccountInfo from './methods/get-account-info.js';
import getAccountUtxo from './methods/get-account-utxo.js';
import getAdaHandle from './methods/get-ada-handle.js';
import getBlock from './methods/get-block.js';
import getTransaction from './methods/get-transaction.js';
import submitTransaction from './methods/push-transaction.js';
Expand Down Expand Up @@ -246,6 +247,13 @@ wss.on('connection', async (ws: Server.Ws) => {
break;
}

case 'GET_ADA_HANDLE': {
validators.GET_ADA_HANDLE(params);
response = await getAdaHandle(id, clientId, params.name);

break;
}

case 'GET_BALANCE_HISTORY': {
validators.GET_BALANCE_HISTORY(params);
response = await getBalanceHistory(
Expand Down
6 changes: 6 additions & 0 deletions src/types/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export type Messages = BaseMessage &
pageSize?: number;
};
}
| {
command: 'GET_ADA_HANDLE';
params: {
name: string;
};
}
| {
command: 'GET_BALANCE_HISTORY';
params: {
Expand Down
2 changes: 2 additions & 0 deletions src/types/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export type Responses = {
| ServerInfo
| AccountInfo
| string
| { address: string }
| null
| Schemas['block_content']
| BalanceHistoryData[]
| TxIdsToTransactionsResponse[]
Expand Down
8 changes: 7 additions & 1 deletion src/utils/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@ const schemas: { [k in Validators]: { properties: unknown; required?: string[] }
},
required: ['descriptor'],
},
GET_ADA_HANDLE: {
properties: {
name: { type: 'string' },
},
required: ['name'],
},
GET_BALANCE_HISTORY: {
properties: {
descriptor: { type: 'string' },
groupBy: { type: ['number', 'string'] },
from: { type: ['number', 'string', 'null'] },
to: { type: ['number', 'string', 'null'] },
},
required: ['descriptor'],
required: ['descriptor', 'groupBy'],
},
GET_BLOCK: {
properties: {
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/fixtures/preprod/get-ada-handle.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { expect } from 'vitest';

export default [
{
handle: 'test',
testName: 'GET_ADA_HANDLE success - preprod',
result: { address: expect.any(String) },
},
{
handle: 'does_not_exist',
testName: 'GET_ADA_HANDLE not existing - preprod',
result: null,
},
] as const;
15 changes: 15 additions & 0 deletions test/e2e/tests/get-ada-handle.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from 'vitest';
import { getFixtures } from '../utils/fixtures-loader.js';
import { getWebSocketClient } from '../utils/setup-websocket-client.js';

const fixtures = await getFixtures('get-ada-handle');

describe('get-ada-handle', () => {
for (const { handle, result, testName } of fixtures) {
test(testName, async () => {
const ws = getWebSocketClient();
const { data } = await ws.sendAndWait('GET_ADA_HANDLE', { name: handle });
expect(data).toMatchObject(result);
});
}
});
57 changes: 57 additions & 0 deletions test/unit/fixtures/getAdaHandle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { BlockfrostServerError } from "@blockfrost/blockfrost-js";

export default [
{
testName: 'getAdaHandle success',
id: 1,
assets: [{
address: 'address',
quantity: '1',
}],
result: {
id: 1,
type: 'message',
data: { address: 'address' },
},
},
{
testName: 'getAdaHandle not found',
id: 1,
error: new BlockfrostServerError({
error: 'error',
message: 'Not found',
status_code: 404,
url: 'url',
}),
result: {
id: 1,
type: 'message',
data: null,
},
},
{
testName: 'getAdaHandle empty result',
id: 1,
assets: [],
result: {
id: 1,
type: 'message',
data: null,
},
},
{
testName: 'getAdaHandle double minted',
id: 1,
assets: [
{
address: 'address1',
quantity: '1',
},
{
address: 'address2',
quantity: '1',
}
],
thrown: new Error('Double minted Ada Handle detected'),
},
];
26 changes: 26 additions & 0 deletions test/unit/tests/methods/get-ada-handle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sinon from 'sinon';
import { describe, test, expect } from 'vitest';
import fixtures from '../../fixtures/getAdaHandle.js';
import { blockfrostAPI } from '../../../../src/utils/blockfrost-api.js';
import getAdaHandle from '../../../../src/methods/get-ada-handle.js';

describe('getAdaHandle', () => {
for (const fixture of fixtures) {
test(fixture.testName, async () => {
const mock1 = fixture.assets ?
sinon.stub(blockfrostAPI, 'assetsAddresses').resolves(fixture.assets) :
sinon.stub(blockfrostAPI, 'assetsAddresses').rejects(fixture.error);

if(fixture.result) {
const result = await getAdaHandle(1, 'test', 'test');

expect(result).toBe(JSON.stringify(fixture.result));
}
else {
await expect(getAdaHandle(1, 'test', 'test')).rejects.toEqual(fixture.thrown);
}

mock1.restore();
});
}
});

0 comments on commit f3af33c

Please sign in to comment.