@nina-protocol/nina-db 0.0.104 → 0.0.106

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
- import anchor from '@project-serum/anchor';
1
+ import * as anchorSerum from '@project-serum/anchor';
2
+ import * as anchorCoral from '@coral-xyz/anchor';
2
3
  import { Metaplex } from '@metaplex-foundation/js';
3
4
  import { Model } from 'objection';
4
5
  import { stripHtmlIfNeeded, tweetNewRelease } from '../utils/index.js';
@@ -10,6 +11,7 @@ import Tag from './Tag.js';
10
11
  import axios from 'axios';
11
12
  import promiseRetry from 'promise-retry';
12
13
  import { customAlphabet } from 'nanoid';
14
+ import { getTokenMetadata } from '@solana/spl-token';
13
15
  const ensureHttps = (uri) => {
14
16
  if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
15
17
  return `https://${uri}`;
@@ -52,21 +54,25 @@ export default class Release extends Model {
52
54
  archived: { type: 'boolean' },
53
55
  },
54
56
  };
55
- static findOrCreate = async (publicKey, hubPublicKey = null) => {
57
+ static findOrCreate = async (publicKey, hubPublicKey = null, programId = process.env.NINA_PROGRAM_V2_ID) => {
56
58
  try {
59
+ console.log('Release.findOrCreate', publicKey, programId);
57
60
  let release = await Release.query().findOne({ publicKey });
58
61
  if (release) {
62
+ console.log('release found', release);
59
63
  return release;
60
64
  }
65
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
61
66
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
62
67
  const provider = new anchor.AnchorProvider(connection, {}, { commitment: 'confirmed' });
63
- const program = await anchor.Program.at(process.env.NINA_PROGRAM_ID, provider);
68
+ const program = await anchor.Program.at(programId, provider);
69
+ const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
64
70
  const metaplex = new Metaplex(connection);
65
71
  let attempts = 0;
66
72
  const releaseAccount = await promiseRetry(async (retry) => {
67
73
  try {
68
74
  attempts += 1;
69
- const result = await program.account.release.fetch(new anchor.web3.PublicKey(publicKey), 'confirmed');
75
+ const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed');
70
76
  return result;
71
77
  }
72
78
  catch (error) {
@@ -78,7 +84,13 @@ export default class Release extends Model {
78
84
  minTimeout: 500,
79
85
  maxTimeout: 1500,
80
86
  });
81
- let metadataAccount = (await metaplex.nfts().findAllByMintList({ mints: [releaseAccount.releaseMint] }, { commitment: 'confirmed' }))[0];
87
+ let metadataAccount;
88
+ if (programId === process.env.NINA_PROGRAM_V2_ID) {
89
+ metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed');
90
+ }
91
+ else {
92
+ metadataAccount = (await metaplex.nfts().findAllByMintList({ mints: [releaseAccount.releaseMint] }, { commitment: 'confirmed' }))[0];
93
+ }
82
94
  if (!metadataAccount) {
83
95
  throw new Error('No metadata account found for release - is not a complete release');
84
96
  }
@@ -93,12 +105,13 @@ export default class Release extends Model {
93
105
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
94
106
  release = await this.createRelease({
95
107
  publicKey,
96
- mint: releaseAccount.releaseMint.toBase58(),
108
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
97
109
  metadata: json,
98
- datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
110
+ datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
99
111
  slug,
100
112
  publisherId: publisher.id,
101
- releaseAccount
113
+ releaseAccount,
114
+ programId,
102
115
  });
103
116
  if (hubPublicKey) {
104
117
  const hub = await Hub.query().findOne({ publicKey: hubPublicKey });
@@ -114,7 +127,7 @@ export default class Release extends Model {
114
127
  return null;
115
128
  }
116
129
  };
117
- static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount }) => {
130
+ static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId }) => {
118
131
  const slug = await this.generateSlug(metadata);
119
132
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
120
133
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -127,7 +140,8 @@ export default class Release extends Model {
127
140
  publisherId,
128
141
  price: `${price}`,
129
142
  paymentMint,
130
- archived: false
143
+ archived: false,
144
+ programId,
131
145
  });
132
146
  if (metadata.properties.tags) {
133
147
  for await (let tag of metadata.properties.tags) {
@@ -135,7 +149,9 @@ export default class Release extends Model {
135
149
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
136
150
  }
137
151
  }
138
- await this.processRevenueShares(releaseAccount, release);
152
+ if (programId === process.env.NINA_PROGRAM_ID) {
153
+ await this.processRevenueShares(releaseAccount, release);
154
+ }
139
155
  tweetNewRelease(metadata, publisherId, slug);
140
156
  return release;
141
157
  };
@@ -20,6 +20,8 @@ class Transaction extends Model {
20
20
  type: {
21
21
  type: 'string',
22
22
  enum: [
23
+ 'ReleaseInitV2',
24
+ 'ReleaseUpdate',
23
25
  'ExchangeAccept',
24
26
  'ExchangeCancel',
25
27
  'ExchangeInit',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nina-protocol/nina-db",
3
- "version": "0.0.104",
3
+ "version": "0.0.106",
4
4
  "description": "",
5
5
  "source": "src/index.js",
6
6
  "main": "dist/index.js",
@@ -23,7 +23,8 @@
23
23
  "@babel/plugin-proposal-object-rest-spread": "^7.20.7",
24
24
  "@babel/preset-es2015": "^7.0.0-beta.53",
25
25
  "@metaplex-foundation/js": "^0.18.1",
26
- "@project-serum/anchor": "^0.25.0",
26
+ "@coral-xyz/anchor": "^0.31.0",
27
+ "@solana/spl-token": "^0.4.9",
27
28
  "axios": "^0.27.2",
28
29
  "knex": "^2.2.0",
29
30
  "nanoid": "^4.0.2",
@@ -46,6 +47,6 @@
46
47
  "rollup-plugin-babel": "^4.4.0",
47
48
  "rollup-plugin-commonjs": "^10.1.0",
48
49
  "rollup-plugin-terser": "^7.0.2",
49
- "typescript": "4.3.5"
50
+ "typescript": "5.7.3"
50
51
  }
51
52
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function(knex) {
6
+ return knex.schema.table('releases', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+
11
+ /**
12
+ * @param { import("knex").Knex } knex
13
+ * @returns { Promise<void> }
14
+ */
15
+ export const down = function(knex) {
16
+ return knex.schema.table('releases', table => {
17
+ table.dropColumn('programId');
18
+ });
19
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @param { import("knex").Knex } knex
3
+ * @returns { Promise<void> }
4
+ */
5
+ export const up = function(knex) {
6
+ return knex.schema.table('transactions', table => {
7
+ table.string('programId').notNullable().defaultTo(process.env.NINA_PROGRAM_ID);
8
+ });
9
+ };
10
+
11
+ /**
12
+ * @param { import("knex").Knex } knex
13
+ * @returns { Promise<void> }
14
+ */
15
+ export const down = function(knex) {
16
+ return knex.schema.table('transactions', table => {
17
+ table.dropColumn('programId');
18
+ });
19
+ };
@@ -1,4 +1,5 @@
1
- import anchor from '@project-serum/anchor';
1
+ import * as anchorSerum from '@project-serum/anchor';
2
+ import * as anchorCoral from '@coral-xyz/anchor';
2
3
  import { Metaplex } from '@metaplex-foundation/js';
3
4
  import { Model } from 'objection';
4
5
  import { stripHtmlIfNeeded, tweetNewRelease }from '../utils/index.js';
@@ -10,6 +11,7 @@ import Tag from './Tag.js';
10
11
  import axios from 'axios';
11
12
  import promiseRetry from 'promise-retry';
12
13
  import { customAlphabet } from 'nanoid';
14
+ import { getTokenMetadata } from '@solana/spl-token';
13
15
 
14
16
  const ensureHttps = (uri) => {
15
17
  if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
@@ -56,27 +58,30 @@ export default class Release extends Model {
56
58
  },
57
59
  }
58
60
 
59
- static findOrCreate = async (publicKey, hubPublicKey=null) => {
61
+ static findOrCreate = async (publicKey, hubPublicKey=null, programId=process.env.NINA_PROGRAM_V2_ID) => {
60
62
  try {
63
+ console.log('Release.findOrCreate', publicKey, programId)
61
64
  let release = await Release.query().findOne({ publicKey });
62
65
  if (release) {
66
+ console.log('release found', release)
63
67
  return release;
64
68
  }
65
69
 
70
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
66
71
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
67
72
  const provider = new anchor.AnchorProvider(connection, {}, {commitment: 'confirmed'})
68
73
  const program = await anchor.Program.at(
69
- process.env.NINA_PROGRAM_ID,
74
+ programId,
70
75
  provider,
71
76
  )
77
+ const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
72
78
  const metaplex = new Metaplex(connection);
73
79
  let attempts = 0;
74
-
75
80
  const releaseAccount = await promiseRetry(
76
81
  async (retry) => {
77
82
  try {
78
83
  attempts += 1
79
- const result = await program.account.release.fetch(new anchor.web3.PublicKey(publicKey), 'confirmed')
84
+ const result = await program.account[programModelName].fetch(new anchor.web3.PublicKey(publicKey), 'confirmed')
80
85
  return result
81
86
  } catch (error) {
82
87
  console.log('error fetching release account', error)
@@ -89,7 +94,12 @@ export default class Release extends Model {
89
94
  }
90
95
  )
91
96
 
92
- let metadataAccount = (await metaplex.nfts().findAllByMintList({mints: [releaseAccount.releaseMint]}, { commitment: 'confirmed' }))[0];
97
+ let metadataAccount
98
+ if (programId === process.env.NINA_PROGRAM_V2_ID) {
99
+ metadataAccount = await getTokenMetadata(connection, releaseAccount.mint, 'confirmed')
100
+ } else {
101
+ metadataAccount = (await metaplex.nfts().findAllByMintList({mints: [releaseAccount.releaseMint]}, { commitment: 'confirmed' }))[0];
102
+ }
93
103
  if (!metadataAccount) {
94
104
  throw new Error('No metadata account found for release - is not a complete release')
95
105
  }
@@ -104,12 +114,13 @@ export default class Release extends Model {
104
114
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
105
115
  release = await this.createRelease({
106
116
  publicKey,
107
- mint: releaseAccount.releaseMint.toBase58(),
117
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
108
118
  metadata: json,
109
- datetime: new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
119
+ datetime: programId === process.env.NINA_PROGRAM_V2_ID ? new Date().toISOString() : new Date(releaseAccount.releaseDatetime.toNumber() * 1000).toISOString(),
110
120
  slug,
111
121
  publisherId: publisher.id,
112
- releaseAccount
122
+ releaseAccount,
123
+ programId,
113
124
  });
114
125
 
115
126
  if (hubPublicKey) {
@@ -128,7 +139,7 @@ export default class Release extends Model {
128
139
  }
129
140
  }
130
141
 
131
- static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount}) => {
142
+ static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId}) => {
132
143
  const slug = await this.generateSlug(metadata);
133
144
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
134
145
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -141,7 +152,8 @@ export default class Release extends Model {
141
152
  publisherId,
142
153
  price: `${price}`,
143
154
  paymentMint,
144
- archived: false
155
+ archived: false,
156
+ programId,
145
157
  })
146
158
  if (metadata.properties.tags) {
147
159
  for await (let tag of metadata.properties.tags) {
@@ -149,7 +161,9 @@ export default class Release extends Model {
149
161
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
150
162
  }
151
163
  }
152
- await this.processRevenueShares(releaseAccount, release);
164
+ if (programId === process.env.NINA_PROGRAM_ID) {
165
+ await this.processRevenueShares(releaseAccount, release);
166
+ }
153
167
  tweetNewRelease(metadata, publisherId, slug);
154
168
  return release;
155
169
  }
@@ -21,6 +21,8 @@ class Transaction extends Model {
21
21
  type: {
22
22
  type: 'string',
23
23
  enum: [
24
+ 'ReleaseInitV2',
25
+ 'ReleaseUpdate',
24
26
  'ExchangeAccept',
25
27
  'ExchangeCancel',
26
28
  'ExchangeInit',