Skip to content

Commit

Permalink
feat: 🎸 pass key count when redeeming NFT
Browse files Browse the repository at this point in the history
allows for more effective batching NFT redeemption on chain v7
  • Loading branch information
polymath-eric authored and sansan committed Oct 4, 2024
1 parent 73a4348 commit 76140dd
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 16 deletions.
10 changes: 9 additions & 1 deletion src/api/procedures/__tests__/redeemNft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ describe('redeemNft procedure', () => {
let collection: NftCollection;
let rawAssetId: PolymeshPrimitivesAssetAssetID;
let id: BigNumber;
let collectionId: BigNumber;
let rawId: u64;
let rawCollectionId: u64;
let assetToMeshAssetIdSpy: jest.SpyInstance;
let bigNumberToU64Spy: jest.SpyInstance<u64, [BigNumber, Context]>;

Expand All @@ -55,7 +57,9 @@ describe('redeemNft procedure', () => {
rawAssetId = dsMockUtils.createMockAssetId(assetId);
collection = entityMockUtils.getNftCollectionInstance({ assetId });
id = new BigNumber(1);
collectionId = new BigNumber(2);
rawId = dsMockUtils.createMockU64(id);
rawCollectionId = dsMockUtils.createMockU64(collectionId);
assetToMeshAssetIdSpy = jest.spyOn(utilsConversionModule, 'assetToMeshAssetId');
bigNumberToU64Spy = jest.spyOn(utilsConversionModule, 'bigNumberToU64');
});
Expand All @@ -64,6 +68,10 @@ describe('redeemNft procedure', () => {
mockContext = dsMockUtils.getContextInstance();
when(assetToMeshAssetIdSpy).calledWith(collection, mockContext).mockReturnValue(rawAssetId);
when(bigNumberToU64Spy).calledWith(id, mockContext).mockReturnValue(rawId);
when(bigNumberToU64Spy).calledWith(collectionId, mockContext).mockReturnValue(rawCollectionId);
dsMockUtils.createQueryMock('nft', 'collectionKeys', {
returnValue: dsMockUtils.createMockBTreeSet(),
});
});

afterEach(() => {
Expand Down Expand Up @@ -112,7 +120,7 @@ describe('redeemNft procedure', () => {
});
expect(result).toEqual({
transaction,
args: [rawAssetId, rawId, rawPortfolioKind],
args: [rawAssetId, rawId, rawPortfolioKind, 0],
resolver: undefined,
});
});
Expand Down
19 changes: 15 additions & 4 deletions src/api/procedures/redeemNft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,23 @@ export async function prepareRedeemNft(
const {
context,
context: {
polymeshApi: { tx },
isV6,
polymeshApi: { tx, query },
},
storage: { fromPortfolio },
} = this;

const { collection, id } = args;

const collectionId = await collection.getCollectionId();
const rawAssetId = assetToMeshAssetId(collection, context);
const rawId = bigNumberToU64(id, context);
const rawCollectionId = bigNumberToU64(collectionId, context);

const [{ free }] = await fromPortfolio.getCollections({ collections: [collection.id] });
const [[{ free }], rawKeySet] = await Promise.all([
fromPortfolio.getCollections({ collections: [collection.id] }),
query.nft.collectionKeys(rawCollectionId),
]);

if (!free.find(heldNft => heldNft.id.eq(id))) {
throw new PolymeshError({
Expand All @@ -51,11 +58,15 @@ export async function prepareRedeemNft(
});
}

const rawId = bigNumberToU64(id, context);
/* istanbul ignore next: this will be removed after dual version support for v6-v7 */
const txArgs = isV6
? [rawAssetId, rawId, portfolioToPortfolioKind(fromPortfolio, context)]
: [rawAssetId, rawId, portfolioToPortfolioKind(fromPortfolio, context), rawKeySet.size];

return {
transaction: tx.nft.redeemNft,
args: [rawAssetId, rawId, portfolioToPortfolioKind(fromPortfolio, context)],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args: txArgs as any,
resolver: undefined,
};
}
Expand Down
8 changes: 4 additions & 4 deletions src/testUtils/mocks/dataSources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3139,12 +3139,12 @@ export const createMockAssetComplianceReport = (assetComplianceReport?: {
requirementSatisfied: bool;
id: u32 | Parameters<typeof createMockU32>[0];
}[];
anyRequirementSatistifed: bool | Parameters<typeof createMockBool>[0];
anyRequirementSatisfied: bool | Parameters<typeof createMockBool>[0];
}): MockCodec<ComplianceReport> => {
const { pausedCompliance, requirements, anyRequirementSatistifed } = assetComplianceReport ?? {
const { pausedCompliance, requirements, anyRequirementSatisfied } = assetComplianceReport ?? {
pausedCompliance: createMockBool(),
requirements: [],
anyRequirementSatistifed: createMockBool(),
anyRequirementSatisfied: createMockBool(),
};

return createMockCodec(
Expand All @@ -3153,7 +3153,7 @@ export const createMockAssetComplianceReport = (assetComplianceReport?: {
requirements: requirements.map(requirement =>
createMockComplianceRequirementReport(requirement)
),
anyRequirementSatistifed: createMockBool(anyRequirementSatistifed),
anyRequirementSatisfied: createMockBool(anyRequirementSatisfied),
},
!assetComplianceReport
);
Expand Down
10 changes: 5 additions & 5 deletions src/utils/__tests__/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3984,7 +3984,7 @@ describe('transferReportToTransferBreakdown', () => {
dsMockUtils.createMockDispatchResult({
Ok: dsMockUtils.createMockAssetComplianceReport({
pausedCompliance: true,
anyRequirementSatistifed: true,
anyRequirementSatisfied: true,
requirements: [],
}),
}) as unknown as Result<ComplianceReport, DispatchError>,
Expand Down Expand Up @@ -4046,7 +4046,7 @@ describe('transferReportToTransferBreakdown', () => {
dsMockUtils.createMockDispatchResult({
Ok: dsMockUtils.createMockAssetComplianceReport({
pausedCompliance: false,
anyRequirementSatistifed: false,
anyRequirementSatisfied: false,
requirements: [],
}),
}) as unknown as Result<ComplianceReport, DispatchError>,
Expand Down Expand Up @@ -4185,7 +4185,7 @@ describe('assetDispatchErrorToTransferError', () => {

expect(result).toEqual(TransferError.InsufficientPortfolioBalance);

dsMockUtils.setErrorMock('statistics', 'InvalidTransfer', {
dsMockUtils.setErrorMock('statistics', 'InvalidTransferStatisticsFailure', {
returnValue: { is: jest.fn().mockReturnValueOnce(true) },
});

Expand Down Expand Up @@ -6644,7 +6644,7 @@ describe('assetComplianceReportToCompliance', () => {
let assetComplianceReport = dsMockUtils.createMockAssetComplianceReport({
pausedCompliance: dsMockUtils.createMockBool(true),
requirements: [rawRequirements],
anyRequirementSatistifed: dsMockUtils.createMockBool(true),
anyRequirementSatisfied: dsMockUtils.createMockBool(true),
});

let result = assetComplianceReportToCompliance(
Expand All @@ -6661,7 +6661,7 @@ describe('assetComplianceReportToCompliance', () => {
assetComplianceReport = dsMockUtils.createMockAssetComplianceReport({
pausedCompliance: dsMockUtils.createMockBool(false),
requirements: [rawRequirements],
anyRequirementSatistifed: dsMockUtils.createMockBool(true),
anyRequirementSatisfied: dsMockUtils.createMockBool(true),
});

result = assetComplianceReportToCompliance(
Expand Down
4 changes: 2 additions & 2 deletions src/utils/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3148,7 +3148,7 @@ export function assetComplianceReportToCompliance(

const {
requirements: rawRequirements,
anyRequirementSatistifed: result,
anyRequirementSatisfied: result,
pausedCompliance: paused,
} = report;
const requirements = rawRequirements.map(requirement =>
Expand Down Expand Up @@ -3630,7 +3630,7 @@ export function assetDispatchErrorToTransferError(
[portfolioErrors.InsufficientPortfolioBalance, TransferError.InsufficientPortfolioBalance],
[assetErrors.InvalidTransferComplianceFailure, TransferError.ComplianceFailure],
[assetErrors.InvalidTransfer, TransferError.ComplianceFailure],
[statisticsError.InvalidTransfer, TransferError.TransferNotAllowed],
[statisticsError.InvalidTransferStatisticsFailure, TransferError.TransferNotAllowed],
];
if (error.isModule) {
const moduleErr = error.asModule;
Expand Down

0 comments on commit 76140dd

Please sign in to comment.