@nina-protocol/nina-db 0.0.103 → 0.0.105

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,7 +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';
13
- import promiseRetry from 'promise-retry';
14
+ import { getTokenMetadata } from '@solana/spl-token';
14
15
  const ensureHttps = (uri) => {
15
16
  if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
16
17
  return `https://${uri}`;
@@ -53,21 +54,25 @@ export default class Release extends Model {
53
54
  archived: { type: 'boolean' },
54
55
  },
55
56
  };
56
- static findOrCreate = async (publicKey, hubPublicKey = null) => {
57
+ static findOrCreate = async (publicKey, hubPublicKey = null, programId = process.env.NINA_PROGRAM_V2_ID) => {
57
58
  try {
59
+ console.log('Release.findOrCreate', publicKey, programId);
58
60
  let release = await Release.query().findOne({ publicKey });
59
61
  if (release) {
62
+ console.log('release found', release);
60
63
  return release;
61
64
  }
65
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
62
66
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
63
67
  const provider = new anchor.AnchorProvider(connection, {}, { commitment: 'confirmed' });
64
- 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';
65
70
  const metaplex = new Metaplex(connection);
66
71
  let attempts = 0;
67
72
  const releaseAccount = await promiseRetry(async (retry) => {
68
73
  try {
69
74
  attempts += 1;
70
- 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');
71
76
  return result;
72
77
  }
73
78
  catch (error) {
@@ -79,7 +84,13 @@ export default class Release extends Model {
79
84
  minTimeout: 500,
80
85
  maxTimeout: 1500,
81
86
  });
82
- 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
+ }
83
94
  if (!metadataAccount) {
84
95
  throw new Error('No metadata account found for release - is not a complete release');
85
96
  }
@@ -94,12 +105,13 @@ export default class Release extends Model {
94
105
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
95
106
  release = await this.createRelease({
96
107
  publicKey,
97
- mint: releaseAccount.releaseMint.toBase58(),
108
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
98
109
  metadata: json,
99
- 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(),
100
111
  slug,
101
112
  publisherId: publisher.id,
102
- releaseAccount
113
+ releaseAccount,
114
+ programId,
103
115
  });
104
116
  if (hubPublicKey) {
105
117
  const hub = await Hub.query().findOne({ publicKey: hubPublicKey });
@@ -115,7 +127,7 @@ export default class Release extends Model {
115
127
  return null;
116
128
  }
117
129
  };
118
- static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount }) => {
130
+ static createRelease = async ({ publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId }) => {
119
131
  const slug = await this.generateSlug(metadata);
120
132
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
121
133
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -128,7 +140,8 @@ export default class Release extends Model {
128
140
  publisherId,
129
141
  price: `${price}`,
130
142
  paymentMint,
131
- archived: false
143
+ archived: false,
144
+ programId,
132
145
  });
133
146
  if (metadata.properties.tags) {
134
147
  for await (let tag of metadata.properties.tags) {
@@ -136,7 +149,9 @@ export default class Release extends Model {
136
149
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
137
150
  }
138
151
  }
139
- await this.processRevenueShares(releaseAccount, release);
152
+ if (programId === process.env.NINA_PROGRAM_ID) {
153
+ await this.processRevenueShares(releaseAccount, release);
154
+ }
140
155
  tweetNewRelease(metadata, publisherId, slug);
141
156
  return release;
142
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.103",
3
+ "version": "0.0.105",
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,7 +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';
13
- import promiseRetry from 'promise-retry';
14
+ import { getTokenMetadata } from '@solana/spl-token';
14
15
 
15
16
  const ensureHttps = (uri) => {
16
17
  if (!uri.startsWith('http://') && !uri.startsWith('https://')) {
@@ -57,27 +58,30 @@ export default class Release extends Model {
57
58
  },
58
59
  }
59
60
 
60
- static findOrCreate = async (publicKey, hubPublicKey=null) => {
61
+ static findOrCreate = async (publicKey, hubPublicKey=null, programId=process.env.NINA_PROGRAM_V2_ID) => {
61
62
  try {
63
+ console.log('Release.findOrCreate', publicKey, programId)
62
64
  let release = await Release.query().findOne({ publicKey });
63
65
  if (release) {
66
+ console.log('release found', release)
64
67
  return release;
65
68
  }
66
69
 
70
+ let anchor = programId === process.env.NINA_PROGRAM_V2_ID ? anchorCoral : anchorSerum;
67
71
  const connection = new anchor.web3.Connection(process.env.SOLANA_CLUSTER_URL);
68
72
  const provider = new anchor.AnchorProvider(connection, {}, {commitment: 'confirmed'})
69
73
  const program = await anchor.Program.at(
70
- process.env.NINA_PROGRAM_ID,
74
+ programId,
71
75
  provider,
72
76
  )
77
+ const programModelName = programId === process.env.NINA_PROGRAM_V2_ID ? 'releaseV2' : 'release';
73
78
  const metaplex = new Metaplex(connection);
74
79
  let attempts = 0;
75
-
76
80
  const releaseAccount = await promiseRetry(
77
81
  async (retry) => {
78
82
  try {
79
83
  attempts += 1
80
- 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')
81
85
  return result
82
86
  } catch (error) {
83
87
  console.log('error fetching release account', error)
@@ -90,7 +94,12 @@ export default class Release extends Model {
90
94
  }
91
95
  )
92
96
 
93
- 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
+ }
94
103
  if (!metadataAccount) {
95
104
  throw new Error('No metadata account found for release - is not a complete release')
96
105
  }
@@ -105,12 +114,13 @@ export default class Release extends Model {
105
114
  let publisher = await Account.findOrCreate(releaseAccount.authority.toBase58());
106
115
  release = await this.createRelease({
107
116
  publicKey,
108
- mint: releaseAccount.releaseMint.toBase58(),
117
+ mint: programId === process.env.NINA_PROGRAM_V2_ID ? releaseAccount.mint.toBase58() : releaseAccount.releaseMint.toBase58(),
109
118
  metadata: json,
110
- 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(),
111
120
  slug,
112
121
  publisherId: publisher.id,
113
- releaseAccount
122
+ releaseAccount,
123
+ programId,
114
124
  });
115
125
 
116
126
  if (hubPublicKey) {
@@ -129,7 +139,7 @@ export default class Release extends Model {
129
139
  }
130
140
  }
131
141
 
132
- static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount}) => {
142
+ static createRelease = async ({publicKey, mint, metadata, datetime, publisherId, releaseAccount, programId}) => {
133
143
  const slug = await this.generateSlug(metadata);
134
144
  const price = releaseAccount.account?.price?.toNumber() || releaseAccount?.price?.toNumber() || 0;
135
145
  const paymentMint = releaseAccount.account?.paymentMint.toBase58() || releaseAccount?.paymentMint.toBase58();
@@ -142,7 +152,8 @@ export default class Release extends Model {
142
152
  publisherId,
143
153
  price: `${price}`,
144
154
  paymentMint,
145
- archived: false
155
+ archived: false,
156
+ programId,
146
157
  })
147
158
  if (metadata.properties.tags) {
148
159
  for await (let tag of metadata.properties.tags) {
@@ -150,7 +161,9 @@ export default class Release extends Model {
150
161
  await Release.relatedQuery('tags').for(release.id).relate(tagRecord.id).onConflict(['tagId', 'releaseId']).ignore();
151
162
  }
152
163
  }
153
- await this.processRevenueShares(releaseAccount, release);
164
+ if (programId === process.env.NINA_PROGRAM_ID) {
165
+ await this.processRevenueShares(releaseAccount, release);
166
+ }
154
167
  tweetNewRelease(metadata, publisherId, slug);
155
168
  return release;
156
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',