diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 10c865aaf4..c5d62cd8a6 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.36.2 + +_01/25/2024_ + +### Changes +https://github.com/gear-tech/gear-js/pull/1477 +- Return support of old vouchers + ## 0.36.1 _01/23/2024_ diff --git a/api/package.json b/api/package.json index 439fe6fa57..20ad31ab7d 100644 --- a/api/package.json +++ b/api/package.json @@ -1,6 +1,6 @@ { "name": "@gear-js/api", - "version": "0.36.1", + "version": "0.36.2", "description": "A JavaScript library that provides functionality to connect GEAR Component APIs.", "main": "cjs/index.js", "module": "index.js", diff --git a/api/src/Voucher.ts b/api/src/Voucher.ts index edfa753519..fc81b64781 100644 --- a/api/src/Voucher.ts +++ b/api/src/Voucher.ts @@ -1,4 +1,3 @@ -import { stringToU8a, u8aToU8a } from '@polkadot/util'; import { BalanceOf } from '@polkadot/types/interfaces'; import { HexString } from '@polkadot/util/types'; import { ISubmittableResult } from '@polkadot/types/types'; @@ -7,8 +6,9 @@ import { SubmittableExtrinsic } from '@polkadot/api/types'; import { blake2AsHex } from '@polkadot/util-crypto'; import { ICallOptions, IUpdateVoucherParams, IVoucherDetails, PalletGearVoucherInternalVoucherInfo } from './types'; +import { decodeAddress, generateVoucherId } from './utils'; import { GearTransaction } from './Transaction'; -import { generateVoucherId } from './utils'; +import { SPEC_VERSION } from './consts'; export class GearVoucher extends GearTransaction { /** @@ -65,9 +65,7 @@ export class GearVoucher extends GearTransaction { program: HexString, value: number | bigint | string, ): { extrinsic: SubmittableExtrinsic<'promise', ISubmittableResult>; voucherId: HexString } { - const whoU8a = u8aToU8a(to); - const programU8a = u8aToU8a(program); - const id = Uint8Array.from([...stringToU8a('modlpy/voucher__'), ...whoU8a, ...programU8a]); + const id = generateVoucherId(to, program); const voucherId = blake2AsHex(id, 256); this.extrinsic = this._api.tx.gearVoucher.issue.call(this, to, program, value); @@ -218,6 +216,16 @@ export class GearVoucher extends GearTransaction { * @returns */ async exists(accountId: string, programId: HexString): Promise { + if (this._api.specVersion < SPEC_VERSION.V1100) { + const id = generateVoucherId(decodeAddress(accountId), programId); + + const balance = await this._api.balance.findOut(id); + if (balance.eqn(0)) { + return false; + } + return true; + } + const keyPrefixes = this._api.query.gearVoucher.vouchers.keyPrefix(accountId); const keysPaged = await this._api.rpc.state.getKeysPaged(keyPrefixes, 1000, keyPrefixes); @@ -245,8 +253,8 @@ export class GearVoucher extends GearTransaction { * @param accountId * @returns */ - async getAllForAccount(accountId: string): Promise> { - const result: Record = {}; + async getAllForAccount(accountId: string, programId?: HexString): Promise> { + const result: Record = {}; const keyPrefix = this._api.query.gearVoucher.vouchers.keyPrefix(accountId); @@ -270,9 +278,19 @@ export class GearVoucher extends GearTransaction { return; } - const programs = typedItem.unwrap().programs.unwrapOrDefault().toJSON() as string[]; + const details = typedItem.unwrap(); + const programs = details.programs.unwrapOrDefault().toJSON() as string[]; + + if (details.programs.isSome && programId && !programs.includes(programId)) { + return; + } - result[voucherId] = programs; + result[voucherId] = { + owner: details.owner.toHex(), + programs, + expiry: details.expiry.toNumber(), + codeUploading: details.codeUploading.isTrue, + }; }); return result; diff --git a/api/src/utils/generate.ts b/api/src/utils/generate.ts index 2828057c97..40b95ba86b 100644 --- a/api/src/utils/generate.ts +++ b/api/src/utils/generate.ts @@ -6,6 +6,7 @@ import { CreateType } from '../metadata'; import { GearApi } from 'GearApi'; import { SPEC_VERSION } from '../consts'; +const VOUCHER_PREFIX_BEFORE_1100 = stringToU8a('modlpy/voucher__'); const VOUCHER_PREFIX = stringToU8a('voucher'); export function generateCodeHash(code: Buffer | Uint8Array | HexString): HexString { @@ -38,8 +39,20 @@ export function generateProgramId( return blake2AsHex(id, 256); } -export function generateVoucherId(nonce: U8aLike): HexString { - const nonceU8a = u8aToU8a(nonce); - const id = Uint8Array.from([...VOUCHER_PREFIX, ...nonceU8a]); +/** + * @deprecated + */ +export function generateVoucherId(who: HexString, programId: HexString): HexString; +export function generateVoucherId(nonce: U8aLike): HexString; +export function generateVoucherId(nonceOrWho: U8aLike | HexString, programId?: HexString): HexString { + const [nonce, who] = typeof nonceOrWho === 'string' && programId ? [undefined, nonceOrWho] : [nonceOrWho, undefined]; + if (nonce) { + const nonceU8a = u8aToU8a(nonce); + const id = Uint8Array.from([...VOUCHER_PREFIX, ...nonceU8a]); + return blake2AsHex(id, 256); + } + const whoU8a = u8aToU8a(who); + const programU8a = u8aToU8a(programId); + const id = Uint8Array.from([...VOUCHER_PREFIX_BEFORE_1100, ...whoU8a, ...programU8a]); return blake2AsHex(id, 256); } diff --git a/api/test/Voucher.test.ts b/api/test/Voucher.test.ts index ef2a946259..8fd07781bc 100644 --- a/api/test/Voucher.test.ts +++ b/api/test/Voucher.test.ts @@ -63,7 +63,7 @@ describe('Voucher', () => { expect(txData).toHaveProperty('holder'); expect(txData).toHaveProperty('program'); expect(txData).toHaveProperty('value'); - expect(Object.keys(txData)).toHaveLength(3); + expect(Object.keys(txData.toJSON())).toHaveLength(3); expect(txData.holder.toHuman()).toBe(charlie.address); expect(txData.program.toHex()).toBe(programId); expect(txData.value.toNumber()).toBe(100_000_000_000_000); @@ -121,8 +121,10 @@ describe('Voucher', () => { test('Get all vouchers for account', async () => { const vouchers = await api.voucher.getAllForAccount(charlie.address); expect(Object.keys(vouchers)).toHaveLength(1); - expect(vouchers[voucher]).toHaveLength(1); - expect(vouchers[voucher][0]).toBe(programId); + expect(vouchers[voucher]).toHaveProperty('programs', [programId]); + expect(vouchers[voucher]).toHaveProperty('owner', decodeAddress(alice.address)); + expect(vouchers[voucher]).toHaveProperty('expiry', validUpTo); + expect(vouchers[voucher]).toHaveProperty('codeUploading', true); }); test('Get voucher details', async () => {