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

Path refactor for v2 #11

Merged
merged 3 commits into from
Nov 20, 2024
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
2 changes: 1 addition & 1 deletion clients/js/src/generated/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
* @see https://github.com/metaplex-foundation/kinobi
*/

export * from './path';
export * from './internalPath';
24 changes: 24 additions & 0 deletions clients/js/src/generated/types/internalPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* This code was AUTOGENERATED using the kinobi library.
* Please DO NOT EDIT THIS FILE, instead use visitors
* to add features, then rerun kinobi to update it.
*
* @see https://github.com/metaplex-foundation/kinobi
*/

import { Serializer, scalarEnum } from '@metaplex-foundation/umi/serializers';

export enum InternalPath {
NoRerollMetadata,
}

export type InternalPathArgs = InternalPath;

export function getInternalPathSerializer(): Serializer<
InternalPathArgs,
InternalPath
> {
return scalarEnum<InternalPath>(InternalPath, {
description: 'InternalPath',
}) as Serializer<InternalPathArgs, InternalPath>;
}
22 changes: 0 additions & 22 deletions clients/js/src/generated/types/path.ts

This file was deleted.

1 change: 1 addition & 0 deletions clients/js/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './generated';
export * from './plugin';
export * from './path';
27 changes: 27 additions & 0 deletions clients/js/src/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { InternalPath } from './generated';

enum CustomPath {
RerollMetadata = 16,
}

export const Path = {
...InternalPath,
...CustomPath,
} as const;

// eslint-disable-next-line @typescript-eslint/no-redeclare
export type Path = InternalPath | CustomPath;

export function buildPath(features: Path[]) {
let path = 0;

// eslint-disable-next-line no-restricted-syntax
for (const feature of features) {
if (feature !== Path.RerollMetadata) {
// eslint-disable-next-line no-bitwise
path |= 1 << feature;
}
}

return path;
}
255 changes: 251 additions & 4 deletions clients/js/test/v1/capture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
transfer,
} from '@metaplex-foundation/mpl-core';
import {
buildPath,
captureV1,
EscrowV1,
fetchEscrowV1,
Expand Down Expand Up @@ -76,7 +77,7 @@ test('it can swap tokens for an asset with reroll', async (t) => {
min: 0,
amount: 5,
feeAmount: 1,
path: Path.RerollMetadata,
path: buildPath([Path.RerollMetadata]),
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

Expand All @@ -94,7 +95,7 @@ test('it can swap tokens for an asset with reroll', async (t) => {
amount: 5n,
feeAmount: 1n,
count: 1n,
path: Path.RerollMetadata,
path: buildPath([Path.RerollMetadata]),
bump: escrow[1],
solFeeAmount: 1_000_000n,
});
Expand Down Expand Up @@ -154,6 +155,134 @@ test('it can swap tokens for an asset with reroll', async (t) => {
t.regex(assetAfter.uri, uriRegex);
});

test('it can swap tokens for an asset without reroll', async (t) => {
// Given a Umi instance using the project's plugin.
const umi = await createUmi();
const feeLocation = generateSigner(umi);
const { assets, collection } = await createCoreCollection(umi);
const tokenMint = generateSigner(umi);
await createFungible(umi, {
name: 'Test Token',
uri: 'www.fungible.com',
sellerFeeBasisPoints: {
basisPoints: 0n,
identifier: '%',
decimals: 2,
},
mint: tokenMint,
}).sendAndConfirm(umi);

await mintV1(umi, {
mint: tokenMint.publicKey,
tokenStandard: TokenStandard.Fungible,
tokenOwner: umi.identity.publicKey,
amount: 1000,
}).sendAndConfirm(umi);

const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection.publicKey),
]);

// Transfer the assets to the escrow.
// eslint-disable-next-line no-restricted-syntax
for (const asset of assets) {
// eslint-disable-next-line no-await-in-loop
await transfer(umi, {
asset,
collection,
newOwner: escrow,
}).sendAndConfirm(umi);
}

await initEscrowV1(umi, {
escrow,
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com/',
max: 9,
min: 0,
amount: 5,
feeAmount: 1,
path: buildPath([Path.NoRerollMetadata]),
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

const escrowData = await fetchEscrowV1(umi, escrow);

t.like(escrowData, <EscrowV1>{
publicKey: publicKey(escrow),
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com/',
max: 9n,
min: 0n,
amount: 5n,
feeAmount: 1n,
count: 1n,
path: buildPath([Path.NoRerollMetadata]),
bump: escrow[1],
solFeeAmount: 1_000_000n,
});

const userTokenBefore = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
umi.identity.publicKey
);
t.deepEqual(userTokenBefore.token.amount, 1000n);
try {
await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
publicKey(escrow)
);
t.fail('Escrow token account should not exist');
} catch (e) {
t.is(e.name, 'AccountNotFoundError');
}

const assetBefore = await fetchAsset(umi, assets[0].publicKey);
t.is(assetBefore.owner, publicKey(escrow));

await captureV1(umi, {
owner: umi.identity,
escrow,
asset: assets[0].publicKey,
collection: collection.publicKey,
feeProjectAccount: escrowData.feeLocation,
token: tokenMint.publicKey,
}).sendAndConfirm(umi);

const escrowTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
publicKey(escrow)
);
t.deepEqual(escrowTokenAfter.token.amount, 5n);
const userTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
umi.identity.publicKey
);
t.deepEqual(userTokenAfter.token.amount, 994n);
const feeTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
escrowData.feeLocation
);
t.deepEqual(feeTokenAfter.token.amount, 1n);
const assetAfter = await fetchAsset(umi, assets[0].publicKey);
t.is(assetAfter.owner, umi.identity.publicKey);

// Make sure the URI has not changed.
t.is(assetAfter.uri, 'https://example.com/asset');
});

test('it can swap tokens for an asset as UpdateDelegate with reroll', async (t) => {
// Given a Umi instance using the project's plugin.
const umi = await createUmi();
Expand Down Expand Up @@ -205,7 +334,7 @@ test('it can swap tokens for an asset as UpdateDelegate with reroll', async (t)
min: 0,
amount: 5,
feeAmount: 1,
path: Path.RerollMetadata,
path: buildPath([Path.RerollMetadata]),
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

Expand All @@ -232,7 +361,7 @@ test('it can swap tokens for an asset as UpdateDelegate with reroll', async (t)
amount: 5n,
feeAmount: 1n,
count: 1n,
path: Path.RerollMetadata,
path: buildPath([Path.RerollMetadata]),
bump: escrow[1],
solFeeAmount: 1_000_000n,
});
Expand Down Expand Up @@ -272,3 +401,121 @@ test('it can swap tokens for an asset as UpdateDelegate with reroll', async (t)
const uriRegex = new RegExp(`${escrowData.uri}\\d+\\.json`);
t.regex(assetAfter.uri, uriRegex);
});

test('it can swap tokens for an asset as UpdateDelegate without reroll', async (t) => {
// Given a Umi instance using the project's plugin.
const umi = await createUmi();
const feeLocation = generateSigner(umi);
const { assets, collection } = await createCoreCollection(umi);
const tokenMint = generateSigner(umi);
await createFungible(umi, {
name: 'Test Token',
uri: 'www.fungible.com',
sellerFeeBasisPoints: {
basisPoints: 0n,
identifier: '%',
decimals: 2,
},
mint: tokenMint,
}).sendAndConfirm(umi);

await mintV1(umi, {
mint: tokenMint.publicKey,
tokenStandard: TokenStandard.Fungible,
tokenOwner: umi.identity.publicKey,
amount: 1000,
}).sendAndConfirm(umi);

const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection.publicKey),
]);

// Transfer the assets to the escrow.
// eslint-disable-next-line no-restricted-syntax
for (const asset of assets) {
// eslint-disable-next-line no-await-in-loop
await transfer(umi, {
asset,
collection,
newOwner: escrow,
}).sendAndConfirm(umi);
}

await initEscrowV1(umi, {
escrow,
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com/',
max: 9,
min: 0,
amount: 5,
feeAmount: 1,
path: buildPath([Path.NoRerollMetadata]),
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

await addCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'UpdateDelegate',
additionalDelegates: [],
authority: { type: 'Address', address: publicKey(escrow) },
},
}).sendAndConfirm(umi);

const escrowData = await fetchEscrowV1(umi, escrow);

t.like(escrowData, <EscrowV1>{
publicKey: publicKey(escrow),
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com/',
max: 9n,
min: 0n,
amount: 5n,
feeAmount: 1n,
count: 1n,
path: buildPath([Path.NoRerollMetadata]),
bump: escrow[1],
solFeeAmount: 1_000_000n,
});

await captureV1(umi, {
owner: umi.identity,
authority: escrow,
escrow,
asset: assets[0].publicKey,
collection: collection.publicKey,
feeProjectAccount: escrowData.feeLocation,
token: tokenMint.publicKey,
}).sendAndConfirm(umi);

const escrowTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
publicKey(escrow)
);
t.deepEqual(escrowTokenAfter.token.amount, 5n);
const userTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
umi.identity.publicKey
);
t.deepEqual(userTokenAfter.token.amount, 994n);
const feeTokenAfter = await fetchDigitalAssetWithAssociatedToken(
umi,
tokenMint.publicKey,
escrowData.feeLocation
);
t.deepEqual(feeTokenAfter.token.amount, 1n);
const assetAfter = await fetchAsset(umi, assets[0].publicKey);
t.is(assetAfter.owner, umi.identity.publicKey);

// Make sure the URI has not changed.
t.is(assetAfter.uri, 'https://example.com/asset');
});
Loading
Loading