From e83c55331b605475459bf9a406b7aa81c8a8a698 Mon Sep 17 00:00:00 2001 From: BenRey <44082144+Ben-Rey@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:46:20 +0100 Subject: [PATCH] feat: add getTargets method and transferFrom functionality to MNS contract; enhance tests (#730) --- src/contracts-wrappers/mns.ts | 50 ++++++++++++++++++++++++-- test/integration/mns.spec.ts | 67 ++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/src/contracts-wrappers/mns.ts b/src/contracts-wrappers/mns.ts index 38ec1753..f768d99f 100644 --- a/src/contracts-wrappers/mns.ts +++ b/src/contracts-wrappers/mns.ts @@ -32,6 +32,8 @@ export const MNS_CONTRACTS = { const DOMAIN_SEPARATOR_KEY = [0x42] const TOKEN_ID_KEY_PREFIX = [0x1] // eslint-disable-next-line @typescript-eslint/no-magic-numbers +const TARGET_KEY_PREFIX = [0x02] +// eslint-disable-next-line @typescript-eslint/no-magic-numbers const DOMAIN_KEY_PREFIX = [0x3] // eslint-disable-next-line @typescript-eslint/no-magic-numbers const ADDRESS_KEY_PREFIX_V2 = [0x6] @@ -95,7 +97,7 @@ export class MNS extends SmartContract { ) } - private async getTokenId(name: string): Promise { + async getTokenId(name: string): Promise { const key = Uint8Array.from([ ...DOMAIN_SEPARATOR_KEY, ...TOKEN_ID_KEY_PREFIX, @@ -130,13 +132,13 @@ export class MNS extends SmartContract { ...OWNED_TOKENS_KEY, ...strToBytes(address), ]) - const ownedkeys = await this.provider.getStorageKeys( + const ownedKeys = await this.provider.getStorageKeys( this.address, filter, final ) - const domainKeys = ownedkeys.map((k) => { + const domainKeys = ownedKeys.map((k) => { const tokenIdBytes = k.slice(filter.length) return Uint8Array.from([ ...DOMAIN_SEPARATOR_KEY, @@ -152,6 +154,24 @@ export class MNS extends SmartContract { return domainsBytes.map((d) => bytesToStr(d)) } + async getTargets(domains: string[], final = false): Promise { + const targetDataStoreEntries = domains.map((name) => + Uint8Array.from([ + ...DOMAIN_SEPARATOR_KEY, + ...TARGET_KEY_PREFIX, + ...strToBytes(name), + ]) + ) + + const targetsBytes = await this.provider.readStorage( + this.address, + targetDataStoreEntries, + final + ) + + return targetsBytes.map(bytesToStr) + } + async dnsAllocCost(domain: string, options?: ReadSCOptions): Promise { const res = await this.read( 'dnsAllocCost', @@ -163,4 +183,28 @@ export class MNS extends SmartContract { return U64.fromBytes(res.value) } + + async transferFrom( + domain: string, + currentOwner: string, + newOwner: string, + options?: CallSCOptions + ): Promise { + const tokenId = await this.getTokenId(domain) + const args = new Args() + .addString(currentOwner) + .addString(newOwner) + .addU256(tokenId) + + return await this.call('transferFrom', args, options) + } + + async balanceOf(owner: string, options?: ReadSCOptions): Promise { + const res = await this.read( + 'balanceOf', + new Args().addString(owner), + options + ) + return U256.fromBytes(res.value) + } } diff --git a/test/integration/mns.spec.ts b/test/integration/mns.spec.ts index 31953df3..a6aefd27 100644 --- a/test/integration/mns.spec.ts +++ b/test/integration/mns.spec.ts @@ -1,4 +1,4 @@ -import { MNS } from '../../src' +import { Account, MNS } from '../../src' import { provider, publicProvider } from './setup' describe('MNS tests', () => { @@ -50,6 +50,71 @@ describe('MNS tests', () => { res = await mns.resolve(domain) expect(res).toBe('') }, 300000) + + test('transfer domain', async () => { + const domain = 'trloloooooooooooooooololololzs' + Date.now() + const account2 = await Account.generate() + let operation = await mns.alloc(domain, provider.address, { + coins: 2064100000n, + }) + + await operation.waitFinalExecution() + + // check resolution + let res = await mns.resolve(domain) + expect(res).toBe(provider.address) + // check balance + let balance = await mns.balanceOf(provider.address) + expect(balance).toBeGreaterThan(0n) + + // transfer domain + operation = await mns.transferFrom( + domain, + provider.address, + account2.address.toString() + ) + await operation.waitFinalExecution() + + const domains = await mns.getOwnedDomains(account2.address.toString()) + expect(domains).toContain(domain) + const balance2 = await mns.balanceOf(account2.address.toString()) + expect(balance2).toBeGreaterThan(0n) + }) + + test('getTargets', async () => { + // Alloc some domains + const domain1 = 'trloloooooooooooooooololololzs1' + const domain2 = 'trloloooooooooooooooololololzs2' + const domain3 = 'trloloooooooooooooooololololzs3' + + const op1 = await mns.alloc(domain1, provider.address, { + coins: 2064100000n, + }) + const op2 = await mns.alloc(domain2, provider.address, { + coins: 2064100000n, + }) + const op3 = await mns.alloc(domain3, provider.address, { + coins: 2064100000n, + }) + + await Promise.all([ + op1.waitFinalExecution(), + op2.waitFinalExecution(), + op3.waitFinalExecution(), + ]) + + const targets = await mns.getTargets([domain1, domain2, domain3]) + expect(targets).toEqual([ + provider.address, + provider.address, + provider.address, + ]) + + // Free the domains + mns.free(domain1) + mns.free(domain2) + mns.free(domain3) + }) }) describe('MNS tests using PublicProvider', () => {