From ef9de9f84a7134e43c7eaaba0233b8eb06a2ccf8 Mon Sep 17 00:00:00 2001 From: shotgunofdeath <42133844+shotgunofdeath@users.noreply.github.com> Date: Tue, 21 May 2024 10:07:48 +0200 Subject: [PATCH] Feat/mpl core alpha (#5) * feat(mpl-core): update to mpl-core alpha --- .github/file-filters.yml | 2 +- package.json | 2 +- pnpm-lock.yaml | 75 ++++++++++++---------- src/helpers.ts | 31 ++++++--- test/_expectedData.ts | 74 +++++++++++---------- test/_setup.ts | 134 +++++++++++++++++++++++---------------- test/das.test.ts | 32 ++++++++-- 7 files changed, 211 insertions(+), 139 deletions(-) diff --git a/.github/file-filters.yml b/.github/file-filters.yml index 9f0a9a0..2790b3f 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -8,4 +8,4 @@ js_client: &js_client - ".github/test-js-client.yml" - ".github/file-filters.yml" - ".github/.env" - - "**/" + - "/**" diff --git a/package.json b/package.json index 3b2ee92..e72039b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ }, "peerDependencies": { "@metaplex-foundation/digital-asset-standard-api": "^1.0.3", - "@metaplex-foundation/mpl-core": "^0.4.7", + "@metaplex-foundation/mpl-core": "1.0.0-alpha.6", "@metaplex-foundation/umi": ">=0.8.2 < 1" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aaddf7b..9298a7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^1.0.3 version: 1.0.3(@metaplex-foundation/umi@0.9.1) '@metaplex-foundation/mpl-core': - specifier: ^0.4.7 - version: 0.4.7(@metaplex-foundation/umi@0.9.1)(@noble/hashes@1.4.0) + specifier: 1.0.0-alpha.6 + version: 1.0.0-alpha.6(@metaplex-foundation/umi@0.9.1)(@noble/hashes@1.4.0) '@metaplex-foundation/umi': specifier: '>=0.8.2 < 1' version: 0.9.1 @@ -21,7 +21,7 @@ devDependencies: version: 4.1.0 '@metaplex-foundation/umi-bundle-tests': specifier: ^0.9.1 - version: 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) + version: 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) '@typescript-eslint/eslint-plugin': specifier: ^7.5.0 version: 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.4.4) @@ -74,8 +74,8 @@ packages: execa: 7.2.0 dev: true - /@babel/runtime@7.24.4: - resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + /@babel/runtime@7.24.5: + resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 @@ -177,8 +177,8 @@ packages: package.json: 2.0.1 dev: false - /@metaplex-foundation/mpl-core@0.4.7(@metaplex-foundation/umi@0.9.1)(@noble/hashes@1.4.0): - resolution: {integrity: sha512-0PvzYp0u3NrstbUzAL6nsUkvSUJukUQCa5CRUx23jrNPsO0nejsgKpx8RqaqrCCYKt2lZnq8TRzHQPBqFkVQIg==} + /@metaplex-foundation/mpl-core@1.0.0-alpha.6(@metaplex-foundation/umi@0.9.1)(@noble/hashes@1.4.0): + resolution: {integrity: sha512-siyjbbeq/+eFuG8Nbq/xJW/hvxGG10vdbtqwSSVfL7QwO0bL77A4F1LgWEqisOXI85RlMui45a5us3A64tZtzA==} peerDependencies: '@metaplex-foundation/umi': '>=0.8.2 < 1' '@noble/hashes': ^1.3.1 @@ -187,35 +187,35 @@ packages: '@noble/hashes': 1.4.0 dev: false - /@metaplex-foundation/umi-bundle-tests@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4): + /@metaplex-foundation/umi-bundle-tests@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8): resolution: {integrity: sha512-neAdkAVnjda8BC5bdkV0/ZsqlZU1BUmdOaI0HI6KvMUltT4+SnrxSPEhnGDZ7XvWcdhGB3TW5ho4GTOF5WrKdA==} peerDependencies: '@metaplex-foundation/umi': ^0.9.1 '@solana/web3.js': ^1.72.0 dependencies: '@metaplex-foundation/umi': 0.9.1 - '@metaplex-foundation/umi-eddsa-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) + '@metaplex-foundation/umi-eddsa-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) '@metaplex-foundation/umi-http-fetch': 0.9.1(@metaplex-foundation/umi@0.9.1) '@metaplex-foundation/umi-program-repository': 0.9.1(@metaplex-foundation/umi@0.9.1) - '@metaplex-foundation/umi-rpc-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) + '@metaplex-foundation/umi-rpc-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) '@metaplex-foundation/umi-serializer-data-view': 0.9.1(@metaplex-foundation/umi@0.9.1) '@metaplex-foundation/umi-storage-mock': 0.9.1(@metaplex-foundation/umi@0.9.1) - '@metaplex-foundation/umi-transaction-factory-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) - '@solana/web3.js': 1.91.4 + '@metaplex-foundation/umi-transaction-factory-web3js': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 transitivePeerDependencies: - encoding dev: true - /@metaplex-foundation/umi-eddsa-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4): + /@metaplex-foundation/umi-eddsa-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8): resolution: {integrity: sha512-D+ZP8jOEzfr1ncF18zRdxfE820xjTf6AIBZd926TRj8dlOFIDfu1J0FGS7pC+52CAC9BRNrRvYQyc1TPORkfTQ==} peerDependencies: '@metaplex-foundation/umi': ^0.9.1 '@solana/web3.js': ^1.72.0 dependencies: '@metaplex-foundation/umi': 0.9.1 - '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) + '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) '@noble/curves': 1.4.0 - '@solana/web3.js': 1.91.4 + '@solana/web3.js': 1.91.8 dev: true /@metaplex-foundation/umi-http-fetch@0.9.1(@metaplex-foundation/umi@0.9.1): @@ -245,15 +245,15 @@ packages: dependencies: '@metaplex-foundation/umi-serializers-encodings': 0.8.9 - /@metaplex-foundation/umi-rpc-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4): + /@metaplex-foundation/umi-rpc-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8): resolution: {integrity: sha512-kOJEc9IWMX+H7dI5zZZimww1w0A6yd2V/fsQHKB/kHddja7JoPK4Au68n45Pi0vb3HY7riCQN9XMqOOPD5tcxA==} peerDependencies: '@metaplex-foundation/umi': ^0.9.1 '@solana/web3.js': ^1.72.0 dependencies: '@metaplex-foundation/umi': 0.9.1 - '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) - '@solana/web3.js': 1.91.4 + '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 dev: true /@metaplex-foundation/umi-serializer-data-view@0.9.1(@metaplex-foundation/umi@0.9.1): @@ -294,25 +294,25 @@ packages: '@metaplex-foundation/umi': 0.9.1 dev: true - /@metaplex-foundation/umi-transaction-factory-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4): + /@metaplex-foundation/umi-transaction-factory-web3js@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8): resolution: {integrity: sha512-DBBvaMpR6pR3ZpyaRD/0QSTjS+3lxHIUZYAqZi0JYsTyYqNTNsdKVbeu6uLjbeyoJbmqgKVZ0nZgcokEKx49eg==} peerDependencies: '@metaplex-foundation/umi': ^0.9.1 '@solana/web3.js': ^1.72.0 dependencies: '@metaplex-foundation/umi': 0.9.1 - '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4) - '@solana/web3.js': 1.91.4 + '@metaplex-foundation/umi-web3js-adapters': 0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8) + '@solana/web3.js': 1.91.8 dev: true - /@metaplex-foundation/umi-web3js-adapters@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.4): + /@metaplex-foundation/umi-web3js-adapters@0.9.1(@metaplex-foundation/umi@0.9.1)(@solana/web3.js@1.91.8): resolution: {integrity: sha512-O6lQGJFebRM8P67ajvUpuctJ/J39Lylp4wyg8E1tHmFxUsdBC7M9qBixi/WmCiNKgSfVrq6MmiYaba3OSrtqwg==} peerDependencies: '@metaplex-foundation/umi': ^0.9.1 '@solana/web3.js': ^1.72.0 dependencies: '@metaplex-foundation/umi': 0.9.1 - '@solana/web3.js': 1.91.4 + '@solana/web3.js': 1.91.8 buffer: 6.0.3 dev: true @@ -386,10 +386,10 @@ packages: buffer: 6.0.3 dev: true - /@solana/web3.js@1.91.4: - resolution: {integrity: sha512-zconqecIcBqEF6JiM4xYF865Xc4aas+iWK5qnu7nwKPq9ilRYcn+2GiwpYXqUqqBUe0XCO17w18KO0F8h+QATg==} + /@solana/web3.js@1.91.8: + resolution: {integrity: sha512-USa6OS1jbh8zOapRJ/CBZImZ8Xb7AJjROZl5adql9TpOoBN9BUzyyouS5oPuZHft7S7eB8uJPuXWYjMi6BHgOw==} dependencies: - '@babel/runtime': 7.24.4 + '@babel/runtime': 7.24.5 '@noble/curves': 1.4.0 '@noble/hashes': 1.4.0 '@solana/buffer-layout': 4.0.1 @@ -402,7 +402,7 @@ packages: fast-stable-stringify: 1.0.0 jayson: 4.1.0 node-fetch: 2.7.0 - rpc-websockets: 7.9.0 + rpc-websockets: 7.11.0 superstruct: 0.14.2 transitivePeerDependencies: - bufferutil @@ -962,7 +962,7 @@ packages: engines: {node: '>=6.14.2'} requiresBuild: true dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 dev: true /call-bind@1.0.7: @@ -2639,6 +2639,12 @@ packages: requiresBuild: true dev: true + /node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} + hasBin: true + requiresBuild: true + dev: true + /node-status-codes@1.0.0: resolution: {integrity: sha512-1cBMgRxdMWE8KeWCqk2RIOrvUb0XCwYfEsY5/y2NlXyq4Y/RumnOZvTj4Nbr77+Vb2C+kyBoRTdkNOS8L3d/aQ==} engines: {node: '>=0.10.0'} @@ -3130,13 +3136,12 @@ packages: glob: 10.3.12 dev: true - /rpc-websockets@7.9.0: - resolution: {integrity: sha512-DwKewQz1IUA5wfLvgM8wDpPRcr+nWSxuFxx5CbrI2z/MyyZ4nXLM86TvIA+cI1ZAdqC8JIBR1mZR55dzaLU+Hw==} + /rpc-websockets@7.11.0: + resolution: {integrity: sha512-IkLYjayPv6Io8C/TdCL5gwgzd1hFz2vmBZrjMw/SPEXo51ETOhnzgS4Qy5GWi2JQN7HKHa66J3+2mv0fgNh/7w==} dependencies: - '@babel/runtime': 7.24.4 eventemitter3: 4.0.7 uuid: 8.3.2 - ws: 8.16.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) + ws: 8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) optionalDependencies: bufferutil: 4.0.8 utf-8-validate: 5.0.10 @@ -3635,7 +3640,7 @@ packages: engines: {node: '>=6.14.2'} requiresBuild: true dependencies: - node-gyp-build: 4.8.0 + node-gyp-build: 4.8.1 dev: true /util-deprecate@1.0.2: @@ -3751,8 +3756,8 @@ packages: optional: true dev: true - /ws@8.16.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + /ws@8.17.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): + resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 diff --git a/src/helpers.ts b/src/helpers.ts index eda71ca..5cd091a 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -8,7 +8,7 @@ import { AddBlocker, AssetV1, Attributes, - BaseUpdateAuthority, + UpdateAuthority, BurnDelegate, CollectionV1, Edition, @@ -17,7 +17,7 @@ import { ImmutableMetadata, Key, mapPlugin, - MasterEdition, + BaseMasterEdition, MPL_CORE_PROGRAM_ID, PermanentBurnDelegate, PermanentFreezeDelegate, @@ -60,8 +60,8 @@ function base64ToUInt8Array(base64: string) { function getUpdateAuthority( groupingItem: DasApiAssetGrouping | undefined, authority: DasApiAssetAuthority -): Record<'updateAuthority', BaseUpdateAuthority> { - const result: { updateAuthority: BaseUpdateAuthority } = { +): Record<'updateAuthority', UpdateAuthority> { + const result: { updateAuthority: UpdateAuthority } = { updateAuthority: { type: 'None' }, }; @@ -84,13 +84,14 @@ function getAccountHeader( executable?: boolean, lamps?: BigIntInput, rentEpoch?: number -): Record<'header', AccountHeader> { +): Record<'header', AccountHeader & { exists: boolean }> { return { header: { executable: executable ?? false, owner: MPL_CORE_PROGRAM_ID, lamports: lamports(lamps ?? -1), ...(rentEpoch !== undefined ? { rentEpoch: BigInt(rentEpoch) } : {}), + exists: true, }, }; } @@ -105,15 +106,27 @@ function getRuleSet(dasRuleSet: string | Record): RuleSet { ) : []; + // RuleSet has both __kind and type for backwards compatibility if (ruleSetKind === 'program_allow_list') { - return ruleSet('ProgramAllowList', [ruleSetData]); + return { + ...ruleSet('ProgramAllowList', [ruleSetData]), + type: 'ProgramAllowList', + addresses: ruleSetData, + }; } if (ruleSetKind === 'program_deny_list') { - return ruleSet('ProgramDenyList', [ruleSetData]); + return { + ...ruleSet('ProgramDenyList', [ruleSetData]), + type: 'ProgramDenyList', + addresses: ruleSetData, + }; } - return ruleSet('None'); + return { + ...ruleSet('None'), + type: 'None', + }; } function dasPluginDataToCorePluginData( @@ -129,7 +142,7 @@ function dasPluginDataToCorePluginData( | PermanentTransferDelegate | PermanentBurnDelegate | Edition - | MasterEdition + | BaseMasterEdition | AddBlocker | ImmutableMetadata { // TODO: Refactor when DAS types are defined diff --git a/test/_expectedData.ts b/test/_expectedData.ts index 17be67c..fd3dbe3 100644 --- a/test/_expectedData.ts +++ b/test/_expectedData.ts @@ -190,27 +190,32 @@ export const dasTestCollection1: CollectionV1WithNoBasisPoints = { // exists: true, }, // pluginHeader: { key: 3, pluginRegistryOffset: 182n }, - transferDelegate: { - authority: { - type: 'Address', - address: publicKey('A8SQ9q2aRg2SAxJtBQxj8XwWMU74H1R7DYVCyNeYnQFx'), - }, - offset: 101n, - }, - burnDelegate: { - authority: { type: 'Owner', address: undefined }, - offset: 102n, - }, + + // This collection was created before owner managed plugins were forbidden to use with collections. + // But these plugins are actually present in the collection data + + // transferDelegate: { + // authority: { + // type: 'Address', + // address: publicKey('A8SQ9q2aRg2SAxJtBQxj8XwWMU74H1R7DYVCyNeYnQFx'), + // }, + // offset: 101n, + // }, + // burnDelegate: { + // authority: { type: 'Owner', address: undefined }, + // offset: 102n, + // }, + // freezeDelegate: { + // authority: { type: 'Owner', address: undefined }, + // offset: 108n, + // frozen: false, + // }, + updateDelegate: { authority: { type: 'UpdateAuthority', address: undefined }, offset: 103n, additionalDelegates: [], }, - freezeDelegate: { - authority: { type: 'Owner', address: undefined }, - offset: 108n, - frozen: false, - }, attributes: { authority: { type: 'UpdateAuthority', address: undefined }, offset: 110n, @@ -253,27 +258,32 @@ export const dasTestCollection2: CollectionV1WithNoBasisPoints = { // exists: true, }, // pluginHeader: { key: 3, pluginRegistryOffset: 182n }, - transferDelegate: { - authority: { - type: 'Address', - address: publicKey('G8xVUAnuYbMFq8pxtWFhUvHC8TVoAkqpWgahizugWFfF'), - }, - offset: 101n, - }, - burnDelegate: { - authority: { type: 'Owner', address: undefined }, - offset: 102n, - }, + + // This collection was created before owner managed plugins were forbidden to use with collections. + // But these plugins are actually present in the collection data + + // transferDelegate: { + // authority: { + // type: 'Address', + // address: publicKey('G8xVUAnuYbMFq8pxtWFhUvHC8TVoAkqpWgahizugWFfF'), + // }, + // offset: 101n, + // }, + // burnDelegate: { + // authority: { type: 'Owner', address: undefined }, + // offset: 102n, + // }, + // freezeDelegate: { + // authority: { type: 'Owner', address: undefined }, + // offset: 108n, + // frozen: false, + // }, + updateDelegate: { authority: { type: 'UpdateAuthority', address: undefined }, offset: 103n, additionalDelegates: [], }, - freezeDelegate: { - authority: { type: 'Owner', address: undefined }, - offset: 108n, - frozen: false, - }, attributes: { authority: { type: 'UpdateAuthority', address: undefined }, offset: 110n, diff --git a/test/_setup.ts b/test/_setup.ts index da6c880..54327ca 100644 --- a/test/_setup.ts +++ b/test/_setup.ts @@ -9,18 +9,17 @@ import { Signer, } from '@metaplex-foundation/umi'; import { - pluginAuthorityPair, AssetV1, - ruleSet, - addressPluginAuthority, CollectionV1, - createV1, fetchAssetV1, DataState, - PluginAuthorityPairArgs, fetchCollectionV1, - createCollectionV1, - updatePluginAuthority, + create, + createCollection as baseCreateCollection, + ExternalPluginAdapterInitInfoArgs, + AssetPluginAuthorityPairArgsV2, + CollectionPluginAuthorityPairArgsV2, + AuthorityManagedPluginArgsV2, } from '@metaplex-foundation/mpl-core'; import { dasApi } from '@metaplex-foundation/digital-asset-standard-api'; import { testPlugins } from '@metaplex-foundation/umi-bundle-tests'; @@ -30,6 +29,22 @@ export const DAS_API_ENDPOINT = process.env.DAS_API_ENDPOINT!; export const createUmiWithDas = (endpoint: string) => createUmi().use(testPlugins(endpoint)).use(dasApi()); +export const prepareAssetForComparison = ( + asset: AssetV1 | CollectionV1, + removePluginHeader = true +) => { + // Needed for passing tests with different RPC providers. + // Most providers do not return rentEpoch and set lamports basis points to -1n + asset.header.lamports.basisPoints = -1n; + delete asset.header.rentEpoch; + + if (removePluginHeader) { + // Remove plugin header for tests + // TODO: Reconstruct plugin header when converting data from DAS + delete asset.pluginHeader; + } +}; + export const ASSET_COMMON_DATA = { name: 'DAS Test Asset', uri: 'https://example.com/das-asset', @@ -49,9 +64,11 @@ type CreateAssetHelperArgs = { uri?: string; authority?: Signer; updateAuthority?: PublicKey | Signer; - collection?: PublicKey; - // TODO use PluginList type here - plugins?: PluginAuthorityPairArgs[]; + collection?: PublicKey | CollectionV1; + plugins?: ( + | ExternalPluginAdapterInitInfoArgs + | AssetPluginAuthorityPairArgsV2 + )[]; }; const createAsset = async (umi: Umi, input: CreateAssetHelperArgs = {}) => { @@ -59,8 +76,13 @@ const createAsset = async (umi: Umi, input: CreateAssetHelperArgs = {}) => { const owner = publicKey(input.owner || input.payer || umi.identity); const asset = input.asset || generateSigner(umi); const updateAuthority = publicKey(input.updateAuthority || payer); - // const tx = - await createV1(umi, { + + const collection = + typeof input.collection === 'string' + ? await fetchCollectionV1(umi, input.collection as PublicKey) + : (input.collection as CollectionV1 | undefined); + + await create(umi, { owner, payer, dataState: input.dataState, @@ -69,7 +91,7 @@ const createAsset = async (umi: Umi, input: CreateAssetHelperArgs = {}) => { name: input.name || ASSET_COMMON_DATA.name, uri: input.uri || ASSET_COMMON_DATA.uri, plugins: input.plugins, - collection: input.collection, + collection, authority: input.authority, }).sendAndConfirm(umi); @@ -82,8 +104,10 @@ type CreateCollectionHelperArgs = { name?: string; uri?: string; updateAuthority?: PublicKey | Signer; - // TODO use CollectionPluginList type here - plugins?: PluginAuthorityPairArgs[]; + plugins?: ( + | ExternalPluginAdapterInitInfoArgs + | CollectionPluginAuthorityPairArgsV2 + )[]; }; const createCollection = async ( @@ -93,7 +117,8 @@ const createCollection = async ( const payer = input.payer || umi.identity; const collection = input.collection || generateSigner(umi); const updateAuthority = publicKey(input.updateAuthority || payer); - await createCollectionV1(umi, { + + await baseCreateCollection(umi, { name: input.name || COLLECTION_COMMON_DATA.name, uri: input.uri || COLLECTION_COMMON_DATA.uri, collection, @@ -105,28 +130,26 @@ const createCollection = async ( return fetchCollectionV1(umi, publicKey(collection)); }; -function getPluginsForCreation(payer: PublicKey) { +function getPluginsForCreation( + payer: PublicKey +): AuthorityManagedPluginArgsV2[] { return [ - pluginAuthorityPair({ + { type: 'UpdateDelegate', - }), - pluginAuthorityPair({ + additionalDelegates: [], + }, + { type: 'Attributes', - data: { attributeList: [{ key: 'some key', value: 'some value' }] }, - }), - pluginAuthorityPair({ + attributeList: [{ key: 'some key', value: 'some value' }], + }, + { type: 'Royalties', - data: { - basisPoints: 5, - creators: [ - { - address: payer, - percentage: 100, - }, - ], - ruleSet: ruleSet('None'), + basisPoints: 500, + creators: [{ address: payer, percentage: 100 }], + ruleSet: { + type: 'None', }, - }), + }, ]; } @@ -165,15 +188,15 @@ export async function createDasTestAssetOrCollection({ payer, plugins: [ ...getPluginsForCreation(payer.publicKey), - pluginAuthorityPair({ + { type: 'MasterEdition', - data: { - maxSupply: 100, - name: 'Test Master Edition Name', - uri: 'https://example.com/das-collection-master-edition', + maxSupply: 100, + name: 'Test Master Edition Name', + uri: 'https://example.com/das-collection-master-edition', + authority: { + type: 'UpdateAuthority', }, - authority: updatePluginAuthority(), - }), + }, ], }); } else { @@ -185,24 +208,27 @@ export async function createDasTestAssetOrCollection({ collection, plugins: [ ...getPluginsForCreation(payer.publicKey), - pluginAuthorityPair({ - authority: addressPluginAuthority( - transferDelegateAuthority.publicKey - ), + { type: 'TransferDelegate', - }), - pluginAuthorityPair({ + authority: { + type: 'Address', + address: transferDelegateAuthority.publicKey, + }, + }, + { type: 'BurnDelegate', - authority: updatePluginAuthority(), - }), - pluginAuthorityPair({ + authority: { + type: 'UpdateAuthority', + }, + }, + { type: 'FreezeDelegate', - data: { frozen: false }, - }), - pluginAuthorityPair({ + frozen: false, + }, + { type: 'Edition', - data: { number: 2 }, - }), + number: 2, + }, ], }); } diff --git a/test/das.test.ts b/test/das.test.ts index e69aa47..a6e87b1 100644 --- a/test/das.test.ts +++ b/test/das.test.ts @@ -1,7 +1,11 @@ import test from 'ava'; import { publicKey } from '@metaplex-foundation/umi'; import { das } from '../src'; -import { createUmiWithDas, DAS_API_ENDPOINT } from './_setup'; +import { + createUmiWithDas, + DAS_API_ENDPOINT, + prepareAssetForComparison, +} from './_setup'; import { dasTestAsset1Owner, dasTestAsset1, @@ -17,7 +21,12 @@ import { dasTestAssetInCollectionPubKey, dasTestCollection2PubKey, } from './_expectedData'; -import { fetchAssetV1, fetchCollectionV1 } from '@metaplex-foundation/mpl-core'; +import { + AssetV1, + CollectionV1, + fetchAssetV1, + fetchCollectionV1, +} from '@metaplex-foundation/mpl-core'; test('das: it can search assets', async (t) => { // Given an Umi instance with DAS API @@ -128,19 +137,21 @@ test('das: it can fetch collections by update authority if update authority is n test('das: it can convert a DAS asset with the edition plugin to the MPL Core asset structure', async (t) => { // Given an Umi instance with DAS API and an asset with the edition plugin const umi = createUmiWithDas(DAS_API_ENDPOINT); - const assetPb = publicKey('94tbAopaajgjRndvvK31TBqNTkNbJdzifwW4ec7iqpYh'); + const assetPubKey = publicKey('94tbAopaajgjRndvvK31TBqNTkNbJdzifwW4ec7iqpYh'); // Then the asset data parsed from DAS const assets = await das.fetchAssetsByOwner(umi, { owner: publicKey('EBgC18R6zKNic1CLYKYEy3SMSz4zweymeqrMHkXeqpag'), }); - const assetDas = assets.find((a) => a.publicKey === assetPb) ?? {}; + const assetDas = assets.find((a) => a.publicKey === assetPubKey) ?? {}; + prepareAssetForComparison(assetDas as AssetV1, false); // Then the asset data fetched via fetchAssetV1 - const assetMplCore = await fetchAssetV1(umi, assetPb); + const assetMplCore = await fetchAssetV1(umi, assetPubKey); + prepareAssetForComparison(assetMplCore); // Assets data structure is the same from both sources - t.like(assetMplCore, assetDas); + t.like(assetDas, assetMplCore); }); test('das: it can convert a DAS collection with the master edition plugin to the MPL Core collection structure', async (t) => { @@ -156,10 +167,17 @@ test('das: it can convert a DAS collection with the master edition plugin to the }); const collectionDas = collections.find((a) => a.publicKey === collectionPubKey) ?? {}; + prepareAssetForComparison(collectionDas as CollectionV1, false); // Then the collection data fetched via fetchCollectionV1 const collectionMplCore = await fetchCollectionV1(umi, collectionPubKey); + prepareAssetForComparison(collectionMplCore); // Collections data structure is the same from both sources - t.like(collectionMplCore, collectionDas); + t.like(collectionDas, collectionMplCore); }); + +// TODO +test.skip('das: oracle', async (t) => {}); +test.skip('das: lifecycle hooks', async (t) => {}); +test.skip('das: data store', async (t) => {});